歡迎光臨
每天分享高質量文章

Kubernetes官方叢集部署工具kubeadm原理解析

根據所處環境的不同,Kubernetes叢集的安裝部署有多種不同的方式。如果是在公有雲上還好,一般都會提供相應的安裝方案。如果是自行搭建私有環境,可選的安裝方案則不盡相同,有時可能需要從零一步步開始,這個過程很容易出錯,這往往使人感覺耗時耗力,望而卻步。
kubeadm作為Kubernetes官方提供的叢集部署管理工具,採用“一鍵式”指令進行叢集的快速初始化和安裝,極大地簡化了部署過程,消除了叢集安裝的痛點。雖然kubeadm目前還不能用於生產,但社群一直在完善kubeadm的功能和穩定性,剛剛釋出的1.10版本中便包含了一系列最佳化補丁,預計在下一個版本可進入GA,能夠用於Kubernetes生產環境的安裝部署。本次分享針對kubeadm的基本原理和一些特性進行講解,和大家一起體會這個安裝部署的“最佳實踐”設計思想。講解內容有不足之處,歡迎大家批評指正,共同探討,謝謝大家!

1. 基本原理

kubeadm做為叢集安裝的“最佳實踐”工具,標的是透過必要的步驟來提供一個最小可用的叢集執行環境。它會啟動叢集的基本元件以及必要的附屬元件,至於為叢集提供更豐富功能(比如監控,度量)的元件,不在其安裝部署的範圍。在環境節點符合其基本要求的前提下,kubeadm只需要兩條基本命令便可以快捷的將一套叢集部署起來。這兩條命令分別是:
  • kubeadm init:初始化叢集並啟動master相關元件,在計劃用做master的節點上執行。

  • kubeadm join:將節點加入上述叢集,在計劃用做node的節點上執行。

下麵分別對這兩條命令的流程進行詳細的說明。在此之前需要特別說明的是,kubeadm並不負責kubectl和kubelet的安裝,因此需要事先將kubectl和kubelet安裝好。kubeadm、kubectl和kubelet的安裝方式請參考:https://kubernetes.io/docs/setup/independent/install-kubeadm/#installing-kubeadm-kubelet-and-kubectl。
1.1 kubeadm init
如果不需要對叢集做任何定製化的配置,直接在master節點上執行該命令即可。該命令的內部流程如下圖所示:

在上圖的第④步完成的時候,正常情況下,Kubernetes的master的各元件便啟動起來了。這裡會有一個雷區:由於kubeadm是以static pod的方式啟動master各元件,這就涉及到元件容器映象的拉取。kubeadm預設的映象源是從Google的gcr.io映象庫,因此需要科學合理地去解決如何訪問該映象庫的問題,或者為kubeadm指定可用的第三方映象庫(據個人所知,如下映象庫可用,比如要拉取apiserver的1.9.6版本映象,地址為:registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver-amd64:v1.9.6)。由於該雷區的存在,可能會使得kubeadm的便捷性大打折扣。
後面的步驟主要是進行master節點的屬性設定、為node節點的加入做準備、啟動附屬元件等。需要註意的是,網路外掛的安裝也不在kubeadm管理的範圍以內,需要根據自己對網路方案的選擇來另行安裝相應的CNI外掛元件。

定製啟動配置引數
如果在啟動叢集的時候希望定製kubeadm本身的引數(比如前文所提到的指定映象庫地址),或者定製master各元件的啟動引數,可以透過給kubeadm init命令傳入–config來指定本地的配置檔案,在該檔案中對期望的引數進行設定。這種方式為kubeadm部署叢集提供了很大的配置靈活性,但它目前還是一個實驗性的功能,後續可能會發生變化。
另外,kubeadm還提供了phase命令,將init過程劃分為模組化的各個階段。如果想對部署過程進行細粒度的控制和幹預,達到定製化的目的,則可以考慮使用該命令。phase命令組合起來與init的工作流是一致的,不過目前它也是一個alpha階段的功能。
1.2 kubeadm join
join的流程就比較簡單了,它主要用來啟動節點並加入叢集。該命令的內部流程如下圖所示:

在node節點加入叢集時,需要建立雙向信任,它分成兩部分:discovery(node信任master)和TLS bootstrap(master信任node)。

discovery
node連線master時使用discovery token和CA public key hash,用來獲取叢集CA證書並完成對master的信任過程,確認所連線的master是所期望的合法master。
除了token方式之外,還可以透過discovery file的方式來完成discovery過程。該檔案是一個kubeconfig配置檔案,其中只包含了apiserver的地址資訊以及叢集CA證書資料。

TLS bootstrap
node連線master時攜帶TLS bootstrap token(通常可以和discovery token使用同一個),用於kubelet向master發起certificate signing request(CSR)時的臨時認證,kubeadm預設設定了master自動批准該CSR。當該CSR得到批准後,master便會為kubelet簽發客戶端證書,用於後續kubelet訪問apiserver時的身份認證。
在kubeadm init過程完成後,會打印出包含上述token引數的join命令,形式如下:
kubeadm join --token 33737d.a1aade1da540d7a0 192.168.122.39:6443 --discovery-token-ca-cert-hash sha256:ba72cd9566cb3703337f6c443564a1c917640b86dbd8de2b9c847814af3f737c
如果後面找不到該命令了,可以透過如下命令重新生成相應的命令:
kubeadm token create --print-join-command
其中token為discovery和TLS bootstrap共用的token,192.168.122.39:6443 為apiserver的IP地址和安全埠,discovery-token-ca-cert-hash為CA證書的HASH,用於校驗master的證書。

定製啟動配置引數
與kubeadm init命令類似,也可以透過傳入–config來指定本地配置檔案的方式給kubeadm join命令定製啟動引數,不再贅述。需要特別說明的是,該配置檔案中並不包含kubelet元件的配置,如果要修改kubelet的引數,需要修改kubelet對應的系統服務檔案,位置一般在/etc/systemd/system/kubelet.service.d/10-kubeadm.conf。

2. 讓安全配置更簡便

Kubernetes提供多種安全認證機制,為了對系統各元件間的通訊進行加密,一般採用TLS進行雙向認證,從前面的解析也已經可以零星的看到TLS和證書的影子。要部署一個TLS安全的Kubernetes叢集,就需要生成並組織好CA、金鑰、證書等一系列檔案,並對Kubernetes元件的相關引數進行正確設定,而這些檔案和引數數量繁多,稍不註意便容易配置錯誤,導致叢集無法正常啟動。
kubeadm則把這些細節全部都隱藏起來了,它直接在程式碼流程中實現相關證書和金鑰的生成過程,併為各元件設定對應的安全引數。這種方式使使用者不用進行安全相關的任何配置,在無需感知的情況下便可以啟動一個通訊安全的叢集,從而大大簡化了叢集安全配置,將此處的痛點降低為零。
內建的證書生成流程如下圖所示:

註:對於上圖中的front proxy,沒有在官方檔案中找到明確的說明,我的理解應該指的就是kubectl proxy。使用者可以透過這個proxy來間接的訪問apiserver,因此與它相關的通訊也是需要進行加密認證的。
kubeadm安裝完叢集後,生成的部分證書和金鑰檔案如下圖所示。圖中未顯示etcd相關的證書,為etcd生成證書的功能是在1.10版本實現的。

3. self-hosting樣式

kubeadm從1.8開始提供了一個實驗性的功能,即支援self-hosting樣式。這種樣式簡單來說就是以Kubernetes原生物件的方式來部署Kubernetes的master元件。(static pod樣式下,雖然這些元件也是以Pod的形式存在的,但它們是由kubelet來管理的,在apiserver看到的只是它們的mirror pod,並不能進行實際管理,因此可以認為它們不是真正意義上的Kubernetes原生物件。)
使用self-hosting樣式的優點在於利用了Kubernetes原生物件的特性,使叢集master元件的管理、升級、回滾、高可用配置等等更加方便。註意,目前self-hosting樣式的實現也有其顯著的缺點:當master節點重啟後,這些元件無法自行啟動。這個缺點以及其他可能的限制會在以後的版本中逐步得到解決。
在self-hosting樣式下,master元件是以DaemonSet物件來管理的。self-hosting樣式的啟動過程如下圖所示(該圖摘自社群@luxas的講稿):

該流程描述如下:
  1. 透過feature gate啟用該樣式;

  2. 讀取master元件在本地對應的static pod manifests(即Pod配置檔案);

  3. 根據上述檔案生成對應的DaemonSet配置檔案;

  4. 建立DaemonSet資源物件,等待Pod啟動;(在這裡當apiserver Pod啟動後會嘗試系結到6443埠,由於static pod的apiserver已經系結對應的埠,因此DaemonSet的Pod會一直處於Crash Loopbackoff狀態,直至後面的步驟完成)

  5. 刪除原來的靜態Pod配置檔案,kubelet隨之刪除對應的靜態Pod;

  6. DaemonSet形式的master元件接管叢集。

在self-hosting樣式下,檢視DaemonSet可以看到如下self-hosted的master元件:

4. 如何支援HA

實際上,kubeadm本身還並沒有真正的原生支援HA,社群給出的藉助kubeadm實現HA的方案參見:https://kubernetes.io/docs/setup/independent/high-availability/。
其思路如下圖所示(該圖摘自社群@luxas的講稿):

主要步驟:
  1. 首先建立一個HA的etcd叢集;

  2. 在首個master節點上使用kubeadm init啟動;

  3. 將首master節點上的證書等檔案複製至其他master節點;

  4. 在其他master節點使用kubeadm init啟動;

  5. 為master節點建立LB;

  6. 將node節點加入叢集。

我沒有實踐該HA方案,不太確定過程中是否有坑以及叢集安裝後的具體狀態,因此這裡就不進一步展開了。
至於kubeadm原生支援HA的設計方案參見:https://github.com/kubernetes/community/pull/1707 ,該方案還在review階段,有興趣的朋友可以閱讀一下。

5. 叢集升級

叢集升級也往往是讓人頭疼的問題,處理起來會比較複雜。類似叢集的安裝過程,kubeadm也同樣的把升級的細節隱藏起來,只需要使用一兩條簡單的命令便可輕鬆完成叢集升級。
首先可以透過kubeadm upgrade plan命令檢視升級計劃,該命令會輸出可升級的最新標的版本。

在上圖中可以看到可升級的1.9系列最新版本為1.9.6。需要註意的有兩點:1. 要執行升級,需要先將kubeadm升級到對應的版本;2. kubeadm並不負責kubelet的升級,需要在升級完master元件後,手工對kubelet進行升級。

在上圖中可以看到可升級的最新穩定版本為1.10.0。註意點同上。
根據上面的結果以及自己的升級需求,選擇相應的標的版本,執行kubeadm upgrade apply [version]即可啟動升級過程。由於暫時未在個人環境上進行升級,這裡就不貼出升級執行過程及結果了,大家可以在自己的環境上進行實驗。
補充:
大家如果想實踐kubeadm的功能但又受困於網路等問題的話,可以訪問Play with Kubernetes(https://labs.play-with-k8s.com/)來進行體驗,個人感覺非常好用。目前它的kubeadm版本是1.8.4,預設部署的Kubernetes版本是1.8.10。由於該環境是基於Docker-in-Docker來實現的,因此在其節點主機上的體驗和實際的主機會有所不同。該實驗環境是社群第三方提供的,因此版本也會有所滯後。

Q&A;

Q:etcd的升級是怎麼處理?
A:etcd也可以由kubeadm進行管理,這種情況下,etcd的升級也就可以由kubeadm來進行了。可以參考分享中kubeadm upgrade plan中的提示。如果kubeadm配置為使用外部etcd,則需要自行進行etcd的升級。

Q:你們使用的網路外掛是?
A:我們使用的是中興通訊自研的網路外掛Knitter,該外掛可以原生支援多網路平面,適合NFV的場景。

Q:kubeadm可以指定倉庫地址,不然在國內就得先註入映象,你可以試試。
A:對的,在分享中關於雷區的說明中有提到可以為kubeadm指定可用的第三方映象庫,需要在啟動引數中進行設定。
Q:一定要使用etcd嗎,可以用其他的資料庫代替嗎?
A:目前Kubernetes只支援使用etcd,在大約兩年前,社群有關於支援Consul的討論,不過後來不了了之。

Q:etcd預設有做故障恢復嗎,如果沒有,有沒有好的方案?
A:由kubeadm啟動的etcd應該是沒有做故障恢復,個人理解可以透過建立外部etcd高可用叢集的方式達到目的。

Q:knitter能描述一下嗎,跟Calico、Flannel有什麼區別呢?你們有測試過多高的負載?
A:knitter已經開源,可以在其專案地址檢視其說明:https://github.com/ZTE/Knitter。不過由於剛剛開源不久,上面的檔案還不是特別完善,敬請保持關註。

Q:CA證書過期怎麼處理?
A:kubeadm建立的CA證書預設的有效期是10年,一般情況下不需要考慮CA證書過期問題。不過apiserver的證書有效期預設的是1年,這個需要考慮過期問題。我在1.9中提過一個PR,在升級叢集的時候,如果發現apiserver的證書到期時間小於180天,會重新生成其證書。

Q:我看過kubelet預設有主動註冊的選項,如果提供證書金鑰應該就不需要使用kubeadm join?
A:是的,不過這個前提就是像你所提到的,需要它已經有相應的證書金鑰,如果不使用kubeadm join的話,就需要手動去為它建立證書和金鑰,可能還需要一些其他配置,過程比較繁瑣。所以如果叢集是由kubeadm來管理的話,還是建議使用kubeadm join來加入。

Q:kubeadm join使用的token是不是有時效的?
A:對,我記得這個時效應該是24小時,如果超過時效,可以使用kubeadm token create來重新生成一個token。

Q:kubectl get daemonset -o wide –all-namespaces可以查到kube-apiserver-master的是self-hosting樣式嗎?
A:如果透過該命令可以查到,那應該就是了。kubeadm在這些DaemonSet的名字中統一加了“self-hosted-”字首。
Kubernetes零基礎進階培訓

本次培訓內容包括:容器原理、Docker架構及工作原理、Docker網路與儲存方案、Harbor、Kubernetes架構、元件、核心機制、外掛、核心模組、Kubernetes網路與儲存、監控、日誌、二次開發以及實踐經驗等,點選瞭解具體培訓內容

4月20日正式上課,點選閱讀原文連結即可報名。
贊(0)

分享創造快樂