天天看點

Kubernetes進階學習之叢集更新遷移和維護實踐

[TOC]

0x00 Kubernetes Etcd 資料備份與恢複

描述:Kubernetes 使用 Etcd 資料庫實時存儲叢集中的資料,可以說 Etcd 是 Kubernetes 的核心元件,猶如人類的大腦。如果 Etcd 資料損壞将導緻 Kubernetes 不可用,在生産環境中 Etcd 資料是一定要做好高可用與資料備份,這裡介紹下如何備份與恢複 Etcd 資料。

Etcd 版本說明:

$ etcdctl version
etcdctl version: 3.4.13
API version: 3.4           

<br/>

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 叢集,執行資料快照備份:

--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 資料:

# 驗證開放端口
$ 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
#!/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
# 建立目錄
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/

下。

文法格式:

/bin/sh -c:執行 shell 指令
--env:設定環境變量,指定 etcdctl 工具使用的 API 版本
-v:docker 挂載選項,用于挂載 Etcd 證書相關目錄以及備份資料存放的目錄
etcdctl snapshot restore:etcd 資料恢複。           

單節點恢複資料:

# 将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 鏡像:

$ mv /etc/kubernetes/manifests.bak /etc/kubernetes/manifests           
  • Step 4.執行如下方式進行檢測ETCD恢複後的狀态
# 方式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-02

Master-03

# 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叢集相關版本:

# 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配置、證書檔案等)

$ 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叢集相關工具

# 更新 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           

Step 3.檢測目前節點是否能更新

$ 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其版本不用進行更新)

# 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版本

# 将原叢集建立配置檔案導出。
# 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叢集相關資訊

# 取消禁用節點排程
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

# 更新後檢視證書到期時間
$ 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叢集

# 删除老舊版本
$ 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           
Kubernetes進階學習之叢集更新遷移和維護實踐

0x02 Kubernetes 單 Master 節點(跨版本)更新實踐

描述: 本章節主要實踐跨版本的更新,實踐從v1.19.13叢集版本更新至1.20主版本中可用的v1.20.9叢集版本(與子版本更新差異不大),此處還是基于并采用的dockershim運作時,在下一章中我們将會把Kubernetes 叢集從 dockershim 遷移到 Containerd.io 運作時。

環境說明:

# 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資料
$ 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配置、證書檔案等)
$ tar -zcf kubernetes-cluster-1.19.13.tar.gz /etc/kubernetes/*           

Tips : 務必備份所有重要元件,例如存儲在資料庫中應用層面的狀态。

2.2 第二步,取消kubernetes相關軟體包 held (使其可以更新)并更新到指定叢集版本

$ 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 第三步, 驗證更新計劃(跨版本更新)

# 此處跨版本更新的可用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版本

# 導出舊叢集配置檔案
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 第五步, 驗證更新後的叢集版本以及版本

# 取消靜止排程恢複叢集正常狀态
$ 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 ps

    docker inspect

    指令來擷取容器資訊。由于你不能列出容器,是以你不能擷取日志、停止容器,甚至不能通過

    docker exec

    在容器中執行指令。
Kubernetes進階學習之叢集更新遷移和維護實踐

1.3 識别依賴于 Docker 的 DaemonSet

描述: 如果某 Pod 想調用運作在節點上的 dockerd,該 Pod 必須滿足以下兩個條件之一:

  • 将包含 Docker 守護程序特權套接字的檔案系統挂載為一個卷
  • 直接以卷的形式挂載 Docker 守護程序特權套接字的特定路徑。

舉例來說:在 COS 鏡像中,Docker 通過

/var/run/docker.sock

開放其 Unix 域套接字。 這意味着 Pod 的規約中需要包含 hostPath 卷以挂載 /var/run/docker.sock。

示例腳本: 用于查找包含直接映射 Docker 套接字的挂載點的 Pod。

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`版本。

# 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           
$ 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"           
$ tar -zcf kubernetes-cluster-1.19.13.tar.gz /etc/kubernetes/*           

Tips : 務必備份所有重要元件,例如存儲在資料庫中應用層面的狀态

# 更新軟體包索引以及安裝依賴的軟體包
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

),執行第三步。

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及其配置

# 備份 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用戶端指令行工具拉取新版本所需的鏡像檔案

# 清空 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運作時添加如下:

# 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後的叢集狀态

# 檢視 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單節點加入到其中進行管理,并檢視相應的資訊

# 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           
Kubernetes進階學習之叢集更新遷移和維護實踐

Tips : kubernetes 叢集更新其實流程大緻相同,不同點在于先更新一部分工作節點,然後在更新一台Master節點,等待正常後,再更新後續節點。

# (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 第一步, 準備資源清單部署指定應用

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 第二步, 利用資源清單進行部署并檢視驗證

# (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           
Kubernetes進階學習之叢集更新遷移和維護實踐

至此 kubernetes 從 dockershim 運作時,遷移到

containerd.io

完畢。

0x04 入坑出坑

問題1.在遷移後發現CoreDNS 鏡像下載下傳失敗

  • 錯誤資訊:
# 鏡像拉取時
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
......           
  • 解決辦法:
# 排除網絡情況後執行如下指令拉取鏡像并更改名稱
$ 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

錯誤

$ 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 端口被其它應用綁定占用。
$ 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           
  • 問題解決:
$ 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

錯誤。

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

    配置項配置如下
# 編輯 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           

繼續閱讀