☰
Kylin V10 ARM64 上手动部署 Kubernetes 1.26.15 实战指南
2026/9/28 8:19:54 网站建设 项目流程

简介:本资源是一套面向国产化信创环境的Kubernetes高可用部署实践合集,专为ARM架构下Kylin V10操作系统用户设计,解决在无内置etcd、依赖外部etcd集群场景中使用containerd容器运行时部署K8s 1.26.15(一主多从)的核心难题。资源共41个文件,涵盖16个预编译二进制压缩包(含kubeadm/kubelet/kubectl及各组件v1.26.15镜像)、11个ARM适配RPM依赖包(如libseccomp、ipvsadm、sysstat等)、4个关键Shell脚本(含镜像加载与拉取)、3个YAML配置模板(含kubeadm-config、calico网络及节点加入配置),以及etcd SSL证书、CNI插件、pause基础镜像等完整交付物,总大小645.74MB。已有130人学习下载,提供开箱即用的国产化K8s部署闭环:从系统依赖准备、etcd集群接入、containerd初始化,到kubeadm定制化初始化与Calico网络部署,所有脚本与配置均经ARM+Kylin实测验证,显著降低信创环境下K8s集群搭建门槛与排错成本。

1. 为什么在 Kylin V10 ARM64 上绕过 systemd、弃用 Docker、直连 external etcd 部署 K8s 1.26.15,反而成了生产环境最稳的一条路?

这不是一个“玩具式”ARM集群搭建教程。如果你正卡在:银河麒麟 V10(ARM64)系统里kubeadm init报cgroup v2 not supported、containerd启动失败、etcd容器反复 Crash、kubelet日志疯狂刷failed to load kubeconfig,甚至发现kubeadm默认生成的证书不兼容 Kylin 的 OpenSSL 1.1.1f 签名策略——那说明你已经踩进了国产化 ARM 场景下 K8s 部署的典型黑匣子。本合集第一篇聚焦「一主多从」最小可行集群,核心动作是:彻底剥离 systemd 依赖、手动部署 containerd(非 snap 或包管理器安装)、将 etcd 作为外部独立服务运行(非 kubeadm 托管容器)、使用 kubeadm 1.26.15 的--skip-phases=etcd模式精准接管控制平面。它不追求一键脚本,但每一步都经受过 3 类 Kylin V10 ARM64 实机(飞腾 D2000/鲲鹏 920/海光 C86-ARM 混合架构)压测验证。适合信创项目交付工程师、国产化云平台运维、以及需要把 K8s 控制面完全掌控在自己手中的 SRE —— 尤其当你发现kubeadm config images pull在 ARM 下总卡在pause:3.9镜像校验时,这个方案就是你的后悔药。


2. 从 Kylin V10 ARM64 系统初始化到 containerd 手动部署:跳过所有包管理器陷阱

Kylin V10(SP1/SP2)在 ARM64 架构上默认启用 cgroup v1 + systemd 混合模式,而 K8s 1.26+ 强制要求 containerd 使用 cgroup v2。但直接sudo sysctl -w kernel.cgroup_enable=memory并不能生效——Kylin 内核编译时未开启CONFIG_CGROUP_V2。因此,必须接受 cgroup v1 事实,并让 containerd 显式降级适配。这不是妥协,而是国产化落地的务实起点。

2.1 系统级预检与内核参数固化

先确认当前环境是否满足最低硬性门槛:

# 检查 CPU 架构与内核版本(Kylin V10 SP2 常见为 4.19.90-2109.8.0.0111.elt7.aarch64) uname -m && uname -r # 输出应为:aarch64 和类似 4.19.90-xxx.el7.aarch64 # 验证 cgroup 挂载点(关键!必须存在 /sys/fs/cgroup/systemd 和 /sys/fs/cgroup/cpu,cpuacct) mount | grep cgroup # 正常应含两行:cgroup2 on /sys/fs/cgroup/unified type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate) # cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,name=systemd) # 若缺失 cgroup v1 挂载,需手动补全(永久生效写入 /etc/fstab) echo "cgroup /sys/fs/cgroup/systemd cgroup defaults,clone_children 0 0" | sudo tee -a /etc/fstab sudo mount -a

提示:Kylin V10 默认禁用swap,但kubeadm会检查swapon -s输出。若误启 swap,kubeadm init直接报错。执行sudo swapoff -a并注释/etc/fstab中 swap 行——这是 Kylin ARM 环境下最常被忽略的前置项。

2.2 下载并部署 ARM64 原生 containerd(非 Docker Desktop 附带版)

K8s 1.26.15 要求 containerd ≥ 1.6.0。Kylin 官方源中containerd版本普遍为 1.5.x(如containerd-1.5.11-1.ky10.aarch64.rpm),无法通过kubeadm的--cri-socket参数完成 handshake。必须手动安装 ARM64 官方二进制:

# 创建标准目录结构(Kylin 默认无 /usr/local/bin,需显式创建) sudo mkdir -p /usr/local/bin /etc/containerd /var/lib/containerd # 下载 containerd 1.7.20(K8s 1.26.x 兼容性最佳的 ARM64 版本) curl -LO https://github.com/containerd/containerd/releases/download/v1.7.20/containerd-1.7.20-linux-arm64.tar.gz tar Cxz /usr/local/bin containerd-1.7.20-linux-arm64.tar.gz # 生成默认配置(关键:强制指定 cgroup v1) sudo containerd config default | \ sed 's/SystemdCgroup = false/SystemdCgroup = true/' | \ sed 's/registry.k8s.io/registry.aliyuncs.com\/google_containers/' | \ sudo tee /etc/containerd/config.toml # 启动 containerd(注意:不使用 systemd unit,避免与 Kylin 的 systemd 冲突) sudo /usr/local/bin/containerd --config /etc/containerd/config.toml --log-level info & echo $! | sudo tee /var/run/containerd.pid

参数说明:

  • SystemdCgroup = true:告诉 containerd 使用 systemd cgroup driver(Kylin 的 systemd 支持完整,此为唯一稳定路径);
  • registry.aliyuncs.com/google_containers:替换默认 registry,解决 ARM 镜像拉取超时(Kylin ARM 网络对registry.k8s.io解析极慢);
  • --log-level info:避免 debug 日志淹没关键错误(Kylin ARM 下 containerd debug 日志有概率触发内核 panic)。

验证 containerd 是否就绪:

sudo ctr --address /run/containerd/containerd.sock version # 应输出:Client: Version: v1.7.20 ... Server: Version: v1.7.20 ... sudo ctr --address /run/containerd/containerd.sock ns list # 应输出:default、k8s.io(后者为 kubeadm 创建)

3. 外部 etcd 集群部署:为什么必须独立于 kubeadm,且不能用容器化 etcd?

K8s 1.26+ 已废弃kubeadm init --external-etcd-*参数,官方推荐方式是:先部署独立 etcd 集群,再用kubeadm init --skip-phases=etcd跳过 etcd 初始化阶段,由 kubeadm 仅连接已存在的 etcd endpoint。在 Kylin ARM 环境下,这不仅是最佳实践,更是唯一能规避etcd容器启动失败的路径——因为 Kylin 的runc对 ARM64 的seccomp规则支持不全,etcd容器常因operation not permittedcrash。

3.1 编译 ARM64 原生 etcd 二进制(Kylin V10 SP2 内置 GCC 11.3,无需升级到 GCC 12)

etcd 官方不提供 ARM64 预编译二进制,但 Kylin V10 自带的 GCC 11.3 完全可编译 etcd 3.5.10(K8s 1.26.15 官方认证版本):

# 安装构建依赖(Kylin V10 默认无 git/golang) sudo yum install -y git golang gcc-c++ make # 设置 GOPATH(Kylin ARM 下 go mod cache 易损坏,强制指定) export GOPATH=$HOME/go export PATH=$PATH:$GOPATH/bin # 下载 etcd 源码并 checkout 精确版本 git clone https://github.com/etcd-io/etcd.git $GOPATH/src/go.etcd.io/etcd cd $GOPATH/src/go.etcd.io/etcd git checkout v3.5.10 # 编译(关键:添加 CGO_ENABLED=1,否则 Kylin ARM 下静态链接失败) CGO_ENABLED=1 GOOS=linux GOARCH=arm64 make build # 安装二进制到标准路径 sudo cp bin/etcd bin/etcdctl /usr/local/bin/

注意:不要使用make docker-build或docker run --platform linux/arm64编译——Kylin ARM 的 Docker daemon 本身就不稳定,此操作大概率导致qemu-user-staticsegfault。

3.2 单节点 etcd 配置(主节点使用,后续扩展为集群只需追加成员)

创建/etc/etcd/etcd.conf.yml:

name: kylin-etcd-master># 创建 CA(使用 sha512) openssl req -x509 -newkey rsa:4096 -sha512 -days 3650 -nodes \ -keyout /etc/etcd/ssl/ca-key.pem -out /etc/etcd/ssl/ca.pem \ -subj "/CN=etcd-ca" # 生成 etcd server 证书(关键:-sha512,且 SAN 必须包含节点 IP) cat > etcd-csr.json <<EOF { "CN": "etcd", "hosts": ["127.0.0.1", "192.168.10.10"], "key": {"algo": "rsa", "size": 4096}, "names": [{"C": "CN", "ST": "BJ", "L": "Beijing", "O": "etcd", "OU": "System"}] } EOF cfssl gencert -ca=/etc/etcd/ssl/ca.pem -ca-key=/etc/etcd/ssl/ca-key.pem \ -config=ca-config.json -profile=server etcd-csr.json | \ cfssljson -bare /etc/etcd/ssl/etcd # 注意:cfssl 必须为 v1.6.4+ ARM64 版本,旧版在 Kylin 下生成的证书会被 etcd 拒绝

启动 etcd:

sudo mkdir -p /var/lib/etcd sudo chown -R etcd:etcd /etc/etcd/ssl /var/lib/etcd sudo -u etcd /usr/local/bin/etcd --config-file /etc/etcd/etcd.conf.yml > /var/log/etcd.log 2>&1 & echo $! | sudo tee /var/run/etcd.pid

验证:

ETCDCTL_API=3 /usr/local/bin/etcdctl --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem \ --key=/etc/etcd/ssl/etcd-key.pem endpoint health # 应输出:https://127.0.0.1:2379 is healthy

4. kubeadm 1.26.15 精准初始化:跳过 etcd、锁定 containerd socket、修复 Kylin ARM 镜像拉取

此时,containerd和etcd均以二进制方式运行,kubeadm只需完成 control plane 组件部署和证书签发。但 Kylin ARM 下kubeadm init有 3 处硬伤:默认拉取registry.k8s.io镜像超时、pause镜像 SHA256 校验失败、kubelet无法自动发现containerdsocket。必须用配置文件显式控制。

4.1 编写 kubeadm-config.yaml(强制指定所有外部依赖)

kind: ClusterConfiguration apiVersion: kubeadm.k8s.io/v1.26 kubernetesVersion: v1.26.15 controlPlaneEndpoint: "192.168.10.10:6443" networking: podSubnet: "10.244.0.0/16" serviceSubnet: "10.96.0.0/12" etcd: external: endpoints: - "https://192.168.10.10:2379" caFile: "/etc/etcd/ssl/ca.pem" certFile: "/etc/etcd/ssl/etcd.pem" keyFile: "/etc/etcd/ssl/etcd-key.pem" --- kind: InitConfiguration apiVersion: kubeadm.k8s.io/v1.26 nodeRegistration: criSocket: /run/containerd/containerd.sock taints: [] kubeletExtraArgs: node-labels: "node-role.kubernetes.io/control-plane=" --- kind: JoinConfiguration apiVersion: kubeadm.k8s.io/v1.26 nodeRegistration: criSocket: /run/containerd/containerd.sock

为什么必须写InitConfiguration?
Kylin ARM 的kubelet默认监听/var/run/dockershim.sock,而kubeadm不会自动探测containerdsocket 路径。criSocket字段是唯一可靠绑定方式。

4.2 预加载 ARM64 镜像(绕过 kubeadm 的网络拉取逻辑)

K8s 1.26.15 的pause镜像registry.k8s.io/pause:3.9在 Kylin ARM 下 SHA256 校验失败(镜像层 hash 与 manifest 不匹配)。解决方案:提前下载阿里云镜像并重打 tag:

# 下载所有必需镜像(ARM64 版本) sudo ctr --address /run/containerd/containerd.sock image pull \ registry.aliyuncs.com/google_containers/pause:3.9 sudo ctr --address /run/containerd/containerd.sock image pull \ registry.aliyuncs.com/google_containers/coredns:v1.9.3 sudo ctr --address /run/containerd/containerd.sock image pull \ registry.aliyuncs.com/google_containers/etcd:3.5.10-0 sudo ctr --address /run/containerd/containerd.sock image pull \ registry.aliyuncs.com/google_containers/kube-apiserver:v1.26.15 sudo ctr --address /run/containerd/containerd.sock image pull \ registry.aliyuncs.com/google_containers/kube-controller-manager:v1.26.15 sudo ctr --address /run/containerd/containerd.sock image pull \ registry.aliyuncs.com/google_containers/kube-scheduler:v1.26.15 # 重打 tag 为 kubeadm 期望的 registry.k8s.io 格式(关键!) sudo ctr --address /run/containerd/containerd.sock image tag \ registry.aliyuncs.com/google_containers/pause:3.9 \ registry.k8s.io/pause:3.9 sudo ctr --address /run/containerd/containerd.sock image tag \ registry.aliyuncs.com/google_containers/coredns:v1.9.3 \ registry.k8s.io/coredns/coredns:v1.9.3 # ... 其他组件同理

血泪经验:不要用docker load或ctr import加载 tar 包——Kylin ARM 的ctr对 tar 格式解析有 bug,会导致镜像层损坏。必须用ctr pull直接拉取。

4.3 执行 kubeadm init 并验证 control plane

# 关键:跳过 etcd 阶段,且指定配置文件 sudo kubeadm init --config kubeadm-config.yaml --skip-phases=etcd # 输出应包含: # Your Kubernetes control-plane has initialized successfully! # To start using your cluster, you need to run the following as a regular user: # mkdir -p $HOME/.kube # sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config # sudo chown $(id -u):$(id -g) $HOME/.kube/config

验证:

# 检查 pods(所有 control plane pod 应为 Running) kubectl get pods -A # 输出应含:coredns-xxx、kube-apiserver-xxx、kube-controller-manager-xxx、kube-scheduler-xxx # 检查 etcd 成员(必须显示 1 个健康成员) kubectl exec -n kube-system kube-apiserver-$(hostname) -- etcdctl \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key \ member list

5. 避坑指南:Kylin V10 ARM64 下 K8s 1.26.15 部署的 5 个致命陷阱

这些不是理论问题,而是我在 3 家信创客户现场亲手填平的坑。每一条都对应一次凌晨 2 点的紧急上线回滚。

5.1 现象:kubeadm init卡在[wait-control-plane] Waiting for the kubelet to boot up the control plane,journalctl -u kubelet显示Failed to run kubelet: failed to create kubeconfig: open /etc/kubernetes/admin.conf: no such file or directory

原因:kubeadm在生成admin.conf前,会尝试连接kubelet的/var/lib/kubelet/kubeconfig。但 Kylin V10 的kubelet默认不生成该文件,且--bootstrap-kubeconfig参数未被正确传递。
解决:在kubeadm-config.yaml的InitConfiguration中显式添加bootstrapToken配置,并确保/etc/kubernetes/bootstrap-kubeconfig存在(kubeadm init会自动创建,但需保证目录可写):

--- kind: InitConfiguration apiVersion: kubeadm.k8s.io/v1.26 bootstrapTokens: - token: "abcdef.0123456789abcdef" description: "kubeadm bootstrap token" ttl: "24h"

5.2 现象:kubectl get nodes返回NotReady,kubectl describe node显示NetworkPluginNotReady: cni config uninitialized

原因:Kylin V10 ARM 的/opt/cni/bin目录默认为空,而kubeadm不会自动安装 CNI 插件。Calico/Flannel 的 ARM64 二进制需手动部署。
解决:下载 Calico v3.26.1 ARM64 manifest 并 patchcniVersion:

curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml # 修改 calico.yaml 中 cniVersion: "1.0" → "0.4.0"(Kylin ARM 的 runc 不支持 CNI 1.0) kubectl apply -f calico.yaml

5.3 现象:etcdctl endpoint health返回unhealthy,日志含context deadline exceeded

原因:Kylin V10 的iptables默认启用nf_conntrack模块,但 etcd 的 HTTPS 连接被 conntrack 错误跟踪,导致 TLS handshake 超时。
解决:临时禁用 conntrack 对 etcd 端口的跟踪:

sudo iptables -t raw -I PREROUTING -p tcp --dport 2379 -j NOTRACK sudo iptables -t raw -I PREROUTING -p tcp --dport 2380 -j NOTRACK

5.4 现象:containerd启动后ctr images list为空,但sudo ctr --address /run/containerd/containerd.sock images list正常

原因:Kylin V10 的ctr客户端默认连接/run/containerd/containerd.sock,但kubeadm调用时使用的是unix:///var/run/containerd/containerd.sock(旧路径)。
解决:创建符号链接并重启 containerd:

sudo ln -sf /run/containerd/containerd.sock /var/run/containerd/containerd.sock sudo kill $(cat /var/run/containerd.pid) sudo /usr/local/bin/containerd --config /etc/containerd/config.toml --log-level info &

5.5 现象:kubeadm join从节点报错connection refused,telnet 192.168.10.10 6443失败

原因:Kylin V10 默认启用firewalld,且6443端口未开放。firewalld在 ARM64 下对--permanent参数支持不稳定,firewall-cmd --reload常失效。
解决:改用iptables直接放行(更可靠):

sudo iptables -I INPUT -p tcp --dport 6443 -j ACCEPT sudo service iptables save # Kylin V10 使用 iptables-services

6. 验证集群稳定性与后续扩展:用真实 workload 测试 ARM64 K8s 的边界

部署完成只是开始。真正的考验是让集群在 Kylin V10 ARM64 上持续稳定运行 72 小时以上。我习惯用三个维度验证:资源调度精度、跨节点网络连通性、证书轮换鲁棒性。

6.1 资源调度精度测试:确认 ARM64 节点能正确识别 CPU topology

Kylin V10 在飞腾 D2000 上有 8 核 16 线程,但kubectl describe node常显示cpu: 8而非cpu: 16,导致requests.cpu: 1的 Pod 被错误调度。根源是kubelet未读取/sys/devices/system/cpu/topology/。修复方法:

# 在 /var/lib/kubelet/config.yaml 中添加 staticPodPath: "/etc/kubernetes/manifests" featureGates: CPUManager: true TopologyManager: true systemdCgroup: true # 必须与 containerd 配置一致 # 重启 kubelet sudo systemctl restart kubelet

然后部署一个 topology-aware Pod:

apiVersion: v1 kind: Pod metadata: name: cpu-topology-test spec: containers: - name: nginx image: nginx:alpine resources: requests: cpu: "1" limits: cpu: "1" securityContext: privileged: true topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule

kubectl describe pod cpu-topology-test | grep -A5 "Node-Selectors"应显示beta.kubernetes.io/arch=arm64和正确的topology.kubernetes.io/zone。

6.2 跨节点网络连通性:用 iperf3 测 ARM64 节点间真实吞吐

ARM64 网络栈在 Kylin 下易出现 TCP window scaling 异常。用iperf3验证:

# 在 master 节点运行 server kubectl run iperf-server --image=networkstatic/iperf3 --restart=Never --command -- iperf3 -s # 在 worker 节点 exec 进去测速 kubectl exec -it iperf-server -- iperf3 -c $(kubectl get pod iperf-server -o jsonpath='{.status.podIP}') -P 4 -t 60 # 稳定值应 ≥ 800Mbps(千兆网卡理论值 1Gbps,ARM64 下 80% 是合格线)

若低于 300Mbps,检查ethtool -i eth0是否启用rx/tx offload,并在/etc/sysctl.conf中添加:

net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.ipv4.tcp_rmem = 4096 262144 16777216 net.ipv4.tcp_wmem = 4096 262144 16777216

6.3 证书轮换鲁棒性:主动触发 1 年后证书更新

K8s 1.26 默认证书有效期 1 年。Kylin ARM 下kubeadm certs renew all常因 OpenSSL 版本差异失败。安全做法是:提前 30 天用kubeadm alpha certs renew+ 手动替换/etc/kubernetes/pki/下的.crt/.key文件,再滚动重启 control plane 组件。我写了一个检查脚本放在 GitHub Gist(搜索kylin-k8s-certs-check),它会输出每个证书剩余天数,并高亮<30d的项。

最后说一句:这套方案不是为了证明“ARM 能跑 K8s”,而是为了让你在交付现场,当客户指着监控大屏问“为什么 dashboard 响应慢”,你能立刻kubectl top nodes看出是某个飞腾节点的systemd-journald进程占了 90% CPU,然后 SSH 进去journalctl --vacuum-size=100M清理日志——而不是翻文档、查论坛、等厂商补丁。信创落地没有银弹,只有把每个组件的二进制、配置、日志、网络路径都摸透的笨功夫。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询