[轉帖]kubeadm 實現細節

kubeadm 實現細節

http://docs.kubernetes.org.cn/829.htmlhtml

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 沒有響應
  • [錯誤] 若是用戶不是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

  1. 預檢檢查能夠經過 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 標誌進行配置。

請注意:

  1. 若是給定的證書和私鑰對都存在,而且其內容評估符合上述規範,則將使用現有文件並跳過給定證書的生成階段。這意味着用戶能夠將現有 CA 複製到 /etc/kubernetes/pki/ca.{crt,key},而後 kubeadm 將使用這些文件來簽署剩餘的證書。請參與 使用自定義證書
  2. 只有 CA 能夠提供 ca.crt 文件,但不提供 ca.key 文件,若是全部其餘證書和 kubeconfig 文件已就位,kubeadm 會識別此狀況並激活 ExternalCA,這也意味着 controller-manager 中的 csrsigner 控制器將不會啓動
  3. 若是 kubeadm 在 ExternalCA 模式下運行; 全部的證書都必須由用戶提供,由於 kubeadm 自己不能生成它們
  4. 在 --dry-run 模式中執行 kubeadm 的狀況下,證書文件被寫入臨時文件夾中
  5. 使用 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)集羣的實際人員。管理員的嵌入式客戶端證書應該:

請注意:

  1. ca.crt 證書嵌入在全部 kubeconfig 文件中。
  2. 若是給定的 kubeconfig 文件存在,而且其內容的評估符合上述規範,則將使用現有文件,並跳過給定 kubeconfig 的生成階段
  3. 若是 kubeadm 以 ExternalCA 模式運行,則全部必需的 kubeconfig 也必須由用戶提供,由於 kubeadm 自己不能生成它們中的任何一個
  4. 若是在 --dry-run 模式下執行 kubeadm ,kubeconfig 文件將寫入臨時文件夾中
  5. 使用 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 都會獲取用戶指定的任何額外卷(主機路徑)

請注意:

  1. --kubernetes-version 當前體系結構中的全部鏡像 將從中 gcr.io/google_containers 中拉取; 若是指定了其餘鏡像倉庫庫或 CI 鏡像倉庫,則將使用此倉庫; 若是一個特定的容器鏡像應該被用於全部控制平面組件,那麼這個特定鏡像將被使用。請參閱 使用自定義鏡像 瞭解更多詳情
  2. 若是在 --dry-run 模式下執行 kubeadm,則將靜態 Pod 文件寫入臨時文件夾
  3. 可使用 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 掛載到 主機文件系統
  • 任何由用戶指定的額外標誌

請注意:

  1. etcd 鏡像將從中 gcr.io/google_containers 中拉取; 若是指定了其餘鏡像倉庫庫,則將使用此倉庫; 若是一個特定的容器鏡像應該被用於全部控制平面組件,那麼這個特定鏡像將被使用。請參閱 使用自定義鏡像 瞭解更多詳情
  2. 若是在 --dry-run 模式下執行 kubeadm,則將靜態 Pod 文件寫入臨時文件夾
  3. 可使用 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 參數 以獲取更多信息。

請注意:

  1. 要使動態 kubelet 配置正常工做,應該在 /etc/systemd/system/kubelet.service.d/10-kubeadm.conf 中指定標誌 --dynamic-config-dir=/var/lib/kubelet/config/dynamic
  2. 經過設置.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:

  1. 將 kubelet 基本配置寫入命名空間 kube-system 的 kubelet-base-config-v1.9 ConfigMap 中
  2. 建立 RBAC 規則來授予該 ConfigMap 對全部引導令牌和全部 kubelet 實例(即組 system:bootstrappers:kubeadm:default-node-token 和 system:nodes)的讀訪問權限
  3. 經過將 Node.spec.configSource 指向新建立的 ConfigMap 來爲初始主節點啓用動態 kubelet 配置功能

將 kubeadm MasterConfiguration 保存在 ConfigMap 中供之後參考

kubeadm 將 kubeadm init 經過標誌或配置文件傳遞給 ConfigMap 的配置保存在 kube-system 命名空間下的 kubeadm-config ConfigMap 中。

這將確保未來(例如 kubeadm upgrade)執行的 kubeadm 行動將可以肯定 實際/當前 的集羣狀態並基於該數據作出新的決定。

請注意:

  1. 在上傳以前,敏感信息(例如令牌)會從配置中刪除
  2. 主配置的上傳能夠經過 kubeadm alpha phase upload-config 命令單獨調用
  3. 若是您使用 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 增長污點

請注意:

  1. 標記 master 階段能夠經過 kubeadm alpha phase mark-master 命令單獨調用

配置 TLS-引導 以加入節點

Kubeadm 使用 引導令牌進行身份驗證 將新節點鏈接到現有集羣; 欲瞭解更多詳情,請參閱 設計方案

kubeadm init 確保爲此過程正確配置全部內容,這包括如下步驟以及設置 API server 和控制器標誌,如前面幾個段落中所述。

請注意:

  1. 可使用 kubeadm alpha phase bootstrap-token all 命令配置節點的 TLS 引導,執行如下段落中描述的全部配置步驟; 或者,每一個步驟均可以單獨調用

建立一個引導令牌

kubeadm init 建立第一個引導令牌,能夠自動生成或由用戶使用 --token 標誌提供; 在引導令牌規範中,令牌應該保存爲命名空間 kube-system 下的 bootstrap-token-<token-id> secret 中。

請注意:

  1. 經過 kubeadm init 建立的默認令牌將用於 TLS 在引導過程當中驗證臨時用戶;這些用戶將成爲 system:bootstrappers:kubeadm:default-node-token 組的成員
  2. 令牌的有效期有限,默認 24 小時(間隔可使用 —token-ttl 標誌變動)
  3. 額外的令牌可使用 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)

請注意:

  1. 訪問 cluster-info ConfigMap 是不 受限制的。若是您將您的主機暴露在互聯網上,這多是問題,也可能不是問題;最壞的狀況是 DoS 攻擊,攻擊者使用 Kube-apiserver 能夠處理的全部請求來爲 cluster-info ConfigMap 提供服務。

安裝插件

Kubeadm 經過 API server 安裝內部 DNS 服務和 kube-proxy 插件組件。

請注意:

  1. 這個階段能夠經過 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 中的權限

請注意:

  1. 若是 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 託管組件

請注意:

  1. 自託管還沒有恢復到節點從新啓動的能力; 這能夠經過外部檢查點或控制平面 Pod 的 kubelet 檢查點來修正。有關更多詳細信息,請參閱 自託管
  2. 若是被調用爲 —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 規範進行變動
  3. 這個階段能夠經過 kubeadm alpha phase selfhosting convert-from-staticpods 命令單獨調用

kubeadm join 階段的內部設計

與 kubeadm init 相似,kubeadm join 內部工做流也是由一系列要執行的原子工做任務組成。

這分爲發現(有 Node 信任 Kubernetes Master)和 TLS 引導(有 Kubernetes Master 信任 Node)。

請參閱 使用引導令牌進行身份驗證 或相應的 設計方案

預檢檢查

kubeadm 在開始鏈接以前執行一組預檢檢查,目的是驗證先決條件並避免常見的集羣啓動問題。

請注意:

  1. kubeadm join 預檢檢查基本上是一個 kubeadm init 預檢檢查的子集
  2. 從 1.9 開始,kubeadm 爲 CRI 泛型功能提供了更好的支持; 在這種狀況下,docker 特定的控件將被跳過或替換爲 crictl 相似控件
  3. 從 1.9 開始,kubeadm 支持加入運行在 Windows 上的節點; 在這種狀況下,會跳過 linux 特定的控制
  4. 在任何狀況下,用戶均可以使用該 --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 進行比較

請注意:

  1. 經過 --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:

  1. 使用引導令牌憑據從 kube-system 命名空間中的 kubelet-base-config-v1.9 ConfigMap 中讀取 kubelet 基本配置,並將其寫入磁盤,做爲 kubelet init 配置文件 /var/lib/kubelet/config/init/kubelet
  2. 當 kubelet 以節點本身的憑據(/etc/kubernetes/kubelet.conf)開始時,更新當前節點配置,指定 node/kubelet 配置的源是上面的 ConfigMap。

請注意:

  1. 要使動態 kubelet 配置正常工做,應在 /etc/systemd/system/kubelet.service.d/10-kubeadm.conf 中指定標誌 --dynamic-config-dir=/var/lib/kubelet/config/dynamic

譯者:chentao1596 / 原文連接

相關文章
相關標籤/搜索