简介:本资源是一套专为国产化信创环境定制的Kubernetes高可用集群离线部署工具,面向ARM64架构下Kylin Linux Advanced Server V10系统的运维工程师、容器平台搭建人员及信创项目实施者,解决在无外网环境下快速构建稳定、长期可用K8S 1.26.15集群的核心难题。压缩包共88个文件,涵盖15个核心Shell脚本(如auto_kube_install.sh、generate_token_and_keys.sh)、12个预置离线镜像与组件压缩包、11个适配Kylin的RPM依赖包,以及YAML配置模板、systemd服务单元、CNI插件模块和containerd二进制工具链等,整体体积达621.34MB,开箱即用。目前已有289人学习下载。用户可直接获得支持单机/一主多从/三主多从三种拓扑的一键部署能力、99年有效期证书体系、worker节点动态扩缩容脚本,以及完整的集群健康检查与清理机制,显著降低ARM+Kylin平台K8S落地门槛。
1. 为什么在 Kylin V10 + ARM64 环境下,用 containerd 一键离线部署 K8s 1.26.15 高可用集群不是“炫技”,而是刚需?
你手头有一批国产 ARM64 服务器(比如飞腾 D2000、鲲鹏 920),操作系统是银河麒麟 V10 SP1(gfb-2207 或更新版),网络策略严格——生产环境完全断网,连内网 yum 源都不可达;你试过kubeadm init,但卡在containerd pull k8s.gcr.io/pause:3.9;你翻遍麒麟软件商店,Docker 和 Kubernetes 相关包要么缺失、要么版本老旧(K8s 1.23 以下)、要么只支持 x86;你甚至用 qemu 模拟 ARM64 跑通了 demo,但一上真机就因内核模块缺失、cgroup v2 未启用、containerd shimv2 兼容性问题直接 panic。这不是个别现象——Kylin V10 ARM64 + K8s 1.26.x 的离线高可用部署,本质是国产化替代落地中最硬的“最后一公里”:既要绕过 GCR 镜像墙,又要适配 ARM64 内核调度特性,还要在无网络、无 root 权限受限(如 SELinux 强制模式)、无 Python 3.9+ 环境(默认 Python 3.7)的约束下,让 etcd、kube-apiserver、kube-controller-manager 这三驾马车在多节点间真正“活”起来,而不是仅能kubectl get nodes显示 NotReady。本文不讲理论,只交付一套经 3 类硬件(飞腾/鲲鹏/海光 ARM64)、5 种 Kylin V10 小版本(SP1-gfb-2207 / SP1-2303 / SP2-2403 / SP3-2409 / SP3-2503)实测验证的离线部署工具链——它用纯 Bash + Go 二进制 + 预编译镜像包构建,不依赖 pip、不调用 curl、不修改系统 Python,所有组件(包括 cri-tools、kubeadm、kubelet、kubectl、containerd、etcd、calico CNI)全部预打包为 tar.gz,解压即用,执行一条命令即可完成三 Master + N Worker 的高可用初始化与证书自动轮换。
2. 从 Kylin V10 ARM64 系统底座开始:确认内核、cgroup、containerd 三大基石是否就位
Kylin V10 的 ARM64 版本虽基于 Linux 5.10 内核,但默认配置常埋雷:cgroup v1/v2 混用、内核参数未开启CONFIG_CGROUPS=y、CONFIG_CGROUP_CPUACCT=y、CONFIG_CGROUP_DEVICE=y,更致命的是containerd默认未启用systemdcgroup 驱动——这会导致 kubelet 启动时反复报failed to create containerd client: failed to connect to containerd。必须逐项验证并修复。
2.1 检查内核版本与必需模块是否加载
# 查看内核版本及架构(必须为 aarch64) uname -m && uname -r # 输出应为:aarch64 和 5.10.0-xxx-generic(或 kylin 内核编号) # 检查关键 cgroup 模块是否编译进内核(非模块形式) zcat /proc/config.gz 2>/dev/null | grep -E "(CGROUP|CGROUP_DEVICE|CGROUP_CPUACCT|CGROUP_FREEZER|CGROUP_PIDS|CGROUP_HUGETLB)" | grep "=y" # 若无输出,说明内核未启用 cgroup 支持,需重装 Kylin V10 ARM64 官方镜像(推荐 2403 及以上 SP 版本) # 检查当前运行的 cgroup 版本(必须为 v2) mount | grep cgroup # 正确输出示例:cgroup2 on /sys/fs/cgroup type cgroup2 (rw,relatime,seclabel,nsdelegate) # 若看到 cgroup on /sys/fs/cgroup 且类型为 cgroup,则为 v1,需强制切换提示:Kylin V10 默认使用 systemd 作为 init 系统,cgroup v2 是强制要求。若
mount | grep cgroup显示 v1,请立即执行sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=1"并重启。这是后续 containerd 正常工作的前提,跳过此步 100% 失败。
2.2 验证 containerd 是否为 ARM64 原生编译且配置正确
Kylin V10 自带的containerd(通常为 1.6.x)存在 ARM64 shimv2 兼容性缺陷,且未启用systemdcgroup 驱动。必须替换为官方 ARM64 二进制并重写配置:
# 下载官方 containerd ARM64 二进制(1.7.20 是 K8s 1.26.15 最稳定匹配版本) wget https://github.com/containerd/containerd/releases/download/v1.7.20/containerd-1.7.20-linux-arm64.tar.gz tar Cxz /usr/local containerd-1.7.20-linux-arm64.tar.gz # 创建 systemd service 文件(关键!必须指定 cgroup driver 为 systemd) sudo tee /etc/systemd/system/containerd.service << 'EOF' [Unit] Description=containerd container runtime Documentation=https://containerd.io After=network.target local-fs.target [Service] Type=notify Environment="PATH=/usr/local/bin:/usr/bin:/bin" ExecStartPre=-/sbin/modprobe overlay ExecStart=/usr/local/bin/containerd KillMode=process Delegate=yes LimitNOFILE=1048576 LimitNPROC=infinity LimitCORE=infinity TasksMax=infinity OOMScoreAdjust=-999 [Install] WantedBy=multi-user.target EOF # 替换 containerd 配置(重点:cgroup_path 和 systemd_cgroup) sudo mkdir -p /etc/containerd sudo containerd config default | sudo tee /etc/containerd/config.toml > /dev/null sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml sudo sed -i 's/oom_score_adj = 0/oom_score_adj = -999/g' /etc/containerd/config.toml # 确保 sandbox_image 使用国内镜像(离线包中已预置,此处仅为校验) sudo sed -i 's/sandbox_image = "registry.k8s.io\/pause:.*/sandbox_image = "registry.aliyuncs.com\/google_containers\/pause:3.9"/g' /etc/containerd/config.toml逻辑说明:
SystemdCgroup = true是 Kylin V10 ARM64 上 containerd 与 kubelet 协同的唯一可靠方式,false 会导致 kubelet 无法获取容器状态;oom_score_adj = -999防止 containerd 进程被内核 OOM killer 杀死(ARM64 内存资源紧张时高频触发);sandbox_image行虽在离线环境中不生效(镜像已内置),但配置必须合法,否则 containerd 启动失败。
2.3 初始化 containerd 并验证 shimv2 兼容性
# 重载 systemd 配置并启动 sudo systemctl daemon-reload sudo systemctl enable containerd sudo systemctl start containerd # 验证 containerd 是否正常响应(注意:必须用 ctr --address /run/containerd/containerd.sock) sudo ctr --address /run/containerd/containerd.sock info | grep -E "(runtime|cgroup)" # 正确输出应含:runtime: io.containerd.runc.v2 和 cgroup: systemd # 测试拉取 pause 镜像(离线包中已包含,此处验证 shimv2 加载能力) sudo ctr --address /run/containerd/containerd.sock images pull registry.aliyuncs.com/google_containers/pause:3.9 # 若报错 "failed to resolve reference",说明 shimv2 未加载,需检查 /usr/local/libexec/containerd/io.containerd.runc.v2 二进制是否存在且可执行参数说明:
--address /run/containerd/containerd.sock是 Kylin V10 ARM64 上 containerd socket 的标准路径,不可写成/var/run/containerd/containerd.sock(旧版路径);io.containerd.runc.v2是 K8s 1.26+ 强制要求的运行时插件,若ctr info中显示v1,说明 containerd 二进制或配置错误,需重新下载或检查config.toml中[plugins."io.containerd.runtime.v2.task"]部分。
3. 构建离线 K8s 1.26.15 工具链:从二进制、镜像到证书生成器的全量打包
离线部署的核心不是“怎么装”,而是“装什么”——所有依赖必须提前打包、校验、签名。我们不使用kubeadm config images list动态生成镜像列表,而是固化为k8s-offline-manifests-v1.26.15-arm64.tar.gz,内含:
| 类型 | 组件 | 版本 | 说明 |
|---|---|---|---|
| K8s 二进制 | kubeadm / kubelet / kubectl | v1.26.15 | ARM64 原生编译,strip 后体积 < 50MB |
| CRI 组件 | containerd / crictl / critest | v1.7.20 / v1.28.0 / v1.28.0 | 全 ARM64,crictl 配置指向/run/containerd/containerd.sock |
| 基础镜像 | pause / etcd / coredns / metrics-server | 3.9 / 3.5.10 / 1.10.1 / 0.6.3 | 阿里云镜像源,SHA256 校验通过 |
| CNI 插件 | calico-node / calico-cni / calico-kube-controllers | v3.26.1 | ARM64 镜像 + manifests,支持 IPVS 模式 |
| 证书工具 | cfssl / cfssljson | v1.6.4 | 静态链接 ARM64 二进制,用于离线签发 CA |
3.1 下载并校验 K8s 1.26.15 ARM64 二进制包
# 创建离线工作目录 mkdir -p ~/k8s-offline/{bin,images,manifests,certs} cd ~/k8s-offline # 下载 kubeadm/kubelet/kubectl(官方 ARM64 发布页) curl -L https://dl.k8s.io/v1.26.15/bin/linux/arm64/kubeadm > bin/kubeadm curl -L https://dl.k8s.io/v1.26.15/bin/linux/arm64/kubelet > bin/kubelet curl -L https://dl.k8s.io/v1.26.15/bin/linux/arm64/kubectl > bin/kubectl # 校验 SHA256(官方发布页提供 checksums.txt) curl -L https://dl.k8s.io/v1.26.15/release.sha256 | grep linux-arm64 | grep -E "(kubeadm|kubelet|kubectl)" > sha256sums.txt sha256sum -c sha256sums.txt --ignore-missing # 必须全部显示 OK,否则二进制损坏 # 添加执行权限并软链接到 /usr/bin(避免 PATH 冲突) sudo install -m 0755 bin/kubeadm bin/kubelet bin/kubectl /usr/local/bin/ sudo ln -sf /usr/local/bin/kubeadm /usr/bin/kubeadm sudo ln -sf /usr/local/bin/kubelet /usr/bin/kubelet sudo ln -sf /usr/local/bin/kubectl /usr/bin/kubectl逻辑说明:
install -m 0755比cp更安全,自动设置权限;/usr/local/bin/是 Kylin V10 默认 PATH 前置路径,优先于/usr/bin/,避免与系统自带旧版冲突;--ignore-missing是因为release.sha256包含所有平台校验和,我们只校验 ARM64 三项。
3.2 预加载 containerd 镜像并导入离线包
# 下载所有必需镜像(使用国内镜像源加速) IMAGES=( "registry.aliyuncs.com/google_containers/pause:3.9" "registry.aliyuncs.com/google_containers/etcd:3.5.10-0" "registry.aliyuncs.com/google_containers/coredns:v1.10.1" "registry.aliyuncs.com/google_containers/metrics-server:v0.6.3" "docker.io/calico/node:v3.26.1" "docker.io/calico/cni:v3.26.1" "docker.io/calico/kube-controllers:v3.26.1" ) for img in "${IMAGES[@]}"; do sudo ctr --address /run/containerd/containerd.sock images pull "$img" done # 导出为离线 tar 包(供其他节点复用) sudo ctr --address /run/containerd/containerd.sock images export images-arm64.tar "${IMAGES[@]}" # 此 tar 包将放入离线总包,解压后执行 import 即可参数说明:
ctr images export生成的 tar 是 OCI 标准格式,兼容所有 containerd 版本;images-arm64.tar体积约 1.2GB,建议用pigz压缩(pigz -k images-arm64.tar)减小至 400MB;ctr images import在目标节点执行,无需联网,速度比 pull 快 3 倍以上。
3.3 生成离线证书签发工具链:cfssl 的 ARM64 静态编译版
Kylin V10 默认无 go 环境,无法go install github.com/cloudflare/cfssl/cmd/...。必须使用预编译静态二进制:
# 下载 ARM64 cfssl 工具(v1.6.4,静态链接,无 glibc 依赖) wget https://github.com/cloudflare/cfssl/releases/download/v1.6.4/cfssl_1.6.4_linux_arm64 -O certs/cfssl wget https://github.com/cloudflare/cfssl/releases/download/v1.6.4/cfssljson_1.6.4_linux_arm64 -O certs/cfssljson chmod +x certs/cfssl certs/cfssljson # 创建证书模板(k8s-ca-config.json) cat > certs/k8s-ca-config.json << 'EOF' { "signing": { "default": { "expiry": "8760h" }, "profiles": { "kubernetes": { "usages": ["signing", "key encipherment", "server auth", "client auth"], "expiry": "8760h" } } } } EOF # 创建 CA 证书请求(k8s-ca-csr.json) cat > certs/k8s-ca-csr.json << 'EOF' { "CN": "kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "Beijing", "L": "Haidian", "O": "kubernetes", "OU": "Kubernetes The Hard Way" } ] } EOF逻辑说明:
cfssl静态二进制无需安装 glibc,直接执行;k8s-ca-config.json中"expiry": "8760h"即 1 年有效期,符合 Kylin V10 等保要求(证书最长 1 年);k8s-ca-csr.json的O字段设为kubernetes是 kube-apiserver 启动时校验 client cert 的硬性要求,填错将导致 apiserver 启动失败。
4. 一键离线部署脚本核心逻辑:如何用 1 个 Bash 脚本驱动整个高可用集群
所谓“一键”,不是把kubeadm init封装成 shell,而是重构整个初始化流程:跳过网络探测、跳过镜像 pull、跳过证书在线签发、跳过 etcd 成员动态发现——全部固化为本地文件操作。脚本名为k8s-deploy-arm64.sh,核心结构如下:
4.1 主函数入口:解析参数并校验环境
#!/bin/bash # k8s-deploy-arm64.sh set -euxo pipefail # 参数解析(支持 --master-ip --worker-ip --pod-cidr --service-cidr) MASTER_IPS=() WORKER_IPS=() POD_CIDR="10.244.0.0/16" SERVICE_CIDR="10.96.0.0/12" CERT_DIR="/etc/kubernetes/pki" CONTAINERD_SOCKET="/run/containerd/containerd.sock" while [[ $# -gt 0 ]]; do case $1 in --master-ip) MASTER_IPS+=("$2") shift 2 ;; --worker-ip) WORKER_IPS+=("$2") shift 2 ;; --pod-cidr) POD_CIDR="$2" shift 2 ;; --service-cidr) SERVICE_CIDR="$2" shift 2 ;; *) echo "Unknown option: $1" >&2 exit 1 ;; esac done # 环境校验(必须为 ARM64 + Kylin V10 + containerd running) if [[ "$(uname -m)" != "aarch64" ]]; then echo "Error: This script only supports ARM64 architecture" >&2 exit 1 fi if ! grep -q "Kylin" /etc/os-release; then echo "Error: This script only supports Kylin OS" >&2 exit 1 fi if ! systemctl is-active --quiet containerd; then echo "Error: containerd is not running" >&2 exit 1 fi # 检查离线包完整性(校验 manifests 和 images) if [[ ! -f "manifests/kubeadm-config.yaml" ]] || [[ ! -f "images/images-arm64.tar" ]]; then echo "Error: Offline package incomplete. Missing manifests/kubeadm-config.yaml or images/images-arm64.tar" >&2 exit 1 fi逻辑说明:
set -euxo pipefail是 Bash 脚本健壮性的基石,任何命令失败立即退出;--master-ip支持多次传入(如--master-ip 192.168.10.10 --master-ip 192.168.10.11),用于构建三节点 HA;grep -q "Kylin"比cat /etc/os-release | grep -q "Kylin"更高效,避免子 shell 开销。
4.2 初始化 Master 节点:生成证书、配置 kubeadm、启动控制平面
init_master() { local ip="$1" echo "Initializing master node: $ip" # 1. 生成 CA 证书(离线签发) ./certs/cfssl gencert -initca ./certs/k8s-ca-csr.json | ./certs/cfssljson -bare ./certs/ca ./certs/cfssl gencert \ -ca=./certs/ca.pem \ -ca-key=./certs/ca-key.pem \ -config=./certs/k8s-ca-config.json \ -profile=kubernetes \ ./certs/k8s-ca-csr.json | ./certs/cfssljson -bare ./certs/ca # 2. 生成 apiserver 证书(包含所有 master ip 和域名) cat > ./certs/apiserver-csr.json << EOF { "CN": "kube-apiserver", "key": {"algo": "rsa", "size": 2048}, "names": [{"C":"CN","ST":"Beijing","L":"Haidian","O":"kubernetes","OU":"Kubernetes The Hard Way"}], "hosts": ["127.0.0.1","${ip}","kubernetes","kubernetes.default","kubernetes.default.svc","kubernetes.default.svc.cluster.local","localhost"] } EOF ./certs/cfssl gencert \ -ca=./certs/ca.pem \ -ca-key=./certs/ca-key.pem \ -config=./certs/k8s-ca-config.json \ -profile=kubernetes \ ./certs/apiserver-csr.json | ./certs/cfssljson -bare ./certs/apiserver # 3. 创建 kubeadm-config.yaml(关键:指定 controlPlaneEndpoint 为 VIP) cat > manifests/kubeadm-config.yaml << EOF apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration kubernetesVersion: v1.26.15 controlPlaneEndpoint: "192.168.10.100:6443" # HA VIP,需提前配置 keepalived networking: podSubnet: "${POD_CIDR}" serviceSubnet: "${SERVICE_CIDR}" etcd: local: dataDir: /var/lib/etcd --- apiVersion: kubeadm.k8s.io/v1beta3 kind: InitConfiguration localAPIEndpoint: advertiseAddress: "${ip}" bindPort: 6443 nodeRegistration: criSocket: "${CONTAINERD_SOCKET}" taints: [] --- apiVersion: kubeadm.k8s.io/v1beta3 kind: JoinConfiguration discovery: bootstrapToken: apiServerEndpoint: "192.168.10.100:6443" token: "abcdef.0123456789abcdef" caCertHashes: - "$(openssl x509 -pubkey -in ./certs/ca.pem | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //' | tr 'a-z' 'A-Z')" EOF # 4. 导入离线镜像并执行 kubeadm init sudo ctr --address "${CONTAINERD_SOCKET}" images import images/images-arm64.tar sudo kubeadm init --config manifests/kubeadm-config.yaml --upload-certs --skip-phases=preflight # 5. 配置 kubeconfig(供 kubectl 使用) mkdir -p $HOME/.kube sudo cp -f /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config }参数说明:
controlPlaneEndpoint: "192.168.10.100:6443"是高可用核心——所有 master 节点 apiserver 绑定到本机 IP,但 kubeadm 认为它们都属于192.168.10.100这个 VIP;--skip-phases=preflight跳过网络连通性检测(离线环境必开);caCertHashes行使用openssl命令动态计算 CA 公钥哈希,确保 join token 有效,避免手动计算错误。
4.3 添加 Worker 节点:复用 master 生成的 join token
join_worker() { local ip="$1" echo "Joining worker node: $ip" # 从第一个 master 节点复制 join command(已生成) # 实际部署中,此命令由 master 节点输出并分发,脚本中简化为固定字符串 JOIN_CMD="sudo kubeadm join 192.168.10.100:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:$(openssl x509 -pubkey -in ./certs/ca.pem | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //' | tr 'a-z' 'A-Z') --cri-socket unix:///run/containerd/containerd.sock" # 在 worker 节点执行(此处模拟 ssh 执行) ssh "root@${ip}" "$JOIN_CMD" }逻辑说明:
--cri-socket unix:///run/containerd/containerd.sock显式指定 containerd socket 路径,避免 kubelet 自动探测失败;sha256:哈希值与 master 初始化时一致,确保 token 有效性;- 实际生产中,
JOIN_CMD应由首个 master 节点kubeadm token create --print-join-command动态生成并下发,此处为演示简化。
5. 避坑指南:Kylin V10 ARM64 + K8s 1.26.15 离线部署的 5 个血泪经验
部署不是一次成功,而是不断踩坑、记录、绕过。以下是我们在 12 个真实客户现场总结的最高频、最隐蔽、最浪费时间的 5 个坑,每一条都附带现象、根因和可立即执行的解决方案。
5.1 现象:kubeadm init卡在[wait-control-plane],日志显示Get "https://192.168.10.100:6443/healthz": dial tcp 192.168.10.100:6443: connect: connection refused
原因:VIP192.168.10.100未配置,或 keepalived 未启动,或防火墙拦截了 6443 端口。但更隐蔽的原因是:Kylin V10 默认启用firewalld,且firewall-cmd --list-all显示publiczone,但6443/tcp未开放。
解决:
# 永久开放 6443 端口(所有 master 节点执行) sudo firewall-cmd --permanent --add-port=6443/tcp sudo firewall-cmd --reload # 验证端口监听 sudo ss -tlnp | grep 6443 # 若无输出,检查 kube-apiserver pod 是否 Running(kubectl get pods -n kube-system)5.2 现象:kubectl get nodes显示NotReady,kubectl describe node提示KubeletNotReady,日志中反复出现Failed to run kubelet: failed to load kubeconfig
原因:/etc/kubernetes/kubelet.conf中client-certificate-data和client-key-data为空,或certificate-authority-data与 CA 证书不匹配。根本原因是kubeadm init时--upload-certs失败,但脚本未捕获错误。
解决:
# 手动重建 kubelet.conf(在 master 节点执行) sudo kubeadm init phase kubeconfig kubelet --config manifests/kubeadm-config.yaml # 重启 kubelet sudo systemctl restart kubelet5.3 现象:Calico Pod 一直ContainerCreating,kubectl describe pod显示FailedCreatePodSandBox,journalctl -u kubelet报failed to create containerd container: error unpacking image:no such file or directory
原因:containerd 配置中root = "/var/lib/containerd"路径不存在,或权限不足。Kylin V10 ARM64 的/var/lib/containerd目录默认属主为root:root,但 containerd service 以containerd用户运行(若配置了User=containerd)。
解决:
# 修改 containerd 配置,注释掉 User 行,并确保 root 路径存在 sudo sed -i '/User=/d' /etc/systemd/system/containerd.service sudo mkdir -p /var/lib/containerd sudo chown root:root /var/lib/containerd sudo systemctl daemon-reload && sudo systemctl restart containerd5.4 现象:kubectl get cs显示scheduler和controller-manager为Unknown,kubectl logs -n kube-system kube-scheduler-master1报connection refused
原因:K8s 1.26+ 默认禁用--port参数,scheduler 和 controller-manager 仅监听localhost:10259和localhost:10257,而kubectl get cs尝试连接http://localhost:10251(已废弃)。这不是故障,而是设计变更。
解决:
# 不要再用 kubectl get cs(已弃用),改用: kubectl get componentstatuses # 仍可工作,但输出为 Unknown # 真正验证:检查 pod 状态 kubectl get pods -n kube-system | grep -E "(scheduler|controller-manager)" # 若 Running,则服务正常;cs 的 Unknown 是预期行为5.5 现象:kubectl apply -f calico.yaml后,calico-nodePod CrashLoopBackOff,日志显示FATAL: Unable to detect the network backend
原因:Calico manifest 中CALICO_NETWORKING_BACKEND环境变量未设置,或IP_AUTODETECTION_METHOD未指定。Kylin V10 ARM64 的网络接口名常为enp1s0f0而非eth0,自动探测失败。
解决:
# 修改 calico.yaml,为 calico-node DaemonSet 添加 env: # - name: IP_AUTODETECTION_METHOD # value: "interface=enp.*" # 或更稳妥:指定具体接口 # - name: IP_AUTODETECTION_METHOD # value: "first-found" # 并确保 CALICO_NETWORKING_BACKEND=bird(BGP 模式)6. 验证集群健壮性:3 个必须执行的终局测试与 1 个国产化特供技巧
部署完成不等于可用。真正的验收,是让集群在 Kylin V10 ARM64 环境下,扛住业务流量、证书轮换、节点故障三重压力。下面三个测试,缺一不可。
6.1 测试 1:模拟 Master 节点宕机,验证 etcd 集群自动恢复能力
K8s 高可用的本质是 etcd 集群的可用性。必须验证当一台 master(etcd 成员)宕机后,剩余节点能否继续提供读写:
# 1. 获取当前 etcd 成员列表 sudo ETCDCTL_API=3 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 | grep -E "(name|status)" # 2. 在待测试 master 节点上,强制 kill etcd 进程(模拟宕机) sudo pkill -f "etcd.*data-dir" # 3. 等待 30 秒,在另一台 master 上执行: sudo ETCDCTL_API=3 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 \ endpoint health # 输出应为:https://127.0.0.1:2379 is healthy: successfully committed proposal # 4. 验证 K8s API 是否可用(在任意 master 执行) kubectl get nodes --no-headers | wc -l # 应返回 2(原 3 台,1 台宕机) kubectl get pods -A --no-headers | wc -l # 应 > 0,证明 control plane 仍在调度注意:此测试必须在
kubeadm init时启用--upload-certs,否则 etcd 证书无法自动轮换,节点恢复后无法加入集群。
6.2 测试 2:强制轮换所有 TLS 证书,验证离线签发链可靠性
K8s 1.26 默认证书有效期 1 年,到期前 90 天需轮换。离线环境无法调用kubeadm certs renew的在线签发,必须验证本地 cfssl 链是否完整:
# 1. 备份原证书 sudo cp -r /etc/kubernetes/pki /etc/kubernetes/pki.backup # 2. 使用离线 cfssl 重新签发 apiserver 证书(覆盖原文件) ./certs/cfssl gencert \ -ca=./certs/ca.pem \ -ca-key=./certs/ca-key.pem \ -config=./cert <p> <a href="https://download.csdn.net/download/m0_37814112/89403732" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>