有心人可能会发现前面的高可用方案部署完成后的节点截图:

截屏2021-03-12 下午3.29.41

Master节点和Node节点的版本不一致,这也牵引出本文的目的,如何简单管理维护一套集群环境,首先当然包括:集群的升级和集群节点的伸缩。

集群版本升级

官方文档地址,不同版本间升级可能会存在差异,本文针对1.19.x升级至1.20.x版本。

升级流程

升级工作的基本流程如下:

  1. 升级主控制平面节点
  2. 升级其他控制平面节点
  3. 升级工作节点

注意事项

下面是官方对于集群升级的须知:

  • 务必仔细认真阅读发行说明
  • 集群应使用静态的控制平面和 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

截屏2021-03-12 下午4.14.41

  • 其他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

截屏2021-03-12 下午4.53.28

可以看见当前所有节点都为1.20.4版本。

升级工作原理

这里引用官方的介绍:

kubeadm upgrade apply 做了以下工作:

  • 检查你的集群是否处于可升级状态:

    • API 服务器是可访问的
    • 所有节点处于 Ready 状态
    • 控制面是健康的
  • 强制执行版本偏差策略。
  • 确保控制面的镜像是可用的或可拉取到服务器上。
  • 如果组件配置要求版本升级,则生成替代配置与/或使用用户提供的覆盖版本配置。
  • 升级控制面组件或回滚(如果其中任何一个组件无法启动)。
  • 应用新的 kube-dnskube-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

截屏2021-03-12 下午3.54.35

然后记得更新下 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的方式恰恰能满足我们的要求。

有兴趣的按照英文文档来实验一下,中文文档还是有些地方滞后,很多命令执行时都提示已经作废。


朱世伟
7 声望7 粉丝