前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kubernetes进阶学习之k8s集群升级迁移和维护实践

Kubernetes进阶学习之k8s集群升级迁移和维护实践

原创
作者头像
全栈工程师修炼指南
修改2021-07-26 11:16:16
1.9K0
修改2021-07-26 11:16:16
举报

TOC

<!-- more -->

0x00 Kubernetes Etcd 数据备份与恢复

描述:Kubernetes 使用 Etcd 数据库实时存储集群中的数据,可以说 Etcd 是 Kubernetes 的核心组件,犹如人类的大脑。如果 Etcd 数据损坏将导致 Kubernetes 不可用,在生产环境中 Etcd 数据是一定要做好高可用与数据备份,这里介绍下如何备份与恢复 Etcd 数据。

Etcd 版本说明:

代码语言:txt
复制
$ etcdctl version
etcdctl version: 3.4.13
API version: 3.4

1) 备份 ETCD 数据实践

  • Step 1.查询当前 Kubernetes 使用的 Etcd 使用的镜像,并记住镜像名称与版本# 由于 k8s.gcr.io 镜像仓库国内被墙,所以使用的是阿里云的 etcd 镜像 $ docker images | grep "etcd" registry.cn-hangzhou.aliyuncs.com/google_containers/etcd 3.4.13-0 0369cf4303ff 10 months ago 253MB
  • Step 2.Kubeadm 安装的 Kubernetes 集群,采用镜像方式部署的 Etcd,所以操作 Etcd 需要使用 Etcd 镜像提供的 Etcdctl 工具 Tips : 如果你是非镜像方式部署 Etcd,可以直接使用 Etcdctl 命令备份数据。

语法格式: 运行 Etcd 镜像,并且使用镜像内部的 etcdctl 工具连接 etcd 集群,执行数据快照备份:

代码语言:txt
复制
--rm : 运行结束后则删除
-v:docker 挂载选项,用于挂载 Etcd 证书相关目录以及备份数据存放的目录
--env:设置环境变量,指定 etcdctl 工具使用的 API 版本
/bin/sh -c:执行 shell 命令
etcdctl  etcd客户端工具
--cacert:etcd CA 证书
--key:etcd 客户端证书 key
--cert:etcd 客户端证书 crt
--endpoints:指定 ETCD 连接地址
snapshot save etcd 数据备份
/backup/etcd-snapshot.db 数据备份名称

以 Docker 镜像 备份 Etcd 数据:

代码语言:txt
复制
# 验证开放端口
$ netstat -ano | grep -e "192.168.12.226:2379"
  # tcp        0      0 192.168.12.226:2379     0.0.0.0:*               LISTEN      off (0.00/0/0)
  # tcp        0      0 192.168.12.226:34376    192.168.12.226:2379     ESTABLISHED keepalive (10.06/0/0)

# etcd 证书一览
$ ls /etc/kubernetes/pki/etcd
  # ca.crt  ca.key  healthcheck-client.crt  healthcheck-client.key  peer.crt  peer.key  server.crt  server.key

# etcd备份文件存储的目录
$ mkdir -vp /data/backup
$ docker run --rm                                    \
-v /data/backup:/backup                              \
-v /etc/kubernetes/pki/etcd:/etc/kubernetes/pki/etcd \
--env ETCDCTL_API=3                                  \
registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.13-0 \
/bin/sh -c "etcdctl --endpoints=https://192.168.12.226:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt                  \
--key=/etc/kubernetes/pki/etcd/healthcheck-client.key     \
--cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt    \
snapshot save /backup/etcd-snapshot.db"
  # {"level":"info","ts":1626848337.5133626,"caller":"snapshot/v3_snapshot.go:119","msg":"created temporary db file","path":"/backup/etcd-snapshot.db.part"}
  # {"level":"info","ts":"2021-07-21T06:18:57.535Z","caller":"clientv3/maintenance.go:200","msg":"opened snapshot stream; downloading"}
  # {"level":"info","ts":1626848337.535256,"caller":"snapshot/v3_snapshot.go:127","msg":"fetching snapshot","endpoint":"https://192.168.12.226:2379"}
  # {"level":"info","ts":"2021-07-21T06:18:57.600Z","caller":"clientv3/maintenance.go:208","msg":"completed snapshot read; closing"}
  # {"level":"info","ts":1626848337.6088023,"caller":"snapshot/v3_snapshot.go:142","msg":"fetched snapshot","endpoint":"https://192.168.12.226:2379","size":"3.8 MB","took":0.095346714}
  # {"level":"info","ts":1626848337.6089203,"caller":"snapshot/v3_snapshot.go:152","msg":"saved","path":"/backup/etcd-snapshot.db"}
  # Snapshot saved at /backup/etcd-snapshot.db

/data/backup$ ls -alh etcd-snapshot.db
-rw------- 1 root root 3.7M Jul 21 14:18 etcd-snapshot.db

二进制 etcdctl 的安装

描述: etcdctl 二进制文件可以在 github.com/coreos/etcd/releases 选择对应的版本下载,例如可以执行以下 install_etcdctl.sh的脚本,修改其中的版本信息。

  • install_etcdctl.sh
代码语言:txt
复制
#!/bin/bash
# Desc: 
export ETCDCTL_API=3
ETCD_VER=v3.4.13
ETCD_DIR=etcd-download
DOWNLOAD_URL=https://github.com/coreos/etcd/releases/download

# Download
mkdir ${ETCD_DIR}
cd ${ETCD_DIR}
wget ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz 
tar -xzvf etcd-${ETCD_VER}-linux-amd64.tar.gz

# Install
cd etcd-${ETCD_VER}-linux-amd64
cp etcdctl /usr/local/bin/
  • 备份 master 主机节点的ETCD
代码语言:txt
复制
# 创建目录
mkdir -pv /backup 

# 备份数据
etcdctl --endpoints=https://192.168.12.226:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
--key=/etc/kubernetes/pki/etcd/healthcheck-client.key \
snapshot save /backup/etcd-snapshot.db

2) 恢复 ETCD 数据实践

描述: 在 Etcd 数据损坏时,可以通过 Etcd 备份数据进行数据恢复,先暂停 Kubernetes 相关组件,然后进入 Etcd 镜像使用 etcdctl 工具执行恢复操作。

  • Step 1.暂停 Kube-Apiserver 与 Etcd 镜像 在恢复 Etcd 数据前,需要停止 kube-apiserver 与 etcd 镜像,因为当这俩镜像停止后 Kubernetes 会自动重启这俩镜像,所以我们可以先暂时移除 /etc/kubernetes/manifests 目录,Kubernetes 检测这个目录文件不存在时会停止 Kubernetes 系统相关镜像,使其不能重启,方便我们进行后续的操作。# 移除且备份 /etc/kubernetes/manifests 目录 $ mv /etc/kubernetes/manifests /etc/kubernetes/manifests.bak # 查看 kube-apiserver、etcd 镜像是否停止 $ docker ps|grep etcd && docker ps|grep kube-apiserver # 备份现有 Etcd 数据 $ mv /var/lib/etcd /var/lib/etcd.bak
  • Step 2.恢复 Etcd 数据 描述: 运行 Etcd 镜像然后执行数据恢复,默认会恢复到 /default.etcd/member/ 目录下,这里使用 mv 命令在移动到挂载目录 /var/lib/etcd/ 下。

语法格式:

代码语言:txt
复制
/bin/sh -c:执行 shell 命令
--env:设置环境变量,指定 etcdctl 工具使用的 API 版本
-v:docker 挂载选项,用于挂载 Etcd 证书相关目录以及备份数据存放的目录
etcdctl snapshot restore:etcd 数据恢复。

单节点恢复数据:

代码语言:txt
复制
# 将db导入到 etcd 之中并将生成文件复制到 /var/lib/etcd/
$ docker run --rm              \
-v /data/backup:/backup        \
-v /var/lib/etcd:/var/lib/etcd \
--env ETCDCTL_API=3            \
registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.13-0  \
/bin/sh -c "etcdctl snapshot restore /backup/etcd-snapshot.db; mv /default.etcd/member/ /var/lib/etcd/"
  • Step 3.恢复 Kube-Apiserver 与 Etcd 镜像 描述: 将 /etc/kubernetes/manifests 目录恢复,使 Kubernetes 重启 Kube-Apiserver 与 Etcd 镜像:
代码语言:txt
复制
$ mv /etc/kubernetes/manifests.bak /etc/kubernetes/manifests
  • Step 4.执行如下方式进行检测ETCD恢复后的状态
代码语言:txt
复制
# 方式1.执行 etcdctl 命令进行检测
etcdctl --endpoints=https://192.168.12.226:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--key=/etc/kubernetes/pki/etcd/healthcheck-client.key \
--cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
endpoint health

# 方式2.执行 Kubectl 命令进行检测,查看命令是否能够正常执行:
$ kubectl get nodes

Tips : 补充说明kubernetes之etcd集群备份恢复, 将 Master-01 生成etcd备份分别复制到 Master-02Master-03

代码语言:txt
复制
# Master-01
etcdctl snapshot restore /backup/etcd-snapshot.db \
--name etcd-0 \
--initial-cluster "etcd-0=https://192.168.1.101:2380,etcd-1=https://192.168.1.102:2380,etcd-2=https://192.168.1.103:2380" \
--initial-cluster-token etcd-cluster \
--initial-advertise-peer-urls https://192.168.1.101:2380 \
--data-dir=/var/lib/etcd/

# Master-02
etcdctl snapshot restore /backup/etcd-snapshot.db \
--name etcd-1 \
--initial-cluster "etcd-0=https://192.168.1.101:2380,etcd-1=https://192.168.1.102:2380,etcd-2=https://192.168.1.103:2380" \
--initial-cluster-token etcd-cluster \
--initial-advertise-peer-urls https://192.168.1.102:2380 \
--data-dir=/var/lib/etcd/

# Master-03
etcdctl snapshot restore /backup/etcd-snapshot.db \
--name etcd-2 \
--initial-cluster "etcd-0=https://192.168.1.101:2380,etcd-1=https://192.168.1.102:2380,etcd-2=https://192.168.1.103:2380" \
--initial-cluster-token etcd-cluster \
--initial-advertise-peer-urls https://192.168.1.103:2380 \
--data-dir=/var/lib/etcd/

0x01 Kubernetes 单 Master 节点(次版本)升级实践

描述: 本章节主要实践次版本的升级,实践从v1.19.10集群版本升级至1.19主版本中最新的v1.19.13集群版本,还是基于并采用的dockershim运行时。

环境说明:

升级前系统容器及其kubernetes集群相关版本:

代码语言:txt
复制
# Container
操作系统 : linux
体系架构 : amd64
操作系统镜像 : Ubuntu 20.04.2 LTS
操作系统内核 : 5.4.0-73-generic
容器引擎 : docker://19.3.14
容器运行时 : containerd.io 1.4.4

# Kubernetes
cri-socket : /var/run/dockershim.sock
kubelet : v1.19.10
kubeadm : v1.19.10
kubectl : v1.19.10
kube proxy : v1.19.10
etcdctl version: 3.4.13
API version: 3.4

Step 1.备份 kubernetes 的 etcd 数据以及备份当前Kubernetes集群创建配置以及相关文件(集群信息、etcd配置、证书文件等)

代码语言:txt
复制
$ mkdir -vp /data/backup
$ docker run --rm                                    \
-v /data/backup:/backup                              \
-v /etc/kubernetes/pki/etcd:/etc/kubernetes/pki/etcd \
--env ETCDCTL_API=3                                  \
registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.13-0 \
/bin/sh -c "etcdctl --endpoints=https://192.168.12.226:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt                  \
--key=/etc/kubernetes/pki/etcd/healthcheck-client.key     \
--cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt    \
snapshot save /backup/etcd-snapshot.db"

$ tar -zcf kubernetes-cluster.tar.gz /etc/kubernetes/*

<br/>

Step 2.下载指定版本的kubernetes集群相关工具

代码语言:txt
复制
# 升级 1.19.10 ~ 1.19.13
apt update && apt-cache madison kubeadm | head -n 15
...
kubeadm | 1.19.13-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
...

# 下载指定版本的 kubeadm kubectl
apt-get install -y kubelet=1.19.13-00 kubeadm=1.19.13-00 kubectl=1.19.13-00
apt-mark hold kubelet kubeadm kubectl

# 禁用节点调度
kubectl cordon master-01

<br/>

Step 3.检测当前节点是否能升级

代码语言:txt
复制
$ kubeadm upgrade plan
[upgrade/versions] Latest version in the v1.19 series: v1.19.13
# Upgrade to the latest version in the v1.19 series:
  # COMPONENT                 CURRENT    AVAILABLE
  # kube-apiserver            v1.19.10   v1.19.13
  # kube-controller-manager   v1.19.10   v1.19.13
  # kube-scheduler            v1.19.10   v1.19.13
  # kube-proxy                v1.19.10   v1.19.13
  # CoreDNS                   1.7.0      1.7.0
  # etcd                      3.4.13-0   3.4.13-0

# 要手动升级到的版本在“首选版本”列中表示。
  # API GROUP                 CURRENT VERSION   PREFERRED VERSION   MANUAL UPGRADE REQUIRED
  # kubeproxy.config.k8s.io   v1alpha1          v1alpha1            no
  # kubelet.config.k8s.io     v1beta1           v1beta1             no

Step 4.下载所有的 v1.19.13 版本的组件镜像(此次CoreDNS和etcd其版本不用进行更新)

代码语言:txt
复制
# kubernetes 重要组件镜像
$ docker images -a | cut -d ' ' -f 1 | grep "google_containers/kube-"
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver

# 下载指定版本的 kubernetes 重要组件镜像
version=v1.19.13
$ for i in $(docker images -a | cut -d ' ' -f 1 | grep "google_containers/kube-");do
  docker pull ${i}:${version}
done
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2 
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.13-0
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:1.7.0

Step 5.升级当前k8s集群版本到v1.19.3版本

代码语言:txt
复制
# 将原集群创建配置文件导出。
# kubectl -n kube-system get cm kubeadm-config -oyaml > kubeadm-config.yaml
kubeadm config view > kubeadm-config.yaml
apiServer:
  certSANs:
  - 192.168.12.111
  extraArgs:
    authorization-mode: Node,RBAC
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: k8s-dev.weiyigeek:6443
controllerManager: {}
dns:
  type: CoreDNS
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.21.3
networking:
  dnsDomain: cluster.local
  podSubnet: 172.16.0.0/16
  serviceSubnet: 10.96.0.0/12
scheduler: {}

# 将集群创建配置文件中 kubernetesVersion 对象 v1.19.10 改变为 v1.19.13。
sed -i 's#1.19.10#1.19.13#g' kubeadm-config.yaml

# 将Kubernetes集群升级到指定版本。
kubeadm upgrade apply v1.19.3 --config kubeadm-config.yaml

  # 阻塞日志一览:
  # [upgrade] Running cluster health checks
  # [upgrade/version] You have chosen to change the cluster version to "v1.19.13"  
  # [upgrade/confirm] Are you sure you want to proceed with the upgrade? [y/N]: y
  # [upgrade/prepull] Pulling images required for setting up a Kubernetes cluster

  # 更新相关组件的Pod
  # [upgrade/apply] Upgrading your Static Pod-hosted control plane to version "v1.19.13"...
  # Static pod: kube-apiserver-master-k8s hash: a0d32a30af20b818a19ceda6f3c8e810
  # Static pod: kube-controller-manager-master-k8s hash: 3746ba71bc8ae5f787c4d7954828e6bb
  # Static pod: kube-scheduler-master-k8s hash: b5d76b6f8724c79709b04e03bfb169f7

  # 对etcd 和各k8s组件证书续期
  # [upgrade/etcd] Upgrading to TLS for etcd
  # [upgrade/staticpods] Writing new Static Pod manifests to "/etc/kubernetes/tmp/kubeadm-upgraded-manifests410267198"
  # [upgrade/staticpods] Preparing for "kube-apiserver" upgrade
  # [upgrade/staticpods] Renewing apiserver certificate、 apiserver-kubelet-client certificate 、front-proxy-client certificate 、apiserver-etcd-client certificate

  # kube-apiserver 组件
  # Static pod: kube-apiserver-master-k8s hash: a0d32a30af20b818a19ceda6f3c8e810
  # [apiclient] Found 1 Pods for label selector component=kube-apiserver
  # [upgrade/staticpods] Component "kube-apiserver" upgraded successfully!

  # kube-controller-manage 组件
  # Static pod: kube-controller-manager-master-k8s hash: 3746ba71bc8ae5f787c4d7954828e6bb
  # [apiclient] Found 1 Pods for label selector component=kube-controller-manager
  # [upgrade/staticpods] Component "kube-controller-manager" upgraded successfully!

  # kube-scheduler 组件
  # Static pod: kube-scheduler-master-k8s hash: b5d76b6f8724c79709b04e03bfb169f7
  # [apiclient] Found 1 Pods for label selector component=kube-scheduler
  # [upgrade/staticpods] Component "kube-scheduler" upgraded successfully!

  # 设置主要组件相关配置文件
  # [upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
  # [kubelet] Creating a ConfigMap "kubelet-config-1.19" in namespace kube-system with the configuration for the kubelets in the cluster
  # [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
  # [bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to get nodes
  # [bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
  # [bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
  # [bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
  # [addons] Applied essential addon: CoreDNS
  # [addons] Applied essential addon: kube-proxy

  # [upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.19.13". Enjoy!  # 出现该句则表示升级成功。

Step 6.查看升级后kubernetes集群相关信息

代码语言:txt
复制
# 取消禁用节点调度
kubectl uncordon master-01

kubectl cluster-info
  # Kubernetes master is running at https://k8s-dev.weiyigeek:6443
  # KubeDNS is running at https://k8s-dev.weiyigeek:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

kubectl get nodes -o wide
  # NAME         STATUS   ROLES    AGE   VERSION    INTERNAL-IP     OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
  # master-k8s   Ready    master   91d   v1.19.13   192.168.12.226  Ubuntu 20.04.2 LTS   5.4.0-73-generic   docker://19.3.15

kubectl get pod -n kube-system -o wide
  # NAME                                       READY   STATUS  
  # calico-kube-controllers-69496d8b75-2fr5p   1/1     Running  
  # calico-node-mmthr                          1/1     Running
  # coredns-6c76c8bb89-mhrnq                   1/1     Running
  # coredns-6c76c8bb89-zbxhh                   1/1     Running
  # etcd-master-k8s                            1/1     Running
  # kube-apiserver-master-k8s                  1/1     Running
  # kube-controller-manager-master-k8s         1/1     Running
  # kube-proxy-m69p8                           1/1     Running
  # kube-scheduler-master-k8s                  1/1     Running
  # metrics-server-77b878fdb-rlqdx             1/1     Running

Tips : 在升级Kubernetes集群后证书相关的到期时间也会延长一年。

Tips : kubeadm upgrade 也会自动对 kubeadm 在节点上所管理的证书执行续约操作。 如果需要略过证书续约操作,可以使用标志 --certificate-renewal=false

代码语言:txt
复制
# 升级后查看证书到期时间
$ openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep ' Not '
  # Not Before: Apr 21 06:20:12 2021 GMT
  # Not After : Jul 21 08:32:57 2022 GMT

# 证书信息批量查询
$ for crt in $(find /etc/kubernetes/pki/ -name "*.crt"); do echo ${crt};openssl x509 -in $crt -noout -dates;echo; done

Step 7.Kuboard 来管理我们升级后的k8s集群

代码语言:txt
复制
# 删除老旧版本
$ curl -k 'http://192.168.12.108:30567/kuboard-api/cluster/k8s-dev.weiyigeek/kind/KubernetesCluster/k8s-dev.weiyigeek/resource/installAgentToKubernetes?token=AflKbsicsKegFpNruDsxWspvTHHh2HnX' > kuboard-agent.yaml && kubectl delete -f ./kuboard-agent.yaml

# 部署新版本
$ curl -k 'http://192.168.12.108:30567/kuboard-api/cluster/k8s-dev.weiyigeek/kind/KubernetesCluster/k8s-dev.weiyigeek/resource/installAgentToKubernetes?token=K2vCJXf9ANrFjnrFbduNBxXusK3DhvIH' > kuboard-agent.yaml && kubectl apply -f ./kuboard-agent.yaml
$ kubectl get pods -n kuboard -l "k8s.kuboard.cn/name in (kuboard-agent, kuboard-agent-2)"
  # NAME                               READY   STATUS    RESTARTS   AGE
  # kuboard-agent-2-5597754bdf-phks5   1/1     Running   0          3m59s
  # kuboard-agent-769876b499-cr7f7     1/1     Running   0          3m59s
WeiyiGeek.Kuboard加入管理升级后k8s集群
WeiyiGeek.Kuboard加入管理升级后k8s集群

0x02 Kubernetes 单 Master 节点(跨版本)升级实践

描述: 本章节主要实践跨版本的升级,实践从v1.19.13集群版本升级至1.20主版本中可用的v1.20.9集群版本(与子版本升级差异不大),此处还是基于并采用的dockershim运行时,在下一章中我们将会把Kubernetes 集群从 dockershim 迁移到 Containerd.io 运行时。

环境说明:

升级前系统容器及其kubernetes集群相关版本:

代码语言:txt
复制
# Container
操作系统 : linux
体系架构 : amd64
操作系统镜像 : Ubuntu 20.04.2 LTS
操作系统内核 : 5.4.0-73-generic
容器引擎 : docker://19.3.15
容器运行时 : containerd.io 1.4.4

# Kubernetes
cri-socket : /var/run/dockershim.sock
kubelet : v1.19.13
kubeadm : v1.19.13
kubectl : v1.19.13
kube proxy : v1.19.13
etcdctl version: 3.4.13
etcdctl API version: 3.4
registry.cn-hangzhou.aliyuncs.com/google_containers/coredns : 1.7.0
registry.cn-hangzhou.aliyuncs.com/google_containers/pause : 3.2

2.1 第一步,同样是备份相关配置文件 (务必备份所有重要组件)。

  • 备份kubernetes的etcd数据
代码语言:txt
复制
$ mkdir -vp /data/backup
$ docker run --rm                                    \
-v /data/backup:/backup                              \
-v /etc/kubernetes/pki/etcd:/etc/kubernetes/pki/etcd \
--env ETCDCTL_API=3                                  \
registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.13-0 \
/bin/sh -c "etcdctl --endpoints=https://192.168.12.226:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt                  \
--key=/etc/kubernetes/pki/etcd/healthcheck-client.key     \
--cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt    \
snapshot save /backup/etcd-snapshot-1.19.13.db"
  • 备份当前Kubernetes集群创建配置以及相关文件(集群信息、etcd配置、证书文件等)
代码语言:txt
复制
$ tar -zcf kubernetes-cluster-1.19.13.tar.gz /etc/kubernetes/*

Tips : 务必备份所有重要组件,例如存储在数据库中应用层面的状态。

2.2 第二步,取消kubernetes相关软件包 held (使其可以升级)并升级到指定集群版本

代码语言:txt
复制
$ apt-mark showhold
  # kubeadm  kubectl kubelet

$ apt-mark unhold kubeadm kubectl kubelet
  # Canceled hold on kubeadm.
  # Canceled hold on kubectl.
  # Canceled hold on kubelet.

# 更新软件包索引以及锁定不进行更新,从 apt-get 1.1 版本起,你也可以使用下面的方法
$ apt update && \
apt-get install -y --allow-change-held-packages kubeadm=1.20.0-00 kubelet=1.20.0-00 kubectl=1.20.0-00  # 此处先下载1.20.x 第一个版本
$ apt-mark hold kubeadm kubectl kubelet
# 降级
# aptitude install kubeadm=1.20.0-00 kubelet=1.20.0-00 kubectl=1.20.0-00

# 验证下载操作的版本是否正常
$ kubeadm version  # GitVersion:"v1.20.0"

# 封锁并释放节点以便重新调度工作负载(如果是负载节点还需设置drain污点)
$ kubectl cordon master-01

Tips : 注意此处为了成功迁移的兼容(可用性)我们先只下载v1.20.x 最初始 kubernetes 版本的各个组件版本(v1.20.x)

2.3 第三步, 验证升级计划(跨版本升级)

代码语言:txt
复制
# 此处跨版本升级的可用k8s集群是v1.20.9版本
$ kubeadm upgrade plan
  # Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
  # COMPONENT   CURRENT       AVAILABLE   
  # kubelet     1 x v1.20.0   v1.20.9

  # Upgrade to the latest stable version:
  # COMPONENT                 CURRENT    AVAILABLE
  # kube-apiserver            v1.19.3    v1.20.9
  # kube-controller-manager   v1.19.3    v1.20.9
  # kube-scheduler            v1.19.3    v1.20.9
  # kube-proxy                v1.19.3    v1.20.9
  # CoreDNS                   1.7.0      1.7.0
  # etcd                      3.4.13-0   3.4.13-0

# 由上可以看出可用的版本为 v1.20.9 我们进行下载安装该版本的k8s相关组件
$ apt-get install -y --allow-change-held-packages kubeadm=1.20.9-00 kubelet=1.20.9-00 kubectl=1.20.9-00
$ kubelet --version
  # Kubernetes v1.20.9

# 拉取 v1.20.9 版本的各个k8s组件
version=v1.20.9
for i in $(docker images -a | cut -d ' ' -f 1 | grep "google_containers/kube-");do
  docker pull ${i}:${version}
done

2.4 第四步,同样我们需要准备集群创建配置文件,并升级到v1.20.9版本

代码语言:txt
复制
# 导出旧集群配置文件
kubeadm config view > kubeadm-config-v1.20.9.yaml

# 将集群创建配置文件中 kubernetesVersion 对象 v1.19.13 改变为 v1.20.9
sed -i 's#1.19.13#1.20.9#g' kubeadm-config-v1.20.9.yaml

# 升级到v1.20.9版本 (v1.19.3 ==>>> v1.20.9)
kubeadm upgrade apply v1.20.9 --config kubeadm-config-v1.20.9.yaml
  # upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.20.9". Enjoy!

2.5 第五步, 验证升级后的集群版本以及版本

代码语言:txt
复制
# 取消静止调度恢复集群正常状态
$ kubectl uncordon master-01

$ kubectl cluster-info
  # Kubernetes control plane is running at https://k8s-test.weiyigeek:6443
  # KubeDNS is running at https://k8s-test.weiyigeek:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

$ kubectl get nodes -o wide
  # NAME         STATUS   ROLES                  AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
  # master-k8s   Ready    control-plane,master   93d   v1.20.9   192.168.12.111   <none>        Ubuntu 20.04.2 LTS   5.4.0-73-generic   docker://19.3.14

$ kubectl get pods -n kube-system
  # NAME                                       READY   STATUS    RESTARTS   AGE
  # calico-kube-controllers-69496d8b75-pgrfj   1/1     Running   0          93d
  # calico-node-fn4lf                          1/1     Running   0          93d
  # coredns-54d67798b7-7gc7x                   1/1     Running   0          19m
  # coredns-54d67798b7-nbf7b                   1/1     Running   0          19m
  # etcd-master-k8s                            1/1     Running   0          21m
  # kube-apiserver-master-k8s                  1/1     Running   0          20m
  # kube-controller-manager-master-k8s         1/1     Running   0          20m
  # kube-proxy-ssdw5                           1/1     Running   0          19m
  # kube-scheduler-master-k8s                  1/1     Running   0          20m
  # metrics-server-77b878fdb-scdzx             1/1     Running   0          93d

至此集群版本升级成功。


0x03 Kubernetes 集群从 Dockershim 迁移到 Containerd.io 运行时

描述: 自从 Kubernetes 1.20 宣布 弃用 dockershim, 不推荐使用对 Docker 的支持,并将在未来版本中删除。建议从 dockershim 迁移到其他替代的 Containerd.io 容器运行时, 但是各种问题可能也随之而来,比如对各类工作负载和 Kubernetes 在生产环境部署会产生什么影响。

Dockershim : Docker 的容器运行时接口 (CRI) shim 已被弃用。

Q: 为什么弃用 dockershim?

答: 维护 dockershim 已经成为 Kubernetes 维护者肩头一个沉重的负担, 创建 CRI 标准就是为了减轻这个负担,同时也可以增加不同容器运行时之间平滑的互操作性。此外与 dockershim 不兼容的一些特性,例如:控制组(cgoups)v2 和用户名字空间(user namespace),已经在新的 CRI 运行时中被实现。

Q: 人们总在谈论 OCI,那是什么?

答: OCI 代表开放容器标准, 它标准化了容器工具和底层实现(technologies)之间的大量接口。 他们维护了打包容器镜像(OCI image-spec)和运行容器(OCI runtime-spec)的标准规范。 他们还以 runc 的形式维护了一个 runtime-spec 的真实实现, 这也是 containerd 和 CRI-O 依赖的默认运行时。 CRI 建立在这些底层规范之上,为管理容器提供端到端的标准。

(1) 检查弃用 Dockershim 对当前环境的影响

描述: 讲解你的集群把 Docker 用作容器运行时的运作机制,并提供使用 dockershim 时,它所扮演角色的详细信息, 继而展示了一组验证步骤,可用来检查弃用 dockershim 对你的工作负载的影响。

1.1 检查你的应用是否依赖于 Docker

判定你是否依赖于 Docker 的方法:

  • 1.确认没有特权 Pod 执行 docker 命令。
  • 2.检查 Kubernetes 基础架构外部节点上的脚本和应用,确认它们没有执行 Docker 命令。
  • 3.检查执行了上述特权操作的第三方工具。
  • 4.确认没有对 dockershim 行为的间接依赖。比如基于特定指标发警报,或者在故障排查指令的一个环节中搜索特定的日志信息。

1.2 检查对比Docker依赖详解

容器运行时是一个软件,用来运行组成 Kubernetes Pod 的容器, 在每一个节点上 kubelet 使用抽象的容器运行时接口,所以你可以任意选用兼容的容器运行时。

  • 在早期版本中 Kubernetes 提供的兼容性只支持一个容器运行时(Docker), 后续为了兼容更多的容器运行时设计出了CRI, 而 kubelet 亦开始支持 CRI。因为 Docker 在 CRI 规范创建之前就已经存在,此时k8s创建一个适配器组件dockershim (允许 kubelet 与 Docker交互) 就好像 Docker 是一个 CRI 兼容的运行时一样。
  • 在1.20版本及其之后建议采用containerd运行时,此时我们将可以省去dockershim 和 docker这个中间商,并且遗留的容器可由 Containerd 这类容器运行时来运行和管理,操作体验也和以前一样。但是你不能再使用 docker psdocker inspect 命令来获取容器信息。由于你不能列出容器,因此你不能获取日志、停止容器,甚至不能通过docker exec在容器中执行命令。
WeiyiGeek.DockerVSContainerd
WeiyiGeek.DockerVSContainerd

1.3 识别依赖于 Docker 的 DaemonSet

描述: 如果某 Pod 想调用运行在节点上的 dockerd,该 Pod 必须满足以下两个条件之一:

  • 将包含 Docker 守护进程特权套接字的文件系统挂载为一个卷
  • 直接以卷的形式挂载 Docker 守护进程特权套接字的特定路径。

举例来说:在 COS 镜像中,Docker 通过 /var/run/docker.sock 开放其 Unix 域套接字。 这意味着 Pod 的规约中需要包含 hostPath 卷以挂载 /var/run/docker.sock。

示例脚本: 用于查找包含直接映射 Docker 套接字的挂载点的 Pod。

代码语言:txt
复制
kubectl get pods --all-namespaces \
-o=jsonpath='{range .items[*]}{"\n"}{.metadata.namespace}{":\t"}{.metadata.name}{":\t"}{range .spec.volumes[*]}{.hostPath.path}{", "}{end}{end}' \
| sort

Tips : 对于 Pod 来说,访问宿主机上的 Docker 还有其他方式。 例如可以挂载 /var/run 的父目录而非其完整路径 (就像这个例子), 上述脚本只检测最常见的使用方式。

1.4 弃用 Dockershim 的常见问题

Q: 在 Kubernetes 1.20 版本中,我还可以用 Docker 吗?

答: 当然可以, 在 1.20 版本中仅有的改变就是, 如果使用 Docker 运行时,启动 kubelet 的过程中将打印一条警告日志。

Q: 我现有的 Docker 镜像还能正常工作吗?

答: 当然可以, docker build 创建的镜像适用于任何 CRI 实现。所有你的现有镜像将和往常一样工作。

Q: 如何拉取私有镜像呢?

答: 当然可以, 所有 CRI 运行时均支持 Kubernetes 中相同的拉取 (pull) Secret 配置,不管是通过 PodSpec 还是通过 ServiceAccount 均可。

Q: 在生产系统中使用其他运行时的例子?

答: containerd,CRI-O两个容器运行时是云原生基金会([CNCF])下的项目。例如:OpenShift 4.x 从 2019 年 6 月以来,就一直在生产环境中使用 CRI-O 运行时。

Q: 当切换 CRI 底层实现时,我应该注意什么?

答: Docker 和大多数 CRI(包括 containerd)的底层容器化代码是相同的,但其周边部分却存在一些不同。日志配置 运行时的资源限制 直接访问 docker 命令或通过控制套接字调用 Docker 的节点供应脚本 需要访问 docker 命令或控制套接字的 kubectl 插件 需要直接访问 Docker 的 Kubernetes 工具, 例如:kube-imagepuller。 像 registry-mirrors 和不安全的注册表这类功能的配置 需要 Docker 保持可用、且运行在 Kubernetes 之外的,其他支持脚本或守护进程(例如:监视或安全代理) GPU 或特殊硬件,以及它们如何与你的运行时和 Kubernetes 集成

(2) 迁移到 containerd 运行时并升级 kubernetes 集群

描述: 本章实践从dokcershim容器时(/var/run/dockershim.sock)迁移到containerd运行时(),并升级k8s集群v1.20.9到v1.21.3版本。

  • 升级前系统容器及其kubernetes集群相关版本:# Container 操作系统 : linux 体系架构 : amd64 操作系统镜像 : Ubuntu 20.04.2 LTS 操作系统内核 : 5.4.0-73-generic 容器引擎 : docker://19.3.15 容器运行时 : containerd.io 1.4.4 # Kubernetes cri-socket : kubelet : v1.20.9 kubeadm : v1.20.9 kubectl : v1.20.9 kube proxy : v1.20.9 etcdctl version: 3.4.13 etcdctl API version: 3.4 registry.cn-hangzhou.aliyuncs.com/google_containers/coredns : 1.7.0 registry.cn-hangzhou.aliyuncs.com/google_containers/pause : 3.2 # NAME STATUS ROLES AGE VERSION INTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME # master-k8s Ready control-plane,master 93d v1.20.9 192.168.12.226 Ubuntu 20.04.2 LTS 5.4.0-73-generic docker://19.3.15

2.1 第一步,同样是备份相关配置文件 (务必备份所有重要组件)。

  • 备份kubernetes的etcd数据
代码语言:txt
复制
$ mkdir -vp /data/backup
$ docker run --rm                                    \
-v /data/backup:/backup                              \
-v /etc/kubernetes/pki/etcd:/etc/kubernetes/pki/etcd \
--env ETCDCTL_API=3                                  \
registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.13-0 \
/bin/sh -c "etcdctl --endpoints=https://192.168.12.226:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt                  \
--key=/etc/kubernetes/pki/etcd/healthcheck-client.key     \
--cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt    \
snapshot save /backup/etcd-snapshot-1.19.13.db"
  • 备份当前Kubernetes集群创建配置以及相关文件(集群信息、etcd配置、证书文件等)
代码语言:txt
复制
$ tar -zcf kubernetes-cluster-1.19.13.tar.gz /etc/kubernetes/*

Tips : 务必备份所有重要组件,例如存储在数据库中应用层面的状态

2.2 第二步,取消kubernetes相关软件包 held (使其可以升级)并升级到指定集群版本

代码语言:txt
复制
# 更新软件包索引以及安装依赖的软件包
apt update && \
sudo apt-get install \
  apt-transport-https \
  ca-certificates \
  curl \
  gnupg \
  lsb-release

# - 添加Docker的官方GPG密钥为后续containerd.io 更新做准备
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# - 使用以下命令设置稳定存储库。要添加nightly或test存储库,请在下面的命令中的单词stable后面添加单词nightly或test(或两者)。
echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/container.list > /dev/null


# 查看是否有禁止软件自动更新安装的设置。
$ apt-mark showhold
  # kubeadm  kubectl kubelet
$ apt-mark unhold kubeadm kubectl kubelet
  # Canceled hold on kubeadm.
  # Canceled hold on kubectl.
  # Canceled hold on kubelet.

# 锁定不进行更新,从 apt-get 1.1 版本起,你也可以使用下面的方法
# Tips : 注意此处为了成功迁移的兼容(可用性验证)我们先只下载`v1.21.x` 最初始 kubernetes 版本的各个组件版本(v1.21.x)
$ apt clean all && \
apt update && apt-get install -y --allow-change-held-packages kubeadm=1.21.0-00 kubelet=1.21.0-00 kubectl=1.21.0-00  # 此处先下载1.20.x 第一个版本
$ apt-mark hold kubeadm kubectl kubelet

# 验证可用的kubernetes版本以及组件的版本
kubeadm upgrade plan
  #   Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
  #   COMPONENT   CURRENT       TARGET
  #   kubelet     1 x v1.21.0   v1.21.3

  #   Upgrade to the latest stable version:
  #   COMPONENT                 CURRENT    TARGET
  #   kube-apiserver            v1.20.9    v1.21.3
  #   kube-controller-manager   v1.20.9    v1.21.3
  #   kube-scheduler            v1.20.9    v1.21.3
  #   kube-proxy                v1.20.9    v1.21.3
  #   CoreDNS                   1.7.0      v1.8.0     # 版本有变化需要重新拉取
  #   etcd                      3.4.13-0   3.4.13-0

# 下载当前最新的版本组件(2021年7月23日 17:18:21)
apt update && apt-get install -y --allow-change-held-packages kubeadm=1.21.3-00 kubelet=1.21.3-00 kubectl=1.21.3-00 
# 验证下载操作的版本是否正常
$ kubeadm version  # GitVersion:"v1.21.3"
$ kubelet --version  # Kubernetes v1.21.3

# 采用 docker 拉取 CoreDNS:v1.8.0 镜像
docker pull coredns/coredns:1.8.0
docker tag coredns/coredns:1.8.0 registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.0

# Tips : 使用cordon命令将标记 Master 节点主机为不可调度,等待迁移后再进行恢复;
kubectl cordon master-k8s

# Tips : 先采用dockershim更新到指定的 kubernetes 版本
kubeadm config view > kubeadm-config-v1.21.3.yaml && sed -i "s#v1.20.9#v1.21.3#g" kubeadm-config-v1.21.3.yaml
kubeadm upgrade apply v1.21.3 --config kubeadm-config-v1.21.3.yaml

Tips : 当集群升级成功后我们进行验证集群状态,待当kube-system名称空间中各组件都正常后(状态为Running),执行第三步。

代码语言:txt
复制
kubectl get nodes -o wide
  # NAME         STATUS   ROLES                  AGE   VERSION   INTERNAL-IP    OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
  # master-k8s   Ready    control-plane,master   94d   v1.21.3   192.168.12.111 Ubuntu 20.04.2 LTS   5.4.0-73-generic   docker://19.3.15

kubectl get pod -n kube-system
  # NAME                                       READY   STATUS    RESTARTS   AGE
  # calico-kube-controllers-69496d8b75-pgrfj   1/1     Running   0          94d
  # calico-node-fn4lf                          1/1     Running   0          94d
  # coredns-6f6b8cc4f6-gmpx8                   1/1     Running   0          6m49s
  # coredns-6f6b8cc4f6-j6lb4                   1/1     Running   0          6m49s
  # etcd-master-k8s                            1/1     Running   0          133m
  # kube-apiserver-master-k8s                  1/1     Running   0          7m39s
  # kube-controller-manager-master-k8s         1/1     Running   0          7m19s
  # kube-proxy-6wrvs                           1/1     Running   0          6m44s
  # kube-scheduler-master-k8s                  1/1     Running   0          7m4s
  # metrics-server-77b878fdb-scdzx             1/1     Running   0          93d

2.3 第三步, 更新安装containerd.io及其配置

代码语言:txt
复制
# 备份 containerd 的 config.toml 配置文件
cp /etc/containerd/config.toml{,.bak}

# 查看当前版本以及可用的containerd版本
$ apt-cache madison containerd.io  # 或者采用 apt-cache policy containerd.io
  # containerd.io |    1.4.8-1 | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
  # containerd.io |    1.4.6-1 | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
  # containerd.io |    1.4.4-1 | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages

# 此处可以按照kubernetes与containerd.io对应兼容版本进行选择,下面我指定了1.4.8-1版本的 containerd.io。
$ apt install -y containerd.io=1.4.8-1  # 升级containerd为指定版本 

# 生成与修改 containerd 配置
containerd config default > /etc/containerd/config.toml
sed -i "s#k8s.gcr.io#registry.cn-hangzhou.aliyuncs.com/google_containers#g"  /etc/containerd/config.toml
sed -i '/containerd.runtimes.runc.options/a\ \ \ \ \ \ \ \ \ \ \ \ SystemdCgroup = true' /etc/containerd/config.toml
sed -i "s#https://registry-1.docker.io#https://xlx9erfu.mirror.aliyuncs.com#g"  /etc/containerd/config.toml

# 自动启动或启动 Containerd 
systemctl daemon-reload
systemctl enable containerd && systemctl restart containerd
systemctl status containerd
  # Jul 23 15:16:33 master-k8s systemd[1]: Started containerd container runtime.
  # Jul 23 15:16:33 master-k8s containerd[1099972]: time="2021-07-23T15:16:33.539416544+08:00" level=info msg="Start event monitor"
  # Jul 23 15:16:33 master-k8s containerd[1099972]: time="2021-07-23T15:16:33.539467558+08:00" level=info msg="Start snapshots syncer"
  # Jul 23 15:16:33 master-k8s containerd[1099972]: time="2021-07-23T15:16:33.539482024+08:00" level=info msg="Start cni network conf syncer"
  # Jul 23 15:16:33 master-k8s containerd[1099972]: time="2021-07-23T15:16:33.539490348+08:00" level=info msg="Start streaming server"

# 生成与修改 containerd 配置 crictl.yaml , 配置 crictl 工具
$ tee /etc/crictl.yaml <<'EOF'
runtime-endpoint: /run/containerd/containerd.sock
image-endpoint: "/run/containerd/containerd.sock"
timeout: 0
debug: false
EOF

# 采用 crictl 验证 cri 插件是否可用:
crictl pull docker.io/library/nginx:alpine
ctr -n k8s.io images ls | grep "nginx"

2.4 第四步, 验证v1.21.3集群所依赖的组件版本并利用containerd.io的ctr客户端命令行工具拉取新版本所需的镜像文件

代码语言:txt
复制
# 清空 ctr 中的所有镜像
# ctr -n k8s.io images remove $(ctr -n k8s.io images list -q)
$ kubeadm config images list --kubernetes-version=1.21.3 --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers -v 5
  # registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.21.3
  # registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.21.3
  # registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.21.3
  # registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.21.3
  # registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.4.1
  # registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.13-0
  # registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.0

# 手动需要单独下载的镜像
$ ctr -n k8s.io images pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2
$ ctr -n k8s.io images pull docker.io/coredns/coredns:1.8.0
$ ctr -n k8s.io images tag docker.io/coredns/coredns:1.8.0 registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.0   # 更改镜像TAG名称
  # registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.0
for i in $(kubeadm config images list --kubernetes-version=1.21.3 --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers -v 5);do
  ctr -n k8s.io images pull ${i}
done

# 查看下载的镜像
$ ctr -n k8s.io images ls | grep "google_containers"

2.5 第五步,更改当前kubernetes集群的运行时

描述:编辑 /var/lib/kubelet/kubeadm-flags.env文件, 并将containerd运行时添加如下:

代码语言:txt
复制
# kubeadm 集群启动参数配置
$ vim /var/lib/kubelet/kubeadm-flags.env
KUBELET_KUBEADM_ARGS="--network-plugin=cni --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2 --container-runtime=remote --container-runtime-endpoint=/run/containerd/containerd.sock"

# 重载 systemd 并重启 kubelet 服务
systemctl daemon-reload && systemctl restart kubelet

2.6 第六步, 查看containerd与kubelet服务,并查看迁移为containerd后的集群状态

代码语言:txt
复制
# 查看 containerd.service kubelet.service 服务状态
$ systemctl status containerd.service kubelet.service

# docker 运行的容器在moby名称空间之中
ctr -n moby c ls
  # CONTAINER                                                           IMAGE    RUNTIME
  # 1cd434f886a25798f41fbb5986a64a33e98d70d51c08f5e1e368603dad6b6c35    -        io.containerd.runtime.v1.linux
  # 262633d2cabd7e53190d0bc57f03823d12798c84e5e76a934e42cbcaa6ea12d3    -        io.containerd.runtime.v1.linux
  # 3be8bd11443ffa7f2b4f76e50495b451179cdd637786a9c7623167906e086d7b    -        io.containerd.runtime.v1.linux

# 重启机器
$ reboot

# 节点维护完后取消禁止调度,集群此时应该恢复为正常
$ kubectl uncordon master-k8s

# 验证 kubernetes 集群状态
$ kubectl get node -o wide
  # NAME         STATUS   ROLES                  AGE   VERSION   INTERNAL-IP      OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
  # master-k8s   Ready    control-plane,master   94d   v1.21.3   192.168.12.111   Ubuntu 20.04.2 LTS   5.4.0-80-generic   containerd://1.4.8

# 验证 kube-system 名称空间中各个 Pods 状态
$ kubectl -n kube-system get pods
  # NAME                                       READY   STATUS    RESTARTS   AGE
  # calico-kube-controllers-69496d8b75-pgrfj   1/1     Running   1          94d
  # calico-node-fn4lf                          1/1     Running   24         94d
  # coredns-6f6b8cc4f6-2l86r                   1/1     Running   1          50m
  # coredns-6f6b8cc4f6-l6k4s                   1/1     Running   1          50m
  # etcd-master-k8s                            1/1     Running   22         47m
  # kube-apiserver-master-k8s                  1/1     Running   26         5h48m
  # kube-controller-manager-master-k8s         1/1     Running   26         5h48m
  # kube-proxy-6wrvs                           1/1     Running   1          5h47m
  # kube-scheduler-master-k8s                  1/1     Running   26         4h44m
  # metrics-server-77b878fdb-scdzx             1/1     Running   2          93d

# 此时再观察moby名称空间的容器已发现没有任何运行的容器
ctr -n moby c ls
  # CONTAINER    IMAGE    RUNTIME

# 可以在k8s.io名称空间中查看运行的容器。
ctr -n k8s.io c ls
  # CONTAINER                                                           IMAGE                                                            RUNTIME                 
  # 05f0436d528550d46227da26a5ae7539439c4dea44d3840ef5ddfdba0f718d07    registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2    io.containerd.runc.v2 
  ......

2.7 第七步,在kuboard将该kubernetes单节点加入到其中进行管理,并查看相应的信息

代码语言:txt
复制
# kuboard k8s集群管理管理运行 agent 的 Pod 状态
kubectl -n kuboard get pods
  # NAME                               READY   STATUS    RESTARTS   AGE
  # kuboard-agent-2-576457f758-m2mts   1/1     Running   0          46s
  # kuboard-agent-dbd689678-dgn7q      1/1     Running   0          46s
WeiyiGeek.kuboard管理k8s集群
WeiyiGeek.kuboard管理k8s集群

Tips : kubernetes 集群升级其实流程大致相同,不同点在于先升级一部分工作节点,然后在升级一台Master节点,等待正常后,再升级后续节点。

代码语言:txt
复制
# (1) 将节点为可调度状态和非可调度状态
kubectl cordon master-01
kubectl uncordon master-01

# (2) 驱逐节点与恢复节点
kubectl drain master-01 --ignore-daemonsets --delete-local-data --force
kubectl undrain master-01

(3) 在迁移后创建并运行应用进一步验证集群是否正常

3.1 第一步, 准备资源清单部署指定应用

代码语言:txt
复制
tee nginx-deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deploy
  namespace: weiyigeek
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-test
  template:
    metadata:
      labels:
        app: nginx-test
    spec:
      initContainers:
      - name: init-html
        image: busybox:latest
        imagePullPolicy: IfNotPresent
        command: ['sh', '-c', "echo environment;env;echo NginxWeb-v${VERSION}-${HOSTNAME} > /usr/share/nginx/html/index.html"]
        env:
        - name: "VERSION"
          value: "1.23.1"
        volumeMounts:
        - name: web
          mountPath: "/usr/share/nginx/html"
        securityContext:
          privileged: true
      containers:
      - name: nginx
        image: nginx:alpine
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        volumeMounts:
        - name: web
          mountPath: "/usr/share/nginx/html"
      volumes:
      - name: web
        emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: weiyigeek
  labels:
    app: nginx-test
spec:
  type: NodePort
  ports:
    - name: nginx
      port: 80
      targetPort: 80
      nodePort: 30000
      protocol: TCP
  selector:
    app: nginx-test
EOF

3.2 第二步, 利用资源清单进行部署并查看验证

代码语言:txt
复制
# (1) 利用 kubectl apply 部署 deployment 控制器
kubectl create ns weiyigeek
kubectl apply -f nginx-deployment.yaml
  # deployment.apps/web-deploy created
  # service/nginx-service created

# (2) 查看状态的nginx的pod与svc
kubectl -n weiyigeek get pod,svc -o wide
  # NAME                          READY   STATUS    RESTARTS   AGE   IP             NODE      
  # web-deploy-5865b8d579-8l2r5   1/1     Running   0          20s   10.99.199.52   master-k8s
  # web-deploy-5865b8d579-hbvfm   1/1     Running   0          23s   10.99.199.51   master-k8s

kubectl -n weiyigeek get -o wide
  # NAME            TYPE       CLUSTER-IP    PORT(S)        AGE     SELECTOR
  # nginx-service   NodePort   10.103.63.67  80:30000/TCP   3m27s   app=nginx-test
WeiyiGeek.nginx-deployment
WeiyiGeek.nginx-deployment

至此 kubernetes 从 dockershim 运行时,迁移到 containerd.io 完毕。


0x04 入坑出坑

问题1.在迁移后发现CoreDNS 镜像下载失败

  • 错误信息:
代码语言:txt
复制
# 镜像拉取时
ctr: failed to resolve reference "registry.cn-hangzhou.aliyuncs.com/google_containers/coredns/coredns:v1.8.0": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed

# 集群升级时
.....
[preflight] Some fatal errors occurred:
        [ERROR ImagePull]: failed to pull image registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.0: output: Error response from daemon: manifest for registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.0 not found: manifest unknown: manifest unknown
, error: exit status 1
......
  • 解决办法:
代码语言:txt
复制
# 排除网络情况后执行如下命令拉取镜像并更改名称
$ ctr -n k8s.io images pull docker.io/coredns/coredns:1.8.0
$ ctr -n k8s.io images tag docker.io/coredns/coredns:1.8.0 registry.cn-hangzhou.aliyuncs.com/google_containers/coredns/coredns:v1.8.0

问题2.迁移后集群中etcd pod 报kubelet Back-off restarting failed container错误

  • 错误信息:
代码语言:txt
复制
$ kubectl -n kube-system describe pods etcd-master-k8s
  # Node-Selectors:    <none>
  # Tolerations:       :NoExecute op=Exists
  # Events:
  #   Type     Reason   Age                     From     Message
  #   ----     ------   ----                    ----     -------
  #   Normal   Pulled   6m49s (x3 over 7m40s)   kubelet  Container image "registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.13-0" already present on machine
  #   ......
  #   Warning  BackOff  2m32s (x39 over 7m40s)  kubelet  Back-off restarting failed container
  • 问题原因: 由于 etcd 的 2380 端口被其它应用绑定占用。
代码语言:txt
复制
$ kubectl -n kube-system logs etcd-master-k8s
  # 2021-07-23 14:16:06.715553 I | embed: peerTLS: cert = /etc/kubernetes/pki/etcd/peer.crt, key = /etc/kubernetes/pki/etcd/peer.key, trusted-ca = /etc/kubernetes/pki/etcd/ca.crt, client-cert-auth = true, crl-file =
  # 2021-07-23 14:16:06.715713 C | etcdmain: listen tcp 192.168.12.111:2380: bind: address already in use
  • 问题解决:
代码语言:txt
复制
$ ctr -n k8s.io i ls -q | grep "google_containers/etcd:3.4.13-0"
  # registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.13-0

$ netstat -anpo | grep "2380"
  # tcp        0      0 192.168.12.111:2380     0.0.0.0:*               LISTEN      1092928/etcd         off (0.00/0/0)

$ kill 1092928

问题3.查看 kubelet.service 服务中报Error syncing pod, skipping" err="failed to \"StartContainer\" for \"kuboard-agent\" with CrashLoopBackOff: \"back-off 10s restarting failed错误。

  • 错误信息:
代码语言:txt
复制
systemctl status kubelet
  # ● kubelet.service - kubelet: The Kubernetes Node Agent
    # Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; 

  # Jul 24 11:57:16 weiyigeek-226 kubelet[941]: I0724 11:57:16.031316     941 scope.go:111] "RemoveContainer" containerID="a27e7e92baa85f9028f411b5cee0f8b479b3a1fa09ef672a3f15868bc18ef004"
  # Jul 24 11:57:16 weiyigeek-226 kubelet[941]: E0724 11:57:16.031885     941 pod_workers.go:190] "Error syncing pod, skipping" err="failed to \"StartContainer\" for \"kuboard-agent\" with CrashLoopBackOff: \"back-off 10s restarting failed c>
  # Jul 24 11:57:19 weiyigeek-226 kubelet[941]: I0724 11:57:19.342054     941 scope.go:111] "RemoveContainer" containerID="a27e7e92baa85f9028f411b5cee0f8b479b3a1fa09ef672a3f15868bc18ef004"
  • 解决办法: kubernetes v1.21.3 版本针对于 KUBELET_POD_INFRA_CONTAINER 配置项配置如下
代码语言:txt
复制
# 编辑 kubeadm-flags.env 文件进行修改
$ vim /var/lib/kubelet/kubeadm-flags.env
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.4.1

更多学习笔记文章请关注 WeiyiGeek 公众账号,学习交流【邮箱联系: Master#weiyigeek.top】

微信公众号关注(点击)

原文地址: https://mp.weixin.qq.com/s/BQypeq5SpdHCzAl94aSYMg

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x00 Kubernetes Etcd 数据备份与恢复
    • 1) 备份 ETCD 数据实践
      • 2) 恢复 ETCD 数据实践
      • 0x01 Kubernetes 单 Master 节点(次版本)升级实践
      • 0x02 Kubernetes 单 Master 节点(跨版本)升级实践
      • 0x03 Kubernetes 集群从 Dockershim 迁移到 Containerd.io 运行时
        • (1) 检查弃用 Dockershim 对当前环境的影响
          • (2) 迁移到 containerd 运行时并升级 kubernetes 集群
            • (3) 在迁移后创建并运行应用进一步验证集群是否正常
            • 0x04 入坑出坑
              • 问题1.在迁移后发现CoreDNS 镜像下载失败
                • 问题2.迁移后集群中etcd pod 报kubelet Back-off restarting failed container错误
                  • 问题3.查看 kubelet.service 服务中报Error syncing pod, skipping" err="failed to \"StartContainer\" for \"kuboard-agent\" with CrashLoopBackOff: \"back-off 10s restarting failed错误。
                  相关产品与服务
                  容器服务
                  腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档