ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

麒麟V10 ARM部署K8S 1.26.15:外部etcd与containerd实战

麒麟V10 ARM部署K8S 1.26.15:外部etcd与containerd实战 简介这份资源面向需要在国产化信创环境中落地容器编排的运维与云原生工程师聚焦Kylin V10操作系统搭配ARM架构服务器、采用外部etcd与containerd运行时部署Kubernetes 1.26.15一主多从集群的完整离线安装包。压缩包共41个文件约645.74MB以gz离线镜像包、rpm系统依赖、sh部署脚本、yaml与yml编排清单为主另含kubeadm、kubectl、kubelet等核心二进制及kubelet.service、10-kubeadm.conf等配置文件覆盖etcd、containerd、Calico网络与CoreDNS等组件的镜像与依赖便于在无外网环境下完成集群搭建。资源同时提供镜像加载与拉取脚本、kubeadm初始化与join节点配置可帮助读者快速复现ARM平台上的高可用控制面与多工作节点拓扑理解外部etcd与containerd的对接方式并积累国产化环境下的排错与调优经验。目前已有130人学习下载适合具备一定Linux与K8S基础、希望深入信创场景的中高级读者参考。1. 麒麟 V10 ARM 上把 K8S 1.26.15 跑起来为什么这套组合值得折腾手里有一批鲲鹏或飞腾的 ARM 服务器系统是银河麒麟 V10要求容器运行时不用 Docker 而用 containerdetcd 还要独立部署在集群外部最后拉起一个 K8S 1.26.15 的一主多从集群——这套需求在信创交付现场出现频率极高。它解决的核心问题是在国产 ARM 芯片加国产操作系统的底座上搭出一套不依赖 Docker、etcd 与 Master 解耦、可横向扩 Node 的 Kubernetes 集群。适合正在做信创迁移、离线交付、或者被要求「全栈国产化」的运维和平台工程师。难点不在 K8S 本身而在 ARM 架构的镜像适配、麒麟 V10 的软件源差异以及外部 etcd 带来的证书和网络配置变化。这篇把每一步的命令、参数和踩过的坑都摊开讲。2. 动手前的底座确认麒麟 V10 ARM 环境与外部 etcd 的选型理由2.1 为什么 etcd 要独立于 Master 节点K8S 默认把 etcd 和 kube-apiserver 塞在同一台机器上用 kubeadm 一键拉起。但生产环境里etcd 是整个集群唯一的强一致数据源它一旦抖动API Server 直接不可用。把 etcd 拆到独立节点好处有三第一etcd 对磁盘 IO 极其敏感独立部署可以给它配 SSD 而不受 Master 上其他组件干扰第二Master 节点可以随时重建etcd 数据不受影响第三多 Master 场景下etcd 集群和 Master 节点数量解耦扩缩容更灵活。在麒麟 V10 ARM 上etcd 必须用 ARM64 版本。官方 release 页面提供 linux-arm64 的静态二进制包直接下载解压即可不依赖系统包管理器。这一点很关键因为麒麟 V10 的 yum 源里 etcd 版本往往偏旧用官方二进制能精确控制版本。2.2 麒麟 V10 上必须提前做的系统配置麒麟 V10 基于 CentOS/RHEL 体系但默认的安全策略和内核参数与标准 CentOS 有差异。以下操作在所有节点etcd 节点、Master、Node上都要执行。关闭 swap这是 K8S 的硬性要求# 临时关闭 swapoff -a # 永久关闭注释掉 /etc/fstab 中的 swap 行 sed -i /swap/s/^/#/ /etc/fstab # 确认已关闭 free -h加载内核模块并设置网络参数# 加载 br_netfilter 和 overlay 模块 cat /etc/modules-load.d/k8s.conf EOF br_netfilter overlay EOF modprobe br_netfilter modprobe overlay # 设置网桥和转发参数 cat /etc/sysctl.d/k8s.conf EOF net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 net.ipv4.ip_forward 1 EOF sysctl --system逻辑说明br_netfilter让 iptables 能过滤网桥流量overlay是 containerd 的默认存储驱动。ip_forward不开Pod 跨节点通信直接断。麒麟 V10 默认可能没加载这两个模块不提前处理后面 kubelet 启动会报错。关闭防火墙和 SELinuxsystemctl stop firewalld systemctl disable firewalld setenforce 0 sed -i s/^SELINUXenforcing/SELINUXpermissive/ /etc/selinux/config提示如果交付环境不允许关闭 SELinux需要为 containerd 和 kubelet 单独配置策略工作量会大很多建议在测试环境先验证。时间同步也必须做etcd 集群对时间偏差敏感# 使用 chrony yum install -y chrony systemctl enable --now chronyd chronyc sources -v2.3 主机名与 hosts 规划一主多从的典型规划如下实际 IP 按现场替换角色主机名IP 示例安装组件etcdetcd01192.168.1.10etcdMasterk8s-master192.168.1.20kube-apiserver、kube-controller-manager、kube-scheduler、kubelet、containerdNode1k8s-node1192.168.1.21kubelet、kube-proxy、containerdNode2k8s-node2192.168.1.22kubelet、kube-proxy、containerd每台机器设置主机名并写入 hostshostnamectl set-hostname k8s-master cat /etc/hosts EOF 192.168.1.10 etcd01 192.168.1.20 k8s-master 192.168.1.21 k8s-node1 192.168.1.22 k8s-node2 EOF3. 外部 etcd 集群部署ARM64 二进制安装与证书签发3.1 下载与安装 etcd ARM64 二进制麒麟 V10 ARM 上不能用 x86 的包必须拿 arm64 版本。常见做法是从 etcd 官方 GitHub release 下载对应版本的 linux-arm64 压缩包传到 etcd 节点。# 解压并安装到 /usr/local tar -xzf etcd-v3.5.12-linux-arm64.tar.gz cd etcd-v3.5.12-linux-arm64 cp etcd etcdctl /usr/local/bin/ chmod x /usr/local/bin/etcd /usr/local/bin/etcdctl # 验证架构 file /usr/local/bin/etcd # 应输出 ARM aarch64 相关信息参数说明etcd 版本建议选 3.5.x 系列与 K8S 1.26 兼容性经过验证。不要用 3.4 以下版本API 有差异。3.2 用 cfssl 签发 etcd 证书etcd 集群通信必须加密。用 cfssl 生成 CA 和证书在任意一台有 cfssl 的机器上操作即可。# 安装 cfsslARM64 版本 # 下载 cfssl、cfssljson、cfssl-certinfo 三个二进制 chmod x cfssl cfssljson cfssl-certinfo mv cfssl cfssljson cfssl-certinfo /usr/local/bin/ # 生成默认 CA 配置 cfssl print-defaults config ca-config.json cfssl print-defaults csr ca-csr.json编辑ca-config.json定义 etcd 的 profile{ signing: { default: { expiry: 87600h }, profiles: { etcd: { expiry: 87600h, usages: [ signing, key encipherment, server auth, client auth ] } } } }编辑ca-csr.json{ CN: etcd-ca, key: { algo: rsa, size: 2048 }, names: [ { C: CN, ST: Beijing, L: Beijing, O: etcd, OU: etcd } ] }生成 CA 证书cfssl gencert -initca ca-csr.json | cfssljson -bare ca # 生成 ca.pem ca-key.pem ca.csr接着生成 etcd 服务端证书。编辑etcd-csr.json注意 hosts 要包含所有 etcd 节点 IP 和 127.0.0.1{ CN: etcd, hosts: [ 127.0.0.1, 192.168.1.10, etcd01 ], key: { algo: rsa, size: 2048 }, names: [ { C: CN, ST: Beijing, L: Beijing, O: etcd, OU: etcd } ] }签发cfssl gencert -caca.pem -ca-keyca-key.pem \ -configca-config.json -profileetcd \ etcd-csr.json | cfssljson -bare etcd # 生成 etcd.pem etcd-key.pem逻辑说明hosts字段决定证书对哪些地址有效漏掉任何一个 etcd 节点 IP该节点启动时会报证书不匹配。profileetcd对应 ca-config.json 里定义的 usages必须同时有 server auth 和 client auth因为 etcd 节点之间既做服务端也做客户端。3.3 编写 etcd 配置文件并启动把证书放到/etc/etcd/ssl/创建配置文件/etc/etcd/etcd.conf.ymlname: etcd01>[Unit] Descriptionetcd service Afternetwork.target [Service] Typenotify ExecStart/usr/local/bin/etcd --config-file/etc/etcd/etcd.conf.yml Restartalways RestartSec5 LimitNOFILE65536 [Install] WantedBymulti-user.target启动并验证systemctl daemon-reload systemctl enable --now etcd systemctl status etcd # 用 etcdctl 验证 export ETCDCTL_API3 etcdctl --endpointshttps://192.168.1.10:2379 \ --cacert/etc/etcd/ssl/ca.pem \ --cert/etc/etcd/ssl/etcd.pem \ --key/etc/etcd/ssl/etcd-key.pem \ endpoint health参数说明initial-cluster-state: new表示新建集群如果是加节点要改成existing。client-cert-auth: true强制客户端证书认证K8S 的 apiserver 连接 etcd 时必须带证书。># 下载 containerd ARM64 版本 tar -xzf containerd-1.6.28-linux-arm64.tar.gz cp bin/* /usr/local/bin/ # 生成默认配置 mkdir -p /etc/containerd containerd config default /etc/containerd/config.toml4.2 修改 containerd 配置对接 systemd cgroup这是最容易翻车的地方。K8S 1.26 默认使用 systemd cgroup 驱动containerd 默认配置用的是 cgroupfs两者不一致会导致 kubelet 报错、Pod 起不来。# 修改 config.toml 中的关键项 sed -i s/SystemdCgroup false/SystemdCgroup true/ /etc/containerd/config.toml # 确认 sandbox 镜像地址国内环境需要替换 grep -n sandbox_image /etc/containerd/config.toml如果拉不到官方 pause 镜像需要替换为可访问的镜像仓库地址[plugins.io.containerd.grpc.v1.cri] sandbox_image registry.aliyuncs.com/google_containers/pause:3.9创建 systemd 服务并启动cat /usr/lib/systemd/system/containerd.service EOF [Unit] Descriptioncontainerd container runtime Afternetwork.target [Service] ExecStartPre/sbin/modprobe overlay ExecStart/usr/local/bin/containerd Restartalways RestartSec5 LimitNOFILE1048576 LimitNPROCinfinity LimitCOREinfinity [Install] WantedBymulti-user.target EOF systemctl daemon-reload systemctl enable --now containerd systemctl status containerd验证 containerd 可用ctr version ctr images pull registry.aliyuncs.com/google_containers/pause:3.9 ctr images ls参数说明SystemdCgroup true必须与 kubelet 的--cgroup-driversystemd一致。sandbox_image是 Pod 的基础容器镜像ARM64 架构下必须确保该镜像有 arm64 版本否则 Pod 永远卡在 Sandbox 创建阶段。4.3 安装 kubelet、kubeadm、kubectlK8S 1.26.15 的 ARM64 二进制包可以从官方或镜像站获取。三个组件在所有 Master 和 Node 上都要装。# 下载 ARM64 二进制 # kubelet kubeadm kubectl 三个文件 chmod x kubelet kubeadm kubectl mv kubelet kubeadm kubectl /usr/local/bin/ # 验证 kubeadm version kubectl version --client创建 kubelet 的 systemd 服务[Unit] Descriptionkubelet: The Kubernetes Node Agent Aftercontainerd.service Wantscontainerd.service [Service] ExecStart/usr/local/bin/kubelet \ --config/var/lib/kubelet/config.yaml \ --kubeconfig/etc/kubernetes/kubelet.conf \ --hostname-override$(hostname) \ --v2 Restartalways RestartSec10 [Install] WantedBymulti-user.target注意kubelet 的 config.yaml 和 kubelet.conf 由 kubeadm init/join 生成此时先不要启动 kubelet等 kubeadm 执行完再启动。5. kubeadm 拉起一主多从外部 etcd 对接与 Node 加入5.1 编写 kubeadm 配置文件kubeadm 默认自己部署 etcd要对接外部 etcd 必须用配置文件指定etcd.external。创建kubeadm-config.yamlapiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration kubernetesVersion: v1.26.15 controlPlaneEndpoint: 192.168.1.20:6443 networking: podSubnet: 10.244.0.0/16 serviceSubnet: 10.96.0.0/12 etcd: external: endpoints: - https://192.168.1.10:2379 caFile: /etc/etcd/ssl/ca.pem certFile: /etc/etcd/ssl/etcd.pem keyFile: /etc/etcd/ssl/etcd-key.pem --- apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd参数说明controlPlaneEndpoint是 API Server 的访问入口单 Master 就写 Master IP。podSubnet要和后面装的 CNI 插件网段一致这里用 Flannel 默认的 10.244.0.0/16。etcd.external下的证书路径必须是 Master 节点上实际存在的路径需要把 etcd 的证书提前拷贝到 Master 的/etc/etcd/ssl/下。5.2 执行 kubeadm init# 预检提前发现问题 kubeadm init --configkubeadm-config.yaml --dry-run # 正式初始化 kubeadm init --configkubeadm-config.yaml --upload-certs # 初始化成功后配置 kubectl mkdir -p $HOME/.kube cp /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config # 验证集群状态 kubectl get nodes kubectl get pods -n kube-system此时 Master 节点状态是 NotReady因为还没装 CNI。kubectl get pods -n kube-system里 kube-apiserver、kube-controller-manager、kube-scheduler 应该是 Runningetcd 不会出现在列表里因为它是外部的。5.3 安装 CNI 插件ARM64 架构下 CNI 插件的镜像必须有 arm64 版本。Flannel 和 Calico 都支持这里以 Flannel 为例# 下载 flannel 的 arm64 镜像并导入或直接使用支持 arm64 的镜像地址 kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml如果离线环境需要提前把 flannel 的 arm64 镜像导入到 containerdctr images import flannel-arm64.tar安装后确认kubectl get pods -n kube-flannel kubectl get nodes # Master 应变为 Ready5.4 Node 节点加入集群在 Master 上生成 join 命令kubeadm token create --print-join-command输出类似kubeadm join 192.168.1.20:6443 --token abcdef.1234567890abcdef \ --discovery-token-ca-cert-hash sha256:xxxxx在每个 Node 上执行这条命令。执行前确保 Node 上 containerd 已启动、kubelet 已安装、系统配置已完成。# 在 Node 上执行 kubeadm join 192.168.1.20:6443 --token abcdef.1234567890abcdef \ --discovery-token-ca-cert-hash sha256:xxxxx加入后在 Master 上验证kubectl get nodes -o wide # 所有节点应为 Ready6. 避坑排查麒麟 V10 ARM 部署 K8S 最容易翻车的 5 个点6.1 kubelet 启动报 failed to run Kubelet: misconfiguration: kubelet cgroup driver: cgroupfs is different from docker cgroup driver: systemd现象kubelet 反复重启日志里出现 cgroup driver 不一致的报错。原因containerd 的SystemdCgroup没设为 true或者 kubelet 的cgroupDriver没设为 systemd两边不一致。解决确认/etc/containerd/config.toml里SystemdCgroup true确认 kubeadm-config.yaml 里KubeletConfiguration的cgroupDriver: systemd然后重启 containerd 和 kubelet。6.2 Pod 卡在 ContainerCreatingdescribe 显示 failed to pull image pause:3.9现象所有 Pod 都起不来kubectl describe pod看到 sandbox 镜像拉取失败。原因containerd 默认的 sandbox_image 指向 registry.k8s.io国内网络拉不到或者该镜像没有 arm64 版本。解决修改 config.toml 里的sandbox_image为可访问的 arm64 pause 镜像地址重启 containerd。离线环境提前用ctr images pull拉好。6.3 kubeadm init 报 etcd 连接超时现象kubeadm init卡在连接 etcd 阶段报 context deadline exceeded。原因Master 节点无法访问 etcd 的 2379 端口或者证书路径不对、证书里没有 Master 的 IP。解决先在 Master 上用 etcdctl 测试连通性确认防火墙、端口、证书三要素。证书的 hosts 字段必须包含 etcd 节点 IPMaster 连接 etcd 用的是 etcd 的服务端证书不需要包含 Master IP但 etcd 的listen-client-urls必须监听正确地址。6.4 Node 加入后状态一直是 NotReady现象kubectl get nodes显示 Node 为 NotReadydescribe 显示 network plugin not ready。原因CNI 插件没装或者 CNI 的镜像没有 arm64 版本导致 DaemonSet 起不来。解决确认 flannel 或 calico 的 DaemonSet Pod 是否 Running检查镜像架构。ARM 环境下必须用支持 arm64 的 CNI 镜像。6.5 麒麟 V10 上 containerd 启动报 failed to load overlay module现象containerd 启动失败日志提示 overlay 模块加载不了。原因麒麟 V10 内核可能没编译 overlay 模块或者模块名不同。解决modprobe overlay手动加载如果失败检查内核版本和模块路径。部分麒麟版本需要安装kmod相关包。实在不行containerd 可以降级用nativesnapshotter但性能会差很多。7. 集群验证与日常运维的一个实用技巧集群拉起来只是开始真正交付前必须做一轮完整验证。我一般会按这个顺序过一遍先kubectl get nodes -o wide确认所有节点 Ready 且内网 IP 正确再kubectl get pods -n kube-system确认核心组件全 Running然后跑一个跨节点的测试 Pod验证网络连通性。# 部署一个测试 Deployment副本分布到不同 Node kubectl create deployment nginx-test --imageregistry.aliyuncs.com/google_containers/nginx:1.25 --replicas3 kubectl get pods -o wide # 确认 Pod 分布在不同 Node 且 Running # 测试跨节点网络 kubectl run test-pod --imageregistry.aliyuncs.com/google_containers/busybox:1.36 --rm -it -- sh # 在 Pod 内 ping 另一个 Pod 的 IPARM64 环境下镜像架构是最隐蔽的坑。很多 x86 上跑得好好的镜像在 ARM 上拉下来直接 exec format error。验证方法是在 Pod 里执行uname -m输出aarch64才对。日常运维中我习惯在 CI 流水线里加一步镜像架构检查用docker manifest inspect或skopeo inspect确认目标镜像有 arm64 层避免部署时才发现。另一个实用技巧是给 kubelet 配--hostname-override。麒麟 V10 在某些云环境下 hostname 会被 DHCP 改掉导致 Node 注册的名字和实际不符kubelet 反复注册失败。在 kubelet 启动参数里显式指定--hostname-override$(hostname)或者写死主机名能省掉很多玄学问题。证书过期也是绕不开的。K8S 1.26 的集群证书默认一年有效期交付后客户可能半年才想起来续。我一般会在部署完就配好自动续签的 cron用kubeadm certs renew all加systemctl restart kubelet组合提前写好脚本放在/etc/cron.monthly/下。血泪经验是别等证书过期了才处理那时候 apiserver 已经起不来连 kubectl 都用不了只能手动进容器恢复非常被动。这套麒麟 V10 加 ARM 加外部 etcd 加 containerd 的组合坑主要集中在架构适配和组件对接上把证书、cgroup、镜像架构这三样盯死基本就能一次跑通。希望帮到你。本文还有配套的精品资源点击获取
返回列表