一、kubernetes訪問控制原理
Authentication(認證)
認證方式現共有8種,可以啓用一種或多種認證方式,只要有一種認證方式通過,就不再進行其它方式的認證。通常啓用X509 Client Certs和Service Accout Tokens兩種認證方式。
Kubernetes集羣有兩類用戶:由Kubernetes管理的Service Accounts (服務賬戶)和(Users Accounts) 普通賬戶。k8s中賬號的概念不是我們理解的賬號,它並不真的存在,它只是形式上存在。
Authorization(授權)
必須經過認證階段,纔到授權請求,根據所有授權策略匹配請求資源屬性,決定允許或拒絕請求。授權方式現共有6種,AlwaysDeny、AlwaysAllow、ABAC、RBAC、Webhook、Node。默認集羣強制開啓RBAC。
Admission Control(准入控制)
用於攔截請求的一種方式,運行在認證、授權之後,是權限認證鏈上的最後一環,對請求API資源對象進行修改和校驗。
注意:以上三個流程必須按照流程走,即先認證,再授權,最後准入控制。
訪問k8s的API Server的客戶端主要分爲兩類:
- kubectl :用戶家目錄中的 .kube/config 裏面保存了客戶端訪問API Server的密鑰相關信息,這樣當用kubectl訪問k8s時,它就會自動讀取該配置文件,向API Server發起認證,然後完成操作請求。
- pod:Pod中的進程需要訪問API Server,如果是人去訪問或編寫的腳本去訪問,這類訪問使用的賬號爲:UserAccount;而Pod自身去連接API Server時,使用的賬號是:ServiceAccount,生產中後者使用居多。
kubectl 向apiserver發起的命令,採用的是http方式,其實就是對URL發起增刪改查的操作。
$ kubectl proxy --port=8888 &
$ curl http://localhost:8888/api/v1/namespaces/default
$ curl http://localhost:8888/apis/apps/v1/namespaces/default/deployments
以上兩種api的區別是:
- api它是一個特殊鏈接,只有在核心v1羣組中的對象才能使用。
- apis 它是一般API訪問的入口固定格式名。
UserAccount與serviceaccount:
用戶賬戶是針對人而言的。 服務賬戶是針對運行在 pod 中的進程而言的。
用戶賬戶是全局性的。 其名稱在集羣各 namespace 中都是全局唯一的,未來的用戶資源不會做 namespace 隔離, 服務賬戶是 namespace 隔離的。
通常情況下,集羣的用戶賬戶可能會從企業數據庫進行同步,其創建需要特殊權限,並且涉及到複雜的業務流程。 服務賬戶創建的目的是爲了更輕量,允許集羣用戶爲了具體的任務創建服務賬戶 ( 即權限最小化原則 )。
二、認證示例
serviceaccount示例
創建serviceaccount:
$ kubectl create serviceaccount admin
serviceaccount/admin created
此時k8s爲用戶自動生成認證信息,但沒有授權
$ kubectl describe sa admin
Name: admin
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: admin-token-6xfpp
Tokens: admin-token-6xfpp
Events: <none>
添加secrets到serviceaccount中:
$ kubectl patch serviceaccount admin -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
把serviceaccount和pod綁定起來:
apiVersion: v1
kind: Pod
metadata:
name: myapp
labels:
app: myapp
spec:
containers:
- name: myapp
image: reg.westos.org/cl/nginx #私有倉庫
ports:
- name: http
containerPort: 80
serviceAccountName: admin
將認證信息添加到serviceAccount中,要比直接在Pod指定imagePullSecrets要安全很多。
UserAccount示例
創建UserAccount:
# cd /etc/kubernetes/pki/
# openssl genrsa -out test.key 2048 #輸出2048位加密的key
# openssl req -new -key test.key -out test.csr -subj "/CN=test" #製作名爲test.csr的證書請求
# openssl x509 -req -in test.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out test.crt -days 365 #申請證書
# openssl x509 -in test.crt -text -noout #查看證書
使用創建的證書:
$ kubectl config set-credentials test --client-certificate=/etc/kubernetes/pki/test.crt --client-key=/etc/kubernetes /pki/test.key --embed-certs=true #注入證書
$ kubectl config view #查看配置
$ kubectl config set-context test@kubernetes --cluster=kubernetes --user=test #將用戶test添加到context中
$ kubectl config use-context test@kubernetes #切換用戶
切換用戶後查看pod:
$ $ kubectl get pod
Error from server (Forbidden): pods is forbidden: User "test" cannot list resource "pods" in API group "" in the namespace "default"
此時用戶通過認證,但還沒有權限操作集羣資源,需要繼續添加授權。
注意授權時需要切換成 kubernetes-admin用戶。
三、RBAC 授權
RBAC(Role Based Access Control):基於角色訪問控制授權。
- 允許管理員通過Kubernetes API動態配置授權策略。RBAC就是用戶通過角色與權限進行關聯。
- RBAC只有授權,沒有拒絕授權,所以只需要定義允許該用戶做什麼即可。
- RBAC包括四種類型:Role、ClusterRole、RoleBinding、ClusterRoleBinding 即角色、角色綁定、集羣角色、集羣角色綁定。
RBAC的三個基本概念: - Subject:被作用者,它表示k8s中的三類主體, user, group, serviceAccount
- Role:角色,它其實是一組規則,定義了一組對 Kubernetes API 對象的操作權限。
- RoleBinding:定義了“被作用者”和“角色”的綁定關係。
Role 和 ClusterRole
- Role是一系列的權限的集合,Role只能授予單個namespace 中資源的訪問權限。
- ClusterRole 跟 Role 類似,但是可以在集羣中全局使用。
RoleBinding和ClusterRoleBinding
- RoleBinding是將Role中定義的權限授予給用戶或用戶組。它包含一個subjects列表(users,groups,service accounts),並引用該Role。
- RoleBinding是對某個namespace 內授權,ClusterRoleBinding適用在集羣範圍內使用。
四、RBAC示例
以下這些示例需要注意的是:在執行部署文件時需要切換成管理員,即kubernetes-admin。
Role示例
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: myrole
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list", "create", "update", "patch", "delete"]
上述部署文件定義可以個名爲myrole的角色,該角色具有對pod一系列操作[“get”, “watch”, “list”, “create”, “update”, “patch”, “delete”]
的權限,並且這個角色是針對默認的namespace。
可以使用 kubectl get role
查看創建的role。
RoleBinding示例
RoleBinding示例:
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: test-read-pods
namespace: default
subjects:
- kind: User
name: test
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: myrole
apiGroup: rbac.authorization.k8s.io
上述部署文件定義了一個名爲test-read-pods的RoleBinding,表示將 用戶test和角色 myrole進行綁定,使test用戶具有角色myrole所擁有的權限。
運行部署文件後切換成test用戶即可查看pod,但是也僅是默認命名空間下的pod,並不能操作svc 或者其他namespace中的pod,這些權限均是在角色中定義好的。
ClusterRole示例
集羣角色示例:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: myclusterrole
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list", "delete", "create", "update"]
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
該部署文件表示定義一個名爲myclusterrole的集羣角色,並且該即集羣角色對pods和deployments有一系列的權限。
使用角色綁定綁定集羣角色
使用rolebinding綁定clusterRole:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: rolebind-myclusterrole
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: myclusterrole
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: test
該部署文件表示使用角色綁定將用戶test與集羣角色myclusterrole進行綁定,使用戶test擁有集羣角色myclusterrole所擁有的權限。
注意該方法需要指定namespace。
運行該文件後test用戶可以對pods和deployments有一系列的操作,但是沒有svc和其他命名空間pod的權限。
clusterrolebinding示例
創建clusterrolebinding:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: clusterrolebinding-myclusterrole
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: myclusterrole
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: test
該部署文件表示使用集羣角色綁定將用戶test與集羣角色綁定,使用戶test在所有命名空間namespace中擁有對pods和deployments的一系列權限,這些權限在集羣角色的部署文件中定義。
六、服務賬戶的自動化
服務賬戶准入控制器(Service account admission controller)
- 如果該 pod 沒有 ServiceAccount 設置,將其 ServiceAccount 設爲 default。
- 保證 pod 所關聯的 ServiceAccount 存在,否則拒絕該 pod。
- 如果 pod 不包含 ImagePullSecrets 設置,那麼 將 ServiceAccount 中的 ImagePullSecrets 信息添加到 pod 中。
- 將一個包含用於 API 訪問的 token 的 volume 添加到 pod 中。
- 將掛載於 /var/run/secrets/kubernetes.io/serviceaccount 的 volumeSource 添加到 pod 下的每個容器中。
Token 控制器(Token controller)
-
檢測服務賬戶的創建,並且創建相應的 Secret 以支持 API 訪問。
-
檢測服務賬戶的刪除,並且刪除所有相應的服務賬戶 Token Secret。
-
檢測 Secret 的增加,保證相應的服務賬戶存在,如有需要,爲 Secret 增加 token。
-
檢測 Secret 的刪除,如有需要,從相應的服務賬戶中移除引用。
服務賬戶控制器(Service account controller)
- 服務賬戶管理器管理各命名空間下的服務賬戶,並且保證每個活躍的命名空間下存在一個名爲 “default” 的服務賬戶
Kubernetes 還擁有“用戶組”(Group)的概念:
ServiceAccount對應內置“用戶”的名字是:
system:serviceaccount:<ServiceAccount名字 >
而用戶組所對應的內置名字是:
system:serviceaccounts:<Namespace名字 >
示例1:表示mynamespace中的所有ServiceAccount
subjects:
- kind: Group
name: system:serviceaccounts:mynamespace
apiGroup: rbac.authorization.k8s.io
示例2:表示整個系統中的所有ServiceAccount
subjects:
- kind: Group
name: system:serviceaccounts
apiGroup: rbac.authorization.k8s.io
ubernetes 還提供了四個預先定義好的 ClusterRole 來供用戶直接使用:
- cluster-amdin 權限最大
- admin
- edit
- view 權限最小
示例:(最佳實踐)
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: readonly-default
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: view
apiGroup: rbac.authorization.k8s.io
上述部署文件表示將默認namespace下的默認ServiceAccount與內置的集羣角色view綁定,使這個ServiceAccount擁有查看集羣的權力。