ARTICLE DETAIL

资讯详情

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

ARM麒麟V10上基于Containerd部署K8s 1.30.14与KubeSphere 4.1.3实践

ARM麒麟V10上基于Containerd部署K8s 1.30.14与KubeSphere 4.1.3实践 先说结论在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版本开始正式移除了内置的dockershimkubelet不再原生支持“通过Docker来管理容器”。你要还想用Docker就得额外装cri-dockerd这个桥接层等于平白多出一道转换。反过来看Containerd本身就是从Docker项目里剥离出来的容器运行时Docker真正跑容器的那部分底层逻辑就是它。kubelet通过CRIContainer 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.19aarch64运行时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再确认一次重点关注型号字段里有没有Kunpeng或Phytium字样这决定了你后续找驱动或调优参数时的方向。2.2 主机规划与hosts配置部署前把节点角色规划清楚避免边部署边改配置。我这次用一台物理节点做All-in-One同时承担etcd、control-plane、worker三个角色。如果你需要更完整的生产环境可以参考下面的规划思路。角色主机名IP示例系统要求etcd control-plane workernode1192.168.10.114C8G起推荐8C16Gcontrol-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默认的主机名往往是一串随机字符建议一开始就改成有意义的名称像我这样用node1、node2形式后续看日志、排查问题会省力不少。2.3 防火墙、SELinux与swap的关闭这是老生常谈但越是基础越容易出错。麒麟V10默认可能开着firewalld也有部分镜像默认SELinux为enforcing状态。K8s集群组件之间的通信端口非常多与其逐个放行不如在测试环境直接关闭防火墙生产环境则在安全组或网络层面统一控制端口规则。systemctl stop firewalld systemctl disable firewalld setenforce 0 sed -i s/^SELINUXenforcing/SELINUXdisabled/ /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-iptables1保证宿主机上通过网桥Calico或Flannel的VXLAN网络传输的数据包能被iptables规则处理不设这个集群内DNS或Service转发大概率出问题。vm.swappiness0则是尽量避免使用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 kubeletcontainerd的日志在journalctl -u containerd容器本身的问题则用crictl logs来查看。千万不要一上来就翻容器日志先把中间层的状态确认清楚。3.2 KubeKey的工作流程与配置意图KubeKey是KubeSphere团队开源的部署工具本质上是一个“部署管理器”。它会自动完成以下步骤通过SSH连接目标机所以要求配置root账户或具有sudo权限的账户检查目标机依赖项缺什么补什么比如curl、socat、conntrack、ebtables下载并安装Containerd生成CRI配置下载K8s核心组件kubeadm、kubelet、kubectl、etcd等组装kubeadm配置并执行init或join部署CNI插件默认是Calico根据配置安装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.34.1 下载KubeKey并创建配置文件在ARM机器上KubeKey的获取有两种方式。一种是执行官方脚本自动下载curl -sfL https://get-kk.kubesphere.io | VERSIONv3.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的高可用集群只需要把三台节点分别加入这三个角色组再把controlPlaneEndpoint的address设成负载均衡器IPKubeKey会自动处理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上偶尔会缺socat、conntrack这些包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的核心Chartks-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应该全部是Running或Completed。我通常会重点确认这几个命名空间kube-system核心组件、kubesphere-systemKubeSphere核心、calico-system网络插件。KubeSphere控制台的访问地址和初始密码可以通过以下命令获取kubectl -n kubesphere-system get svc ks-console默认是NodePort方式暴露端口30880。浏览器访问https://节点IP:30880就能打开登录页面。默认账号是admin初始密码是P88w0rd。首次登录会强制要求修改密码记得改成符合安全策略的强密码。这里要特别提醒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而不是nerdctl或ctr。crictl是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一直CrashLoopBackOff或Init:Error就要看具体日志。ARM环境下calico-node有时会因内核模块或镜像架构问题启动失败。确认节点上dmesg | tail -50没有奇怪的报错再用kubectl logs -n calico-system pod名查看容器日志。网络插件的坑还有一个是Pod网段和物理网络冲突。如果你的物理网络恰好使用了10.233.0.0/16网段那就要调整kubePodsCIDR和kubeServiceCIDR改成别的网段。这个问题在配置阶段就要注意不然后续排错会非常痛苦。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高可用都跑通了。你如果按照这篇文章的顺序走下来大概率能一次成功。如果卡在某个环节把报错日志多看几层先判断是系统层、网络层还是镜像层的问题再对照上面的排查思路去定位基本都能解决。国产化环境的部署本质上没什么神秘的技术就是把细节处理扎实剩下的交给工具去跑。
返回列表