跳转至

K8s 1.36.4 HA 集群部署 SOP

本 SOP 配套实现体:k8s_136_cluster_deploy/(Python 工程)。 第 5 章的分步操作用于人阅读、复核与手工复现;幂等、备份、回滚均由实现体保证,一切以实现体为准。

目录

  1. 背景
  2. 目标
  3. 前置条件
  4. 影响范围
  5. 分步操作(5.1 基线 / 5.2 containerd / 5.3 k8s 组件 / 5.4 控制面 HA / 5.5 镜像分发 / 5.6 控制面初始化 / 5.7 节点加入 / 5.8 Calico / 5.9 附加组件 / 5.10 缩容与扩回)
  6. 验证
  7. 回滚
  8. 风险说明
  9. 附录 A. 交付物清单 | 附录 B. 关键决策记录

1. 背景

现有集群基线来自旧版本脚本(原 ori_ins_script 为 k8s 1.22 + Docker 运行时 + Calico 手工 scp 证书, 后经 k8s_cluster_deploy(1.34.3 + Flannel)与 k8s_v134_upgrade 演进)。本次在新环境重建集群:

  • 目标版本提升到当前受支持的 1.36.4(1.34.11 将于 2026-10-27 EOL)
  • 运行环境由 CentOS 7 换为 Rocky Linux 9.8,容器运行时统一为 containerd
  • CNI 由 Flannel 换为 Calico 3.32.2(Tigera Operator),为后续 NetworkPolicy 留出能力
  • Web UI 由已归档的 Kubernetes Dashboard 换为官方继任者 Headlamp
  • 控制面 etcd 数据落独立盘(/var/lib/etcd,10G xfs)

触发条件:新环境 6 台 Rocky 9.8 虚拟机已就绪且处于干净状态(无 containerd / kubelet 残留)。

2. 目标

变更完成后应达到如下可验证状态:

项 目标状态
集群版本 kubectl version 显示 v1.36.4
节点 6 台全部 Ready(3 控制面 + 3 工作节点)
控制面 VIP https://192.168.31.8:16443/healthz 返回 ok
etcd 3 成员健康,数据目录 /var/lib/etcd 落在独立盘 /dev/vdb
CNI tigerastatus 全部 Available,Pod 网段 10.244.0.0/16 与 192.168.31.0/24 不冲突
附加组件 metrics-server 可 kubectl top nodes;Headlamp Deployment 就绪
幂等 二次执行零变更、全跳过

当前实际形态(2026-09-16 缩容后):全部虚拟机运行于同一台 KVM 宿主机,宿主机自身即单点, 多 master 无法提供宿主机级高可用,故已在部署完成后缩容为单控制面(操作见 5.10):

项 当前状态
节点 4 台 Ready:k8s-master-01 + k8s-node-01/02/03
控制面 仅 k8s-master-01;etcd 单成员(quorum=1),数据仍在独立盘 /dev/vdb
已下线 k8s-master-02/03 虚拟机(关机、autostart 已禁用、磁盘保留),一条 --expand 即可恢复
保留项 haproxy 3 后端、keepalived 3 peer、VIP、kubeconfig 的 controlPlaneEndpoint 均未改动

第 2 章上表是「首次部署应达到的状态」;缩容属于部署后的可选变更,两者由同一实现体保证幂等。

3. 前置条件

项 要求
操作系统 Rocky Linux 9.8(x86_64),内核 5.14+
节点 .10–.15 共 6 台,root 免密 SSH(端口 22);hostname 无需预置,脚本按配置设置
etcd 盘 可选:独立盘已挂载到 /var/lib/etcd;缺盘时行为由 cluster.etcd_disk_policy 决定(auto 回退系统盘 / require 直接失败)
VIP 192.168.31.8 空闲,且不在 DHCP 地址池内(须人工确认)
网卡 节点业务网卡为 ens2(脚本会校验其存在性,报错时列出实际网卡名)
网络 节点可经旁路网关访问海外源(已实测:quay.io / ghcr.io / registry.k8s.io 均可直连,带宽 300–450KB/s)
工具 本机 Python ≥ 3.9(工程使用独立 venv),无需 helm
配置 config/deploy.yaml 已按环境填写并 chmod 600
时间同步 由脚本保证:baseline.manage_chrony=true 时自动安装/启用 chrony 并校验偏差

执行前检查:

cd k8s_136_cluster_deploy                                     # 以下命令均在工程根目录执行
.venv/bin/python main.py --config config/deploy.yaml --dry-run    # 预演,仅只读查询

4. 影响范围

项 说明
主机清单 k8s-master-01/02/03(192.168.31.10/11/12)、k8s-node-01/02/03(192.168.31.13/14/15)
是否停服 6 台均为新建机器,无在跑业务,不停服;若机器已被他用,须先确认无作业
窗口期 单次执行预计 40–90 分钟,其中镜像拉取与 Calico 就绪占比最大(受 300–450KB/s 带宽制约)
高危变更 ① SELinux 置 permissive 并持久化禁用;② firewalld 停止并禁用;③ 覆盖 /etc/hosts、/etc/fstab、/etc/sysctl.d/k8s.conf、containerd/keepalived/haproxy 配置;④ 重启 containerd、haproxy、keepalived
网络影响 期间 VIP 会经历 keepalived 起停;集群内无既有业务,无流量损失
不可回滚项 etcd 数据层不可自动回滚,回滚仅覆盖宿主机配置层

5. 分步操作

对应实现:k8s_136_cluster_deploy/deployer.py(方法名见各行注释)。以下为等价手工序列,供复核与手工复现。

5.0 预演与执行入口

cd k8s_136_cluster_deploy
.venv/bin/python main.py --config config/deploy.yaml --dry-run    # 预演:打印全部变更/跳过明细,不改系统
.venv/bin/python main.py --config config/deploy.yaml              # 正式执行(对应 deployer.run)

5.1 系统基线(_stage_baseline)

# 以下每条命令均对 6 台执行;高危动作前先备份原文件
# 基础工具:Rocky 9 最小化安装不含 tar / conntrack / socat,必须先补齐
rpm -q tar conntrack-tools socat || dnf install -y tar conntrack-tools socat
# 主机名:kubeadm 以实际 hostname 注册节点,必须与配置一致(新节点常仍是 localhost)
hostnamectl set-hostname k8s-master-01
# 时间同步:安装并启用 chrony;NTP 源见 baseline.ntp_servers,留空则保留节点现有源
rpm -q chrony || dnf install -y chrony
systemctl enable --now chronyd
chronyc tracking                                                     # 校验时钟偏差(超过 max_clock_offset_seconds 即失败)
cp -a /etc/selinux/config /etc/selinux/config.bak.$(date +%Y%m%d)   # 高危:变更前备份
setenforce 0                                                        # 高危:立即置 permissive
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config        # 高危:持久化禁用(彻底生效需重启)
systemctl disable --now firewalld                                   # 高危:停止并禁用防火墙
# /etc/hosts 仅补缺失的节点解析行(不整体覆盖)
printf '192.168.31.11   k8s-master-02\n' >> /etc/hosts              # 缺失时才追加

printf 'overlay\nbr_netfilter\n' > /etc/modules-load.d/k8s.conf    # 内核模块开机加载
printf 'net.bridge.bridge-nf-call-iptables = 1\nnet.bridge.bridge-nf-call-ip6tables = 1\nnet.ipv4.ip_forward = 1\nvm.swappiness = 0\n' > /etc/sysctl.d/k8s.conf
modprobe overlay; modprobe br_netfilter; sysctl --system

# 仅 3 台 master:etcd 数据目录(无独立盘时即系统盘目录;脚本只建目录,不分区不格式化)
mkdir -p /var/lib/etcd
# 仅 3 台 master:把 etcd 盘从设备名改为 UUID(规避设备名漂移)
blkid -s UUID -o value /dev/vdb                                     # 先取 UUID
cp -a /etc/fstab /etc/fstab.bak.$(date +%Y%m%d)                     # 高危:变更前备份
sed -i 's|^/dev/vdb|UUID=<上一步的UUID>|' /etc/fstab                # 高危:改写挂载项
systemctl daemon-reload && findmnt --verify --verbose

5.2 containerd 运行时(_stage_containerd)

dnf install -y dnf-plugins-core
dnf config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
dnf install -y containerd.io                                        # 2.x
containerd config default > /tmp/ct_new.toml                        # 生成基线而非硬编码模板
sed -i 's/^\s*SystemdCgroup = .*/\1SystemdCgroup = true/' /tmp/ct_new.toml
# containerd 2.x 的字段名是 sandbox(1.x 才是 sandbox_image),两种都尝试替换
sed -i 's|^\s*sandbox_image = .*|\1sandbox_image = "registry.k8s.io/pause:3.10.2"|' /tmp/ct_new.toml
sed -i 's|^\s*sandbox = .*|\1sandbox = "registry.k8s.io/pause:3.10.2"|' /tmp/ct_new.toml
sed -i 's|^\s*config_path = .*|\1config_path = "/etc/containerd/certs.d"|g' /tmp/ct_new.toml
cp -a /etc/containerd/config.toml /etc/containerd/config.toml.bak.$(date +%Y%m%d)   # 高危:覆盖前备份
install -m 0644 /tmp/ct_new.toml /etc/containerd/config.toml        # 内容一致则跳过
systemctl daemon-reload && systemctl enable --now containerd && systemctl restart containerd
printf 'runtime-endpoint: unix:///run/containerd/containerd.sock\nimage-endpoint: unix:///run/containerd/containerd.sock\ntimeout: 10\ndebug: false\n' > /etc/crictl.yaml

5.3 k8s 组件(_stage_k8s_pkgs)

printf '[kubernetes]\nname=Kubernetes\nbaseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.36/rpm/\nenabled=1\ngpgcheck=0\n' > /etc/yum.repos.d/kubernetes.repo
dnf install -y kubelet-1.36.4 kubeadm-1.36.4 kubectl-1.36.4          # 三件套版本必须一致
dnf install -y cri-tools                                             # 提供 crictl,容器运行时排障必备(配合 5.2 生成的 /etc/crictl.yaml)
dnf install -y python3-dnf-plugin-versionlock
dnf versionlock add kubelet kubeadm kubectl                          # 锁定版本,防误升级
systemctl enable kubelet                                             # 仅设自启,不启动(等 init)

5.4 控制面 HA(_stage_ha,仅 master)

dnf install -y keepalived haproxy
# /etc/haproxy/haproxy.cfg:frontend 监听 *:16443,backend 指向三台 master 的 6443
#                           stats 页改为仅监听 127.0.0.1:9000 且启用认证(原脚本曾裸露在 *:9000)
# /etc/keepalived/keepalived.conf:state MASTER/BACKUP、interface ens2、unicast_peer 两两互指、
#                                  auth_pass 使用配置中的自定义口令(禁用默认弱口令)
# /etc/keepalived/check_haproxy.sh:haproxy 进程消失则 stop keepalived,触发 VIP 漂移
systemctl enable --now haproxy keepalived                            # 高危:启停 HA 服务

5.5 镜像预拉取与分发(_stage_prefetch_images)

# 目的:节点直连海外仅 300–450KB/s,改为母机拉一次后分发
kubeadm config images list --kubernetes-version v1.36.4 --image-repository registry.k8s.io   # 解析控制面镜像清单
ctr -n k8s.io images pull quay.io/calico/node:v3.32.2                # Calico 组件镜像逐个拉取
ctr -n k8s.io images pull ghcr.io/headlamp-k8s/headlamp:v0.45.0
ctr -n k8s.io images pull registry.k8s.io/metrics-server/metrics-server:v0.9.0
ctr -n k8s.io images export /root/k8s_deploy_work/images/k8s_images.tar <全部镜像>   # 母机导出
# 本机下载归档后 SFTP 分发到其余 5 台
ctr -n k8s.io images import /root/k8s_deploy_work/images/k8s_images.tar              # 各节点导入

5.6 控制面初始化(_stage_init_cluster,母机 master-01)

# /root/kubeadm-config.yaml(kubeadm.k8s.io/v1beta4)
#   controlPlaneEndpoint: "192.168.31.8:16443"
#   imageRepository: registry.k8s.io
#   podSubnet: 10.244.0.0/16 / serviceSubnet: 10.96.0.0/12
#   etcd.local.dataDir: /var/lib/etcd          # 显式声明,数据落独立盘
#   certificateValidityPeriod: 8760h / caCertificateValidityPeriod: 87600h
#   nodeRegistration.criSocket: unix:///run/containerd/containerd.sock
kubeadm init --config /root/kubeadm-config.yaml --upload-certs        # 高危:初始化控制面
mkdir -p /root/.kube && cp -f /etc/kubernetes/admin.conf /root/.kube/config && chmod 600 /root/.kube/config

5.7 其余节点加入(_stage_join_nodes)

kubeadm token create --print-join-command                            # 母机生成 join 命令
kubeadm init phase upload-certs --upload-certs                       # 取证书 key
# 其余 master(高危:加入控制面)
<join 命令> --control-plane --certificate-key <证书key>
# worker
<join 命令>
# 说明:实现体将 join 命令与证书 key 经 base64 包装执行,避免 token 明文落日志

5.8 Calico(_stage_calico,母机)

kubectl --kubeconfig=/etc/kubernetes/admin.conf apply -f /root/k8s_deploy_work/tigera-operator.yaml
# Operator 安装后 CRD 需要时间进入 API discovery,必须轮询等待,否则下面 apply Installation 会报
# "no matches for kind \"Installation\" in version \"operator.tigera.io/v1\""
kubectl --kubeconfig=/etc/kubernetes/admin.conf get crd installations.operator.tigera.io -o name   # 直到返回结果
# /root/calico-installation.yaml(Installation CR)
#   calicoNetwork.ipPools[0].cidr = 10.244.0.0/16            # 显式指定,规避默认 192.168.0.0/16 与节点网段冲突
#   calicoNetwork.ipPools[0].encapsulation = IPIPCrossSubnet
#   calicoNetwork.nodeAddressAutodetectionV4.interface = ens2 # 显式指定网卡,避免自动探测选错
kubectl --kubeconfig=/etc/kubernetes/admin.conf apply -f /root/calico-installation.yaml

5.9 附加组件(_stage_addons,母机)

# metrics-server:镜像定点替换为已预拉取的版本,并追加 --kubelet-insecure-tls(kubelet 自签证书)
kubectl --kubeconfig=/etc/kubernetes/admin.conf apply -f /root/k8s_deploy_work/metrics-server-patched.yaml
# Headlamp:镜像固定为 ghcr.io/headlamp-k8s/headlamp:v0.45.0(不使用 latest)
kubectl --kubeconfig=/etc/kubernetes/admin.conf apply -f /root/k8s_deploy_work/headlamp-patched.yaml

5.10 控制面缩容 / 扩回(control_plane_scale.py,独立工具)

实现:k8s_136_cluster_deploy/control_plane_scale.py。配置文件不变(始终保留 6 台定义), 缩容与扩回都以同一份配置为依据,因此随时可逆。

# 缩容到单 master:预检 → etcd 快照 → 移除成员 → 关虚拟机并禁自启动 → 清理幽灵节点/孤儿 Pod → 验证
.venv/bin/python control_plane_scale.py --config config/deploy.yaml --shrink

# 扩回 3 master:恢复自启动并开虚拟机 → kubeadm reset → 清空失效 etcd 数据
#                 → 清理 kubeadm-config 过期 clusterStatus → join(kubeadm 自动 member add)→ 验证
.venv/bin/python control_plane_scale.py --config config/deploy.yaml --expand

# 预演(两个方向都支持,只读)
.venv/bin/python control_plane_scale.py --config config/deploy.yaml --expand --dry-run

保留项(回扩零改动):haproxy 的 3 个后端、keepalived 的 3 个 unicast_peer、VIP 192.168.31.8:16443、kubeconfig 的 controlPlaneEndpoint、master-02/03 的虚拟机磁盘。

时效约束(关键):缩容必须在 etcd 仍满足多数派时执行——只剩单个成员时已无法在线移除成员, 只能走灾难恢复(--force-new-cluster)。实现体在前置校验阶段直接拒绝并提示先启动其余 master。

顺序约束(关键):必须先移除 etcd 成员、再关机。反过来会先失去多数派,导致成员移除无法执行。

6. 验证

# 6.1 节点全部 Ready(首次部署完成后为 6 台;缩容后为 4 台,见 5.10)
kubectl --kubeconfig=/etc/kubernetes/admin.conf get nodes -o wide
# 预期:6 行,STATUS 均为 Ready,ROLES 含 control-plane 的为 3 台

# 6.2 控制面 VIP 与 apiserver 就绪
curl -sk https://192.168.31.8:16443/healthz                 # 预期:ok
kubectl --kubeconfig=/etc/kubernetes/admin.conf get --raw='/readyz'   # 预期:ok

# 6.3 etcd 成员与数据目录落盘
kubectl --kubeconfig=/etc/kubernetes/admin.conf -n kube-system get pods -l component=etcd -o wide
for ip in 192.168.31.10 192.168.31.11 192.168.31.12; do
  ssh root@$ip "findmnt -no SOURCE,SIZE,FSTYPE /var/lib/etcd"   # 预期:/dev/vdb 10G xfs
done

# 6.4 系统 Pod 无异常
kubectl --kubeconfig=/etc/kubernetes/admin.conf get pods -A | grep -Ev 'Running|Completed'
# 预期:无输出(Calico 首次就绪可能需数分钟,期间 calico-node 为 Init 属正常)

# 6.5 CNI 状态与地址池
kubectl --kubeconfig=/etc/kubernetes/admin.conf get tigerastatus
kubectl --kubeconfig=/etc/kubernetes/admin.conf get ippools.crd.projectcalico.org -o yaml | grep cidr
# 预期:tigerastatus 含 Available=True;cidr 为 10.244.0.0/16

# 6.6 附加组件
kubectl --kubeconfig=/etc/kubernetes/admin.conf top nodes               # 预期:输出 CPU/内存用量
kubectl --kubeconfig=/etc/kubernetes/admin.conf get deploy -A | grep headlamp
kubectl --kubeconfig=/etc/kubernetes/admin.conf -n kube-system get deploy headlamp -o wide 2>/dev/null

# 6.7 证书有效期(本次已把有效期显式设为 1 年 / CA 10 年)
ssh root@192.168.31.10 "kubeadm certs check-expiration"

# 6.8 幂等复跑(关键验收)
.venv/bin/python main.py --config config/deploy.yaml
# 预期:状态 success / skipped,变更 0、失败 0,日志中大量 [跳过]

7. 回滚

备份位置与用途的完整台账见 k8s_136_cluster_deploy/backup/README.md(含实现体运行时备份目录 backups/ 与原位 .bak 的登记)。每台节点 /root/k8s_backup_<时间戳>/host_config.tgz 含: /etc/selinux/config、/etc/fstab、/etc/hosts、/etc/sysctl.d/k8s.conf、 /etc/modules-load.d/k8s.conf、/etc/containerd、/etc/kubernetes、/etc/keepalived、/etc/haproxy、 /etc/yum.repos.d/kubernetes.repo、/etc/crictl.yaml。

# 7.1 自动回滚(以最近一次备份为准,实现体逐台恢复)
.venv/bin/python main.py --config config/deploy.yaml --rollback

# 7.2 手工回滚单台(等价命令)
ssh root@192.168.31.10 "ls -1d /root/k8s_backup_* | sort | tail -1"      # 确认备份目录
ssh root@192.168.31.10 "tar xzf /root/k8s_backup_<时间戳>/host_config.tgz -C /"   # 高危:覆盖当前配置
ssh root@192.168.31.10 "systemctl daemon-reload && systemctl restart containerd keepalived haproxy"

# 7.3 回滚后验证
ssh root@192.168.31.10 "getenforce; grep ^SELINUX= /etc/selinux/config; systemctl is-active firewalld"

回滚边界(必须明确):

  • 仅恢复宿主机配置层;/var/lib/etcd 中的集群数据不会被回滚
  • 如需彻底清除集群,须人工在母机执行 kubeadm reset -f,并清理 3 台 master 的 /var/lib/etcd(高危:不可逆)
  • 自动回滚触发条件:执行阶段抛异常且配置 auto_rollback: true(默认 false,需人工确认后执行)

回滚失败判据:配置恢复命令返回非 0、或 tar 报错、或恢复后 systemctl is-active 非 active。

8. 风险说明

风险 影响 缓解措施
SELinux 直接禁用降低安全基线 主机失去强制访问控制 已按需求启用;变更前备份 /etc/selinux/config,可随时回滚;后续可评估改用 enforcing + container-selinux
firewalld 停用 主机端口完全暴露于内网 仅测试学习环境采用;生产应改为按端口白名单放行
VIP 与 DHCP 池冲突 keepalived 地址冲突、控制面抖动 执行前人工确认 192.168.31.8 不在 DHCP 池;pre_check 会探测占用(--force 可跳过,不推荐)
镜像拉取慢或失败 部署时长不可控 母机预拉取 + 分发;控制面镜像走 registry.k8s.io,带宽实测 300–450KB/s
Calico 默认池与节点网段重叠 Pod 无法通信 已在 Installation CR 显式指定 10.244.0.0/16,且与 kubeadm podSubnet 强校验一致
Calico 自动探测选错网卡 节点间 Pod 网络不通 已显式指定 nodeAddressAutodetectionV4.interface: ens2
metrics-server 使用 --kubelet-insecure-tls 跳过 kubelet 证书校验 内网环境风险可控;如需收紧可改为注入集群 CA 并移除该参数
10G etcd 盘容量偏紧 数据增长后写满导致 etcd 不可写 保持默认后端配额 2GiB;建议将 etcd_db_size 纳入监控告警
etcd 回退到系统盘 etcd 与系统共享磁盘 IO,fsync 延迟劣化 仅在无独立盘且 etcd_disk_policy=auto 时发生,日志以 [高亮] 明确标注;生产环境应设 require
数据盘存在却未挂载 误以为 etcd 跑在独立盘上 该场景一律报错而非静默回退;若确实要用系统盘,把 etcd_disk_device 置空
重复执行产生意外变更 配置被覆盖 全流程先状态检查、再变更;写文件按 SHA256 比对;二次执行零变更
修改节点 hostname 影响依赖主机名的服务与 SSH 提示符 仅在基线阶段(集群初始化之前)执行,幂等(一致即跳过);变更前自动备份 /etc/hostname 与 /etc/hosts
覆盖 chrony 时间源 可能与节点现有 NTP 架构冲突 baseline.ntp_servers 留空即不覆盖;填写后变更前自动备份 /etc/chrony.conf
当前 SELinux 禁用未重启生效 getenforce 可能仍显示 Permissive 配置已持久化,择机重启后彻底生效;Permissive 状态不影响集群运行

附录 A. 交付物清单

路径(相对项目根 k8s_ins/) 说明
k8s_136_cluster_deploy/main.py 部署入口(--config / --dry-run / --rollback / --force)
k8s_136_cluster_deploy/deployer.py 九阶段部署器
k8s_136_cluster_deploy/control_plane_scale.py 控制面缩容 / 扩回(双向、幂等)
k8s_136_cluster_deploy/config/deploy.yaml.example 配置样例(全量注释)
k8s_136_cluster_deploy/config/deploy.yaml 本环境实际配置(含凭据,不入版本库)
k8s_136_cluster_deploy/utils/ 工程私有工具(哈希幂等写、命令转义、业务异常)
k8s_136_cluster_deploy/docs/SOP.md 本文档(变更实施 / 验证 / 回滚)
k8s_136_cluster_deploy/docs/RUNBOOK.md 日常运行与使用手册(值班用)
k8s_136_cluster_deploy/docs/INCIDENT-20260916-etcd-quorum-lost.md 故障复盘(etcd 失多数派)
k8s_136_cluster_deploy/backup/README.md 备份台账
k8s_136_cluster_deploy/backups/ 实现体运行时备份(etcd 快照、清单)

附录 B. 关键决策记录

决策 取舍
CNI 选 Calico 3.32 + Tigera Operator(而非 Flannel) 保留 NetworkPolicy 能力;代价是多一层 Operator 与 CRD 时序要求
Web UI 用 Headlamp 取代 Dashboard Dashboard 已归档,Headlamp 为其官方继任者
SELinux 直接禁用而非 enforcing + 放行 学习环境简化;已记为风险项,配置可回滚
镜像采取「母机拉取 + ctr 分发」 节点直连海外仅 300–450KB/s,分发避免 6 台重复拉取
缩容为单控制面 单 KVM 宿主机使多 master 无宿主机级 HA 收益;保留一键回扩能力与全部配置
etcd 盘 auto 策略且不自动分区 有独立盘则用、无则回退系统盘;不做 mkfs,避免误判导致数据被抹
未实现 etcd 定时快照 用户未纳入本次范围;--shrink 前会强制快照,手工快照命令见 RUNBOOK 第 6 章
未实现 etcd 盘自动分区格式化 属破坏性操作,需显式授权;当前以「人工准备 + 预检拦截」替代

来源:/home/rain/Documents/k8s_ins/k8s_136_cluster_deploy/docs/SOP.md | 最后更新:2026-09-19 16:17(由 build/sync.py 同步,请勿在站点侧修改)