- 1 核心設計原則
- 2 常量和衆所周知的值和路徑
- 3 kubeadm init 工做流程內部設計
- 3.1 預檢檢查
- 3.2 生成必要的證書
- 3.3 爲控制平面組件生成 kubeconfig 文件
- 3.4 爲控制平面組件生成靜態 Pod 清單
- 3.5 爲本地 etcd 生成靜態 Pod 清單
- 3.6 (可選,1.9 版本中爲 alpha)編寫 init kubelet 配置
- 3.7 等待控制平面啓動
- 3.8 (可選,1.9 版本中爲 alpha)編寫基本 kubelet 配置
- 3.9 將 kubeadm MasterConfiguration 保存在 ConfigMap 中供之後參考
- 3.10 標記 master
- 3.11 配置 TLS-引導 以加入節點
- 3.12 安裝插件
- 3.13 (可選,v1.9 中是 alpha)自託管
- 4 kubeadm join 階段的內部設計
- 5 TLS 引導
kubeadm init 和 kubeadm join 爲從頭開始建立一個 Kubernetes 集羣的最佳實踐共同提供了一個很好的用戶體驗。可是,kubeadm 如何 作到這一點可能並不明顯。前端
本文檔提供了有關發生了什麼事情的更多詳細信息,旨在分享關於 Kubernetes 集羣最佳實踐的知識。node
核心設計原則
使用 kubeadm init 和 kubeadm join 設置的集羣應該:linux
- 安全:
- 它應該採用最新的最佳作法,如:
- 強制實施 RBAC
- 使用節點受權器
- 控制平面組件之間使用安全通訊
- API server 和 kubelet 之間使用安全通訊
- 鎖定 kubelet API
- 鎖定對系統組件(如 kube-proxy 和 kube-dns)的 API 訪問權限
- 鎖定引導令牌能夠訪問的內容
- 等等
- 它應該採用最新的最佳作法,如:
- 使用方便:
- 用戶只需運行幾個命令便可:
- kubeadm init
- export KUBECONFIG=/etc/kubernetes/admin.conf
- kubectl apply -f <network-of-choice.yaml>
- kubeadm join --token <token> <master-ip>:<master-port>
- 用戶只需運行幾個命令便可:
- 可擴展:
- 例如,它 不 應該支持任何網絡提供商,相反,配置網絡應該是超出了它的範圍
- 應該提供使用配置文件自定義各類參數的可能性
常量和衆所周知的值和路徑
爲了下降複雜性並簡化 kubeadm 實施的部署解決方案的開發,kubeadm 使用一組有限的常量值,用於衆所周知的路徑和文件名。git
Kubernetes 目錄 /etc/kubernetes 在應用中是一個常量,由於它明顯是大多數狀況下的給定路徑,也是最直觀的位置; 其餘常量路徑和文件名是:github
- /etc/kubernetes/manifests 做爲 kubelet 尋找靜態 Pod 的路徑。靜態 Pod 清單的名稱是:
- etcd.yaml
- kube-apiserver.yaml
- kube-controller-manager.yaml
- kube-scheduler.yaml
- /etc/kubernetes/ 做爲存儲具備控制平面組件標識的 kubeconfig 文件的路徑。kubeconfig 文件的名稱是:
- kubelet.conf (bootstrap-kubelet.conf - 在 TLS 引導期間)
- controller-manager.conf
- scheduler.conf
- admin.conf 用於集羣管理員和 kubeadm 自己
- 證書和密鑰文件的名稱:
- ca.crt,ca.key 爲 Kubernetes 證書頒發機構
- apiserver.crt,apiserver.key 用於 API server 證書
- apiserver-kubelet-client.crt,apiserver-kubelet-client.key 用於由 API server 安全地鏈接到 kubelet 的客戶端證書
- sa.pub,sa.key 用於簽署 ServiceAccount 時控制器管理器使用的密鑰
- front-proxy-ca.crt,front-proxy-ca.key 用於前臺代理證書頒發機構
- front-proxy-client.crt,front-proxy-client.key 用於前端代理客戶端
kubeadm init 工做流程內部設計
kubeadm init 內部工做流程 由一系列要執行的原子工做任務組成,如 kubeadm init 所述。web
kubeadm alpha phase 命令容許用戶單獨調用每一個任務,並最終提供可重用和可組合的 API/工具箱,可供其餘 Kubernetes 引導工具、任何 IT 自動化工具或高級用戶建立自定義集羣使用。docker
預檢檢查
Kubeadm 在啓動 init 以前執行一組預檢檢查,目的是驗證先決條件並避免常見的集羣啓動問題。在任何狀況下,用戶均可以使用 --ignore-preflight-errors 選項跳過特定的預檢檢查(或最終全部預檢檢查)。json
- [警告]若是要使用的 Kubernetes 版本(與 --kubernetes-version 標記一塊兒指定)至少比 kubeadm CLI 版本高一個次要版本
- Kubernetes 系統要求:
- 若是在 Linux 上運行:
- [錯誤] 若是不是 Kernel 3.10+ 或具備特定 KernelSpec 的 4+
- [錯誤] 若是須要的 cgroups 子系統沒有設置
- 若是使用 docker:
- [警告/錯誤] 若是 Docker 服務不存在,若是它被禁用,若是它不是 active 狀態
- [錯誤] 若是 Docker 端點不存在或不起做用
- [警告] 若是 docker 版本 > 17.03
- 若是使用其餘 cri 引擎:
- [錯誤] 若是 crictl 沒有響應
- 若是在 Linux 上運行:
- [錯誤] 若是用戶不是root用戶
- [錯誤] 若是機器主機名不是有效的 DNS 子域
- [警告] 若是經過網絡查找沒法到達主機名
- [錯誤] 若是 kubelet 版本低於 kubeadm 支持的最小 kubelet 版本(當前小版本 -1)
- [錯誤] 若是 kubelet 版本至少比所需的控制平面版本更高一些(不受支持的版本)
- [警告] 若是 kubelet 服務不存在或禁用
- [警告] 若是 firewalld 處於活動狀態
- [錯誤] 若是 API server 的 bindPort 或者 port 10250/10251/10252 已經被使用
- [錯誤] 若是/etc/kubernetes/manifest 文件夾已經存在,而且非空
- [錯誤] 若是 /proc/sys/net/bridge/bridge-nf-call-iptables 文件不存在或者不包含 1
- [錯誤] 若是發佈地址是 ipv6 而且 /proc/sys/net/bridge/bridge-nf-call-ip6tables 不存在或者不包含 1
- [錯誤] 若是 swap 打開
- [錯誤] 若是 ip、iptables、mount 或者 nsenter 命令沒有出如今命令路徑中
- [警告] 若是 ebtables、ethtool、socat、tc、touch 和 crictl 命令沒有出如今命令路徑中
- [警告] 若是 API server、Controller-manager、Scheduler 的額外參數中包含一些無效的選項
- [警告] 若是鏈接到 https://API.AdvertiseAddress:API.BindPort 須要經過代理
- [警告] 若是鏈接到服務子網須要經過代理(只檢查第一個地址)
- [警告] 若是鏈接到 pod 子網須要經過代理(只檢查第一個地址)
- 若是提供外部 etcd:
- [錯誤] 若是 etcd 版本低於 3.0.14
- [錯誤] 若是指定了 etcd 證書或密鑰,但未提供
- 若是不提供外部 etcd(所以將安裝本地 etcd):
- [錯誤] 若是使用端口 2379
- [錯誤] 若是 Etcd.DataDir 文件夾已經存在而且不是空的
- 若是受權模式是 ABAC:
- [錯誤] 若是 abac_policy.json 不存在
- 若是受權模式是 WebHook:
- [錯誤] 若是 webhook_authz.conf 不存在
請注意:bootstrap
- 預檢檢查能夠經過 kubeadm alpha phase preflight 命令單獨調用
生成必要的證書
Kubeadm 爲不一樣目的生成證書和私鑰對:
- Kubernetes 集羣的自簽名證書頒發機構保存到 ca.crt 文件和 ca.key 私鑰文件中
- API server 的服務證書,使用 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
- 由用戶指定的其餘替代名稱
- 用於 API server 的安全鏈接到 kubelet 的客戶端證書,使用 ca.crt 做爲 CA 生成並使用私鑰 apiserver-kubelet-client.key 保存到文件 apiserver-kubelet-client.crt中。這個證書應該在 system:masters 組織中
- 一個用於簽名 ServiceAccount 令牌的私鑰,該令牌與它的公鑰 sa.pub 一塊兒保存到 sa.key 文件中。
- 前端代理的證書頒發機構保存到 front-proxy-ca.crt 文件中,其密鑰爲 front-proxy-ca.key
- 前端代理客戶端的客戶證書,使用 front-proxy-ca.crt 做爲 CA 生成,並使用其私鑰 front-proxy-client.key 保存到 front-proxy-client.crt 文件中
證書默認存儲在 /etc/kubernetes/pki 中,但該目錄可以使用 --cert-dir 標誌進行配置。
請注意:
- 若是給定的證書和私鑰對都存在,而且其內容評估符合上述規範,則將使用現有文件並跳過給定證書的生成階段。這意味着用戶能夠將現有 CA 複製到 /etc/kubernetes/pki/ca.{crt,key},而後 kubeadm 將使用這些文件來簽署剩餘的證書。請參與 使用自定義證書
- 只有 CA 能夠提供 ca.crt 文件,但不提供 ca.key 文件,若是全部其餘證書和 kubeconfig 文件已就位,kubeadm 會識別此狀況並激活 ExternalCA,這也意味着 controller-manager 中的 csrsigner 控制器將不會啓動
- 若是 kubeadm 在 ExternalCA 模式下運行; 全部的證書都必須由用戶提供,由於 kubeadm 自己不能生成它們
- 在 --dry-run 模式中執行 kubeadm 的狀況下,證書文件被寫入臨時文件夾中
- 使用 kubeadm alpha phase certs all 命令能夠單獨調用證書生成動做
爲控制平面組件生成 kubeconfig 文件
具備控制平面組件標識的 Kubeadm kubeconfig 文件:
- kubelet 使用的 kubeconfig 文件:/etc/kubernetes/kubelet.conf; 在這個文件內嵌入一個具備 kubelet 身份的客戶端證書。這個客戶證書應該:
- 在 system:nodes 組織中,符合 節點受權 模塊的要求
- 有 CN system:node:<hostname-lowercased>
- controller-manager 使用的 kubeconfig 文件:/etc/kubernetes/controller-manager.conf; 在這個文件內嵌入一個帶有 controller-manager 身份的客戶端證書。此客戶端證書應具備 CN system:kube-controller-manager,默認由 RBAC 核心組件角色 定義
- scheduler 使用的 kubeconfig 文件:/etc/kubernetes/scheduler.conf; 在這個文件內嵌入一個帶有 scheduler 標識的客戶端證書。此客戶端證書應具備 CN system:kube-scheduler,默認由 RBAC 核心組件角色 定義
此外,生成一個 kubeadm 去使用它本身以及管理員使用的 kubeconfig 文件,並保存到 /etc/kubernetes/admin.conf 文件中。這裏的 「管理員」 定義了正在管理集羣並但願徹底控制(root)集羣的實際人員。管理員的嵌入式客戶端證書應該:
- 在 system:masters 組織中,默認由 RBAC 用戶所面對的角色綁定 定義
- 包括一個 CN,但能夠是任何東西。Kubeadm 使用 kubernetes-admin CN
請注意:
- ca.crt 證書嵌入在全部 kubeconfig 文件中。
- 若是給定的 kubeconfig 文件存在,而且其內容的評估符合上述規範,則將使用現有文件,並跳過給定 kubeconfig 的生成階段
- 若是 kubeadm 以 ExternalCA 模式運行,則全部必需的 kubeconfig 也必須由用戶提供,由於 kubeadm 自己不能生成它們中的任何一個
- 若是在 --dry-run 模式下執行 kubeadm ,kubeconfig 文件將寫入臨時文件夾中
- 使用 kubeadm alpha phase kubeconfig all 命令能夠單獨調用 Kubeconfig 文件生成動做
爲控制平面組件生成靜態 Pod 清單
kubeadm 將控制平面組件的靜態 Pod 清單文件寫入 /etc/kubernetes/manifests; Kubelet 會監控這個目錄,在啓動時建立 pod。
靜態 Pod 清單共享一組通用屬性:
- 全部靜態 Pod 都部署在 kube-system 命名空間上
- 全部靜態 Pod 均可以獲取 tier:control-plane 和 component:{component-name} 標記
- 全部的靜態 Pod 都會得到 scheduler.alpha.kubernetes.io/critical-pod 註解(這將轉移到適當的解決方案,即在準備就緒時使用 pod 優先級和搶佔)
- 在全部靜態 Pod 上設置 hostNetwork: true,以便在網絡配置以前容許控制平面啓動; 所以:
- controller-manager 和 scheduler 使用來指代該 API server 的地址爲 127.0.0.1
- 若是使用本地 etcd 服務器,etcd-servers 地址將被設置爲 127.0.0.1:2379
- controller-manager 和 scheduler 均啓用選舉
- controller-manager 和 scheduler 將引用 kubeconfig 文件及其各自的惟一標識
- 全部靜態 Pod 都會得到用戶指定的額外標誌,如 將自定義參數傳遞給控制平面組件 所述
- 全部靜態 Pod 都會獲取用戶指定的任何額外卷(主機路徑)
請注意:
- --kubernetes-version 當前體系結構中的全部鏡像 將從中 gcr.io/google_containers 中拉取; 若是指定了其餘鏡像倉庫庫或 CI 鏡像倉庫,則將使用此倉庫; 若是一個特定的容器鏡像應該被用於全部控制平面組件,那麼這個特定鏡像將被使用。請參閱 使用自定義鏡像 瞭解更多詳情
- 若是在 --dry-run 模式下執行 kubeadm,則將靜態 Pod 文件寫入臨時文件夾
- 可使用 kubeadm alpha phase controlplane all 命令單獨調用生成主組件的靜態 Pod 清單
API server
API server 的靜態 Pod 清單受用戶提供的如下參數的影響:
- 須要指定要綁定到的 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 功能,將在將來的版本中刪除)
- 若是 kubeadm 被調用爲 --feature-gates=HighAvailability,則標誌 --endpoint-reconciler-type=lease 被設置,從而啓用內部 API server VIP 的 endpoints 的自動協調
- 若是 kubeadm 被調用爲 --feature-gates=DynamicKubeletConfig,則 API 服務器上的相應功能將經過 --feature-gates=DynamicKubeletConfig=true 標誌激活
其餘無條件設置的 API server 標誌是:
- --insecure-port=0 避免與 api server 的不安全鏈接
- --enable-bootstrap-token-auth=true 啓用 BootstrapTokenAuthenticator 驗證模塊。有關更多詳細信息,請參閱 TLS 引導
- --allow-privileged 爲 true (如 kube proxy 所要求的)
- --requestheader-client-ca-file 爲 front-proxy-ca.crt
- --admission-control 爲:
- Initializers 啓用 動態准入控制
- NamespaceLifecycle 例如避免刪除系統保留的命名空間
- LimitRanger 和 ResourceQuota 強制限制命名空間
- ServiceAccount 強制執行服務賬戶自動化
- PersistentVolumeLabel 將區域或區域標籤附加到由雲提供商定義的 PersistentVolumes (此准入控制器已被棄用,並將在將來的版本中被刪除。沒有明確選擇使用 gce 或 aws 做爲雲提供商時,它在默認狀況下跟 1.9 版本同樣,並非由 kubeadm 部署)
- DefaultStorageClass 在 PersistentVolumeClaim 對象上強制執行默認存儲類
- DefaultTolerationSeconds
- NodeRestriction 限制 kubelet 能夠修改的內容(例如,只有該節點上的 pod)
- --kubelet-preferred-address-types 爲 InternalIP,ExternalIP,Hostname;,這使得 kubectl logs 和其餘 api server-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 Aggregation)通訊的其餘標誌:
- --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
Controller manager
API server 的靜態 Pod 清單受用戶提供的如下參數的影響:
- 若是調用 kubeadm 時指定一個 --pod-network-cidr,某些 CNI 網絡插件所需的子網管理器功能能夠經過設置來啓用:
- --allocate-node-cidrs=true
- --cluster-cidr 和 --node-cidr-mask-size 根據給定的 CIDR 標誌
- 若是指定了雲提供商,則要配置相應的 --cloud-provider,若是這樣的文件存在,還要配置 --cloud-config 路徑(這是實驗性的、alpha 功能,將在將來的版本中刪除)
其餘無條件設置的標誌是:
- --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
Scheduler
Scheduler 的靜態 Pod 清單不受用戶提供的參數的影響。
爲本地 etcd 生成靜態 Pod 清單
若是用戶指定了外部 etcd,則此步驟將被跳過,不然 kubeadm 將生成一個靜態的 Pod 清單文件,用於建立在 Pod 中運行的本地 etcd 實例,其中包含如下屬性:
- 監聽 localhost:2379 並使用 HostNetwork=true
- 作一個 hostPath,從 dataDir 掛載到 主機文件系統
- 任何由用戶指定的額外標誌
請注意:
- etcd 鏡像將從中 gcr.io/google_containers 中拉取; 若是指定了其餘鏡像倉庫庫,則將使用此倉庫; 若是一個特定的容器鏡像應該被用於全部控制平面組件,那麼這個特定鏡像將被使用。請參閱 使用自定義鏡像 瞭解更多詳情
- 若是在 --dry-run 模式下執行 kubeadm,則將靜態 Pod 文件寫入臨時文件夾
- 可使用 kubeadm alpha phase etcd local 命令爲本地 etcd 生成的靜態 Pod 清單
(可選,1.9 版本中爲 alpha)編寫 init kubelet 配置
若是 kubeadm 被調用爲 --feature-gates=DynamicKubeletConfig,它會將 kubelet init 配置寫入 /var/lib/kubelet/config/init/kubelet 文件。
init 配置用於在此特定節點上啓動 kubelet,爲 kubelet 插入文件提供替代方案; 這種配置將被如下步驟中所述的 Kubelet 基本配置替代。請參閱 經過配置文件設置 Kubelet 參數 以獲取更多信息。
請注意:
- 要使動態 kubelet 配置正常工做,應該在 /etc/systemd/system/kubelet.service.d/10-kubeadm.conf 中指定標誌 --dynamic-config-dir=/var/lib/kubelet/config/dynamic
- 經過設置.kubeletConfiguration.baseConfig,Kubelet init 配置能夠經過使用 kubeadm MasterConfiguration 文件進行修改。請參閱 在配置文件中使用 kubelet init 以獲取更多信息。
等待控制平面啓動
這是 kubeadm 集羣的關鍵時刻。kubeadm 等待 localhost:6443/healthz 返回 ok,可是爲了檢測死鎖狀況,若是localhost:10255/healthz(kubelet liveness)或 localhost:10255/healthz/syncloop(kubelet readiness)分別在 40 秒和 60 秒後不返回 ok,kubeadm 就會快速失敗。
kubeadm 依靠 kubelet 來拉取控制平面鏡像,並以靜態 Pod 的形式正確運行它們。控制平面啓動後,kubeadm 完成如下段落中描述的任務。
(可選,1.9 版本中爲 alpha)編寫基本 kubelet 配置
若是 kubeadm 被調用爲 --feature-gates=DynamicKubeletConfig:
- 將 kubelet 基本配置寫入命名空間 kube-system 的 kubelet-base-config-v1.9 ConfigMap 中
- 建立 RBAC 規則來授予該 ConfigMap 對全部引導令牌和全部 kubelet 實例(即組 system:bootstrappers:kubeadm:default-node-token 和 system:nodes)的讀訪問權限
- 經過將 Node.spec.configSource 指向新建立的 ConfigMap 來爲初始主節點啓用動態 kubelet 配置功能
將 kubeadm MasterConfiguration 保存在 ConfigMap 中供之後參考
kubeadm 將 kubeadm init 經過標誌或配置文件傳遞給 ConfigMap 的配置保存在 kube-system 命名空間下的 kubeadm-config ConfigMap 中。
這將確保未來(例如 kubeadm upgrade)執行的 kubeadm 行動將可以肯定 實際/當前 的集羣狀態並基於該數據作出新的決定。
請注意:
- 在上傳以前,敏感信息(例如令牌)會從配置中刪除
- 主配置的上傳能夠經過 kubeadm alpha phase upload-config 命令單獨調用
- 若是您使用 kubeadm v1.7.x 或更低版本初始化集羣,則必須在使用 kubeadm upgrade 到 v1.8 以前手動建立 master 的配置 ConfigMap 。爲了促進這項任務,kubeadm config upload (from-flags|from-file) 已經實施
標記 master
一旦控制平面可用,kubeadm 將執行如下操做:
- 用 node-role.kubernetes.io/master="" 給 master 增長標籤
- 用 node-role.kubernetes.io/master:NoSchedule 給 master 增長污點
請注意:
- 標記 master 階段能夠經過 kubeadm alpha phase mark-master 命令單獨調用
配置 TLS-引導 以加入節點
Kubeadm 使用 引導令牌進行身份驗證 將新節點鏈接到現有集羣; 欲瞭解更多詳情,請參閱 設計方案。
kubeadm init 確保爲此過程正確配置全部內容,這包括如下步驟以及設置 API server 和控制器標誌,如前面幾個段落中所述。
請注意:
- 可使用 kubeadm alpha phase bootstrap-token all 命令配置節點的 TLS 引導,執行如下段落中描述的全部配置步驟; 或者,每一個步驟均可以單獨調用
建立一個引導令牌
kubeadm init 建立第一個引導令牌,能夠自動生成或由用戶使用 --token 標誌提供; 在引導令牌規範中,令牌應該保存爲命名空間 kube-system 下的 bootstrap-token-<token-id> 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 確保引導令牌將得到 csrapprover 控制器自動批准的 CSR 請求。
這是經過 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 控制器自動批准的 CSR 請求。
這是經過 system:nodes 組和默認的角色 system:certificates.k8s.io:certificatesigningrequests:selfnodeclient 之間建立一個名爲 kubeadm:node-autoapprove-certificate-rotation 的 ClusterRoleBinding 來實現的。
建立公共集羣信息 ConfigMap
此階段在 kube-public 命名空間中建立 cluster-info ConfigMap。
此外,還建立了一個角色和一個 RoleBinding,爲未經身份驗證的用戶授予對 ConfigMap 的訪問權(即 RBAC 組中的用戶 system:unauthenticated)
請注意:
- 訪問 cluster-info ConfigMap 是不 受限制的。若是您將您的主機暴露在互聯網上,這多是問題,也可能不是問題;最壞的狀況是 DoS 攻擊,攻擊者使用 Kube-apiserver 能夠處理的全部請求來爲 cluster-info ConfigMap 提供服務。
安裝插件
Kubeadm 經過 API server 安裝內部 DNS 服務和 kube-proxy 插件組件。
請注意:
- 這個階段能夠經過 kubeadm alpha phase addon all 命令單獨調用
代理
在命名空間 kube-system 下爲 kube-proxy 建立一個 ServiceAccount;而後使用 DaemonSet 部署 kube-proxy:
- master 的憑證(ca.crt 和 token)來自 ServiceAccount
- master 的位置來自 ConfigMap
- kube-proxy ServiceAccount 綁定到 system:node-proxier ClusterRole 中的權限
DNS
在命名空間 kube-system 下爲 kube-dns 建立一個 ServiceAccount。
部署 kube-dns 的 Deployment 和 Service:
- 這是相對上游來講沒有修改的 kube-dns 部署
- kube-dns ServiceAccount 綁定到 system:kube-dns ClusterRole 中的權限
請注意:
- 若是 kubeadm 被調用爲 --feature-gates=CoreDNS,則會安裝 CoreDNS 而不是 kube-dns
(可選,v1.9 中是 alpha)自託管
只有在 kubeadm init 被調用爲 —features-gates=selfHosting 才執行此階段
自託管階段基本上用 DaemonSet 取代控制平面組件的靜態 Pod; 這是經過執行 API server、scheduler 和 controller manager 靜態 Pod 的如下過程來實現的:
- 從磁盤加載靜態 Pod 規格
- 從靜態的 Pod 清單文件中提取 PodSpec
- 改變 PodSpec 與自託管兼容,更詳細的內容:
- 爲帶有 node-role.kubernetes.io/master="" 標籤的節點增長節點選擇器屬性
- 爲污點 node-role.kubernetes.io/master:NoSchedule 增長一個容忍
- 設置 spec.DNSPolicy 爲 ClusterFirstWithHostNet
- 爲有問題的自託管組件構建一個新的 DaemonSet 對象。使用上面提到的 PodSpec
- 在 kube-system 命名空間中建立 DaemonSet 資源。等到 Pod 運行。
- 刪除靜態的 Pod 清單文件。kubelet 將中止正在運行的原始靜態 Pod 託管組件
請注意:
- 自託管還沒有恢復到節點從新啓動的能力; 這能夠經過外部檢查點或控制平面 Pod 的 kubelet 檢查點來修正。有關更多詳細信息,請參閱 自託管。
- 若是被調用爲 —features-gates=StoreCertsInSecrets,如下附加步驟將被執行
- 在 kube-system 命名空間下使用各自的證書和祕鑰建立 ca、apiserver、apiserver-kubelet-client、sa、front-proxy-ca、front-proxy-client TLS secrets 。重要!將 CA 密鑰存儲在 Secret 中可能會產生安全隱患
- 使用各自的 kubeconfig 文件在命名空間 kube-system 中建立 schedler.conf 和 controller-manager.conf secret
- 經過將主機路徑卷替換爲上述 secret 中的投影卷,對全部 POD 規範進行變動
- 這個階段能夠經過 kubeadm alpha phase selfhosting convert-from-staticpods 命令單獨調用
kubeadm join 階段的內部設計
與 kubeadm init 相似,kubeadm join 內部工做流也是由一系列要執行的原子工做任務組成。
這分爲發現(有 Node 信任 Kubernetes Master)和 TLS 引導(有 Kubernetes Master 信任 Node)。
請參閱 使用引導令牌進行身份驗證 或相應的 設計方案。
預檢檢查
kubeadm 在開始鏈接以前執行一組預檢檢查,目的是驗證先決條件並避免常見的集羣啓動問題。
請注意:
- kubeadm join 預檢檢查基本上是一個 kubeadm init 預檢檢查的子集
- 從 1.9 開始,kubeadm 爲 CRI 泛型功能提供了更好的支持; 在這種狀況下,docker 特定的控件將被跳過或替換爲 crictl 相似控件
- 從 1.9 開始,kubeadm 支持加入運行在 Windows 上的節點; 在這種狀況下,會跳過 linux 特定的控制
- 在任何狀況下,用戶均可以使用該 --ignore-preflight-errors 選項跳過特定的預檢檢查(或最終全部預檢檢查)
發現集羣信息
有兩個主要的發現方案。首先是使用共享令牌以及 API server 的 IP 地址。第二個是提供一個文件(標準 kubeconfig 文件的一個子集)。
共享令牌發現
若是 kubeadm join 被調用爲 --discovery-token,則使用令牌發現; 在這種狀況下,節點基本上從命名空間 kube-public 下 cluster-info ConfigMap 中檢索集羣 CA 證書 。
爲了防止 「中間人」 攻擊,採起了幾個步驟:
- 首先,經過不安全的鏈接檢索 CA 證書(這是可能的,由於 kubeadm init 對 system:unauthenticated 授予了訪問 cluster-info 用戶的權限)
- 而後 CA 證書經過如下驗證步驟:
- 基本驗證:針對 JWT 簽名使用令牌 ID
- 發佈密鑰驗證:使用提供的 --discovery-token-ca-cert-hash。此值可在 kubeadm init 的輸出中獲取,也可使用標準工具計算(散列是在 SPKI(Subject Public Key Info)對象的字節上計算的,如 RFC 7469 中所示)。--discovery-token-ca-cert-hash 標誌能夠重複屢次,以容許多個公鑰。 -做爲附加驗證,CA 證書經過安全鏈接進行檢索,而後與最初檢索的 CA 進行比較
請注意:
- 經過 --discovery-token-unsafe-skip-ca-verification 標誌能夠跳過發佈密鑰驗證; 這削弱了 kubeadm 安全模型,由於其餘人可能潛在模仿 Kubernetes Master。
文件/https 發現
若是 kubeadm join 被調用爲 --discovery-file,則使用文件發現; 此文件能夠是本地文件或經過 HTTPS URL 下載; 在 HTTPS 的狀況下,主機安裝的 CA 用於驗證鏈接。
經過文件發現,集羣 CA 證書被提供到文件自己; 事實上,發現的文件是一個 kubeconfig 文件,其中只設置了 server 和 certificate-authority-data 屬性,如 kubeadm join 參考文檔中所述; 當與集羣創建鏈接時,kubeadm 嘗試訪問 cluster-info ConfigMap,若是可用,則使用它。
TLS 引導
一旦知道了集羣信息,就會編寫文件 bootstrap-kubelet.conf,從而容許 kubelet 執行 TLS 引導(相反,直到 v1.7 TLS 引導被 kubeadm 管理)。
TLS 引導機制使用共享令牌臨時向 Kubernetes Master 進行身份驗證,以提交本地建立的密鑰對的證書籤名請求(CSR)。
而後自動批准該請求,而且該操做完成保存 ca.crt 文件和用於加入集羣的 kubelet.conf 文件,而 bootstrap-kubelet.conf 被刪除。
請注意:
- 臨時驗證是根據 kubeadm init 過程當中保存的令牌進行驗證的(或者使用 kubeadm token 建立的附加令牌)
- 對 kubeadm init 過程當中被授予訪問 CSR api 的 system:bootstrappers:kubeadm:default-node-token 組的用戶成員的臨時身份驗證解析
- 自動 CSR 審批由 csrapprover 控制器管理,與 kubeadm init 過程的配置相一致
(可選,1.9 版本中爲 alpha)編寫init kubelet配置
若是 kubeadm 被調用爲 --feature-gates=DynamicKubeletConfig:
- 使用引導令牌憑據從 kube-system 命名空間中的 kubelet-base-config-v1.9 ConfigMap 中讀取 kubelet 基本配置,並將其寫入磁盤,做爲 kubelet init 配置文件 /var/lib/kubelet/config/init/kubelet
- 當 kubelet 以節點本身的憑據(/etc/kubernetes/kubelet.conf)開始時,更新當前節點配置,指定 node/kubelet 配置的源是上面的 ConfigMap。
請注意:
- 要使動態 kubelet 配置正常工做,應在 /etc/systemd/system/kubelet.service.d/10-kubeadm.conf 中指定標誌 --dynamic-config-dir=/var/lib/kubelet/config/dynamic
譯者:chentao1596 / 原文連接