Kubernetes中的使用者
K8S中有兩種使用者(User)——服務賬號(ServiceAccount)和普通意義上的使用者(User)
ServiceAccount是由K8S管理的,而User通常是在外部管理,K8S不儲存使用者列表——也就是說,新增/編輯/刪除使用者都是在外部進行,無需與K8S API互動,雖然K8S並不管理使用者,但是在K8S接收API請求時,是可以認知到發出請求的使用者的,實際上,所有對K8S的API請求都需要繫結身份資訊(User或者ServiceAccount),這意味著,可以為User配置K8S叢集中的請求許可權
有什麼區別?
最主要的區別上面已經說過了,即ServiceAccount是K8S內部資源,而User是獨立於K8S之外的。從它們的本質可以看出:
-
User通常是人來使用,而ServiceAccount是某個服務/資源/程式使用的
-
User獨立在K8S之外,也就是說User是可以作用於全域性的,在任何名稱空間都可被認知,並且需要在全域性唯一
而ServiceAccount作為K8S內部的某種資源,是存在於某個名稱空間之中的,在不同名稱空間中的同名ServiceAccount被認為是不同的資源 -
K8S不會管理User,所以User的建立/編輯/登出等,需要依賴外部的管理機制,K8S所能認知的只有一個使用者名稱
ServiceAccount是由K8S管理的,建立等操作,都通過K8S完成
這裡說的新增使用者指的是普通意義上的使用者,即存在於叢集外的使用者,為k8s的使用者。
實際上叫做新增使用者也不準確,使用者早已存在,這裡所做的只是使K8S能夠試別此使用者,並且控制此使用者在叢集內的許可權
使用者驗證
儘管K8S認知使用者靠的只是使用者的名字,但是隻需要一個名字就能請求K8S的API顯然是不合理的,所以依然需要驗證此使用者的身份
在K8S中,主要有以下幾種驗證方式:
-
X509客戶端證書
客戶端證書驗證通過為API Server指定--client-ca-file=xxx
選項啟用,API Server通過此ca檔案來驗證API請求攜帶的客戶端證書的有效性,一旦驗證成功,API Server就會將客戶端證書Subject裡的CN屬性作為此次請求的使用者名稱 -
靜態token檔案
通過指定--token-auth-file=SOMEFILE
選項來啟用bearer token驗證方式,引用的檔案是一個包含了 token,使用者名稱,使用者ID 的csv檔案
請求時,帶上Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269
頭資訊即可通過bearer token驗證 -
靜態密碼檔案
通過指定--basic-auth-file=SOMEFILE
選項啟用密碼驗證,類似的,引用的檔案時一個包含 密碼,使用者名稱,使用者ID 的csv檔案
請求時需要將Authorization
頭設定為Basic BASE64ENCODED(USER:PASSWORD)
這裡只介紹客戶端驗證
為使用者生成證書
假設我們操作的使用者名稱為tom
-
首先需要為此使用者建立一個私鑰
openssl genrsa -out tom.key 2048
-
接著用此私鑰建立一個csr(證書籤名請求)檔案,其中我們需要在subject裡帶上使用者資訊(CN為使用者名稱,O為使用者組)
openssl req -new -key tom.key -out tom.csr -subj "/CN=tom/O=MGM"
其中/O引數可以出現多次,即可以有多個使用者組 -
找到K8S叢集(API Server)的CA證書檔案,其位置取決於安裝叢集的方式,通常會在
/etc/kubernetes/pki/
路徑下,會有兩個檔案,一個是CA證書(ca.crt),一個是CA私鑰(ca.key) -
通過叢集的CA證書和之前建立的csr檔案,來為使用者頒發證書
openssl x509 -req -in tom.csr -CA path/to/ca.crt -CAkey path/to/ca.key -CAcreateserial -out tom.crt -days 365
-CA和-CAkey引數需要指定叢集CA證書所在位置,-days引數指定此證書的過期時間,這裡為365天 -
最後將證書(tom.crt)和私鑰(tom.key)儲存起來,這兩個檔案將被用來驗證API請求
為使用者新增基於角色的訪問控制(RBAC)
角色(Role)
在RBAC中,角色有兩種——普通角色(Role)和叢集角色(ClusterRole),ClusterRole是特殊的Role,相對於Role來說:
-
Role屬於某個名稱空間,而ClusterRole屬於整個叢集,其中包括所有的名稱空間
-
ClusterRole能夠授予叢集範圍的許可權,比如node資源的管理,比如非資源型別的介面請求(如"/healthz"),比如可以請求全名稱空間的資源(通過指定 --all-namespaces)
為使用者新增角色
首先創造一個角色
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: a-1
name: admin
rules:
- apiGroups: [""]
resources: ["*"]
verbs: ["*"]
這是在a-1名稱空間內建立了一個admin管理員角色,這裡只是用admin角色舉例,實際上如果只是為了授予使用者某名稱空間管理員的許可權的話,是不需要新建一個角色的,K8S已經內建了一個名為admin的ClusterRole
將角色和使用者繫結
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: admin-binding
namespace: a-1
subjects:
- kind: User
name: tom
apiGroup: ""
roleRef:
kind: Role
name: admin
apiGroup: ""
如yaml中所示,RoleBinding資源建立了一個 Role-User 之間的關係,roleRef
節點指定此RoleBinding所引用的角色,subjects
節點指定了此RoleBinding的受體,可以是User,也可以是前面說過的ServiceAccount,在這裡只包含了名為 tom 的使用者
新增名稱空間管理員的另一種方式
前面說過,K8S內建了一個名為admin的ClusterRole,所以實際上我們無需建立一個admin Role,直接對叢集預設的admin ClusterRole新增RoleBinding就可以了
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: admin-binding
namespace: a-1
subjects:
- kind: User
name: tom
apiGroup: ""
roleRef:
kind: ClusterRole
name: admin
apiGroup: ""
這裡雖然引用的是作為ClusterRole的admin角色,但是其許可權被限制在RoleBinding admin-binding所處的名稱空間,即a-1內
如果想要新增全名稱空間或者說全叢集的管理員,可以使用cluster-admin角色
到此為止,我們已經:
- 為tom使用者提供了基於X509證書的驗證
- 為a-1名稱空間創造了一個admin角色
- 為使用者tom和角色admin建立了繫結關係
為kubectl配置使用者
tom已經是管理員了,現在我們想要通過kubectl以tom的身份來操作叢集,需要將tom的認證資訊新增進kubectl的配置,即~/.kube/config中
這裡假設config中已經配置好了k8s叢集
-
通過命令
kubectl config set-credentials tom --client-certificate=path/to/tom.crt --client-key=path/to/tom.key
將使用者tom的驗證資訊新增進kubectl的配置
此命令會在配置中新增一個名為tom的使用者 -
kubectl config set-context tom@aliyun --cluster=aliyun --namespace=a-1 --user=tom
此命令新增了一個context配置——設定使用aliyun叢集,預設使用a-1名稱空間,使用使用者tom進行驗證 -
在命令中帶上
kubectl --context=tom@aliyun ...
引數即可指定kubectl使用之前新增的名為tom@aliyun的context操作叢集
也可以通過命令kubectl config use-context tom@aliyun
來設定當前使用的context
Tips: 將認證資訊嵌入kubectl的配置中
通過kubectl config set-credentials
命令新增的使用者,其預設使用的是引用證書檔案路徑的方式,表現在~/.kube/config中,就是:
users:
- name: tom
user:
client-certificate: path/to/tom.crt
client-key: path/to/tom.key
如果覺得這樣總是帶著兩個證書檔案不方便的話,可以將證書內容直接放到config檔案裡
-
將tom.crt/tom.key的內容用BASE64編碼
cat tom.crt | base64 --wrap=0
cat tom.key | base64 --wrap=0
-
將獲取的編碼後的文字複製進config檔案中
users:
- name: ich
user:
client-certificate-data: ...
client-key-data: ...
這樣就不再需要證書和私鑰檔案了,當然這兩個檔案還是儲存起來比較好
與企業自有使用者系統整合
通常來說,對於Kubernetes的操作是由平臺或應用的運維人員來完成,多數情況下,可以直接為相應人員手動或者自動地建立證書或service account,不需要與企業人員系統整合。
如果確實有與企業人員系統整合的需求的話,可以考慮:
- 實現自動化的證書籤發並繫結到企業人員系統中
- 使用OIDC認證外掛,尤其是在企業人員系統已經支援OIDC的情況下,比如企業如果使用Azure ActiveDirectory或者Google Identity作為企業的Identity Provider時,這些Identity Provider均已實現了OIDC
- 使用Webhook Token Authentication
參考資料:
Authenticating - Kubernetes Docs
Configure RBAC in your Kubernetes Cluster
Using RBAC Authorization - Kubernetes Docs
Kubectl Reference Docs#config
Kubernetes auth: X509 client certificates