惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
宝玉的分享
宝玉的分享
博客园 - 【当耐特】
有赞技术团队
有赞技术团队
G
Google Developers Blog
Microsoft Security Blog
Microsoft Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
The Cloudflare Blog
Blog — PlanetScale
Blog — PlanetScale
博客园_首页
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
罗磊的独立博客
T
Tailwind CSS Blog
博客园 - 叶小钗
T
The Blog of Author Tim Ferriss
Engineering at Meta
Engineering at Meta
博客园 - 聂微东
博客园 - Franky
B
Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
F
Fortinet All Blogs

陈少文的网站

巨变与机遇的未来十年 Kubernetes 平台管理软件压力测试方案 使用镜像部署 Hexo 静态页面 终于等到你 - GitHub 镜像仓库服务(ghcr.io) 一起来学 Go --(6)Interface 一起来学 Go --(5)Goroutine 和 Channel 什么是函数式编程 如何在 Kubernetes 集群集成 Kata 柯里化与偏函数 使用 PyGithub 自动创建 Label 软件产品是团队能力的输出 Helm 2 、Helm 3 比较 IoT 变现 Kubernetes 中的 DNS 服务 国内的 Helm 镜像源 Harbor 使用自签证书支持 Https 访问 DevOps 工具链之 Prow 如何使用 kfctl 安装 Kubeflow VS Code 无法下载 Go 插件的工具包 工程师更应具有服务精神 你不知道的 Docker 使用技巧 使用 Docker 运行 Tensorflow 论中国 什么是左移 如何清空 Git 仓库全部历史记录 一禅小和尚 有风吹过厨房 时间的玫瑰 如何在 CentOS 安装 GPU 驱动 开发 Tips(19)
如何修复变更 IP 之后的 Kubernetes 集群
微信公众号 · 2022-10-25 · via 陈少文的网站

Please enable Javascript to view the contents

记录一次因为 IP 变更导致集群故障的修复过程。有两个集群,一个是单节点(allinone),另一个是四节点(3 master 1 node)的集群。

1. 更新 Etcd 证书

  • 【在每个 Etcd 节点】备份 Etcd 证书
1
cp -R /etc/ssl/etcd/ssl /etc/ssl/etcd/ssl-bak
  • 查看 Etcd 证书中的域
1
2
3
openssl x509 -in /etc/ssl/etcd/ssl/node-node1.pem -noout -text|grep DNS

                DNS:etcd, DNS:etcd.kube-system, DNS:etcd.kube-system.svc, DNS:etcd.kube-system.svc.cluster.local, DNS:localhost, DNS:node1, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1, IP Address:x.x.x.1

需要记录下全部的 DNS、IP 值,用于生成新的证书。

  • 【在每个 Etcd 节点】清理旧的 Etcd 证书
1
rm -f /etc/ssl/etcd/ssl/*
  • 【在一个 Etcd 节点】生成 Etcd 证书配置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
vim /etc/ssl/etcd/ssl/openssl.conf

[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name

[req_distinguished_name]

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

[ ssl_client ]
extendedKeyUsage = clientAuth, serverAuth
basicConstraints = CA:FALSE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
subjectAltName = @alt_names

[ v3_ca ]
basicConstraints = CA:TRUE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
authorityKeyIdentifier=keyid:always,issuer

[alt_names]
DNS.1 = localhost
DNS.2 = etcd.kube-system.svc.cluster.local
DNS.3 = etcd.kube-system.svc
DNS.4 = etcd.kube-system
DNS.5 = etcd
DNS.6 = xxx
IP.1 = 127.0.0.1
IP.2 = x.x.x.x

需要包含所有部署 Etcd 节点的主机名和 IP 地址。

  • 【在一个 Etcd 节点】生成 Etcd 的 CA 证书
1
2
3
cd /etc/ssl/etcd/ssl
openssl genrsa -out ca-key.pem 2048
openssl req -x509 -new -nodes -key ca-key.pem -days 3650 -out ca.pem -subj "/CN=etcd-ca"
  • 【在一个 Etcd 节点】给每个节点生成 Etcd 的 Admin 证书

通过 export host=node1 设置不同环境变量,给每一个节点生成证书。这里的 node1 是主机名,保持与之前一致,避免因改名找不到证书。

1
2
3
openssl genrsa -out admin-${host}-key.pem 2048
openssl req -new -key admin-${host}-key.pem -out admin-${host}.csr -subj "/CN=etcd-admin-${host}"
openssl x509 -req -in admin-${host}.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out admin-${host}.pem -days 3650 -extensions ssl_client  -extfile openssl.conf
  • 【在一个 Etcd 节点】给每个节点生成 Etcd 的 Member 证书

通过 export host=node1 切换节点,给每一个节点生成证书。

1
2
3
openssl genrsa -out member-${host}-key.pem 2048
openssl req -new -key member-${host}-key.pem -out member-${host}.csr -subj "/CN=etcd-member-${host}" -config openssl.conf
openssl x509 -req -in member-${host}.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out member-${host}.pem -days 3650 -extensions ssl_client -extfile openssl.conf
  • 【在一个 Etcd 节点】给每个节点生成 Etcd 的 Node 证书

通过 export host=node1 切换节点,给每一个节点生成证书。

1
2
3
openssl genrsa -out node-${host}-key.pem 2048
openssl req -new -key node-${host}-key.pem -out node-${host}.csr -subj "/CN=etcd-node-${host}"
openssl x509 -req -in node-${host}.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out node-${host}.pem -days 3650 -extensions ssl_client  -extfile openssl.conf
  • 【在一个 Etcd 节点】分发生成的证书

需要将 /etc/ssl/etcd/ssl/ 下的证书,分发到各个 Etcd 节点上。

  • 【在一个 Etcd 节点】查看 etcd 配置

这里 Etcd 是以二进制启动的,在 systemd 中可以找到 etcd 配置文件的存放位置。

1
2
3
4
cat /etc/systemd/system/etcd.service

...
EnvironmentFile=/etc/etcd.env
  • 【每个 Etcd 节点】替换 IP

由于有多个 Etcd 节点,因此需要替换多组 IP,这里以三节点为例。

1
2
3
4
5
6
7
8
export oldip1=x.x.x.1
export newip1=x.x.10.1

export oldip2=x.x.x.2
export newip2=x.x.10.2

export oldip3=x.x.x.3
export newip3=x.x.10.3
1
2
3
sed -i "s/$oldip1/$newip1/" /etc/etcd.env
sed -i "s/$oldip2/$newip2/" /etc/etcd.env
sed -i "s/$oldip3/$newip3/" /etc/etcd.env

/etc/hosts 也需要替换 IP,因为有时配置文件中使用的是主机名。

1
2
3
sed -i "s/$oldip1/$newip1/" /etc/hosts
sed -i "s/$oldip2/$newip2/" /etc/hosts
sed -i "s/$oldip3/$newip3/" /etc/hosts

如果有定时备份任务,也需要替换下相关 IP。

1
2
3
sed -i "s/$oldip1/$newip1/" /usr/local/bin/kube-scripts/etcd-backup.sh
sed -i "s/$oldip2/$newip2/" /usr/local/bin/kube-scripts/etcd-backup.sh
sed -i "s/$oldip3/$newip3/" /usr/local/bin/kube-scripts/etcd-backup.sh
  • 【每个 Etcd 节点】从备份中恢复 Etcd 数据

如果是单节点的 Etcd 可以跳过此步骤。由于节点 IP 发生变化,Etcd 集群已经无法运行。多节点 Etcd 需要使用备份数据才能够恢复,这是因为 Etcd 的节点信息被存在磁盘数据中,仅修改配置文件并没有用。

将 Etcd 备份文件 snapshot.db 分发到每个 Etcd 节点上。

在每个节点上执行如下命令:

1
2
3
4
5
etcdctl snapshot restore snapshot.db --name etcd-node1 \
        --initial-cluster "etcd-node1=https://x.x.10.1:2380,etcd-node2=https://x.x.10.2:2380,etcd-node3=https://x.x.10.3:2380" \
        --initial-cluster-token k8s_etcd \
        --initial-advertise-peer-urls https://x.x.10.1:2380 \
        --data-dir=/var/lib/etcd

需要注意,每个节点上的 etcd-node1 名字, --initial-advertise-peer-urls 参数会有差异。

  • 【每个 Etcd 节点】重启 etcd
  • 【每个 Etcd 节点】查看 etcd 状态

2. 更新 K8s 证书

  • 备份证书
1
cp -R /etc/kubernetes/ /etc/kubernetes-bak
  • 【每个 Kubernetes 节点】替换相关文件中的 IP 地址
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# master 节点
export oldip1=x.x.x.1
export newip1=x.x.10.1

export oldip2=x.x.x.2
export newip2=x.x.10.2

export oldip3=x.x.x.3
export newip3=x.x.10.3

# node 节点
export oldip4=x.x.x.4
export newip4=x.x.10.4
1
2
3
4
find /etc/kubernetes -type f | xargs sed -i "s/$oldip1/$newip1/"
find /etc/kubernetes -type f | xargs sed -i "s/$oldip2/$newip2/"
find /etc/kubernetes -type f | xargs sed -i "s/$oldip3/$newip3/"
find /etc/kubernetes -type f | xargs sed -i "s/$oldip4/$newip4/"
1
2
3
4
sed -i "s/$oldip1/$newip1/" /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
sed -i "s/$oldip2/$newip2/" /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
sed -i "s/$oldip3/$newip3/" /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
sed -i "s/$oldip4/$newip4/" /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
1
2
3
4
sed -i "s/$oldip1/$newip1/" /etc/kubernetes/kubeadm-config.yaml
sed -i "s/$oldip2/$newip2/" /etc/kubernetes/kubeadm-config.yaml
sed -i "s/$oldip3/$newip3/" /etc/kubernetes/kubeadm-config.yaml
sed -i "s/$oldip4/$newip4/" /etc/kubernetes/kubeadm-config.yaml
1
2
3
4
sed -i "s/$oldip1/$newip1/" /etc/hosts
sed -i "s/$oldip2/$newip2/" /etc/hosts
sed -i "s/$oldip3/$newip3/" /etc/hosts
sed -i "s/$oldip4/$newip4/" /etc/hosts
  • 【在一个 master 节点】生成证书
1
rm -f /etc/kubernetes/pki/apiserver*
1
kubeadm init phase certs all --config /etc/kubernetes/kubeadm-config.yaml
  • 【每个 Kubernetes 节点】将生成的证书分发到节点上

node 节点不需要 key,只需要 crt。

3. 更新集群组件的 Conf 文件

  • 【在一个 master 节点】生成新的配置文件
1
2
cd /etc/kubernetes
rm -f admin.conf kubelet.conf controller-manager.conf scheduler.conf
1
kubeadm init phase kubeconfig all --config /etc/kubernetes/kubeadm-config.yaml
  • 【每个 Kubernetes 节点】将新的配置文件分发到每个节点

每个节点都需要 /etc/kubernetes/kubelet.conf,每个 master 节点都需要 /etc/kubernetes/controller-manager.conf/etc/kubernetes/scheduler.conf

  • 【在需要使用 kubectl 的节点】 配置用户访问凭证
1
2

cp /etc/kubernetes/admin.conf $HOME/.kube/config
  • 【每个 Kubernetes 节点】重启 kubelet
1
2
systemctl daemon-reload
systemctl restart kubelet
  • 【每个 Kubernetes 节点】查看 kubelet 状态
1
systemctl status kubelet

4. 修复 ConfigMap

  • 替换 IP
1
kubectl -n kube-system edit cm kube-proxy

kube-proxy 会影响节点通信。如果使用的 LB 或者域名作为 Apiserver 入口,也可以不进行替换。至于 kubeadm-config ,在上面步骤中已经自动替换,因此也不需要额外处理。

5. 总结

强烈建议,不要修改集群主机的 IP 地址。如果是预期内的主机 IP 变更,可以通过备份-恢复的方式重建集群。

如果是非预期的主机 IP 变更,建议按照上述顺序进行修复:

  1. Etcd
  2. K8s 证书
  3. K8s Master 节点、Node 节点核心组件
  4. 集群 ConfigMap 配置

上述内容虽然记录了修复过程。但多 master 节点修复时,现场很复杂。容器在不断重启,期间还一直报错端口冲突,为此我还重启了一次机器。修复过程记录可能有不完善的地方,但是只需要按照顺序,一个组件一个组件修复应该问题不大。


微信公众号