1. 程式人生 > >K8S 原始碼探祕 之 kubeadm init 執行流程分析

K8S 原始碼探祕 之 kubeadm init 執行流程分析

一、引言

       kubeadm 是 k8s 重要的快速部署工具,也是其原生支援的部署工具,在實現自動化部署方面具有重要的研究價值。

       本文將基於 Kubernetes 1.12 版本,分析其 init 初始化叢集的執行流程,希望對讀者進一步理解 k8s 有所幫助!

二、流程介紹

       首先,上一張整體執行流程圖(可以點選看大圖!!!):

 

       kubeadm 在執行 init 的過程中,主要包含:配置載入、環境檢測、叢集初始化、安裝後配置等步驟。

       配置初始化指的是載入系統預設引數、解析和應用使用者指定的配置、設定動態配置項(如節點名稱、節點 IP 等)以及驗證配置有效性等過程。配置的初始化過程很大程度上依賴 cobra CLI 解析工具實現,關於 cobra 的使用請參考博文K8S 原始碼探祕 之 命令列解析工具 cobra;預設配置的載入過程介紹請參考博文K8S 原始碼探祕 之 預設引數的載入過程(Scheme 初瞭解)

       環境檢測涉及的東西較多,我將其獨立成一個章節進行介紹,參見 3.1 節。

       映象檢測和拉取指的是 kubeadm 在執行叢集初始化前,會首先檢查本地是否包含系統執行所需的基礎映象,如果沒有則通過網路從公有倉庫拉取,這些映象必須的包括:kube-apiserver、kube-controller-manager、kube-scheduler、kube-proxy以及pause。此外,當使用 Local etcd 時,kubeadm 會額外拉取 etcd 映象。至於 DNS,CoreDNS 和 KubeDNS 是二選一的,根據配置進行相應映象的拉取。使用 CoreDNS 只需要拉取一個映象,即 coredns;而使用 KubeDNS 時則需要拉取三個映象,分別是:k8s-dns-kube-dns、k8s-dns-sidecard、k8s-dns-dnsmasq-nanny。

       配置本地 kubelet 服務指的是根據叢集初始化配置對本地的 kubelet 服務重新進行配置的過程。首先,kubeadm 會停止本地的 kubelet 服務;而後配置兩個檔案,即 /var/lib/kubelet/kubeadm-flags.env 和 /var/lib/kubelet/config.yaml,這兩個檔案聲明瞭本地 kubelet 啟動需要應用的配置引數;最後重啟 kubelet 服務。

       檢測和生成相關證書指的是使用使用者指定的 CA 或者採用自簽名的方式生成 k8s 各元件的證書檔案,以便各元件通訊時使用安全的連線。生成的證書檔案存放在 /etc/kubernetes/pki 目錄下,各服務元件對應的配置則存放在 /etc/kubernetes 目錄下,分別為:admin.conf、kubelet.conf、controller-manager.conf、scheduler.conf。

        檢測和生成 audit 策略檔案,該功能需要在配置引數裡啟用 Auditing 特性才會執行。關於 Auditing 的相關說明,請參照官網:https://kubernetes.io/docs/tasks/debug-application-cluster/audit/。簡單來說,該步驟就是檢查一下使用者是否提供了 audit 策略檔案,如果沒有指定則自動建立一個,路徑 /etc/kubernetes/audit/audit.yaml。該檔案指明審計功能應該記錄哪些內容。

        生成 manifest 檔案指的是生成 Control Plane 各服務元件的執行說明檔案,包括 kube-apiserver.yaml、kube-controller-manager.yaml、kube-scheduler.yaml,如果需要執行 Local etcd,則同時生成 etcd.yaml,這些檔案都位於 kubernetes 配置目錄 /etc/kubernetes/manifests/ 下。當這些檔案生成後,kubelet 會自動檢測到,從而以容器形式啟動相應的服務。

         當服務開始執行後,kubeadm 會建立一個 kube-apiserver 的 client,以一定間隔時間持續嘗試連線 apiserver,直到探測到 apiserver 是正常執行的,或者重試超時宣告初始化失敗。與此同時,kubeadm 也會持續檢查 kubelet 的執行狀態是否正常,直到探測成功,或者重試超過指定次數宣告初始化失敗。這也就是等待 Control Plane 啟動完成的過程了。

          待主體服務執行起來後,kubeadm 會執行一系列的後續操作,該部分獨立成一個章節進行介紹,參見 3.2 節。

三、關鍵步驟精講

3.1  安裝預檢

       kubeadm 在執行安裝之前進行了相當細緻的環境檢測,下面就來扒一朳:

       1) 檢查執行 init 命令的使用者是否為 root,如果不是 root,直接快速失敗(fail fast);

       2) 檢查待安裝的 k8s 版本是否被當前版本的 kubeadm 支援(kubeadm 版本 >= 待安裝 k8s 版本);

       3) 檢查防火牆,如果防火牆未關閉,提示開放埠 10250;

       4) 檢查埠是否已被佔用,6443(或你指定的監聽埠)、10251、10252;

       5) 檢查檔案是否已經存在,/etc/kubernetes/manifests/*.yaml;

       6) 檢查是否存在代理,連線本機網路、服務網路、Pod網路,都會檢查,目前不允許代理;

       7) 檢查容器執行時,使用 CRI 還是 Docker,如果是 Docker,進一步檢查 Docker 服務是否已啟動,是否設定了開機自啟動;

       8) 對於 Linux 系統,會額外檢查以下內容:

           8.1) 檢查以下命令是否存在:crictl、ip、iptables、mount、nsenter、ebtables、ethtool、socat、tc、touch;

           8.2) 檢查 /proc/sys/net/bridge/bridge-nf-call-iptables、/proc/sys/net/ipv4/ip-forward 內容是否為 1;

           8.3) 檢查 swap 是否是關閉狀態;

        9) 檢查核心是否被支援,Docker 版本及後端儲存 GraphDriver 是否被支援;

             對於 Linux 系統,還需檢查 OS 版本和 cgroup 支援程度(支援哪些資源的隔離);

        10) 檢查主機名訪問可達性;

        11) 檢查 kubelet 版本,要高於 kubeadm 需要的最低版本,同時不高於待安裝的 k8s 版本;

        12) 檢查 kubelet 服務是否開機自啟動;

        13) 檢查 10250 埠是否被佔用;

        14) 如果開啟 IPVS 功能,檢查系統核心是否載入了 ipvs 模組;

        15) 對於 etcd,如果使用 Local etcd,則檢查 2379 埠是否被佔用, /var/lib/etcd/ 是否為空目錄;

              如果使用 External etcd,則檢查證書檔案是否存在(CA、key、cert),驗證 etcd 服務版本是否符合要求;

        16) 如果使用 IPv6,

               檢查 /proc/sys/net/bridge/bridge-nf-call-iptables、/proc/sys/net/ipv6/conf/default/forwarding 內容是否為 1;

          以上就是 kubeadm init 需要檢查的所有專案了!

3.2  完成安裝前的配置

       1) 在 kube-system 名稱空間建立 ConfigMap kubeadm-config,同時對其配置 RBAC 許可權;

       2) 在 kube-system 名稱空間建立 ConfigMap kubelet-config-<version>,同時對其配置 RBAC 許可權;

       3) 為當前節點(Master)打標記:node-role.kubernetes.io/master=;

       4) 為當前節點(Master)補充 Annotation;

       5) 如果啟用了 DynamicKubeletConfig 特性,設定本節點 kubelet 的配置資料來源為 ConfigMap 形式;

       6) 建立 BootStrap token Secret,並對其配置 RBAC 許可權;

       7) 在 kube-public 名稱空間建立 ConfigMap cluster-info,同時對其配置 RBAC 許可權;

       8) 與 apiserver 通訊,部署 DNS 服務;

       9) 與 apiserver 通訊,部署 kube-proxy 服務;

       10) 如果啟用了 self-hosted 特性,將 Control Plane 轉為 DaemonSet 形式執行;

       11) 列印 join 語句;

        以上就是 kubeadm 最後所做的操作了,為執行 kubeadm join 做好了鋪墊。