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

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)

分享創造快樂