一、环境前置说明

📁 系统路径定义

项目

路径

etcd 数据目录

/data/k3s/server/db/etcd

etcd 证书目录

/data/k3s/server/tls/etcd

etcd snapshot 目录

/data/k3s/server/db/snapshots

⚠️ 本文档适用于 K3s 内嵌 etcd 模式(非外部 etcd)


二、单节点 K3s IP 变更与恢复

📘 适用场景

  • 仅 1 个 K3s 节点(embedded etcd 模式)

  • 节点 IP 发生变化(迁移至新网段)

  • 希望保留原有数据重新初始化


✅ 方案 1:保留数据(推荐优先)

操作步骤

1️⃣ 设置 etcdctl 环境变量

export ETCDCTL_API=3
export ETCDCTL_ENDPOINTS="https://127.0.0.1:2379"
export ETCDCTL_CACERT="/data/k3s/server/tls/etcd/server-ca.crt"
export ETCDCTL_CERT="/data/k3s/server/tls/etcd/server-client.crt"
export ETCDCTL_KEY="/data/k3s/server/tls/etcd/server-client.key"

2️⃣ 查看 etcd 成员信息

etcdctl member list

示例输出:

30293a1fdd9f5501, started, it-tools-e0975476, https://172.0.0.100:2380, https://172.0.0.100:2379, false

3️⃣ 更新成员 peer 地址

etcdctl member update 30293a1fdd9f5501 --peer-urls=https://10.0.0.100:2380

⚠️ etcdctl 只能修改 peer-urls,不能修改 client-urls client-urls 由 K3s 启动时生成


🧩 4️⃣ 更新 K3s 配置(两种方式任选其一)

✅ 方式 A:推荐使用配置文件 /etc/rancher/k3s/config.yaml

编辑(或新建):

node-ip: 10.0.0.100
advertise-address: 10.0.0.100
node-name: it-tools-e0975476
tls-san:
  - 127.0.0.1
  - 10.0.0.100

说明:

  • YAML 方式更清晰、易维护;

  • 建议配合 ExecStart=/usr/local/bin/k3s server --config /etc/rancher/k3s/config.yaml 使用;

  • 修改后执行:

    systemctl daemon-reload
    systemctl restart k3s

⚙️ 方式 B:使用 systemd 启动参数(等价方案)

/etc/systemd/system/k3s.serviceExecStart 末尾追加以下参数:

'--node-ip' \
'10.0.0.100' \
'--advertise-address' \
'10.0.0.100' \
'--tls-san' \
'10.0.0.100' \
'--tls-san' \
'127.0.0.1' \

说明:

  • 与 YAML 方式效果完全相同;

  • 不过参数较多,维护复杂;

  • 后续若 IP 变动或节点迁移,建议改用 YAML 模式。


5️⃣ 轮换证书(确保包含新 IP/SAN)

k3s certificate rotate

6️⃣ 执行 cluster-reset(同步 etcd 元数据)

systemctl stop k3s
k3s server --cluster-reset
systemctl start k3s

7️⃣ 验证

kubectl get node
kubectl get pods -A
ss -ltnp | grep -E ':2379|:2380'

应显示:

127.0.0.1:2379
10.0.0.100:2379
10.0.0.100:2380

🔄 方案 2:删除数据重新初始化(不保留数据)

适用

  • 节点数据损坏 / 不需要保留现有集群数据。

操作步骤

systemctl stop k3s
rm -rf /data/k3s/server/db
systemctl start k3s

验证

kubectl get node

三、多节点 K3s etcd 集群 IP 变更恢复

📊 情况分析

  • 三个节点的 etcd IP 全部改变;

  • 无法通过 etcdctl member update 单独修复;

  • 具备 etcd snapshot 或希望全新初始化。


✅ 方案 1:基于 snapshot 的恢复(推荐)

主节点操作

systemctl stop k3s
rm -rf /data/k3s/server/db
k3s server --cluster-reset --cluster-reset-restore-path=/data/k3s/server/db/snapshots/etcd-snapshot-xxxx
systemctl start k3s

snapshot 文件名示例:etcd-snapshot-1750983000

验证:

etcdctl endpoint health
kubectl get node

其余节点重新加入:

systemctl stop k3s
rm -rf /data/k3s/server/db /etc/rancher/k3s
cat /var/lib/rancher/k3s/server/node-token
curl -sfL https://get.k3s.io | K3S_URL=https://<主节点IP>:6443 K3S_TOKEN=<token> sh -

🔁 方案 2:重新创建全新集群

systemctl stop k3s
rm -rf /data/k3s/server/db /etc/rancher/k3s
curl -sfL https://get.k3s.io | sh -

其余节点加入:

curl -sfL https://get.k3s.io | K3S_URL=https://<主节点IP>:6443 K3S_TOKEN=<token> sh -

四、旧节点清理(IP 或节点名变更后)

当节点 IP 或 hostname 改变后,旧节点仍会留在 etcd 与 Kubernetes 中。

操作步骤

1️⃣ 列出 etcd 成员

etcdctl member list

2️⃣ 删除旧成员 找到旧 IP(例如 172.0.0.100)对应的 member ID:

etcdctl member remove <memberID>

3️⃣ 删除 Kubernetes 中的旧节点对象

kubectl delete node <旧节点名称>

4️⃣ 验证

etcdctl member list
kubectl get node -owide

✅ 只应剩下当前活跃节点。


五、后续运维建议

1️⃣ 启用 etcd snapshot 定时备份

k3s server --etcd-snapshot-schedule-cron="0 0 * * *"

2️⃣ 验证备份状态

ls /data/k3s/server/db/snapshots

3️⃣ 备份重要配置 建议定期备份:

  • /etc/rancher/k3s/config.yaml

  • /data/k3s/server/tls/etcd/

  • /data/k3s/server/db/snapshots/


🧩 六、常见问题 FAQ

问题

原因

解决方式

K3s 日志提示 “not a member of the etcd cluster”

etcd 元数据与当前 IP 不一致

执行 k3s server --cluster-reset

日志中出现 “authentication handshake failed”

etcd 证书缺少新 IP SAN

执行 k3s certificate rotate

etcdctl 无法修改 client-urls

client-urls 由 K3s 启动参数控制

编辑配置并重启

etcd 无法启动但有 snapshot

使用 --cluster-reset-restore-path 恢复

单节点数据损坏

删除 /server/db 目录重新初始化

旧节点仍在集群中

etcd 残留成员或 Node 对象未删除

etcdctl member remove + kubectl delete node


✅ 七、简化决策表

场景

操作

单节点 IP 变化且要保留数据

member update → 修改配置 → cluster-reset

单节点 IP 变化且不保留数据

删除 /server/db 目录重启

多节点所有 IP 改变

snapshot 恢复 + 节点重加

握手失败 / TLS 报错

k3s certificate rotate

数据目录损坏

删除后重启或 snapshot 恢复

旧节点残留

etcdctl member remove + kubectl delete node