天天看點

一文帶你徹底厘清 Kubernetes 中的證書工作機制

雲栖号資訊:【 點選檢視更多行業資訊

在這裡您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!

接觸 Kubernetes 以來,我經常看到 Kubernetes 在不同的地方使用了證書(Certificate),在 Kubernetes 安裝群組件啟動參數中也需要配置大量證書相關的參數。但是 Kubernetes 的文檔在解釋這些證書的工作機制方面做得并不是太好。經過大量的相關閱讀和分析工作後,我基本弄清楚了 Kubernetes 中證書的使用方式。在本文中,我将試圖以一種比官方文檔更容易了解的方式來說明 Kubernetes 中證書相關的工作機制,如果你也存在這方面的疑惑,希望這篇文章對你有所幫助。

Kubernetes 元件的認證方式

首先讓我們來看一下 Kubernetes 中的元件:在 Kubernetes 中包含多個以獨立程序形式運作的元件,這些元件之間通過 HTTP/GRPC 互相通信,以協同完成叢集中應用的部署和管理工作。

一文帶你徹底厘清 Kubernetes 中的證書工作機制

Kubernetes 元件,圖檔來源kubernetes.io

從圖中可以看到,Kubernetes 控制平面中包含了 etctd,kube-api-server,kube-scheduler,kube-controller-manager 等元件,這些元件會互相進行遠端調用,例如 kube-api-server 會調用 etcd 接口存儲資料,kube-controller-manager 會調用 kube-api-server 接口查詢叢集中的對象狀态;同時,kube-api-server 也會和在工作節點上的 kubelet 和 kube-proxy 進行通信,以在工作節點上部署和管理應用。

以上這些元件之間的互相調用都是通過網絡進行的。在進行網絡通信時,通信雙方需要驗證對方的身份,以避免惡意第三方僞造身份竊取資訊或者對系統進行攻擊。為了互相驗證對方的身份,通信雙方中的任何一方都需要做下面兩件事情:

  • 向對方提供标明自己身份的一個證書
  • 驗證對方提供的身份證書是否合法,是否僞造的?

在 Kubernetes 中使用了數字證書來提供身份證明,我們可以把數字證書簡單了解為我們在日常生活中使用的“身份證”,上面标注了證書擁有者的身份資訊,例如名稱,所屬組織機構等。為了保證證書的權威性,會采用一個通信雙方都信任的 CA(證書機構,Certificate Authority)來頒發證書。這就類似于現實生活中頒發“身份證”的政府機構。數字證書中最重要的内容實際上是證書擁有者的公鑰,該公鑰代表了使用者的身份。本文假設讀者已經了解數字證書和 CA 的基本原理,如果你對此不太清楚,或者希望重新溫習一下相關知識。

CA (證書機構),圖檔來源www.trustauth.cn

在 Kubernetes 的元件之間進行通信時,數字證書的驗證是在協定層面通過 TLS 完成的,除了需要在建立通信時提供相關的證書和密鑰外,在應用層面并不需要進行特殊處理。采用 TLS 進行驗證有兩種方式:

  • 伺服器單向認證:隻需要伺服器端提供證書,用戶端通過伺服器端證書驗證服務的身份,但伺服器并不驗證用戶端的身份。這種情況一般适用于對 Internet 開放的服務,例如搜尋引擎網站,任何用戶端都可以連接配接到伺服器上進行通路,但用戶端需要驗證伺服器的身份,以避免連接配接到僞造的惡意伺服器。
  • 雙向 TLS 認證:除了用戶端需要驗證伺服器的證書,伺服器也要通過用戶端證書驗證用戶端的身份。這種情況下伺服器提供的是敏感資訊,隻允許特定身份的用戶端通路。

在 Kubernetes 中,各個元件提供的接口中包含了叢集的内部資訊。如果這些接口被非法通路,将影響叢集的安全,是以元件之間的通信需要采用雙向 TLS 認證。即用戶端和伺服器端都需要驗證對方的身份資訊。在兩個元件進行雙向認證時,會涉及到下面這些證書相關的檔案:

  • 伺服器端證書:伺服器用于證明自身身份的數字證書,裡面主要包含了伺服器端的公鑰以及伺服器的身份資訊。
  • 伺服器端私鑰:伺服器端證書中包含的公鑰所對應的私鑰。公鑰和私鑰是成對使用的,在進行 TLS 驗證時,伺服器使用該私鑰來向用戶端證明自己是伺服器端證書的擁有者。
  • 用戶端證書:用戶端用于證明自身身份的數字證書,裡面主要包含了用戶端的公鑰以及用戶端的身份資訊。
  • 用戶端私鑰:用戶端證書中包含的公鑰所對應的私鑰,同理,用戶端使用該私鑰來向伺服器端證明自己是用戶端證書的擁有者。
  • 伺服器端 CA 根證書:簽發伺服器端證書的 CA 根證書,用戶端使用該 CA 根證書來驗證伺服器端證書的合法性。
  • 用戶端端 CA 根證書:簽發用戶端證書的 CA 根證書,伺服器端使用該 CA 根證書來驗證用戶端證書的合法性。

下面這張來自《The magic of TLS, X509 and mutual authentication explained》文章中的圖形象地解釋了雙向 TLS 認證的原理。如果你需要了解更多關于 TLS 認證的原理,可以閱讀一下 Medium 上的原文。

一文帶你徹底厘清 Kubernetes 中的證書工作機制

圖檔來源 The magic of TLS, X509 and mutual authentication explained

Kubernetes 中使用到的CA和證書

Kubernetes 中使用了大量的證書,本文不會試圖覆寫到所有可能使用到的證書,但會讨論到主要的證書。了解了這些證書的使用方法和原理後,也能很快了解其他可能遇到的證書檔案。下圖示識出了在 Kubernetes 中主要使用到的證書和其使用的位置:

一文帶你徹底厘清 Kubernetes 中的證書工作機制

Kubernetes 中使用到的主要證書

上圖中使用序号對證書進行了标注。圖中的箭頭表明了元件的調用方向,箭頭所指方向為服務提供方,另一頭為服務調用方。為了實作 TLS 雙向認證,服務提供方需要使用一個伺服器證書,服務調用方則需要提供一個用戶端證書,并且雙方都需要使用一個 CA 證書來驗證對方提供的證書。為了簡明起見,上圖中隻标注了證書使用方提供的證書,并沒有标注證書的驗證方驗證使用的 CA 證書。圖中标注的這些證書的作用分别如下:

  • etcd 叢集中各個節點之間互相通信使用的證書。由于一個 etctd 節點既為其他節點提供服務,又需要作為用戶端通路其他節點,是以該證書同時用作伺服器證書和用戶端證書。
  • etcd 叢集向外提供服務使用的證書。該證書是伺服器證書。
  • kube-apiserver 作為用戶端通路 etcd 使用的證書。該證書是用戶端證書。
  • kube-apiserver 對外提供服務使用的證書。該證書是伺服器證書。
  • kube-controller-manager 作為用戶端通路 kube-apiserver 使用的證書,該證書是用戶端證書。
  • kube-scheduler 作為用戶端通路 kube-apiserver 使用的證書,該證書是用戶端證書。
  • kube-proxy 作為用戶端通路 kube-apiserver 使用的證書,該證書是用戶端證書。
  • kubelet 作為用戶端通路 kube-apiserver 使用的證書,該證書是用戶端證書。
  • 管理者使用者通過 kubectl 通路 kube-apiserver 使用的證書,該證書是用戶端證書。
  • kubelet 對外提供服務使用的證書。該證書是伺服器證書。
  • kube-apiserver 作為用戶端通路 kubelet 采用的證書。該證書是用戶端證書。
  • kube-controller-manager 用于生成和驗證 service-account token 的證書。該證書并不會像其他證書一樣用于身份認證,而是将證書中的公鑰/私鑰對用于 service account token 的生成和驗證。kube-controller-manager 會用該證書的私鑰來生成 service account token,然後以 secret 的方式加載到 Pod 中。Pod 中的應用可以使用該 token 來通路 kube-apiserver, kube-apiserver 會使用該證書中的公鑰來驗證請求中的 token。我們将在文中稍後部分詳細介紹該證書的使用方法。

通過這張圖,對證書機制比較了解的讀者可能已經看出,我們其實可以使用多個不同的 CA 來頒發這些證書。隻要在通信的元件中正确配置用于驗證對方證書的 CA 根證書,就可以使用不同的 CA 來頒發不同用途的證書。但我們一般建議采用統一的 CA 來頒發 kubernetes 叢集中的所有證書,這是因為采用一個叢集根 CA 的方式比采用多個 CA 的方式更容易管理,可以避免多個CA 導緻的複雜的證書配置、更新等問題,減少由于證書配置錯誤導緻的叢集故障。

Kubernetes 中的證書配置

前面我們介紹了 Kubernetes 叢集中主要使用到的證書。下面我們分别看一下如何将這些證書及其對應的私鑰和 CA 根證書需要配置到 Kubernetes 中各個元件中,以供各個元件進行使用。這裡假設使用一個叢集根 CA 來頒發所有相關證書,是以涉及到 CA 的配置對應的證書檔案名都是相同的。

etcd 證書配置

需要在 etcd 的啟動指令行中配置以下證書相關參數:

  • etcd 對外提供服務的伺服器證書及私鑰。
  • etcd 節點之間互相進行認證的 peer 證書、私鑰以及驗證 peer 的 CA。
  • etcd 驗證通路其服務的用戶端的 CA。
/usr/local/bin/etcd \
--cert-file=/etc/etcd/kube-etcd.pem \                   # 對外提供服務的伺服器證書
--key-file=/etc/etcd/kube-etcd-key.pem \                # 伺服器證書對應的私鑰
--peer-cert-file=/etc/etcd/kube-etcd-peer.pem \         # peer 證書,用于 etcd 節點之間的互相通路
--peer-key-file=/etc/etcd/kube-etcd-peer-key.pem \      # peer 證書對應的私鑰
--trusted-ca-file=/etc/etcd/cluster-root-ca.pem \       # 用于驗證通路 etcd 伺服器的用戶端證書的 CA 根證書
--peer-trusted-ca-file=/etc/etcd/cluster-root-ca.pem\   # 用于驗證 peer 證書的 CA 根證書
           

kube-apiserver 證書配置

需要在 kube-apiserver 中配置以下證書相關參數:

  • kube-apiserver 對外提供服務的伺服器證書及私鑰。
  • kube-apiserver 通路 etcd 所需的用戶端證書及私鑰。
  • kube-apiserver 通路 kubelet 所需的用戶端證書及私鑰。
  • 驗證通路其服務的用戶端的 CA。
  • 驗證 etcd 伺服器證書的 CA 根證書。
  • 驗證 service account token 的公鑰。
/usr/local/bin/kube-apiserver \ 
--tls-cert-file=/var/lib/kubernetes/kube-apiserver.pem \                             # 用于對外提供服務的伺服器證書
--tls-private-key-file=/var/lib/kubernetes/kube-apiserver-key.pem \                  # 伺服器證書對應的私鑰
--etcd-certfile=/var/lib/kubernetes/kube-apiserver-etcd-client.pem \                 # 用于通路 etcd 的用戶端證書
--etcd-keyfile=/var/lib/kubernetes/kube-apiserver-etcd-client-key.pem \              # 用于通路 etcd 的用戶端證書的私鑰
--kubelet-client-certificate=/var/lib/kubernetes/kube-apiserver-kubelet-client.pem \ # 用于通路 kubelet 的用戶端證書
--kubelet-client-key=/var/lib/kubernetes/kube-apiserver-kubelet-client-key.pem \     # 用于通路 kubelet 的用戶端證書的私鑰
--client-ca-file=/var/lib/kubernetes/cluster-root-ca.pem \                           # 用于驗證通路 kube-apiserver 的用戶端的證書的 CA 根證書
--etcd-cafile=/var/lib/kubernetes/cluster-root-ca.pem \                              # 用于驗證 etcd 伺服器證書的 CA 根證書  
--kubelet-certificate-authority=/var/lib/kubernetes/cluster-root-ca.pem \            # 用于驗證 kubelet 伺服器證書的 CA 根證書
--service-account-key-file=/var/lib/kubernetes/service-account.pem \                 # 用于驗證 service account token 的公鑰
           

采用 kubeconfig 通路 kube-apiserver

Kubernetes 中的各個元件,包括kube-controller-mananger、kube-scheduler、kube-proxy、kubelet等,采用一個kubeconfig 檔案中配置的資訊來通路 kube-apiserver。該檔案中包含了 kube-apiserver 的位址,驗證 kube-apiserver 伺服器證書的 CA 證書,自己的用戶端證書和私鑰等通路資訊。

在一個使用 minikube 安裝的叢集中,生成的 kubeconfig 配置檔案如下所示,這四個檔案分别為 admin 使用者, kube-controller-mananger、kubelet 和 kube-scheduler 的kubeconfig配置檔案。

一文帶你徹底厘清 Kubernetes 中的證書工作機制

我們打開 controller-manager.conf 來看一下。

server: https://localhost:8443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: system:kube-controller-manager
name: system:kube-controller-manager@kubernetes
current-context: system:kube-controller-manager@kubernetes
kind: Config
preferences: {}
users:
- name: system:kube-controller-manager
user:
# 用于通路 kube-apiserver 的用戶端證書
           
# 用戶端證書對應的私鑰

client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBMEk3YUlzV3poMUl           

可以看到,通路 kube-apiserver 所需要的相關證書内容已經被采用 base64 編碼寫入了檔案中。其他幾個檔案中的内容也是類似的,隻是配置的使用者名和用戶端證書有所不同。

在啟動這些元件時,需要在參數中指出 kubeconfig 檔案的路徑,例如 kube-controller-manager 的啟動指令如下。

--kubeconfig=/etc/kubernetes/controller-manager.conf 
# 下面幾個證書和通路 kube-apiserver 無關,我們會在後面介紹到
--cluster-signing-cert-file=/var/lib/kubernetes/cluster-root-ca.pem             # 用于簽發證書的 CA 根證書
--cluster-signing-key-file=/var/lib/kubernetes/cluster-root-ca-key.pem          # 用于簽發證書的 CA 根證書的私鑰  
--service-account-private-key-file=/var/lib/kubernetes/service-account-key.pem  # 用于對 service           

Service Account 證書

Kubernetes 中有兩類使用者,一類為 user account,一類為 service account。 service account 主要被 pod 用于通路 kube-apiserver。 在為一個 pod 指定了 service account 後,kubernetes 會為該 service account 生成一個 JWT token,并使用 secret 将該 service account token 加載到 pod 上。pod 中的應用可以使用 service account token 來通路 api server。service account 證書被用于生成和驗證 service account token。該證書的用法和前面介紹的其他證書不同,因為實際上使用的是其公鑰和私鑰,而并不需要對證書進行驗證。

我們可以看到 service account 證書的公鑰和私鑰分别被配置到了 kube-apiserver 和 kube-controller-manager 的指令行參數中,如下所示:

--service-account-key-file=/var/lib/kubernetes/service-account.pem \\          # 用于驗證 service account token 的公鑰
...

/usr/local/bin/kube-controller-manager \\
--service-account-private-key-file=/var/lib/kubernetes/service-account-key.pem  # 用于對 servi           

下圖展示了 Kubernetes 中生成、使用和驗證 service account token 的過程。

一文帶你徹底厘清 Kubernetes 中的證書工作機制

認證方法:用戶端證書還是 token ?

我們可以看到,Kubernetes 提供了兩種用戶端認證的方法,控制面元件采用的是用戶端數字證書;而在叢集中部署的應用則采用了 service account token 的方式。為什麼 Kubernetes 不為 service account 也生成一個證書,并采用該證書進行身份認證呢? 實際上 Istio 就是這樣做的,Istio 會自動為每個 service account 生成一個證書,并使用該證書來在 pod 中的應用之間建立雙向 tls 認證。我沒有找到 Kubernetes 這個設計決策的相關說明,如果你知道原因或對此有自己的見解,歡迎聯系我進行探讨。

Kubernetes 證書簽發

Kubernetes 提供了一個 certificates.k8s.io API,可以使用配置的 CA 根證書來簽發使用者證書。該 API 由 kube-controller-manager 實作,其簽發證書使用的根證書在下面的指令行中進行配置。我們希望 Kubernetes 采用叢集根 CA 來簽發使用者證書,是以在 kube-controller-manager 的指令行參數中将相關參數配置為了叢集根 CA。

/usr/local/bin/kube-controller-manager \
--cluster-signing-cert-file=/var/lib/kubernetes/cluster-root-ca.pem             # 用于簽發證書的 CA 根證書
--cluster-signing-key-file=/var/lib/kubernetes/cluster-root-ca-key.pem          # 用于簽發證書的 CA 根證書的私鑰  
... 
           

使用 TLS bootstrapping 簡化 Kubelet 證書制作

在安裝 Kubernetes 時,我們需要為每一個工作節點上的 Kubelet 分别生成一個證書。由于工作節點可能很多,手動生成 Kubelet 證書的過程會比較繁瑣。為了解決這個問題,Kubernetes 提供了 TLS bootstrapping 的方式來簡化 Kubelet 證書的生成過程。其原理是預先提供一個 bootstrapping token,kubelet 通過該 kubelet 調用 kube-apiserver 的證書簽發 API 來生成 自己需要的證書。要啟用該功能,需要在 kube-apiserver 中啟用 --enable-bootstrap-token-auth ,并建立一個 kubelet 通路 kube-apiserver 使用的 bootstrap token secret。如果使用 kubeadmin 安裝,可以使用 kubeadm token create指令來建立 token。

采用TLS bootstrapping 生成證書的流程如下:

1.調用 kube-apiserver 生成一個 bootstrap token。

2.将該 bootstrap token 寫入到一個 kubeconfig 檔案中,作為 kubelet 調用 kube-apiserver 的用戶端驗證方式。

3.通過 --bootstrap-kubeconfig 啟動參數将 bootstrap token 傳遞給 kubelet 程序。

4.Kubelet 采用 bootstrap token 調用 kube-apiserver API,生成自己所需的伺服器和用戶端證書。

5.證書生成後,Kubelet 采用生成的證書和 kube-apiserver 進行通信,并删除本地的 kubeconfig 檔案,以避免 bootstrap token 洩漏風險。

小結

Kubernetes 中使用了大量的證書來確定叢集的安全,弄清楚這些證書的用途和配置方法将有助于我們深入了解 Kubernetes 的安裝過程群組件的配置。本文是筆者在學習 過程中整理的 Kubernetes 叢集中主要使用到的證書,由于筆者對 Kubernetes 的了解有限,文章中難免存在部分錯誤,歡迎指正。

【雲栖号線上課堂】每天都有産品技術專家分享!

課程位址:

https://yqh.aliyun.com/live

立即加入社群,與專家面對面,及時了解課程最新動态!

【雲栖号線上課堂 社群】

https://c.tb.cn/F3.Z8gvnK

原文釋出時間:2020-05-21

本文作者:大衛

本文來自:“

dockone

”,了解相關資訊可以關注“dockone”

繼續閱讀