14.1 使用 kubeadm 部署 Kubernetes

kubeadm 提供了 kubeadm init 以及 kubeadm join 這兩個指令,作為快速建立 Kubernetes 叢集的常用工具。

版本說明:Kubernetes 版本更新較快 (約每 4 個月一個新版本),本文件基於 Kubernetes 1.36 編寫。更完整的安裝和相容性說明請以 Kubernetes 官方 kubeadm 文件containerd 官方文件 為準。

14.1.1 安裝 containerd

參考安裝 Docker 一節新增 apt/yum 源,之後執行如下指令。

# debian 系

$ sudo apt install containerd.io

# rhel 系

$ sudo yum install containerd.io

14.1.2 設定 containerd

先生成預設設定檔案,然後只調整與 kubeadm 相關的關鍵項:

$ sudo mkdir -p /etc/containerd
$ containerd config default | sudo tee /etc/containerd/config.toml > /dev/null

開啟 /etc/containerd/config.toml,確認 runc 選項使用 systemd cgroup 驅動:

# containerd 2.x(當前預設版本)
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.runc.options]
  SystemdCgroup = true

# containerd 1.x(舊版本)使用以下路徑,2.x 亦相容
# [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
#   SystemdCgroup = true

提示containerd config default 生成的預設設定會自動使用當前版本的正確路徑。如果你使用的是 containerd 2.x,設定中的外掛路徑將以 io.containerd.cri.v1.runtime 開頭;如果仍在使用 1.x,則為 io.containerd.grpc.v1.cri

預設設定裡的其它內容通常可以保持不變。修改完成後重啟 containerd:

$ sudo systemctl restart containerd

14.1.3 安裝 kubeletkubeadmkubectlcri-toolskubernetes-cni

需要在每台機器上安裝以下的軟體套件:

Ubuntu/Debian

$ K8S_MINOR="v1.36"

$ sudo apt-get update
$ sudo apt-get install -y ca-certificates curl gpg

$ sudo install -m 0755 -d /etc/apt/keyrings
$ curl -fsSL "https://pkgs.k8s.io/core:/stable:/${K8S_MINOR}/deb/Release.key" | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
$ sudo chmod a+r /etc/apt/keyrings/kubernetes-apt-keyring.gpg

$ echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/${K8S_MINOR}/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list > /dev/null

$ sudo apt-get update
$ sudo apt-get install -y kubelet kubeadm kubectl cri-tools kubernetes-cni

$ sudo apt-mark hold kubelet kubeadm kubectl

CentOS/Fedora

$ K8S_MINOR="v1.36"

$ cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/${K8S_MINOR}/rpm/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/${K8S_MINOR}/rpm/repodata/repomd.xml.key
EOF

$ sudo yum install -y kubelet kubeadm kubectl cri-tools kubernetes-cni

14.1.4 修改核心的執行引數

載入核心模組

$ cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

$ sudo modprobe overlay
$ sudo modprobe br_netfilter

cgroup v2 要求:必須

Kubernetes v1.36 預設要求節點使用 cgroup v2。kubelet 在 cgroup v1 節點上預設會拒絕啟動,但管理員可以在 kubelet 設定中設定 failCgroupV1: false 來相容 cgroup v1(僅建議用於遺留系統轉場期)。驗證節點是否支援 cgroup v2:

$ mount | grep cgroup2

如果輸出包含 cgroup2,則系統已支援 cgroup v2。對於仍在使用 cgroup v1 的系統(如較舊的 RHEL 8),建議升級核心或更新系統設定以啟用 cgroup v2。

停用 swap:必須

kubelet 預設要求停用 swap,否則可能導致初始化失敗或節點無法加入叢集。

$ sudo swapoff -a

# 如需永久停用,可在 /etc/fstab 中註解 swap 對應行
$ cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

# 應用設定

$ sysctl --system

14.1.5 設定 kubelet

為了讓 kubelet 正確執行,我們需要對其進行一些必要的設定。

修改 kubelet.service(可選:IPVS 模式)

注意:kube-proxy 的 IPVS 模式已在 Kubernetes 1.35 中被標記為棄用;Kubernetes 1.36 文件仍將其列為已棄用模式,並推薦遷移到 nftables。新部署應使用預設的 iptables 模式或 nftables 模式(Kubernetes 1.33+ 穩定)。以下 IPVS 設定僅供舊環境參考。

/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf 寫入以下內容

# 啟用 ipvs 相關核心模組(已棄用,建議遷移至 nftables)

[Service]
ExecStartPre=-/sbin/modprobe ip_vs
ExecStartPre=-/sbin/modprobe ip_vs_rr
ExecStartPre=-/sbin/modprobe ip_vs_wrr
ExecStartPre=-/sbin/modprobe ip_vs_sh

執行以下指令應用設定。

$ sudo systemctl daemon-reload

14.1.6 部署

安裝設定完成後,我們將分別在 Master 節點和 Worker 節點上進行部署操作。

master

$ sudo systemctl enable containerd

$ sudo systemctl start containerd

$ sudo kubeadm init \
      --pod-network-cidr 10.244.0.0/16 \
      --cri-socket unix:///run/containerd/containerd.sock \
      --v 5
  • --pod-network-cidr 10.244.0.0/16 引數與後續 CNI 外掛有關,這裡以 flannel 為例,若後續部署其他型別的網路外掛請更改此引數。
  • kubeadm 預設使用 registry.k8s.io 拉取 Kubernetes 控制平面鏡像。受限網路環境可透過 kubeadm 設定檔案中的 imageRepository 指向受信任映象倉庫;不要把第三方映象倉庫當成通用預設值。

kubeadm 預檢失敗,應按提示修復缺失依賴、核心引數、swap 或執行時設定。實驗環境確需忽略預檢時,只忽略明確理解且可接受的單項檢查,不建議使用 --ignore-preflight-errors=all

執行成功會輸出

...
[addons] Applied essential addon: CoreDNS
I1116 12:35:13.270407   86677 request.go:538] Throttling request took 181.409184ms, request: POST:https://<CONTROL_PLANE_HOST>:6443/api/v1/namespaces/kube-system/serviceaccounts
I1116 12:35:13.470292   86677 request.go:538] Throttling request took 186.088112ms, request: POST:https://<CONTROL_PLANE_HOST>:6443/api/v1/namespaces/kube-system/configmaps
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join <CONTROL_PLANE_HOST>:6443 --token <TOKEN> \
    --discovery-token-ca-cert-hash sha256:<DISCOVERY_TOKEN_CA_CERT_HASH>

node 工作節點

另一主機 重複 部署 小節以前的步驟,安裝設定好 kubelet。根據提示,加入到叢集。

$ systemctl enable containerd

$ systemctl start containerd

$ kubeadm join <CONTROL_PLANE_HOST>:6443 \
    --token <TOKEN> \
    --discovery-token-ca-cert-hash sha256:<DISCOVERY_TOKEN_CA_CERT_HASH> \
    --cri-socket unix:///run/containerd/containerd.sock

其中 <CONTROL_PLANE_HOST><TOKEN><DISCOVERY_TOKEN_CA_CERT_HASH> 應使用你自己的 kubeadm init 輸出,不要複用範例值。

14.1.7 檢視服務

所有服務啟動後,透過 crictl 檢視本地實際執行的容器。這些服務大概分為三類:主節點服務、工作節點服務和其它服務。

CONTAINER_RUNTIME_ENDPOINT=unix:///run/containerd/containerd.sock crictl ps -a

主節點服務

  • apiserver 是整個系統的對外介面,提供 RESTful 方式供用戶端和其它元件呼叫;

  • scheduler 負責對資源進行排程,分配某個 pod 到某個節點上;

  • controller-manager 負責管理控制器,包括 endpoint-controller (重新整理服務和 pod 的關聯訊息) 和 replication-controller (維護某個 pod 的複製為設定的數值)。

工作節點服務

  • proxy 為 pod 上的服務提供訪問的代理。

其它服務

  • Etcd 是所有狀態的儲存資料庫;

14.1.8 使用

/etc/kubernetes/admin.conf 複製到 ~/.kube/config

執行 $ kubectl get all -A 檢視啟動的服務。

由於未部署 CNI 外掛,CoreDNS 未正常啟動。如何使用 Kubernetes,請參考後續章節。

14.1.9 部署 CNI

這裡以 flannel 為例進行介紹。

flannel

檢查 podCIDR 設定

$ kubectl get node -o yaml | grep CIDR

# 輸出

    podCIDR: 10.244.0.0/16
    podCIDRs:
# 注意:以下以 v0.28.4 為範例;安裝前請到 releases 頁面核驗當前版本
# 參見 https://github.com/flannel-io/flannel/releases
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.4/Documentation/kube-flannel.yml

14.1.10 master 節點預設不能執行 pod

如果用 kubeadm 部署一個單節點叢集,預設情況下無法使用,請執行以下指令解除限制

$ kubectl taint nodes --all node-role.kubernetes.io/control-plane-

# 較舊版本使用 master taint

# $ kubectl taint nodes --all node-role.kubernetes.io/master-

# 恢復預設值

# $ kubectl taint nodes NODE_NAME node-role.kubernetes.io/control-plane=true:NoSchedule

...
第 115 页,共 196 页
使用 mdPress 构建