實現細節
Kubernetes v1.10 [穩定版]kubeadm init 和 kubeadm join 結合使用,為從頭開始建立裸 Kubernetes 叢集提供了一個很好的使用者體驗,符合最佳實踐。然而,如何 kubeadm 實現這一點可能並不顯而易見。
本文件提供了關於幕後操作的更多細節,旨在分享關於 Kubernetes 叢集最佳實踐的知識。
核心設計原則
kubeadm init 和 kubeadm join 設定的叢集應該是
- 安全的:它應該採用最新的最佳實踐,例如
- 強制執行 RBAC
- 使用 Node Authorizer
- 在控制平面元件之間使用安全通訊
- 在 API 伺服器和 kubelet 之間使用安全通訊
- 鎖定 kubelet API
- 鎖定對 kube-proxy 和 CoreDNS 等系統元件的 API 訪問
- 鎖定引導令牌 (Bootstrap Token) 可以訪問的內容
- 使用者友好:使用者只需執行幾個命令即可
kubeadm initexport KUBECONFIG=/etc/kubernetes/admin.confkubectl apply -f <您選擇的網路外掛.yaml>kubeadm join --token <token> <endpoint>:<port>
- 可擴充套件的:
- 它不應該偏向任何特定的網路提供商。配置叢集網路超出了範圍
- 它應該提供使用配置檔案來自定義各種引數的可能性
常量和知名值及路徑
為了降低複雜性並簡化基於 kubeadm 構建的更高級別工具的開發,它使用一組有限的常量值來表示知名的路徑和檔名。
Kubernetes 目錄 /etc/kubernetes 是應用程式中的一個常量,因為它在大多數情況下是明確給定的路徑,也是最直觀的位置;其他常量路徑和檔名是
/etc/kubernetes/manifests是 kubelet 查詢靜態 Pod manifest 的路徑。靜態 Pod manifest 的名稱是etcd.yamlkube-apiserver.yamlkube-controller-manager.yamlkube-scheduler.yaml
/etc/kubernetes/是儲存控制平面元件標識的 kubeconfig 檔案的路徑。kubeconfig 檔案的名稱是kubelet.conf(TLS 引導期間為bootstrap-kubelet.conf)controller-manager.confscheduler.confadmin.conf用於叢集管理員和 kubeadm 本身super-admin.conf用於叢集超級管理員,可以繞過 RBAC
證書和金鑰檔案的名稱
ca.crt,ca.key用於 Kubernetes 證書頒發機構apiserver.crt,apiserver.key用於 API 伺服器證書apiserver-kubelet-client.crt,apiserver-kubelet-client.key用於 API 伺服器安全連線 kubelet 所使用的客戶端證書sa.pub,sa.key用於控制器管理器在簽名 ServiceAccount 時使用的金鑰front-proxy-ca.crt,front-proxy-ca.key用於前端代理證書頒發機構front-proxy-client.crt,front-proxy-client.key用於前端代理客戶端
kubeadm 配置檔案格式
大多數 kubeadm 命令支援 --config 標誌,該標誌允許從磁碟傳遞配置檔案。配置檔案格式遵循常見的 Kubernetes API apiVersion / kind 方案,但被視為元件配置檔案格式。幾個 Kubernetes 元件,例如 kubelet,也支援基於檔案的配置。
不同的 kubeadm 子命令需要不同型別的配置檔案。例如,InitConfiguration 用於 kubeadm init,JoinConfiguration 用於 kubeadm join,UpgradeConfiguration 用於 kubeadm upgrade,ResetConfiguration 用於 kubeadm reset。
kubeadm config migrate 命令可用於將舊格式的配置檔案遷移到更新(當前)的配置格式。kubeadm 工具僅支援從已棄用的配置格式遷移到當前格式。
有關更多詳細資訊,請參閱 kubeadm 配置參考頁面。
kubeadm init 工作流程內部設計
kubeadm init 由一系列原子工作任務組成,如 kubeadm init 內部工作流程中所述。
kubeadm init phase 命令允許使用者單獨呼叫每個任務,並最終提供一個可重用和可組合的 API/工具集,該工具集可供其他 Kubernetes 引導工具、任何 IT 自動化工具或高階使用者用於建立自定義叢集。
預檢檢查
Kubeadm 在啟動 init 之前執行一系列預檢檢查,目的是驗證先決條件並避免常見的叢集啟動問題。使用者可以透過 --ignore-preflight-errors 選項跳過特定的預檢檢查或所有檢查。
- [警告] 如果要使用的 Kubernetes 版本(透過
--kubernetes-version標誌指定)比 kubeadm CLI 版本高至少一個次版本。 - Kubernetes 系統要求
- 如果執行在 Linux 上
- [錯誤] 如果核心版本低於最低要求版本
- [錯誤] 如果必需的 cgroups 子系統未設定
- 如果執行在 Linux 上
- [錯誤] 如果 CRI 端點無響應
- [錯誤] 如果使用者不是 root
- [錯誤] 如果機器主機名不是有效的 DNS 子域
- [警告] 如果主機名無法透過網路查詢到達
- [錯誤] 如果 kubelet 版本低於 kubeadm 支援的最低 kubelet 版本(當前次版本 -1)
- [錯誤] 如果 kubelet 版本比所需控制平面版本高至少一個次版本(不支援的版本偏差)
- [警告] 如果 kubelet 服務不存在或已被停用
- [警告] 如果 firewalld 正在執行
- [錯誤] 如果 API 伺服器 bindPort 或埠 10250/10251/10252 已被使用
- [錯誤] 如果
/etc/kubernetes/manifest資料夾已存在且非空 - [錯誤] 如果 swap 已開啟
- [錯誤] 如果
ip,iptables,mount,nsenter命令不在命令路徑中 - [警告] 如果
ethtool,tc,touch命令不在命令路徑中 - [警告] 如果 API 伺服器、控制器管理器、排程器的附加引數標誌包含一些無效選項
- [警告] 如果連線到 https://API.AdvertiseAddress:API.BindPort 時經過代理
- [警告] 如果連線到服務子網時經過代理(僅檢查第一個地址)
- [警告] 如果連線到 Pod 子網時經過代理(僅檢查第一個地址)
- 如果提供了外部 etcd
- [錯誤] 如果 etcd 版本低於最低要求版本
- [錯誤] 如果指定了 etcd 證書或金鑰,但未提供
- 如果未提供外部 etcd(因此將安裝本地 etcd)
- [錯誤] 如果埠 2379 已被使用
- [錯誤] 如果 Etcd.DataDir 資料夾已存在且非空
- 如果授權模式為 ABAC
- [錯誤] 如果 abac_policy.json 不存在
- 如果授權模式為 WebHook
- [錯誤] 如果 webhook_authz.conf 不存在
注意
可以透過kubeadm init phase preflight 命令單獨呼叫預檢檢查。生成必要的證書
Kubeadm 為不同目的生成證書和私鑰對
用於 Kubernetes 叢集的自簽名證書頒發機構,儲存在
ca.crt檔案中,私鑰為ca.key檔案API 伺服器的服務證書,使用
ca.crt作為 CA 生成,儲存在apiserver.crt檔案中,其私鑰為apiserver.key。此證書應包含以下備用名稱- Kubernetes 服務的內部 ClusterIP(服務 CIDR 中的第一個地址,例如,如果服務子網是
10.96.0.0/12,則為10.96.0.1) - Kubernetes DNS 名稱,例如,如果
--service-dns-domain標誌值為cluster.local,則為kubernetes.default.svc.cluster.local,再加上預設 DNS 名稱kubernetes.default.svc,kubernetes.default,kubernetes - 節點名稱
--apiserver-advertise-address- 使用者指定的其他備用名稱
- Kubernetes 服務的內部 ClusterIP(服務 CIDR 中的第一個地址,例如,如果服務子網是
API 伺服器安全連線 kubelet 的客戶端證書,使用
ca.crt作為 CA 生成,儲存在apiserver-kubelet-client.crt檔案中,其私鑰為apiserver-kubelet-client.key。此證書應屬於system:masters組織用於簽名 ServiceAccount Token 的私鑰,儲存在
sa.key檔案中,公鑰為sa.pub用於前端代理的證書頒發機構,儲存在
front-proxy-ca.crt檔案中,私鑰為front-proxy-ca.key前端代理客戶端的客戶端證書,使用
front-proxy-ca.crt作為 CA 生成,儲存在front-proxy-client.crt檔案中,私鑰為front-proxy-client.key
證書預設儲存在 /etc/kubernetes/pki 中,但可以透過 --cert-dir 標誌配置此目錄。
請注意
- 如果給定的證書和私鑰對都存在,並且其內容被評估為符合上述規範,則將使用現有檔案,並跳過給定證書的生成階段。這意味著使用者可以例如將現有 CA 複製到
/etc/kubernetes/pki/ca.{crt,key},然後 kubeadm 將使用這些檔案來簽名其餘證書。另請參閱 使用自定義證書 - 對於 CA,可以提供
ca.crt檔案但不能提供ca.key檔案。如果所有其他證書和 kubeconfig 檔案都已到位,kubeadm 將識別此條件並激活 ExternalCA,這也意味著控制器管理器中的csrsigner控制器將不會啟動 - 如果 kubeadm 在 外部 CA 模式下執行;所有證書必須由使用者提供,因為 kubeadm 無法自行生成它們
- 如果 kubeadm 在
--dry-run模式下執行,證書檔案將寫入臨時資料夾 - 可以透過
kubeadm init phase certs all命令單獨呼叫證書生成。
為控制平面元件生成 kubeconfig 檔案
Kubeadm 為控制平面元件生成具有身份的 kubeconfig 檔案
用於 kubelet 在 TLS 引導期間使用的 kubeconfig 檔案 -
/etc/kubernetes/bootstrap-kubelet.conf。在此檔案內部,有一個引導令牌或嵌入的客戶端證書,用於將此節點與叢集進行身份驗證。此客戶端證書應
- 屬於
system:nodes組織,這是 Node Authorization 模組的要求 - Common Name (CN) 為
system:node:<hostname-lowercased>
- 屬於
用於控制器管理器的 kubeconfig 檔案,
/etc/kubernetes/controller-manager.conf;在此檔案內部嵌入了一個具有控制器管理器身份的客戶端證書。此客戶端證書應具有 CNsystem:kube-controller-manager,如預設 RBAC 核心元件角色所定義用於排程器的 kubeconfig 檔案,
/etc/kubernetes/scheduler.conf;在此檔案內部嵌入了一個具有排程器身份的客戶端證書。此客戶端證書應具有 CNsystem:kube-scheduler,如預設 RBAC 核心元件角色所定義
此外,還會生成一個用於 kubeadm 作為管理實體的 kubeconfig 檔案,並存儲在 /etc/kubernetes/admin.conf 中。此檔案包含一個具有 Subject: O = kubeadm:cluster-admins, CN = kubernetes-admin 的證書。kubeadm:cluster-admins 是由 kubeadm 管理的一個組。它在 kubeadm init 期間透過使用 super-admin.conf 檔案繫結到 cluster-admin ClusterRole,該檔案不需要 RBAC。此 admin.conf 檔案必須保留在控制平面節點上,並且不應與額外的使用者共享。
在 kubeadm init 期間,還會生成另一個 kubeconfig 檔案並存儲在 /etc/kubernetes/super-admin.conf 中。此檔案包含一個具有 Subject: O = system:masters, CN = kubernetes-super-admin 的證書。system:masters 是一個超級使用者組,可以繞過 RBAC,當叢集因 RBAC 配置錯誤而鎖定在緊急情況下,super-admin.conf 檔案很有用。super-admin.conf 檔案必須儲存在安全的位置,並且不應與額外的使用者共享。
有關 RBAC 和內建 ClusterRoles 及組的更多資訊,請參閱 RBAC 使用者可見角色繫結。
您可以執行 kubeadm kubeconfig user 為其他使用者生成 kubeconfig 檔案。
注意
生成的配置檔案包含嵌入的認證金鑰,您應將其視為機密。另外請注意
ca.crt證書嵌入到所有 kubeconfig 檔案中。- 如果給定的 kubeconfig 檔案存在,並且其內容被評估為符合上述規範,則將使用現有檔案,並跳過給定 kubeconfig 的生成階段
- 如果 kubeadm 在 ExternalCA 模式下執行;所有必需的 kubeconfig 也必須由使用者提供,因為 kubeadm 無法自行生成任何它們
- 如果 kubeadm 在
--dry-run模式下執行,kubeconfig 檔案將寫入臨時資料夾 - 可以透過
kubeadm init phase kubeconfig all命令單獨呼叫 kubeconfig 檔案的生成。
為控制平面元件生成靜態 Pod manifest
Kubeadm 將控制平面元件的靜態 Pod manifest 檔案寫入 /etc/kubernetes/manifests。kubelet 在啟動時會監視此目錄以建立 Pod。
靜態 Pod manifest 共享一組通用屬性
所有靜態 Pod 都部署在
kube-system名稱空間中所有靜態 Pod 都具有
tier:control-plane和component:{component-name}標籤所有靜態 Pod 都使用
system-node-critical優先順序類所有靜態 Pod 都設定
hostNetwork: true,以允許在配置網路之前啟動控制平面;因此- 控制器管理器和排程器用來引用 API 伺服器的
address是127.0.0.1 - 如果 etcd 伺服器本地設定,
etcd-server地址將設定為127.0.0.1:2379
- 控制器管理器和排程器用來引用 API 伺服器的
控制器管理器和排程器均啟用 leader election
控制器管理器和排程器將引用具有各自唯一身份的 kubeconfig 檔案
所有靜態 Pod 都會獲得您指定的任何額外標誌或補丁,如 傳遞自定義引數給控制平面元件中所述
所有靜態 Pod 都會獲得使用者指定的任何額外卷(Host path)
請注意
- 預設情況下,所有映象都將從 registry.k8s.io 拉取。有關自定義映象倉庫,請參閱 使用自定義映象。
- 如果 kubeadm 在
--dry-run模式下執行,靜態 Pod 檔案將寫入臨時資料夾 - 可以透過
kubeadm init phase control-plane all命令單獨呼叫控制平面元件的靜態 Pod manifest 生成。
API 伺服器
API 伺服器的靜態 Pod manifest 受使用者提供的以下引數影響
apiserver-advertise-address和apiserver-bind-port用於繫結;如果未提供,則這些值預設為機器上的預設網路介面的 IP 地址和埠 6443- 用於服務的
service-cluster-ip-range - 如果指定了外部 etcd 伺服器,則為
etcd-servers地址和相關的 TLS 設定(etcd-cafile,etcd-certfile,etcd-keyfile);如果未提供外部 etcd 伺服器,則使用本地 etcd(透過主機網路) - 如果指定了雲提供商,則配置相應的
--cloud-provider引數,如果存在此類檔案,則配置--cloud-config路徑(此功能是實驗性的,alpha 版本,未來版本中將被移除)
其他無條件設定的 API 伺服器標誌是
--insecure-port=0以避免對 api 伺服器進行不安全連線--enable-bootstrap-token-auth=true以啟用BootstrapTokenAuthenticator認證模組。有關更多詳細資訊,請參閱 TLS 引導--allow-privileged設定為true(例如 kube proxy 所需)--requestheader-client-ca-file設定為front-proxy-ca.crt--enable-admission-plugins設定為NamespaceLifecycle例如,以避免刪除系統保留的名稱空間LimitRanger和ResourceQuota以強制執行名稱空間限制ServiceAccount以強制執行服務賬戶自動化PersistentVolumeLabel根據雲提供商定義的標籤,將區域或可用區標籤附加到 PersistentVolumes(此 Admission Controller 已棄用,並且從 v1.9 開始,在未明確選擇使用gce或aws作為雲提供商時,kubeadm 預設不再部署它)DefaultStorageClass以在PersistentVolumeClaim物件上強制執行預設儲存類DefaultTolerationSecondsNodeRestriction以限制 kubelet 可以修改的內容(例如,僅限此節點上的 Pod)
--kubelet-preferred-address-types設定為InternalIP,ExternalIP,Hostname;這使得kubectl logs以及其他 API 伺服器-kubelet 通訊在節點主機名無法解析的環境中能夠正常工作用於使用前續步驟中生成的證書的標誌
--client-ca-file設定為ca.crt--tls-cert-file設定為apiserver.crt--tls-private-key-file設定為apiserver.key--kubelet-client-certificate設定為apiserver-kubelet-client.crt--kubelet-client-key設定為apiserver-kubelet-client.key--service-account-key-file設定為sa.pub--requestheader-client-ca-file設定為front-proxy-ca.crt--proxy-client-cert-file設定為front-proxy-client.crt--proxy-client-key-file設定為front-proxy-client.key
用於保護前端代理(API 聚合)通訊的其他標誌
--requestheader-username-headers=X-Remote-User--requestheader-group-headers=X-Remote-Group--requestheader-extra-headers-prefix=X-Remote-Extra---requestheader-allowed-names=front-proxy-client
控制器管理器
控制器管理器的靜態 Pod manifest 受使用者提供的以下引數影響
如果呼叫 kubeadm 時指定了
--pod-network-cidr,則透過設定來啟用某些 CNI 網路外掛所需的子網管理器功能--allocate-node-cidrs=true--cluster-cidr和--node-cidr-mask-size標誌,根據給定的 CIDR 進行設定
其他無條件設定的標誌是
--controllers啟用所有預設控制器,加上用於 TLS 引導的BootstrapSigner和TokenCleaner控制器。有關更多詳細資訊,請參閱 TLS 引導。--use-service-account-credentials設定為true用於使用前續步驟中生成的證書的標誌
--root-ca-file設定為ca.crt--cluster-signing-cert-file設定為ca.crt,如果外部 CA 模式被停用,否則設定為""--cluster-signing-key-file設定為ca.key,如果外部 CA 模式被停用,否則設定為""--service-account-private-key-file設定為sa.key
排程器
排程器的靜態 Pod manifest 不受使用者提供的引數影響。
生成本地 etcd 的靜態 Pod manifest
如果您指定了外部 etcd,此步驟將被跳過,否則 kubeadm 將生成一個用於建立本地 etcd 例項的靜態 Pod manifest 檔案,該例項具有以下屬性
- 監聽
localhost:2379並使用HostNetwork=true - 將
dataDir的hostPath掛載到主機的檔案系統 - 使用者指定的任何額外標誌
請注意
- 預設情況下,etcd 容器映象將從
registry.gcr.io拉取。有關自定義映象倉庫,請參閱 使用自定義映象。 - 如果您在
--dry-run模式下執行 kubeadm,etcd 靜態 Pod manifest 將寫入臨時資料夾。 - 您可以使用
kubeadm init phase etcd local命令直接呼叫本地 etcd 的靜態 Pod manifest 生成。
等待控制平面啟動
在控制平面節點上,kubeadm 最多等待 4 分鐘,直到控制平面元件和 kubelet 可用。它透過對相應的元件 /healthz 或 /livez 端點執行健康檢查來完成此操作。
在控制平面啟動後,kubeadm 將完成以下段落中描述的任務。
將 kubeadm ClusterConfiguration 儲存到 ConfigMap 以供後續引用
kubeadm 將傳遞給 kubeadm init 的配置儲存在 kube-system 名稱空間下的名為 kubeadm-config 的 ConfigMap 中。
這將確保將來執行的 kubeadm 操作(例如 kubeadm upgrade)能夠確定叢集的實際/當前狀態,並基於該資料做出新決策。
請注意
- 在儲存 ClusterConfiguration 之前,令牌等敏感資訊將從配置中剝離
- 可以透過命令
kubeadm init phase upload-config單獨呼叫控制平面節點配置的上傳。
將節點標記為控制平面
一旦控制平面可用,kubeadm 將執行以下操作
- 使用
node-role.kubernetes.io/control-plane=""標籤標記節點為控制平面 - 使用
node-role.kubernetes.io/control-plane:NoSchedule汙點標記節點
請注意,標記控制平面節點的階段可以透過命令 kubeadm init phase mark-control-plane 單獨呼叫。
配置節點的 TLS 引導
Kubeadm 使用 透過引導令牌進行認證 來將新節點加入現有叢集;有關更多詳細資訊,請參閱 設計提案。
kubeadm init 確保一切都已正確配置以用於此過程,這包括以下步驟以及如前段所述設定 API 伺服器和控制器標誌。
注意
可以使用命令kubeadm init phase bootstrap-token 配置節點的 TLS 引導,執行以下段落中描述的所有配置步驟;或者,也可以單獨呼叫每個步驟。建立引導令牌
kubeadm init 建立第一個引導令牌,該令牌要麼自動生成,要麼由使用者透過 --token 標誌提供;如引導令牌規範中所記錄,令牌應以 bootstrap-token-<token-id> 的名稱儲存在 kube-system 名稱空間下的 secret 中。
請注意
kubeadm init建立的預設令牌將用於驗證 TLS 引導過程中的臨時使用者;這些使用者將是system:bootstrappers:kubeadm:default-node-token組的成員- 令牌的有效性有限,預設為 24 小時(可以透過
—token-ttl標誌更改間隔) - 可以使用
kubeadm token命令建立其他令牌,該命令還提供其他有用的令牌管理功能。
允許加入的節點呼叫 CSR API
Kubeadm 確保 system:bootstrappers:kubeadm:default-node-token 組中的使用者能夠訪問證書籤名 API。
這是透過在上述組和預設 RBAC 角色 system:node-bootstrapper 之間建立名為 kubeadm:kubelet-bootstrap 的 ClusterRoleBinding 來實現的。
設定新引導令牌的自動批准
Kubeadm 確保引導令牌的 CSR 請求將被 csrapprover 控制器自動批准。
這是透過在 system:bootstrappers:kubeadm:default-node-token 組和預設角色 system:certificates.k8s.io:certificatesigningrequests:nodeclient 之間建立名為 kubeadm:node-autoapprove-bootstrap 的 ClusterRoleBinding 來實現的。
角色 system:certificates.k8s.io:certificatesigningrequests:nodeclient 也應被建立,授予對 /apis/certificates.k8s.io/certificatesigningrequests/nodeclient 的 POST 許可權。
設定節點證書自動批准輪換
Kubeadm 確保節點的證書輪換已啟用,並且新節點證書請求將被 csrapprover 控制器自動批准。
這是透過在 system:nodes 組和預設角色 system:certificates.k8s.io:certificatesigningrequests:selfnodeclient 之間建立名為 kubeadm:node-autoapprove-certificate-rotation 的 ClusterRoleBinding 來實現的。
建立公共 cluster-info ConfigMap
此階段將在 kube-public 名稱空間中建立 cluster-info ConfigMap。
此外,它還會建立一個 Role 和一個 RoleBinding,授予未認證使用者(即 RBAC 組 system:unauthenticated 中的使用者)對 ConfigMap 的訪問許可權。
注意
對cluster-info ConfigMap 的訪問沒有進行速率限制。如果將叢集的 API 伺服器暴露給網際網路,這可能會有問題,也可能不會。最壞的情況是 DoS 攻擊,攻擊者利用 kube-apiserver 可以處理的所有 in-flight 請求來提供 cluster-info ConfigMap。安裝外掛
Kubeadm 透過 API 伺服器安裝內部 DNS 伺服器和 kube-proxy 外掛元件。
注意
可以透過命令kubeadm init phase addon all 單獨呼叫此階段。proxy
在 kube-system 名稱空間中為 kube-proxy 建立了一個 ServiceAccount;然後 kube-proxy 作為 DaemonSet 部署
- 到控制平面的憑證(
ca.crt和token)來自 ServiceAccount - API 伺服器的位置(URL)來自 ConfigMap
kube-proxyServiceAccount 被繫結到system:node-proxierClusterRole 中的許可權
DNS
CoreDNS 服務因與舊版
kube-dns外掛相容性原因而命名為kube-dns。在
kube-system名稱空間中為 CoreDNS 建立了一個 ServiceAccount。corednsServiceAccount 被繫結到system:corednsClusterRole 中的許可權
在 Kubernetes 1.21 版本中,使用 kubeadm 的 kube-dns 支援已被移除。即使相關 Service 被命名為 kube-dns,您仍然可以使用 CoreDNS 與 kubeadm。
kubeadm join 階段內部設計
與 kubeadm init 類似,kubeadm join 的內部工作流程也包含一系列原子工作任務。
這分為發現(讓節點信任 Kubernetes API Server)和 TLS 引導(讓 Kubernetes API Server 信任節點)。
請參閱 透過引導令牌進行認證 或相應的 設計提案。
預檢檢查
kubeadm 在啟動 join 之前執行一系列預檢檢查,目的是驗證先決條件並避免常見的叢集啟動問題。
另外請注意
kubeadm join的預檢檢查基本上是kubeadm init預檢檢查的一個子集- 如果您正在加入 Windows 節點,Linux 特定的控制元件將被跳過。
- 在任何情況下,使用者都可以透過
--ignore-preflight-errors選項跳過特定的預檢檢查(或最終所有預檢檢查)。
發現 cluster-info
有兩種主要的發現方案。第一種是使用共享令牌以及 API 伺服器的 IP 地址。第二種是提供一個檔案(該檔案是標準 kubeconfig 檔案的子集)。
共享令牌發現
如果使用 --discovery-token 呼叫 kubeadm join,則使用令牌發現;在這種情況下,節點基本上從 kube-public 名稱空間中的 cluster-info ConfigMap 中檢索叢集 CA 證書。
為了防止“中間人”攻擊,採取了幾個步驟
首先,透過不安全連線檢索 CA 證書(這是可能的,因為
kubeadm init被授予了對system:unauthenticated使用者的cluster-info訪問許可權)然後,CA 證書經過以下驗證步驟
- 基本驗證:使用令牌 ID 對 JWT 簽名進行驗證
- 公鑰驗證:使用提供的
--discovery-token-ca-cert-hash。此值在kubeadm init的輸出中可用,或者可以使用標準工具計算(雜湊是根據 Subject Public Key Info (SPKI) 物件的位元組計算的,如 RFC7469 中所述)。--discovery-token-ca-cert-hash標誌可以重複多次以允許一個以上的公鑰。 - 作為額外的驗證,透過安全連線檢索 CA 證書,然後與最初檢索的 CA 進行比較
注意
您可以透過在命令列中傳遞--discovery-token-unsafe-skip-ca-verification 標誌來跳過 CA 驗證。這會削弱 kubeadm 的安全模型,因為其他人可能能夠冒充 Kubernetes API 伺服器。檔案/https 發現
如果使用 --discovery-file 呼叫 kubeadm join,則使用檔案發現;此檔案可以是本地檔案,也可以透過 HTTPS URL 下載;對於 HTTPS,主機的安裝 CA 捆綁包用於驗證連線。
對於檔案發現,叢集 CA 證書包含在檔案本身中;事實上,發現檔案是一個只有 server 和 certificate-authority-data 屬性設定的 kubeconfig 檔案,如 kubeadm join 參考文件中所述;當與叢集建立連線時,kubeadm 會嘗試訪問 cluster-info ConfigMap,如果可用,則使用它。
TLS 引導
一旦知道了叢集資訊,就會寫入 bootstrap-kubelet.conf 檔案,從而允許 kubelet 進行 TLS 引導。
TLS 引導機制使用共享令牌臨時向 Kubernetes API Server 進行身份驗證,以提交一個證書籤名請求 (CSR) 來生成本地建立的金鑰對。
然後,該請求會自動批准,操作完成,儲存用於 kubelet 加入叢集的 ca.crt 檔案和 kubelet.conf 檔案,同時刪除 bootstrap-kubelet.conf。
注意
- 臨時身份驗證是針對在
kubeadm init過程中儲存的令牌(或使用kubeadm token命令建立的其他令牌)進行的驗證 - 臨時身份驗證會解析到一個使用者,該使用者屬於
system:bootstrappers:kubeadm:default-node-token組,該組在kubeadm init過程中被授予了對 CSR API 的訪問許可權 - CSR 的自動批准由 csrapprover 控制器根據
kubeadm init過程中的配置進行管理
kubeadm upgrade 工作流程內部設計
kubeadm upgrade 具有用於處理 kubeadm 建立的 Kubernetes 叢集升級的子命令。您必須在控制平面節點上執行 kubeadm upgrade apply(您可以選擇其中一個);這將啟動升級過程。然後,您在所有剩餘節點(工作節點和控制平面節點)上執行 kubeadm upgrade node。
kubeadm upgrade apply 和 kubeadm upgrade node 都具有 phase 子命令,可訪問升級過程的內部階段。有關更多詳細資訊,請參閱 kubeadm upgrade phase。
其他實用的升級命令是 kubeadm upgrade plan 和 kubeadm upgrade diff。
所有升級子命令都支援傳遞配置檔案。
kubeadm upgrade plan
您可以在執行 kubeadm upgrade apply 之前選擇性地執行 kubeadm upgrade plan。plan 子命令檢查可用於升級的版本,並驗證當前叢集是否可升級。
kubeadm upgrade diff
這顯示了將應用於現有控制平面節點靜態 Pod manifest 的差異。更詳細的方式是執行 kubeadm upgrade apply --dry-run 或 kubeadm upgrade node --dry-run。
kubeadm upgrade apply
kubeadm upgrade apply 準備叢集以升級所有節點,並升級執行它的控制平面節點。它執行的步驟是
- 像
kubeadm init和kubeadm join一樣執行預檢檢查,確保容器映象已下載且叢集狀態良好,可以升級。 - 升級磁碟上
/etc/kubernetes/manifests中的控制平面 manifest 檔案,並在檔案更改時等待 kubelet 重啟元件。 - 將更新的 kubeadm 和 kubelet 配置上傳到叢集中的
kubeadm-config和kubelet-configConfigMaps(都在kube-system名稱空間中)。 - 在
/var/lib/kubelet/config.yaml中寫入此節點的更新的 kubelet 配置,並讀取節點的/var/lib/kubelet/instance-config.yaml檔案,將containerRuntimeEndpoint等欄位從此例項配置合併到/var/lib/kubelet/config.yaml中。 - 配置 bootstrap token 和
cluster-infoConfigMap 以支援 RBAC 規則。這與kubeadm init階段相同,並確保叢集繼續支援使用 bootstrap token 加入的節點。 - 有條件地升級 kube-proxy 和 CoreDNS 外掛,前提是叢集中所有現有的 kube-apiservers 已升級到目標版本。
- 執行任何升級後任務,例如清理特定於版本的已棄用功能。
kubeadm upgrade node
kubeadm upgrade node 在叢集升級開始後(透過執行 kubeadm upgrade apply)升級單個控制平面或工作節點。該命令透過檢查檔案 /etc/kubernetes/manifests/kube-apiserver.yaml 是否存在來檢測節點是否為控制平面節點。找到該檔案後,kubeadm 工具推斷該節點上有一個正在執行的 kube-apiserver Pod。
- 像
kubeadm upgrade apply一樣執行預檢檢查。 - 對於控制平面節點,升級磁碟上
/etc/kubernetes/manifests中的控制平面 manifest 檔案,並在檔案更改時等待 kubelet 重啟元件。 - 在
/var/lib/kubelet/config.yaml中寫入此節點的更新的 kubelet 配置,並讀取節點的/var/lib/kubelet/instance-config.yaml檔案,將containerRuntimeEndpoint等欄位從此例項配置合併到/var/lib/kubelet/config.yaml中。 - (對於控制平面節點) 有條件地升級 kube-proxy 和 CoreDNS 外掛,前提是叢集中所有現有的 API 伺服器都已升級到目標版本。
- 執行任何升級後任務,例如清理特定於版本的已棄用功能。
kubeadm reset 工作流程內部設計
您可以在之前執行過 kubeadm 命令的節點上使用 kubeadm reset 子命令。此子命令執行 **盡力而為** 的節點清理。如果某些操作失敗,您必須干預並執行手動清理。
該命令支援階段。有關更多詳細資訊,請參閱 kubeadm reset phase。
該命令支援配置檔案。
此外
- IPVS、iptables 和 nftables 規則 **不會** 被清理。
- CNI(網路外掛)配置 **不會** 被清理。
- 使用者主目錄中的
.kube/**不會** 被清理。
該命令包含以下階段
- 在節點上執行預檢檢查以確定其是否健康。
- 對於控制平面節點,移除任何本地 etcd 成員資料。
- 停止 kubelet。
- 停止正在執行的容器。
- 解除安裝
/var/lib/kubelet中任何已掛載的目錄。 - 刪除 kubeadm 在
/var/lib/kubelet和/etc/kubernetes中管理的所有檔案和目錄。