[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
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運作時,此時我們将可以省去
這個中間商,并且遺留的容器可由 Containerd 這類容器運作時來運作和管理,操作體驗也和以前一樣。但是你不能再使用dockershim 和 docker
或docker ps
指令來擷取容器資訊。由于你不能列出容器,是以你不能擷取日志、停止容器,甚至不能通過docker inspect
在容器中執行指令。docker exec
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
下的項目。例如:OpenShift 4.x 從 2019 年 6 月以來,就一直在生産環境中使用 CRI-O 運作時。
([CNCF])
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
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 從 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
錯誤
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
錯誤。
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