ServiceAccount 是什么
Service Account為Pod中的進程和外部用戶提供身份信息。所有的kubernetes集群中賬戶分為兩類,Kubernetes管理的serviceaccount(服務賬戶)和useraccount(用戶賬戶)。
大家都知道api server的集群的入口,對於kunbernetes的api server 是肯定不能隨便訪問。所以我們必須需要一些認證信息。例如:
當用戶訪問集群(例如使用kubectl
命令)時,apiserver 會將您認證為一個特定的 User Account(目前通常是admin
,除非您的系統管理員自定義了集群配置)。Pod 容器中的進程也可以與 apiserver 聯系。 當它們在聯系 apiserver 的時候,它們會被認證為一個特定的 Service Account。
因為kubernetes是高度模塊化,所有認證方式和授權方式都可以通過插件的方式讓客戶自定義的,可以支持很多種。客戶端請求的時候首先需要進行認證,認證通過后再進行授權檢查,因有些操作需要級聯到其他資源或者環境,但是級聯環境是否有授權權限,這時候需要准入控制。
認證插件
- bearer token 當使用來自 http 客戶端的 bearer token 時,API server 期望
Authorization
header 中包含Bearer token
的值。Bearer token 必須是一個字符串序列,只需使用 HTTP 的編碼和引用功能就可以將其放入到 HTTP header 中。 - 客戶端證書 客戶端請求前需要,需要發送api server的辦法的證書,由api server來確認是否他來簽署的,引用的文件必須包含一個或多個證書頒發機構,用於驗證提交給 API server 的客戶端證書。如果客戶端證書已提交並驗證,則使用 subject 的 Common Name(CN)作為請求的用戶名。反過來,api server也要驗證客戶端的證書,所有對於客戶端也應該有一個證書,提供api server 驗證,此過程是雙向驗證。
- HTTP BASE 認證: 通過用戶名+密碼方式認證。
當啟用了多個認證模塊時,第一個認證模塊成功認證后將短路請求,不會進行第二個模塊的認證。API server 不會保證認證的順序。
用戶賬戶需要哪些信息:
- user 保護UserName和UID,UserName是標識最終用戶的字符串,UID是標識最終用戶的字符串,比用戶名更加一致切唯一。
- group 一組將用戶和常規用戶組相關聯的字符串
- extra 包含其他有用認證信息的字符串列表
上述是來自集群外部的訪問,我們可以理解成是User Account,是給kubernetes集群外部用戶,例如(系統管理員、用戶/租戶等)。Service Account而是給運行在Pod的容器、或者Pod使用的身份認證。
正常情況下,為了確保kubernetes集群的安全性,Api Server 都會給客戶端進行身份認證,但是Pod訪問Kubernetes Api Server服務時,也是需要身份認證的。如下圖:
我們在每一個namespace下看到都有一個secret,而我們看svc的時候,api server通過svc的訪問訪問的,他們的Endpoints是api server。
$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 52d $ kubectl describe svc kubernetes Name: kubernetes Namespace: default Labels: component=apiserver provider=kubernetes Annotations: <none> Selector: <none> Type: ClusterIP IP: 10.96.0.1 Port: https 443/TCP TargetPort: 6443/TCP Endpoints: 172.16.138.40:6443,172.16.138.41:6443 Session Affinity: None Events: <none> $ kubectl get secret -n default NAME TYPE DATA AGE default-token-lplp6 kubernetes.io/service-account-token 3 52d $ kubectl get secret -n ingress-nginx NAME TYPE DATA AGE default-token-v58zx kubernetes.io/service-account-token 3 52d
每個Namespace下都有一個名為default的默認的 Service Account對象,這個Service Account里面有一個名為Tokens的可以當作Volume一樣被Mount到Pod里的secret,當Pod啟動時候,這個Secret會自動Mount到Pod的指定目錄下,用來完成Pod中的進程訪問API server時的身份認證過程。下面可以看到
$ kubectl describe pod my-demo ..... Volumes: appindex: Type: HostPath (bare host directory volume) Path: /data/pod/myapp HostPathType: DirectoryOrCreate default-token-lplp6: Type: Secret (a volume populated by a Secret) SecretName: default-token-lplp6 Optional: false .....
創建一個serviceaccount
$ kubectl create serviceaccount jaxzhai $ kubectl get sa NAME SECRETS AGE default 1 52d jaxzhai 1 8s $ kubectl describe sa jaxzhai Name: jaxzhai Namespace: default Labels: <none> Annotations: <none> Image pull secrets: <none> Mountable secrets: jaxzhai-token-9n5th Tokens: jaxzhai-token-9n5th Events: <none>
$ kubectl get secret
NAME TYPE DATA AGE
default-token-lplp6 kubernetes.io/service-account-token 3 52d
jaxzhai-token-9n5th kubernetes.io/service-account-token 3 4m
這里我們看到Kubernetes集群會自動創建一個token的secert,並被jaxzhai這個serviceaccount引用。
設置非默認的 service account,只需要在 pod 的spec.serviceAccountName
字段中將name設置為您想要用的 service account 名字即可。
在 pod 創建之初 service account 就必須已經存在,否則創建將被拒絕。
您不能更新已創建的 pod 的 service account。
在pod中使用service account
apiVersion: v1 kind: Pod metadata: name: my-sa-demo namespace: default labels: name: myapp tier: appfront spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80 serviceAccountName: jaxzhai $ kubectl apply -f myapp-serviceaccount.yaml pod/my-sa-demo created $ kubectl describe pod my-sa-demo ...... Volumes: jaxzhai-token-9n5th: Type: Secret (a volume populated by a Secret) SecretName: jaxzhai-token-9n5th Optional: false QoS Class: BestEffort ......