有心人可能会发现前面的高可用方案部署完成后的节点截图:
Master节点和Node节点的版本不一致,这也牵引出本文的目的,如何简单管理维护一套集群环境,首先当然包括:集群的升级和集群节点的伸缩。
集群版本升级
官方文档地址,不同版本间升级可能会存在差异,本文针对1.19.x升级至1.20.x版本。
升级流程
升级工作的基本流程如下:
- 升级主控制平面节点
- 升级其他控制平面节点
- 升级工作节点
注意事项
下面是官方对于集群升级的须知:
- 务必仔细认真阅读发行说明。
- 集群应使用静态的控制平面和 etcd Pod 或者外部 etcd。
- 务必备份所有重要组件,例如存储在数据库中应用层面的状态。
kubeadm upgrade
不会影响你的工作负载,只会涉及 Kubernetes 内部的组件,但备份终究是好的。- 必须禁用交换分区
附加信息
- 在对 kubelet 作次版本升级时需要腾空节点。 对于控制面节点,其上可能运行着 CoreDNS Pods 或者其它非常重要的负载。
- 升级后,因为容器规约的哈希值已更改,所有容器都会被重新启动。
Master节点升级
按照升级流程,首先对主控Master节点升级,然后再对其他Master节点进行升级
kubeadm升级
主控Master节点
# 用最新的补丁版本号替换 1.20.x-0 中的 x yum install -y kubeadm-1.20.4-0 --disableexcludes=kubernetes # 验证下载操作正常,并且 kubeadm 版本正确: kubeadm version # 验证升级计划: kubeadm upgrade plan # 选择要升级到的目标版本,运行合适的命令。例如: # 将 x 替换为你为此次升级所选择的补丁版本号 sudo kubeadm upgrade apply v1.20.4
其他Master节点
sudo kubeadm upgrade node
kubelet 和 kubectl升级
此处需要根据官方说明先做腾空节点操作。
腾空节点
通过将节点标记为不可调度并腾空节点为节点作升级准备:
# 将 <node-to-drain> 替换为你要腾空的控制面节点名称,kubectl get nods中的名称 kubectl drain <node-to-drain> --ignore-daemonsets
kubectl drain
命令可以用来标记某个节点即将停止服务。 运行 kubectl drain
命令时,工具会尝试驱逐机器上的所有 Pod。 kubectl
所提交的驱逐请求可能会暂时被拒绝,所以该工具会定时重试失败的请求, 直到所有的 Pod 都被终止,或者达到配置的超时时间。
升级 kubelet 和 kubectl
yum install -y kubelet-1.20.4-0 kubectl-1.20.4-0 --disableexcludes=kubernetes sudo systemctl daemon-reload sudo systemctl restart kubelet
解除节点的保护
通过将节点标记为可调度,让其重新上线:
# 将 <node-to-drain> 替换为你的节点名称 kubectl uncordon <node-to-drain>
升级node节点
kubeadm升级
# 用最新的补丁版本替换 1.20.x-00 中的 x
yum install -y kubeadm-1.20.x-0 --disableexcludes=kubernetes
执行 "kubeadm upgrade"
对于工作节点,下面的命令会升级本地的 kubelet 配置:
sudo kubeadm upgrade node
kubelet 和 kubectl升级
腾空节点
将节点标记为不可调度并驱逐所有负载,准备节点的维护:
# 将 <node-to-drain> 替换为你正在腾空的节点的名称 kubectl drain <node-to-drain> --ignore-daemonsets
升级 kubelet 和 kubectl
# 将 1.20.x-0 x 替换为最新的补丁版本 yum install -y kubelet-1.20.x-0 kubectl-1.20.x-0 --disableexcludes=kubernetes
重启 kubelet
sudo systemctl daemon-reload sudo systemctl restart kubelet
取消对节点的保护
通过将节点标记为可调度,让节点重新上线:
# 将 <node-to-drain> 替换为当前节点的名称 kubectl uncordon <node-to-drain>
验证集群
kubectl get nodes
可以看见当前所有节点都为1.20.4版本。
升级工作原理
这里引用官方的介绍:
kubeadm upgrade apply
做了以下工作:
检查你的集群是否处于可升级状态:
- API 服务器是可访问的
- 所有节点处于
Ready
状态- 控制面是健康的
- 强制执行版本偏差策略。
- 确保控制面的镜像是可用的或可拉取到服务器上。
- 如果组件配置要求版本升级,则生成替代配置与/或使用用户提供的覆盖版本配置。
- 升级控制面组件或回滚(如果其中任何一个组件无法启动)。
- 应用新的
kube-dns
和kube-proxy
清单,并强制创建所有必需的 RBAC 规则。- 如果旧文件在 180 天后过期,将创建 API 服务器的新证书和密钥文件并备份旧文件。
kubeadm upgrade node
在其他控制平节点上执行以下操作:
- 从集群中获取 kubeadm
ClusterConfiguration
。- (可选操作)备份 kube-apiserver 证书。
- 升级控制平面组件的静态 Pod 清单。
- 为本节点升级 kubelet 配置
kubeadm upgrade node
在工作节点上完成以下工作:
- 从集群取回 kubeadm
ClusterConfiguration
。- 为本节点升级 kubelet 配置。
集群添加和删除节点
移除
从集群中移除节点时,Master和Node节点方式一致。
## 清空
kubectl drain <node-to-drain> --delete-local-data --force --ignore-daemonsets
kubeadm reset
kubectl delete node <node name>
- 首先驱逐节点
- 重置kubeadm
- 删除节点
新增Node节点
在 kubeadm 初始化集群成功后会返回 join 命令, 里面有 token,discovery-token-ca-cert-hash等参数, 但他们是有过期时间的. token 的过期时间是24小时, certificate-key 过期时间是2小时。通过以下命令可以查看token列表
kubeadm token list
当token失效后,新增新的Node节点时,需要重新创建新的token:
# 创建新的token
kubeadm token create --print-join-command
# 使用join命令加入集群,kubernetes-vip是vip地址,若只有一个master节点,此处换成master的地址
kubeadm join kubernetes-vip:9443 --token bayqt8.eaafmfthasquy4yn --discovery-token-ca-cert-hash sha256:250115fad0a4b6852a919dbba4222ac65bc64843c660363ab119606ff8819d0a
新增Master节点
新增Master节点额外需要certificate-key参数,使用以下命令生成:
# 生成certificate-key
kubeadm init phase upload-certs --upload-certs
# 使用Node节点的join命令并且拼上--control-plane --certificate-key参数
kubeadm join kubernetes-vip:9443 --token bayqt8.eaafmfthasquy4yn --discovery-token-ca-cert-hash sha256:250115fad0a4b6852a919dbba4222ac65bc64843c660363ab119606ff8819d0a --control-plane --certificate-key bfd5bc7ff4aa54e1cba9a5979210c06ae087ae6fb9979af8f851554638889d7b
证书失效管理
Kubernetes集群的证书有效期默认为1年,过期后集群将不能正常访问,但是证书会随着版本升级的过程自动续期,所以官方建议经常做版本升级,否则只能手动的更新证书有效期。网上资料目前主要分3种:1. 手动更新证书 2. 通过Kubernetes 证书 API 更新证书 3. 修改kubeadm源码证书时长,然后编译创建集群。(此种方法不建议)
手动更新证书
# 查看证书时效
kubeadm certs check-expiration
接下来我们来更新我们的集群证书,下面的操作都是在 Master 节点上进行,首先备份原有证书:
$ mkdir /etc/kubernetes.bak
$ cp -r /etc/kubernetes/pki/ /etc/kubernetes.bak
$ cp /etc/kubernetes/*.conf /etc/kubernetes.bak
然后备份 etcd 数据目录:
$ cp -r /var/lib/etcd /var/lib/etcd.bak
更新证书命令:
kubeadm certs renew all --config=kubeadm.yaml
然后记得更新下 kubeconfig 文件:
$ kubeadm init phase kubeconfig all --config kubeadm.yaml
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/admin.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/kubelet.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/controller-manager.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/scheduler.conf"
将新生成的 admin 配置文件覆盖掉原本的 admin 文件:
$ mv $HOME/.kube/config $HOME/.kube/config.old
$ cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ chown $(id -u):$(id -g) $HOME/.kube/config
完成后重启 kube-apiserver、kube-controller、kube-scheduler、etcd 这4个容器即可,我们可以查看 apiserver 的证书的有效期来验证是否更新成功:
echo | openssl s_client -showcerts -connect 127.0.0.1:6443 -servername api 2>/dev/null | openssl x509 -noout -enddate
notAfter=Mar 16 06:41:24 2022 GMT
看到现在的有效期是一年过后的,证明已经更新成功了。
Kubernetes 证书 API 更新证书
对于线上环境我们可能并不会去冒险经常更新集群或者去更新证书,这些毕竟是有风险的,所以我们希望生成的证书有效期足够长,虽然从安全性角度来说不推荐这样做,但是对于某些场景下一个足够长的证书有效期也是非常有必要的,Kubernetes 证书 API的方式恰恰能满足我们的要求。
有兴趣的按照英文文档来实验一下,中文文档还是有些地方滞后,很多命令执行时都提示已经作废。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。