ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

麒麟V10 ARM64上containerd版K8S 1.26.15一主一从部署实战

麒麟V10 ARM64上containerd版K8S 1.26.15一主一从部署实战 简介本资源合集面向需要在国产化信创环境下搭建云原生平台的运维与开发人员聚焦Kylin V10操作系统与ARM架构CPU的组合通过containerd容器运行时部署Kubernetes 1.26.15一主一从集群。内容涵盖系统准备、容器运行时配置、K8S组件安装、主从节点配置、CNI网络插件选型及RBAC安全与持久化存储等关键环节适合具备一定Linux与容器基础、希望掌握ARM64平台K8S落地实践的中高级读者。资源包共38个文件约619.64MB以gz压缩包、rpm安装包、sh脚本、yaml配置及service、conf等文件为主分别对应镜像归档、依赖组件、自动化脚本与集群配置文件便于按部署流程分步取用。目前已有264人学习下载。借助其中的配置脚本、二进制文件与自定义YAML读者可快速复现ARM架构下的集群搭建过程理解containerd与K8S的协作机制并积累边缘计算与物联网场景下的排错与调优经验。1. 麒麟 V10 ARM 上跑 containerd 版 K8S 1.26.15一主一从到底能不能落地手里有一台麒麟 V10 的 ARM 服务器想搭一套 Kubernetes 做验证或跑内部业务结果第一步就被卡住——网上教程清一色 x86 Docker照着敲apt install docker.io直接报找不到包。这不是你环境的问题是路线选错了。Kylin V10 基于 RPM 体系ARM64 架构下 Docker 的官方源覆盖并不完整而 containerd 作为 K8S 1.26 时代默认推荐的容器运行时反而在 ARM 上更干净。这套方案要解决的就是在麒麟 V10 ARM64 机器上用 containerd 从零拉起一个一主一从的 K8S 1.26.15 集群不依赖任何外网镜像加速的玄学操作每一步都能复现。适合手里有国产化 ARM 服务器、需要做信创环境验证或内部小集群部署的运维和开发。下面按「环境准备 → containerd 落地 → 集群初始化 → 从节点加入 → 排错」的顺序讲透。2. 环境底座Kylin V10 ARM64 的前置检查与内核参数2.1 先确认你的机器到底是不是 ARM64 且内核够用很多人拿到机器直接开干结果uname -m出来是aarch64却装错了 RPM 包。麒麟 V10 服务器版在 ARM 上通常返回aarch64这是正常的 ARM64 标识。先做三件事确认架构、确认内核版本、确认 SELinux 和防火墙状态。K8S 1.26.15 要求内核不低于 4.x麒麟 V10 SP2/SP3 自带内核一般在 4.19 以上基本够用。但如果你的内核低于 4.19cgroup v2 和部分网络特性会缺后面 kubelet 启动会报failed to get cgroup之类的错。# 确认架构aarch64 即 ARM64 uname -m # 确认内核版本建议 4.19 以上 uname -r # 查看系统版本 cat /etc/kylin-release # 关闭 SELinuxK8S 默认要求 setenforce 0 sed -i s/^SELINUXenforcing/SELINUXpermissive/ /etc/selinux/config # 关闭 swapkubelet 强制要求 swapoff -a sed -i /swap/s/^/#/ /etc/fstab这几条命令的逻辑setenforce 0是临时关闭改配置文件是永久生效swap 必须关否则 kubelet 直接拒绝启动。参数上注意/etc/fstab里注释 swap 行时用#开头别把整行删了方便回滚。2.2 内核模块和 sysctl 参数不设这些后面必翻车containerd 和 K8S 的网络依赖overlay和br_netfilter两个内核模块。ARM 版麒麟默认可能没加载br_netfilter导致 Pod 跨节点通信失败现象是 Pod 能起但 ping 不通另一个节点上的 Pod。这一步是血泪经验别跳过。# 加载内核模块 modprobe overlay modprobe br_netfilter # 写入开机自动加载 cat /etc/modules-load.d/k8s.conf EOF overlay br_netfilter EOF # 设置网桥和转发参数 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 --systemnet.ipv4.ip_forward 1是 Pod 跨节点通信的基础bridge-nf-call-iptables让 iptables 能处理网桥流量。执行完用sysctl net.ipv4.ip_forward验证返回值为 1。如果modprobe br_netfilter报模块不存在说明内核裁剪过需要换内核或找麒麟的 kernel-modules-extra 包补上。2.3 时间同步和主机名小细节决定证书能不能过K8S 的证书和 token 对时间敏感两台机器时间差超过几分钟从节点加入时会报x509: certificate has expired。麒麟 V10 默认可能没开 chronyd。# 启动时间同步 systemctl enable --now chronyd chronyc sources -v # 设置主机名主从要区分 hostnamectl set-hostname k8s-master # 从节点执行hostnamectl set-hostname k8s-node1 # 写入 hosts方便互相解析 cat /etc/hosts EOF 192.168.1.10 k8s-master 192.168.1.11 k8s-node1 EOF主机名不要用下划线K8S 的 DNS 规范只认字母数字和连字符。hosts 里的 IP 换成你实际的内网地址。做完这些两台机器互相ping k8s-master和ping k8s-node1要能通这是后面 kubeadm join 的前提。3. containerd 在 ARM64 上的安装与配置绕开 Docker 的坑3.1 为什么 ARM 上优先选 containerd 而不是 DockerK8S 1.24 之后移除了 dockershimDocker 不再是默认运行时。在 ARM64 的麒麟 V10 上Docker 的官方仓库对 aarch64 的支持时好时坏而 containerd 的二进制包直接提供 ARM64 版本解压即用不依赖包管理器。另一个原因是 containerd 更轻调用链短出问题时ctr和crictl两个工具就能定位不像 Docker 那样多一层。常见做法是直接从 containerd 官方 release 下载 ARM64 的 tar 包手动铺到/usr/local。3.2 下载与安装 containerd 的 ARM64 二进制假设你已经把 containerd 的 ARM64 压缩包传到了机器上内网环境用 scp有外网的用 curl。版本选 1.6.x 系列和 K8S 1.26 匹配。# 解压到 /usr/local tar -C /usr/local -xzf containerd-1.6.24-linux-arm64.tar.gz # 确认二进制存在 ls /usr/local/bin/containerd ls /usr/local/bin/ctr # 生成默认配置 mkdir -p /etc/containerd containerd config default /etc/containerd/config.toml解压后/usr/local/bin下会有containerd、ctr、containerd-shim-runc-v2等。containerd config default生成的是完整默认配置后面要改两个关键点。3.3 改两个必调参数SystemdCgroup 和 sandbox 镜像默认配置里SystemdCgroup false而 K8S 1.26 的 kubelet 默认用 systemd 管理 cgroup两边不一致会导致 Pod 启动后反复重启日志里刷failed to create containerd task: cgroup。必须改成 true。另一个是 sandbox 镜像地址默认指向registry.k8s.io国内环境拉不动需要换成你能访问的镜像仓库。# 修改 SystemdCgroup sed -i s/SystemdCgroup false/SystemdCgroup true/ /etc/containerd/config.toml # 查看 sandbox 镜像配置行 grep -n sandbox_image /etc/containerd/config.tomlsandbox_image那一行默认是registry.k8s.io/pause:3.9把它改成你内网仓库或可访问的地址比如your-registry.local/pause:3.9。改完保存。3.4 配置 containerd 的 systemd 服务并启动containerd 官方包不带 systemd unit 文件需要自己写一个。cat /etc/systemd/system/containerd.service EOF [Unit] Descriptioncontainerd container runtime Afternetwork.target [Service] ExecStartPre/sbin/modprobe overlay ExecStart/usr/local/bin/containerd Restartalways RestartSec5 Delegateyes KillModeprocess OOMScoreAdjust-999 LimitNOFILE1048576 LimitNPROCinfinity LimitCOREinfinity [Install] WantedBymulti-user.target EOF systemctl daemon-reload systemctl enable --now containerd systemctl status containerdDelegateyes让 containerd 能管理自己的 cgroup 子树不加这个 kubelet 会报权限问题。LimitNOFILE调大是因为容器多了文件描述符不够。启动后用ctr version验证能打印出 Server 和 Client 版本就说明 containerd 活了。3.5 装 crictl 并指向 containerd 的 socketkubelet 通过 CRI 接口和 containerd 通信调试时用crictl比ctr更贴近 K8S 视角。# 下载 crictl 的 ARM64 版本解压到 /usr/local/bin tar -C /usr/local/bin -xzf crictl-v1.26.0-linux-arm64.tar.gz # 配置 crictl 指向 containerd cat /etc/crictl.yaml EOF runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock timeout: 10 debug: false EOF # 验证 crictl infocrictl info能返回 JSON 格式的运行时信息就对了。如果报连接拒绝检查 containerd 是否真的在跑以及 socket 路径是不是/run/containerd/containerd.sock。有些发行版会放到/var/run那是/run的软链不影响。4. kubeadm 初始化主节点K8S 1.26.15 的 ARM64 落地4.1 安装 kubelet、kubeadm、kubectl 三个 RPM 包麒麟 V10 是 RPM 体系K8S 官方提供 aarch64 的 RPM 包。如果你有内网 yum 源直接yum install没有的话下载 rpm 包用rpm -ivh本地装。三个包版本必须一致都是 1.26.15。# 本地安装示例包名按实际下载的来 rpm -ivh kubelet-1.26.15-0.aarch64.rpm rpm -ivh kubeadm-1.26.15-0.aarch64.rpm rpm -ivh kubectl-1.26.15-0.aarch64.rpm # 设置 kubelet 开机自启先别启动等 kubeadm init systemctl enable kubelet # 验证版本 kubeadm version kubectl version --client装完 kubelet 后它不会自动跑起来这是正常的kubeadm init 会生成配置再启动它。如果rpm -ivh报依赖缺失通常是conntrack、socat、ebtables这几个用 yum 补上。4.2 准备 kubeadm 配置文件把镜像地址和网段一次写对直接kubeadm init用默认参数会去拉registry.k8s.io的镜像ARM64 环境下大概率超时。正确做法是写一个配置文件指定imageRepository指向你的内网仓库或可访问的镜像源同时定好 Pod 网段。# kubeadm-config.yaml apiVersion: kubeadm.k8s.io/v1beta3 kind: InitConfiguration localAPIEndpoint: advertiseAddress: 192.168.1.10 bindPort: 6443 nodeRegistration: criSocket: unix:///run/containerd/containerd.sock imagePullPolicy: IfNotPresent --- apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration kubernetesVersion: v1.26.15 imageRepository: your-registry.local/k8s networking: podSubnet: 10.244.0.0/16 serviceSubnet: 10.96.0.0/12advertiseAddress换成你主节点的内网 IPcriSocket必须指向 containerd 的 socket写错会报failed to get runtime。imageRepository是你实际能拉镜像的地址podSubnet用 Flannel 的话默认 10.244.0.0/16。4.3 预拉镜像和正式 init配置文件写好先预拉镜像这一步能把网络问题提前暴露。# 预拉镜像 kubeadm config images pull --config kubeadm-config.yaml # 正式初始化 kubeadm init --config kubeadm-config.yaml --upload-certs--upload-certs会把证书加密上传方便后面加主节点虽然一主一从用不上但留着不碍事。init 成功后终端会打印一段kubeadm join命令里面有 token 和 hash复制下来从节点要用。如果卡在[wait-control-plane]超过两分钟多半是镜像没拉全或 containerd 配置有问题用crictl images看镜像列表。4.4 配置 kubectl 并验证主节点状态init 完成后按提示配置 kubectl。mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config # 查看节点此时是 NotReady因为还没装网络插件 kubectl get nodes # 查看系统 Pod kubectl get pods -n kube-system节点显示NotReady是正常的CNI 没装之前都这样。kube-system下的kube-apiserver、etcd、kube-scheduler、kube-controller-manager应该是 Runningcoredns会 Pending等网络插件装好就起来。4.5 装 Flannel 网络插件ARM64 镜像要选对Flannel 的默认 manifest 里镜像有 amd64 和 arm64 多架构但如果你内网仓库只同步了 amd64ARM 节点会拉失败报exec format error。确认你的仓库里 flannel 镜像是 arm64 的。# 应用 Flannel kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml # 如果内网先下载 yml 改镜像地址再 apply # kubectl apply -f kube-flannel-custom.yml # 观察 Pod 起来 kubectl get pods -n kube-flannel -wFlannel 的 DaemonSet 在每个节点跑一个kube-flannelPod起来后主节点变 Ready。如果 Pod 一直CrashLoopBackOff看日志kubectl logs -n kube-flannel pod常见是podSubnet和 Flannel 配置里的网段不一致。5. 从节点加入与集群验证一主一从的收尾动作5.1 从节点重复前置步骤再执行 join从节点不需要再跑kubeadm init但第 2 章的内核参数、第 3 章的 containerd 安装配置必须一模一样做一遍。containerd 的 socket 路径、SystemdCgroup 配置、crictl 配置都要对齐。做完后在从节点执行主节点 init 时打印的 join 命令。# 在主节点重新生成 token如果原来的过期了 kubeadm token create --print-join-command # 在从节点执行形如 kubeadm join 192.168.1.10:6443 --token abcdef.1234567890abcdef \ --discovery-token-ca-cert-hash sha256:xxxxxxxxtoken 默认 24 小时过期过期了用kubeadm token create重新生成。join 过程中如果报connection refused检查主节点 6443 端口是否监听、防火墙是否放行。5.2 验证两节点 Ready 和跨节点 Pod 通信回到主节点看节点列表。kubectl get nodes -o wide两个节点都应该是ReadyINTERNAL-IP显示各自内网地址。然后跑一个跨节点通信测试这是验证 CNI 是否真正工作的关键。# 在主节点跑一个 nginx kubectl run nginx --imagenginx --port80 # 查看它调度到哪个节点 kubectl get pod nginx -o wide # 在另一个节点上用 crictl 进 Pod 网络测试或直接创建测试 Pod kubectl run test --imagebusybox --rm -it --restartNever -- wget -qO- nginx如果wget能返回 nginx 欢迎页说明 Pod 跨节点网络通了。如果超时回到第 2 章检查br_netfilter和ip_forward这是最常见的两个原因。5.3 用 kubectl 做一次完整的调度验证光看节点 Ready 不够要确认调度器真的能把 Pod 分配到从节点。# 创建一个带节点亲和性的 Deployment强制调度到从节点 cat test-schedule.yaml EOF apiVersion: apps/v1 kind: Deployment metadata: name: schedule-test spec: replicas: 2 selector: matchLabels: app: schedule-test template: metadata: labels: app: schedule-test spec: containers: - name: pause image: your-registry.local/pause:3.9 EOF kubectl apply -f test-schedule.yaml kubectl get pods -o wide -l appschedule-test两个副本应该分别落在两个节点上或者至少有一个在从节点。如果全挤在主节点检查从节点是否有污点kubectl describe node k8s-node1 | grep Taints新加入的节点默认没有污点能正常调度。6. 避坑与排查ARM 麒麟环境下最容易翻车的五个点6.1 镜像 exec format error拉到了 amd64 镜像现象Pod 一直CrashLoopBackOffkubectl describe pod里事件显示exec format error或no match for platform in manifest。原因是你用的镜像仓库里只有 amd64 版本ARM 节点拉下来跑不了。解决确认镜像的 manifest 支持 arm64用docker manifest inspect或crictl inspecti看架构内网仓库要同步多架构镜像或者单独打 arm64 tag。6.2 kubelet 启动报 failed to get cgroup现象systemctl status kubelet显示failed to get cgroup或cgroup driver mismatch。原因是 containerd 的SystemdCgroup还是 false和 kubelet 的 systemd 驱动不一致。解决回到/etc/containerd/config.toml把SystemdCgroup true改对systemctl restart containerd后重启 kubelet。这个坑在第 3 章已经提前埋了伏笔但实际做的时候还是有人漏。6.3 从节点 join 报 x509 证书错误现象kubeadm join输出x509: certificate has expired or is not yet valid。原因是两台机器时间不同步或者 join 用的 token 过期。解决先chronyc sources确认时间同步再date对比两台机器token 过期就回主节点kubeadm token create --print-join-command重新生成。时间差超过证书有效期默认一年的情况极少但几分钟的偏差就足以让 TLS 握手失败。6.4 Flannel Pod 起不来日志报 subnet 冲突现象kube-flannel的 Pod 反复重启日志里failed to acquire lease或subnet 10.244.x.x/24 overlaps。原因是 kubeadm 配置的podSubnet和 Flannel 的Network字段不一致或者两个节点分配到了同一个子网。解决确认kubeadm-config.yaml里podSubnet: 10.244.0.0/16Flannel 的 ConfigMap 里Network也是10.244.0.0/16两者必须完全一致。6.5 crictl 连不上 containerd现象crictl info报connection refused或no such file or directory。原因是 crictl 配置的 endpoint 和 containerd 实际监听的 socket 不一致。解决systemctl status containerd看它监听的路径默认是/run/containerd/containerd.sock检查/etc/crictl.yaml里的runtime-endpoint是否写对。如果 containerd 根本没起来看journalctl -u containerd的报错常见是配置文件语法错误。7. 把一主一从跑稳之后几个能省时间的进阶习惯集群跑起来只是开始真正省时间的是后面这些习惯。第一个是给 kubelet 配--node-labels和污点管理一主一从的环境里主节点默认有node-role.kubernetes.io/control-plane:NoSchedule污点如果你想让主节点也跑业务 Pod得手动去掉但生产环境不建议。第二个是定期kubeadm certs check-expiration看证书到期时间K8S 的证书默认一年到期后 apiserver 直接起不来这个后悔药不好吃。第三个是把kubeadm-config.yaml、containerd 的config.toml、crictl 配置这三个文件纳入版本管理下次扩容或重建直接复用不用再回忆参数。验证集群是否真的稳我一般会做三件事连续创建删除 20 个 Pod 看调度是否正常、重启一次 containerd 看 Pod 是否自动恢复、把从节点关机再开机看它能否重新加入。这三步过了这套一主一从才算能交付。ARM 环境下的 K8S 没有 x86 那么多现成脚本但只要 containerd 的 cgroup 驱动、内核模块、镜像架构这三样对齐剩下的和 x86 没本质区别。我自己踩得最狠的一次是镜像架构没确认排查了两个小时才发现是 amd64 的包在 ARM 上跑不起来希望帮到你。本文还有配套的精品资源点击获取
返回列表