天天看點

關于ServiceAccount以及在叢集内通路K8S API

作者:不背鍋運維

在之前的兩篇文章中提到,有4種方式使用 ConfigMap 配置 Pod 中的容器,關于之前的兩篇可參考:

  • 《一文了解K8S的ConfigMap》
  • 《下篇1:将 ConfigMap 中的鍵值對作為容器的環境變量》

本篇的實戰場景就以通路API的方式讀取 ConfigMap,也就是編寫代碼在 Pod 中運作,然後使用 K8S API 來讀取 ConfigMap的内容。但是,這個場景涉及到服務賬号、K8S叢集内身份驗證的相關知識點。為了控制篇幅(主要是文章太長,擔心沒人看到最後),打算再拆分兩篇。本篇盡力先把涉及到的知識點搞清楚,下一篇再真正進入實戰環節,例如寫代碼,制作鏡像等等。

其實,這個實戰場景,也剛好彌補了在之前分享過的 下篇(開始寫代碼):運維開發人員不得不看的K8S API實戰》 中缺少的 “叢集内進行身份驗證” 的内容。

在繼續之前,如果對K8S API的使用套路還一無所知,可結合參考:

  • 《上篇:運維人員不得不看的K8S API入門實戰,嘔心瀝血整理得又臭又長,有人看嗎?》
  • 《下篇(開始寫代碼):運維開發人員不得不看的K8S API實戰》

K8S的賬号類型

在K8S中,主要有兩種賬号類型:

  1. User Accounts(使用者賬号):使用者賬号用于辨別和驗證 Kubernetes 叢集的使用者。使用者賬号通常由叢集管理者建立,并與相應的身份驗證憑據(如使用者名和密碼、令牌等)關聯。使用者賬号用于進行叢集管理操作,如建立、删除和更新資源,以及通路叢集中的敏感資訊。
  2. Service Accounts(服務賬号):服務賬号是用于身份驗證和授權 Pod 内的應用程式的一種機制。每個 Pod 都可以與一個 Service Account 相關聯,并使用該 Service Account 進行與 Kubernetes API Server 的通信。服務賬号通常用于在 Pod 内的應用程式與叢集中的其他資源進行互動,如讀取 ConfigMap、通路 Secrets 等。
更多資訊可參考官方文檔:authentication

關于ServiceAccount和在K8S叢集内身份驗證

上次的實戰場景 《下篇(開始寫代碼):運維開發人員不得不看的K8S API實戰》 主要是在K8S叢集外進行身份驗證,因為調用K8S API的代碼是運作在叢集外部。而這次的場景是:調用K8S API的代碼運作在POD容器裡,也就是要在K8S叢集内部進行身份驗證。

當調用K8S API的代碼(應用程式代碼)運作在POD裡的容器時,Pod中的應用程式可以使用其關聯的 ServiceAccount 去通路 API Server 中的 Kubernetes 資源(比如通路ConfigMap資源)。在通路資源時,ServiceAccount 會使用其所配置設定的 RBAC 角色來确定它有哪些權限。為了友善了解,我簡單畫了個圖,如下:

關于ServiceAccount以及在叢集内通路K8S API
  • 身份認證:應用程式可以使用與之關聯的 ServiceAccount 進行身份認證,以證明其對 Kubernetes 叢集中的資源的合法通路權限。
  • 通路授權:通過與通路控制政策(如 Role、ClusterRole)結合使用,可以為 ServiceAccount 配置設定特定的角色和權限,進而限制應用程式對資源的通路範圍和操作權限。
關于ServiceAccount的更多資訊可參考官方文檔:service-accounts

關于每個命名空間下預設的服務賬号:default

官方文檔提到:預設服務賬戶是Kubernetes在建立叢集時自動為每個命名空間建立的一個ServiceAccount對象。每個命名空間中的服務賬戶預設情況下沒有任何權限,除非啟用了基于角色的通路控制(RBAC),此時Kubernetes會授予所有經過身份驗證的主體預設的API發現權限。如果在一個命名空間中删除了ServiceAccount對象,控制平面會自動替換為一個新的ServiceAccount對象。如果在一個命名空間中部署一個Pod,并且沒有手動為Pod配置設定一個ServiceAccount,Kubernetes會将該命名空間的預設ServiceAccount配置設定給該Pod。

接下來,檢視一下預設命名空間(default)下的serviceaccount:

[root@k8s-b-master ~]# kubectl get serviceaccount
NAME      SECRETS   AGE
default   0         16d
[root@k8s-b-master ~]# kubectl get serviceaccount default -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2023-04-30T03:24:16Z"
  name: default
  namespace: default
  resourceVersion: "359"
  uid: 47c8dccd-2d91-47cf-b0b7-ce4d02b610a8
[root@k8s-b-master ~]# 
           

建立一個名為goweb的自定義命名空間,建立後,在該命名空間下已經自動建立了一個名為default的serviceaccount對象:

[root@k8s-b-master ~]# kubectl create ns goweb
namespace/goweb created
[root@k8s-b-master ~]# kubectl get serviceaccount -n goweb
NAME      SECRETS   AGE
default   0         8s
[root@k8s-b-master ~]# kubectl get serviceaccount default -n goweb -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2023-05-17T03:26:41Z"
  name: default
  namespace: goweb
  resourceVersion: "284809"
  uid: c0254d59-c625-4ef9-a619-1c51fdcfeef6
[root@k8s-b-master ~]# 
           

到了這裡,可能會提出這樣的問題:建立自定義的命名空間後,為什麼會自動建立一個名為default的ServiceAccount?

這是因為ServiceAccount是用于身份驗證和授權的一種機制,每個Pod都需要與一個ServiceAccount關聯,以确定Pod在叢集中的身份和權限。

預設的ServiceAccount是為了確定在建立Pod時不會發生錯誤。如果沒有顯式地指定Pod要使用的ServiceAccount,Kubernetes會自動将命名空間的預設ServiceAccount配置設定給該Pod。這樣,Pod就能夠獲得基本的權限和憑據,以便與叢集中的其他元件進行通信。

預設的ServiceAccount通常沒有具體的權限,除非通過其他方式為其配置設定了角色和權限。預設情況下,它隻擁有基本的API發現權限,允許Pod發現叢集中的其他API資源。

可以通過為Pod顯式指定不同的ServiceAccount來覆寫預設行為,以滿足特定的安全需求和通路控制政策,這也就是下篇要做的事情:為 Pod配置ServiceAccount。

為Pod配置ServiceAccount的步驟

為控制篇幅,為Pod配置ServiceAccount,以及編寫使用Go調用K8S API的代碼、制作鏡像等等均放到下篇分享。

為Pod配置ServiceAccount的步驟很簡單,下面僅給出步驟,如下:

  1. 建立ServiceAccount
  2. 建立Role:定義所需的權限
  3. 建立RoleBinding,将ServiceAccount和Role關聯起來
  4. 将ServiceAccount對象配置設定給Pod
更多資訊可參考官方文檔:configure-service-account

繼續閱讀