ARM麒麟V10上基于Containerd部署K8s 1.30.14与KubeSphere 4.1.3实践
2026/9/23 2:49:33 网站建设 项目流程

先说结论:在ARM架构的银河麒麟V10上用Containerd部署Kubernetes 1.30.14加KubeSphere 4.1.3,完全可行,而且用KubeKey这条路比我预想中顺利不少。但“可行”不等于“顺手”,系统底层的网络参数、软件源、镜像拉取这些问题,一个处理不好就能卡住一整天。这篇文章是我在华为泰山服务器上从零部署的完整记录,操作系统是麒麟V10高级服务器版(SP3),运行时直连Containerd,不装Docker,平台侧是KubeSphere 4.1.3。整个过程涵盖环境准备、核心原理、部署步骤、常见排错四部分,适合正在做国产化环境容器化落地的运维和开发人员参考。

1. 项目背景与方案选型

1.1 国产化环境里最常见的组合

这两年国产化替代推进得很快,ARM加麒麟V10的组合越来越多地出现在政务、金融、能源的项目里。我这里说的“ARM架构”,主力就是鲲鹏920和飞腾系列处理器,对应的操作系统是银河麒麟高级服务器操作系统V10,也就是常说的麒麟V10服务器版。这个环境我前后部署过多次,可以说已经成为国产化交付绕不开的标准组合之一。

但系统装完只是起点。业务要交付,应用要运行,就得有一套容器化平台撑起来。Kubernetes本身不挑底层架构,x86能跑的东西,放ARM上大多也能跑。真正的区别在于生态:工具链、镜像、二进制包,在ARM上确实会比x86多出不少隐藏的坑。比如说,有些镜像仓库里的tag默认拉下来的可能是amd64的镜像,没有多架构manifest支持的话,在ARM节点上启动就是exec format error。这些坑,后文会在对应环节里逐个说明。

那为什么选KubeSphere而不是别的?因为光有K8s还不够。尤其是把平台交付给业务团队或运维团队时,你需要一个可视化的界面来管理资源、看监控、发应用、开租户。KubeSphere提供的是应用管理、可观测性、多租户、DevOps、服务网格这些能力,装完就有,省去自己拼装一堆开源组件的人力成本。4.1.3这个版本属于4.x系列的稳定补丁版,底层架构和3.x时代有本质变化,越往后用越能体会到这套新架构的轻量。

1.2 运行时为什么是Containerd而不是Docker

这个问题几乎每个刚接触K8s的朋友都会问。原因其实不复杂:Kubernetes从1.24版本开始,正式移除了内置的dockershim,kubelet不再原生支持“通过Docker来管理容器”。你要还想用Docker,就得额外装cri-dockerd这个桥接层,等于平白多出一道转换。

反过来看Containerd本身就是从Docker项目里剥离出来的容器运行时,Docker真正跑容器的那部分底层逻辑就是它。kubelet通过CRI(Container Runtime Interface,容器运行时接口)直接跟Containerd通信,少一层转换,少一个常驻进程,内存和CPU占用也更低。K8s 1.30里,Containerd是绝对的主流选择,没有理由再绕回Docker那条路。

打个生活化的比方:Docker像是一个“前台、客房、餐厅、保洁”全包的全套酒店服务,而Containerd则只专注“房间入住和退房”这一件事。K8s本身就是酒店调度中心,它需要的不是保洁阿姨来打扫房间,只需要有人把房间准备好、能住人就行,这个角色就是Containerd。你要真把保洁阿姨也叫来,功能没多出来多少,走廊里倒是多了一堆人占地方。

1.3 版本组合与资源配置建议

版本选型是很多人纠结的地方。我这次用的是Kubernetes v1.30.14配合KubeSphere v4.1.3,部署工具用KubeKey。这三个版本在实际验证中兼容性没问题。

组件版本说明
操作系统银河麒麟V10高级服务器版 SP3内核4.19,aarch64
运行时Containerd 1.7.xKubeKey自动安装并配置
Kubernetesv1.30.141.30系列的稳定补丁版
KubeSpherev4.1.34.x系列,核心可插拔
部署工具KubeKey v3.1.x支持ARM架构自动适配

资源规划方面,单节点All-in-One方式最低4核8G,但真心建议8核16G起步。我初期用4核8G试过一次,etcd、kube-apiserver、KubeSphere核心组件同时跑起来,内存直接告急,Pod不断被驱逐。磁盘上,/var/lib/containerd目录务必要留足空间,建议单独挂一块数据盘,至少100G起步。如果你是拿来做若依微服务这类业务交付的,worker节点的磁盘就按业务数据量再加。

另外强调一点:KubeKey部署时,配置里有一个autoRenewCerts字段,一定记得设成true。K8s的PKI证书默认有效期一年,如果不启用自动续签,一年后集群证书到期,轻则kubectl命令报错,重则整个集群不可用。KubeKey会在证书到期前自动处理续签,这一步很多人忽略,等真正踩到证书过期的坑时再补就麻烦得多。

2. 部署前的系统环境准备

2.1 确认系统版本与CPU架构

在麒麟V10上做任何操作前,先花两分钟确认系统基本信息,避免后续所有动作建立在错误的基础上。以我用的节点为例:

cat /etc/os-release uname -m

输出里uname -m应该是aarch64,这代表机器是ARM 64位架构。如果显示x86_64,那说明你拿到的机器并不是ARM平台,后续所有“ARM适配”的文章结论都对你无效。麒麟V10的系统版本则可以通过/etc/os-release查看,不同的SP版本在软件源和内核上略有差异,我的操作主要基于SP3验证。

CPU信息可以通过lscpu再确认一次,重点关注型号字段里有没有KunpengPhytium字样,这决定了你后续找驱动或调优参数时的方向。

2.2 主机规划与hosts配置

部署前把节点角色规划清楚,避免边部署边改配置。我这次用一台物理节点做All-in-One,同时承担etcd、control-plane、worker三个角色。如果你需要更完整的生产环境,可以参考下面的规划思路。

角色主机名IP示例系统要求
etcd + control-plane + workernode1192.168.10.114C8G起,推荐8C16G
control-plane + workernode2192.168.10.12同上
workernode3192.168.10.13按业务需求

/etc/hosts务必配置好,KubeKey部署时需要通过主机名或IP进行节点间通信,不配置的话,后面kubeadm join阶段极容易出现证书主机名不匹配的报错:

192.168.10.11 node1 192.168.10.12 node2 192.168.10.13 node3

顺便说一句,麒麟V10默认的主机名往往是一串随机字符,建议一开始就改成有意义的名称,像我这样用node1node2形式,后续看日志、排查问题会省力不少。

2.3 防火墙、SELinux与swap的关闭

这是老生常谈,但越是基础越容易出错。麒麟V10默认可能开着firewalld,也有部分镜像默认SELinux为enforcing状态。K8s集群组件之间的通信端口非常多,与其逐个放行,不如在测试环境直接关闭防火墙,生产环境则在安全组或网络层面统一控制端口规则。

systemctl stop firewalld && systemctl disable firewalld setenforce 0 sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config swapoff -a sed -i '/ swap / s/^/#/' /etc/fstab

这三步做完,建议重启一次系统,确认SELinux确实变成disabled状态,swap确实不再自动挂载。我的经验是,很多人只执行了setenforce 0,但没改/etc/selinux/config,结果机器一重启,SELinux又自动开启,kubelet起不来,排查了半天才发现是SELinux在捣乱。

2.4 内核模块与网络参数调优

K8s依赖Linux内核的overlay文件系统来管理镜像层,也依赖br_netfilter模块让iptables规则能够作用于桥接流量。不加载这两个模块,节点即使注册成功,网络插件也起不来。

cat <<EOF | tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF modprobe overlay modprobe br_netfilter cat <<EOF | tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 vm.swappiness = 0 EOF sysctl --system

这里重点解释几个参数的含义。net.bridge.bridge-nf-call-iptables=1保证宿主机上通过网桥(Calico或Flannel的VXLAN网络)传输的数据包能被iptables规则处理,不设这个,集群内DNS或Service转发大概率出问题。vm.swappiness=0则是尽量避免使用swap,因为K8s要求节点关闭swap,虽然我们已经在fstab里注释掉了,但把swappiness设成0可以防止某些场景下内存交换导致的性能抖动。

这些参数在麒麟V10上可以直接生效。执行完sysctl --system后,可以用sysctl net.bridge.bridge-nf-call-iptables验证一下,输出为1就说明配置成功。

3. 核心原理与方案设计

3.1 Containerd在K8s里的完整调用链

很多人用Containerd只是因为它“能跑”,但排错时不理解内部链路会非常被动。K8s节点上的容器调用链大致是这样的:

kubelet -> CRI (Container Runtime Interface) -> containerd -> containerd-shim -> runc -> 容器进程

kubelet通过CRI调用containerd创建容器时,containerd会为每个Pod对应的容器再拉起一个containerd-shim进程,由shim负责承载容器生命周期,真正创建和运行容器进程的工作则交给runc。分层带来的好处是,容器进程崩溃时不会拖垮kubelet或containerd主进程,shim会替你照料好容器的退出状态。

这套链路下,排错时你要看的日志就分几层:kubelet的日志在journalctl -u kubelet,containerd的日志在journalctl -u containerd,容器本身的问题则用crictl logs来查看。千万不要一上来就翻容器日志,先把中间层的状态确认清楚。

3.2 KubeKey的工作流程与配置意图

KubeKey是KubeSphere团队开源的部署工具,本质上是一个“部署管理器”。它会自动完成以下步骤:

  1. 通过SSH连接目标机(所以要求配置root账户或具有sudo权限的账户)
  2. 检查目标机依赖项,缺什么补什么(比如curl、socat、conntrack、ebtables)
  3. 下载并安装Containerd,生成CRI配置
  4. 下载K8s核心组件(kubeadm、kubelet、kubectl、etcd等)
  5. 组装kubeadm配置并执行init或join
  6. 部署CNI插件,默认是Calico
  7. 根据配置安装KubeSphere核心组件

理解这个流程,对排错很有帮助。比如,当部署卡在“Downloading k8s images”这一步,那问题大概率出在网络或镜像仓库上,而不是K8s本身的配置不对。当卡在“Creating the kubelet”阶段,就要去检查系统侧配置是否有遗漏。

KubeKey和kubeadm的关系可以这样理解:kubeadm是官方的建集群工具,但你要先准备好节点、运行时、镜像包,还得手动拼装kubeadm配置;KubeKey把这些重复劳动全部收拢成一个配置文件,指定版本、角色、镜像仓库,一条命令跑完,适合批量交付和快速复现。

3.3 ARM架构下镜像与二进制的适配机制

ARM环境最容易踩的坑就是“架构不对”。KubeKey本身是有linux-arm64版本的,下载时选对对应架构的包即可。镜像层面的适配则依赖镜像仓库是否支持多架构manifest。支持多架构的仓库,比如docker.io和阿里云的官方镜像仓库,会在kubelet拉取时根据节点架构自动返回对应的arm64镜像。

但国产化环境常常处于内网,没有公网镜像仓库可访问。这时候KubeKey的离线包就派上用场了。离线包里同时打包了amd64和arm64两套镜像清单,部署时指定arch: arm64即可。如果你需要自己手动拉镜像,建议用crictl pull而不是Docker的docker pull,因为crictl直连containerd,拉完的镜像直接在节点上可用,不会出现“Docker里能看到镜像但kubelet拉不到”的尴尬。

另外注意,ARM架构下部分如KubeSphere扩展中心里的组件,可能对特定架构支持度不一致。我遇到过一个情况是:某个服务网格组件在ARM上能安装,但Envoy数据面镜像启动异常。遇到这种问题,先查镜像是否有多架构tag,没有的话就得考虑换用兼容组件或停留在KubeSphere核心功能。

4. 核心实操:从零部署K8s 1.30.14与KubeSphere 4.1.3

4.1 下载KubeKey并创建配置文件

在ARM机器上,KubeKey的获取有两种方式。一种是执行官方脚本自动下载:

curl -sfL https://get-kk.kubesphere.io | VERSION=v3.1.2 sh -

脚本会自动识别系统架构并下载对应版本。如果机器无法访问公网,就手动下载对应架构的压缩包再解压:

wget https://github.com/kubesphere/kubekey/releases/download/v3.1.2/kubekey-v3.1.2-linux-arm64.tar.gz tar -zxvf kubekey-v3.1.2-linux-arm64.tar.gz

解压后得到一个kk可执行文件,把它放到/usr/local/bin下方便使用。执行./kk version确认版本。

接着创建部署配置文件:

./kk create config --with-kubernetes v1.30.14 --with-kubesphere v4.1.3 -f config.yaml

这条命令会生成一个名为config.yaml的文件,里面是KubeKey部署集群的所有配置项。我先贴出一份单节点All-in-One的完整配置,然后逐段解释关键字段。

apiVersion: kubekey.kubesphere.io/v1alpha1 kind: Cluster metadata: name: kylin-arm-single spec: hosts: - {name: node1, address: 192.168.10.11, internalAddress: 192.168.10.11, user: root, password: "你的密码"} roleGroups: etcd: - node1 control-plane: - node1 worker: - node1 controlPlaneEndpoint: domain: lb.kubesphere.local address: "" port: 6443 kubernetes: version: v1.30.14 clusterName: cluster.local autoRenewCerts: true containerManager: containerd kubeSphere: version: v4.1.3 enabled: true network: plugin: calico kubePodsCIDR: 10.233.64.0/18 kubeServiceCIDR: 10.233.0.0/18 registry: registryMirrors: [] insecureRegistries: [] addons: []

4.2 单节点All-in-One配置逐段解读

首先是hosts段。KubeKey通过SSH接管节点,需要能够登录的user和密码。如果生产环境不想用root,可以指定一个具有sudo权限的普通用户,但要注意该用户必须能免密执行sudo命令。internalAddress用于K8s组件之间的通信,多数场景下和address相同;如果节点有多网卡,比如业务网和管理网分离,这两个字段就要分别指向对应网段的IP。

roleGroups定义了各节点的角色。etcd角色决定哪些节点运行etcd数据库,control-plane决定哪些节点运行kube-apiserver等控制面组件,worker则是业务工作节点。单节点场景,三个角色都落在同一台机器上,这就是All-in-One。如果你规划的是三台master的高可用集群,只需要把三台节点分别加入这三个角色组,再把controlPlaneEndpointaddress设成负载均衡器IP,KubeKey会自动处理HA拓扑。

kubernetes段里,version指定K8s版本,clusterName是集群的内部域名,保持cluster.local即可。autoRenewCerts: true这个字段必须加上,它对应我前面说的证书自动续签。containerManager: containerd明确告诉KubeKey使用Containerd作为运行时,kubelet和容器运行时之间直连CRI。

kubeSphere段里的enabled: true是让KubeKey在部署完K8s后自动安装KubeSphere核心。network段默认用Calico作为CNI插件,Pod和Service的网段保持默认值就行,但注意不要和物理网络冲突。

4.3 执行集群部署并观察关键阶段

配置文件修改完成后,开始正式部署:

./kk create cluster -f config.yaml

这条命令的执行过程会输出大量日志。第一次跑的时候,建议盯着观察,每个阶段的意义理解清楚。我按实际日志顺序拆解一下:

第一个阶段是环境预检。KubeKey会检查目标机的操作系统、架构、磁盘空间、内存大小、依赖命令是否存在。这个阶段如果报错,大多数是依赖缺失或密码错误。麒麟V10上偶尔会缺socatconntrack这些包,KubeKey会自动尝试安装,但需要系统的yum源可用。

第二个阶段是下载组件和镜像。KubeKey会下载kubeadm、kubelet、kubectl、etcd,并通过containerd拉取K8s核心镜像(pause、etcd、coredns等)。这一步最耗时,也最容易失败。如果卡住,优先检查网络连通性和镜像仓库的连通性。国产化内网环境下,建议提前准备好离线包,把下载环节跳过。

第三个阶段是执行kubeadm init。K8s控制平面组件会逐个启动,KubeKey日志里会输出Your Kubernetes control-plane has initialized successfully.,这就说明集群控制面已经就绪。接着KubeKey会自动安装Calico网络插件,Calico的Pod全部进入Running状态后,节点就Ready了。

最后一个阶段是部署KubeSphere。KubeKey会先安装KubeSphere的核心Chart(ks-core),然后拉起ks-console等服务。整个部署时间取决于网络和硬件配置,40分钟到一两个小时都有可能。等看到类似KubeSphere has been installed successfully的提示时,部署就完成了。

4.4 部署完成后的验证与KubeSphere初始化

部署完成后,在节点上执行:

kubectl get nodes -o wide kubectl get pods -A

理想状态下,kubectl get nodes输出中的节点状态是Readykubectl get pods -A里的Pod应该全部是RunningCompleted。我通常会重点确认这几个命名空间:kube-system(核心组件)、kubesphere-system(KubeSphere核心)、calico-system(网络插件)。

KubeSphere控制台的访问地址和初始密码,可以通过以下命令获取:

kubectl -n kubesphere-system get svc ks-console

默认是NodePort方式暴露,端口30880。浏览器访问https://节点IP:30880就能打开登录页面。默认账号是admin,初始密码是P@88w0rd。首次登录会强制要求修改密码,记得改成符合安全策略的强密码。

这里要特别提醒KubeSphere 4.x和3.x的一个核心差异:3.x时代安装完成后,所有功能模块默认齐全;4.x的核心是一个轻量的底座,像DevOps、服务网格、告警、日志等能力需要登录控制台后,在“扩展中心”里按需启用。这也是4.x“可插拔”架构的体现。第一次登录后,记得去扩展中心逛逛,把需要的组件启用起来,组件启用后会自动拉起对应的Pod。

5. 常见问题与排查技巧实录

5.1 麒麟系统层的隐蔽问题

国产化系统的坑很多时候不在K8s本身,而在系统侧的细枝末节。我给三个高频案例。

第一个是时间同步。ARM服务器如果没有配置NTP或chrony,系统时间会逐渐漂移。K8s对时间偏移极其敏感,证书校验、etcd选举都会受影响。表现是kubeadm init报x509 certificate has expired or is not yet valid,很多人想半天想不到是时间问题。解决方式是提前配置chrony或ntpd,指向内网时间源。

第二个是yum源问题。麒麟V10默认软件源的可用性在不同SP版本间差异很大。KubeKey在预检阶段如果要自动安装依赖包,需要yum源能正常工作。如果部署时报Failed to install dependencies,先手动执行yum install -y socat conntrack ebtables ipset验证源是否可用,不行就换个源或者手动装依赖。

第三个是磁盘分区。/var/lib/containerd目录空间不足,会导致镜像拉取失败或Pod容器启动失败。日志里常见no space left on device。建议部署前单独挂数据盘到/var/lib/containerd,或者至少提前做好分区规划。

5.2 Containerd与镜像拉取问题

节点状态一直NotReady,第一件事看kubelet日志:

journalctl -u kubelet -f

常见错误之一是镜像拉不下来。比如coredns: image pull failed。在ARM环境中,要先确认镜像仓库是否支持多架构。手动预拉镜像可以使用:

crictl pull registry.aliyuncs.com/google_containers/coredns:v1.11.3 crictl images

这里演示用的是crictl而不是nerdctlctrcrictl是K8s社区专门面向CRI运行时的命令行工具,它能看到kubelet视角下的Pod和容器,排错时优先级最高。

另一个容易被忽略的问题是Containerd的sandbox_image配置。如果kubelet启动时,pause容器一直处于ImagePullBackOff状态,大概率是sandbox_image指向的镜像地址无法访问。用KubeKey部署时,它会自动完成这个配置,但如果你后续手动修改过Containerd的/etc/containerd/config.toml,一定要确认[plugins."io.containerd.grpc.v1.cri"]下的sandbox_image配置正确。

5.3 节点状态与网络问题

节点NotReady但镜像正常,那十有八九是CNI网络插件的问题。检查方式:

kubectl get pods -n calico-system -o wide

如果calico的Pod一直CrashLoopBackOffInit:Error,就要看具体日志。ARM环境下,calico-node有时会因内核模块或镜像架构问题启动失败。确认节点上dmesg | tail -50没有奇怪的报错,再用kubectl logs -n calico-system <pod名>查看容器日志。

网络插件的坑,还有一个是Pod网段和物理网络冲突。如果你的物理网络恰好使用了10.233.0.0/16网段,那就要调整kubePodsCIDRkubeServiceCIDR,改成别的网段。这个问题在配置阶段就要注意,不然后续排错会非常痛苦。

swap未彻底关闭,也会导致kubelet报Running with swap on is not supported。验证命令是free -h,只有Swap一栏全部是0才是彻底关闭。很多时候swapoff -a后,fstab文件里还残留挂载项,重启后swap又回来了,所以前面我特别强调要注释fstab里的swap行。

5.4 KubeSphere控制台与扩展中心问题

部署完成后,控制台访问不了是最常见的求助问题。先确认svc存在:

kubectl -n kubesphere-system get svc ks-console

如果svc存在,但通过节点IP加30880端口访问不了,检查防火墙是否放行、节点的ip_forward是否开启。有时也会因为浏览器强制HTTP跳转HTTPS导致页面打不开,直接使用https://协议访问就好。

登录后扩展中心显示空白或组件安装失败,常见原因是KubeSphere底层要和镜像仓库、应用商店等服务通信,环境访问受限时就会出现加载异常。此外,4.x的扩展中心组件安装后,其Pod默认调度到各个节点上,如果某个节点资源不足,Pod会一直处于Pending状态,需要扩容或手动给节点打标签后解除调度限制。

我在实际项目里还遇到过一个挺隐蔽的问题:单节点All-in-One部署时,control-plane节点通常会带node-role.kubernetes.io/master:NoSchedule污点,业务Pod默认不会调度上去。KubeSphere的组件自己做了容忍,能正常工作,但你自己部署的业务应用如果不加容忍,就会发现Pod一直Pending。这在单节点环境里非常常见——明明是单机环境,业务应用却怎么也调度不上来。解决方案是给worker角色再单独分配节点(如果有的话),或者在单节点上删除这个污点:

kubectl taint nodes --all node-role.kubernetes.io/master-

删除污点后,业务Pod才能正常调度到唯一节点上。这一点对单节点上跑若依微服务整套环境的场景尤其重要。

5.5 效率提升与经验总结

最后分享两个实操中的效率技巧。第一,KubeKey支持离线部署,这在大规模交付和隔离网络场景下非常实用。在有网环境下载好KubeKey的os-pkgs和K8s镜像包,传到目标机后,配置里的registry段指向本地镜像仓库,部署时KubeKey会优先使用本地镜像,速度比在线拉取快一个数量级。

第二,部署过程中KubeKey会在目前目录生成kkcluster开头的临时目录,里面保留了详细的部署日志。如果部署失败需要排查,先看这个目录下的日志,往往比journalctl更直观。不要急着删掉,等集群稳定运行后再清理。

这套方案我已经在ARM架构的麒麟V10环境上复现过多次,从单节点All-in-One到三master高可用都跑通了。你如果按照这篇文章的顺序走下来,大概率能一次成功。如果卡在某个环节,把报错日志多看几层,先判断是系统层、网络层还是镜像层的问题,再对照上面的排查思路去定位,基本都能解决。国产化环境的部署本质上没什么神秘的技术,就是把细节处理扎实,剩下的交给工具去跑。

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

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

立即咨询