二进制 k8s 集群下线 master 组件流程分析和实践
事出因果
自己虚拟跑了一个
3 master + 2 node
的k8s 集群
,因为当初验证部署脚本,验证完成后,就开始部署一些服务来验证环境可用性,目前的环境情况,其实也不需要 3 master 这样的架构,有点浪费电脑的资源,于是有了这样的一个想法虽说虚拟机,不影响,只需要铲了重装就好,但是这样的习惯也并非好事情
咱要做一个优雅的人,要让他优雅的离场,毕竟也是功臣,怎能直接踹了她 [ k8s 这么可爱,一 jio 上去会哭很久的吧 ]
环境介绍
先介绍一下我的集群架构和情况
部署方式
-二进制
etcd 节点数量
-3个
k8s master 组件节点数量
-3个
k8s apiserver 是否开启高可用
-使用 nginx 做反向代理,并使用 upstream 负载均衡到三个 apiserver 节点
使用 127.0.0.1 来访问本机 nginx 反向代理,因此所有 node 节点均有 nginx
个人思路
- 我的架构没有涉及到
keepalived
一类的高可用,也没有云主机的SLB
做高可用,我这里需要先把nginx
的upstream
模块内需要下线的节点先置为down
- 我这边也不考虑替换证书的
apiserver
访问地址,还是延续我之前的127.0.0.1:8443
- 如果有更换
apiserver
访问地址的需求,需要用之前的ca
根证书,重新生成相关的kubeconfig
文件,并做替换
- 如果有更换
- 我这边也不考虑替换证书的
- 修改
apiserver
访问的etcd
地址,以及相关的etcd
证书文件 - 下线需要下线的
etcd
节点- 通过
etcdctl member remove
的方式,先将需要下线的etcd
节点踢出集群
- 通过
etcd
重启无异常后,重启apiserver
节点
准备实践
当前 master 节点信息
节点 ip | 节点角色 | 是否下线 |
---|---|---|
172.72.0.95 | master 节点 | 不下线 |
172.72.0.96 | master 节点 | 下线 etcd 和 master 组件 |
172.72.0.97 | master 节点 | 下线 etcd 和 master 组件 |
切换 apiserver 访问流量
如上面所说,我这边需要把所有节点的
nginx
的配置做一个修改,将需要下线的节点置为down
大家要按照自己实际的场景做处理,这里无法一一道来,整体思路就是将需要下线的节点踢出高可用的场景
- 以下的操作,仅代表个人环境,大家了解一个思路就好了,具体的实操,还是要以自己的实际环境为准
查看 nginx 配置文件
先看看 nginx 配置文件在哪
systemctl cat kube-nginx
# /etc/systemd/system/kube-nginx.service
[Unit]
Description=kube-apiserver nginx proxy
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
ExecStartPre=/approot/data/k8s/bin/nginx \
-c /approot/data/k8s/kube-nginx/kube-nginx.conf \
-p /approot/data/k8s/kube-nginx -t
ExecStart=/approot/data/k8s/bin/nginx \
-c /approot/data/k8s/kube-nginx/kube-nginx.conf \
-p /approot/data/k8s/kube-nginx
ExecReload=/approot/data/k8s/bin/nginx \
-c /approot/data/k8s/kube-nginx/kube-nginx.conf \
-p /approot/data/k8s/kube-nginx -s reload
PrivateTmp=true
Restart=always
RestartSec=5
StartLimitInterval=0
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
修改 nginx 配置文件
worker_processes 1;
events {
worker_connections 1024;
}
stream {
upstream apiserver {
hash $remote_addr consistent;
server 172.72.0.95:6443 max_fails=3 fail_timeout=30s;
server 172.72.0.96:6443 max_fails=3 fail_timeout=30s down;
server 172.72.0.97:6443 max_fails=3 fail_timeout=30s down;
}
server {
listen *:8443;
proxy_connect_timeout 1s;
proxy_pass apiserver;
}
}
验证配置文件,这里是为了美观,毕竟路径太长了
nginx_home='/approot/data/k8s/kube-nginx'
使用
-p
参数修改prefix
路径,nginx
编译完,默认的prefix
路径是编译的时候指定的路径,在这里使用会报错
nginx -p ${nginx_home} \
-c ${nginx_home}/kube-nginx.conf -t
返回如下结果,说明配置文件格式没有问题
nginx: the configuration file /approot/data/k8s/kube-nginx/kube-nginx.conf syntax is ok
nginx: configuration file /approot/data/k8s/kube-nginx/kube-nginx.conf test is successful
重载
nginx
,因为的systemctl
配置了reload
参数,如果没有配置,使用nginx -s reload
也可以实现
reload
相比restart
要优雅很多
systemctl reload kube-nginx
所有的节点,都按照上面的方式修改
nginx
的配置文件,实现apiserver
流量的切换
停止下线节点的 apiserver 服务
既然已经把
apiserver
的访问转移到指定的节点了,那正常情况下,咱们停止了下线节点的apiserver
服务,不会对集群造成影响(顺便把开机自启也关了)
systemctl disable kube-apiserver --now
此时,我们可以去不下线的节点执行
kubectl get node
验证是否正常能获取的到节点信息,没有问题就可以继续停止下一个下线节点的apiserver
服务
将 master 节点的 pod 驱逐到其他节点
生成新的证书
如果新的
csr json
文件找不到了,那就只能通过openssl
校验证书,获取对应的信息,重新生成证书
csr json
文件模板
{
"CN": "",
"hosts": [
"127.0.0.1",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "",
"size":
},
"names": [
{
"C": "",
"ST": "",
"L": "",
"O": "",
"OU": ""
}
]
}
从原有的
pem
文件获取csr json
文件的内容 [这里就举个例子,pem 文件名称以自己实际的为准]
openssl x509 -noout -text -in kubernetes.pem | egrep -i 'issuer|dns|public'
CN
、C
、ST
、L
、O
、OU
、CN
都在Issuer
字段可以获取的到hosts
在DNS
字段可以获取的到key
在Public Key Algorithm
和Public-Key
里面可以获取得到,这里对应的algo
是rsa
,size
是2048
Issuer: C=CN, ST=ShangHai, L=ShangHai, O=k8s, OU=System, CN=kubernetes
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster, DNS:kubernetes.default.svc.cluster.local, IP Address:172.72.0.95, IP Address:172.72.0.96, IP Address:172.72.0.97, IP Address:127.0.0.1, IP Address:10.254.0.1
生成 etcd 新证书
配置 csr-json 文件,去除需要下线节点的 ip
{
"CN": "etcd",
"hosts": [
"172.72.0.95",
"127.0.0.1"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "ShangHai",
"L": "ShangHai",
"O": "k8s",
"OU": "System"
}
]
}
生成新的 pem 文件
cfssl gencert -ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes etcd-csr.json | cfssljson -bare etcd
备份老的
etcd
证书,注意,这里的路径也要以自己的实际路径为准
mv /etc/kubernetes/ssl/etcd.pem{,-bak-$(date +%FT%T%z)}
mv /etc/kubernetes/ssl/etcd-key.pem{,-bak-$(date +%FT%T%z)}
复制新的
etcd
证书到etcd
证书路径,这里先不着急重启服务,因为还没将要下线的节点踢出集群
生成 apiserver 新证书
配置 csr-json 文件,去除需要下线节点的 ip
{
"CN": "kubernetes",
"hosts": [
"172.72.0.95",
"127.0.0.1",
"10.254.0.1",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "ShangHai",
"L": "ShangHai",
"O": "k8s",
"OU": "System"
}
]
}
生成新的 pem 文件
cfssl gencert -ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
备份老的
apiserver
证书,注意,这里的路径也要以自己的实际路径为准
mv /etc/kubernetes/ssl/kubernetes.pem{,-bak-$(date +%FT%T%z)}
mv /etc/kubernetes/ssl/kubernetes-key.pem{,-bak-$(date +%FT%T%z)}
复制新的
apiserver
证书到apiserver
证书路径,这里先不着急重启服务,因为还没修改etcd
集群的访问地址
修改 apiserver 配置文件
我的二进制部署,是将
apiserver
启动参数写进systemctl
管理的service
文件内的,没有单独的去引用,这里需要备份一下service
文件
cp /etc/systemd/system/kube-apiserver.service{,-bak-$(date +%FT%T%z)}
修改
etcd
的地址,只保留需要的节点,同样先不重启apiserver
服务
--etcd-servers=https://172.72.0.95:2379
下线 etcd 节点
查找当前 leader 节点
找
leader
节点是因为leader
节点的数据是最新的,操作之前,需要先快照一下etcd
的数据,出了问题还能恢复回去
这里也是用的新生成的
etcd
证书来查询的
etcdctl -w table \
--cert /etc/kubernetes/ssl/etcd.pem \
--key /etc/kubernetes/ssl/etcd-key.pem \
--cacert /etc/kubernetes/ssl/ca.pem \
--endpoints https://172.72.0.95:2379 \
endpoint status --cluster
这里可以看到,
172.72.0.96
节点是leader
+--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| https://172.72.0.95:2379 | 26c65c850c80d42d | 3.4.12 | 4.5 MB | false | false | 263 | 642041 | 642041 | |
| https://172.72.0.96:2379 | 2ae7ff74540f0760 | 3.4.12 | 4.5 MB | true | false | 263 | 642041 | 642041 | |
| https://172.72.0.97:2379 | 4785dde924d48108 | 3.4.12 | 4.6 MB | false | false | 263 | 642041 | 642041 | |
+--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
etcd 数据快照
这里的
--endpoints
使用172.72.0.96
etcdctl -w table \
--cert /etc/kubernetes/ssl/etcd.pem \
--key /etc/kubernetes/ssl/etcd-key.pem \
--cacert /etc/kubernetes/ssl/ca.pem \
--endpoints https://172.72.0.96:2379 \
snapshot save 172.72.0.95-etcd-snapshot.db
etcd 节点下线
查看节点信息
etcdctl -w table \
--cert /etc/kubernetes/ssl/etcd.pem \
--key /etc/kubernetes/ssl/etcd-key.pem \
--cacert /etc/kubernetes/ssl/ca.pem \
--endpoints https://172.72.0.95:2379 \
member list
返回的结果如下,后面开始下线对应的节点
+------------------+---------+-------------+--------------------------+--------------------------+------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER |
+------------------+---------+-------------+--------------------------+--------------------------+------------+
| 26c65c850c80d42d | started | 172.72.0.95 | https://172.72.0.95:2380 | https://172.72.0.95:2379 | false |
| 2ae7ff74540f0760 | started | 172.72.0.96 | https://172.72.0.96:2380 | https://172.72.0.96:2379 | false |
| 4785dde924d48108 | started | 172.72.0.97 | https://172.72.0.97:2380 | https://172.72.0.97:2379 | false |
+------------------+---------+-------------+--------------------------+--------------------------+------------+
下线
172.72.0.97
节点,预期会返回类似如下的输出Member 4785dde924d48108 removed from cluster 5957c47fd14d3795
etcdctl \
--cert /etc/kubernetes/ssl/etcd.pem \
--key /etc/kubernetes/ssl/etcd-key.pem \
--cacert /etc/kubernetes/ssl/ca.pem \
--endpoints https://172.72.0.95:2379 \
member remove 4785dde924d48108
下线
172.72.0.96
节点,预期会返回类似如下的输出Member 2ae7ff74540f0760 removed from cluster 5957c47fd14d3795
etcdctl \
--cert /etc/kubernetes/ssl/etcd.pem \
--key /etc/kubernetes/ssl/etcd-key.pem \
--cacert /etc/kubernetes/ssl/ca.pem \
--endpoints https://172.72.0.95:2379 \
member remove 2ae7ff74540f0760
再次查看
etcd
节点信息,就只剩下当前需要保留的节点了
+------------------+---------+-------------+--------------------------+--------------------------+------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER |
+------------------+---------+-------------+--------------------------+--------------------------+------------+
| 26c65c850c80d42d | started | 172.72.0.95 | https://172.72.0.95:2380 | https://172.72.0.95:2379 | false |
+------------------+---------+-------------+--------------------------+--------------------------+------------+
停止下线节点 etcd 服务
systemctl disable kube-etcd --now
修改保留节点的 etcd 配置文件
这里只保留当前节点的信息
--initial-cluster=172.72.0.95=https://172.72.0.95:2380
重载一下 service 文件
systemctl daemon-reload
重启 etcd 服务
这里我们重启一下当前保留的
etcd
节点,确保etcd
能正常工作
systemctl restart kube-etcd
查看集群健康状态
etcdctl -w table \
--cert /etc/kubernetes/ssl/etcd.pem \
--key /etc/kubernetes/ssl/etcd-key.pem \
--cacert /etc/kubernetes/ssl/ca.pem \
--endpoints https://172.72.0.95:2379 \
endpoint health
返回类似如下的信息,说明
etcd
服务是正常的
+--------------------------+--------+------------+-------+
| ENDPOINT | HEALTH | TOOK | ERROR |
+--------------------------+--------+------------+-------+
| https://172.72.0.95:2379 | true | 5.818866ms | |
+--------------------------+--------+------------+-------+
重启 apiserver 节点
systemctl restart kube-apiserver
验证节点是否正常
查看 k8s 节点信息是否正常加载
kubectl get node
删一个带有副本控制集的 pod,验证是否会重启 pod
kubectl delete pod -n monitor node-exporter-jlxxl
关闭下线节点其他 k8s master 组件
要记得把开机自启也关闭了
systemctl disable kube-controller-manager kube-scheduler --now
到此,关于 master 节点缩容的实践就结束了