導讀
上一篇說了k8s的RBAC授權模式,今天就來簡單看一下其中涉及到的ServiceAccount。
簡介
k8s創建兩套獨立的賬號系統,原因如下:
(1)User賬號給用戶用,Service Account是給Pod里的進程使用的,面向的對象不同
(2)User賬號是全局性的,Service Account則屬於某個具體的Namespace
(3)User賬號是與后端的用戶數據庫同步的,創建一個新用戶通常要走一套復雜的業務流程才能實現,Service Account的創建則需要極輕量級的實現方式,集群管理員可以很容易地為某些特定任務創建一個Service Account
(4)對於一個復雜的系統來說,多個組件通常擁有各種賬號的配置信息,Service Account是Namespace隔離的,可以針對組件進行一對一的定義,同時具備很好的“便攜性”
Controller Manager創建了ServiceAccount Controller和Token Controller這兩個安全相關的控制器。其中ServiceAccount Controller一直監聽Service Account和Namespace的事件,如果在一個Namespace中沒有default Service Account,那么Service Account會給Namespace創建一個默認(default)的Service Account。
如果Controller manager進程在啟動時指定API Service私鑰(service-accountprivate-key-file參數),那么Controller manager會創建Token Controller,Token Controller也監聽Service Account事件。
當我們在API Server的鑒權過程中啟用了Service Account類型的准入控制器,即在kube-apiserver啟動參數中包括下面的內容時:
--admission_control=ServiceAccount
則針對Pod新增或修改的請求,Service Account准入控制器會驗證Pod里的Service Account是否合法:
(1)如果spec.serviceAccount域沒有被設置,則Kubernetes默認為其指定名稱為default的Service Account。
(2)如果指定了spec.serviceAccountName並且不是default,如果此Service Account不存在,則該Pod操作失敗。
(3)如果在Pod中沒有指定ImagePullSecrets,那么這個spec.serviceAccount域指定的Service Account的ImagePullSecrets會自動加入到該Pod中。
(4)給Pod添加一個特殊的Volume,在該Volume中包含ServiceAccount Secret中的Token,並將Volume掛載到Pod中所有容器的指定目錄下(/var/run/secrets/kubernetes.io/serviceaccount)。
ServiceAccount
ServiceAccount是一種賬號,給運行在Pod里面的進程提供必要的身份證明。
做過業務系統的同學應該都知道系統中會有一種叫做角色的定義,角色是擁有某些權限的集合,而上一篇說到的Role就是這個角色,而這個ServiceAccount就相當於是擁有某個角色的賬號,也就擁有了某些權限。

為了確保k8s集群的安全,API Server都會對客戶端進行安全認證。在Pod中訪問API Server服務時,是以Service方式訪問名為Kubernetes這個服務的,是以類似HTTP Token的新認證方式:Service Account Auth,Pod在調用API Server時,在Http Header中傳遞了一個Token字符串,類似於之前提到的Http Token認證方式,有以下幾處不同:
(1)Token內容來自Pod指定路徑下的一個文件(文件名為token),由Kubernetes Controller進程用API Server的私鑰(--service-account-private-zkey-file指定的私鑰)簽名指定生成的一個JWT Secret。
(2)通過HTTPS方式與API Server建立連接后,會用Pod里指定路徑下的一個CA證書(文件名為ca.crt)驗證API Server發來的證書,驗證是否為CA證書簽名的合法證書。
(3)API Server收到Token后,采用自身私鑰(service-accountkey-file指定,如果沒有指定,則默認采用tls-private-key-file指定的參數)對Token進行合法性驗證。
上面的認證過程中所涉及的Pod中的以下三個文件:token、ca.crt、namespace,三個文件都在/run/secrets/kubernetes.io/serviceaccount目錄下

這三個文件由於參與到Pod進程和API Server認證的過程中,起到了類似Secret(私密憑據)的作用,所以被稱為Kubernetes Secret對象,Secret從屬於Service Account資源對象,一個Service Account對象里面可以包括多個不同的Secret對象,分別用於不同目的的認證活動。
一個Secret也是有這三樣東西:

查看Service Account詳細信息
kubectl describe serviceaccounts
查看Secret
kubectl get secrets
在每個Namespace下都有一個名為default的默認Service Account對象,在這個ServiceAccount里面有一個名為Tokens的可以當做Volume被掛載到Pod里的Secret,當Pod啟動時,這個Secret會自動被掛載到Pod的指定目錄下,用來協助完成Pod中的進程訪問API Server時的身份鑒權。


一個ServiceAccount可包含多個Secret
其中
(1)名為Tokens的Secret用於訪問API Server的Secret,也被稱為Service Account Secret。
(2)名為imagePullSecrets的Secret用於下載容器鏡像時的認證過程,通常鏡像庫運行在Insecure模式下,所以這個為空
(3)用戶自定義的其他Secret,用於用戶的進程。
如果一個Pod在定義時沒有指定spec.serviceAccountName屬性,則會默認賦值為default,可進行如下指定:
apiVersion: v1 kind: Pod metadata: name: pod spec: containers: - name: podtest image: nginx serviceAccountName: myServiceAccount
創建ServiceAccount
apiVersion: v1 kind: ServiceAccount metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard-admin namespace: kube-system
將這個ServiceAccount跟ClusterRole進行綁定:
apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: kubernetes-dashboard-admin labels: k8s-app: kubernetes-dashboard roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: kubernetes-dashboard-admin namespace: kube-system
這樣ServiceAccount就擁有了ClusterRole的權限
在Pod中使用ServiceAccount
apiVersion: v1 kind: Pod metadata: name: pod namespace: kube-system spec: containers: - name: podtest image: nginx serviceAccountName: kubernetes-dashboard-admin
===============================
我是Liusy,一個喜歡健身的程序員。
歡迎關注微信公眾號【上古偽神】,一起交流Java技術及健身,獲取更多干貨,領取Java進階干貨,領取最新大廠面試資料,一起成為Java大神。
來都來了,關注一波再溜唄。