一、簡介 kubernetes 集群相關所有的交互都通過apiserver來完成,對於這樣集中式管理的系統來說,許可權管理尤其重要,在1.5版的時候引入了RBAC(Role Base Access Control)的許可權控制機制。 啟用RBAC,需要在 apiserver 中添加參數--authori ...
目錄
一、簡介
kubernetes 集群相關所有的交互都通過apiserver來完成,對於這樣集中式管理的系統來說,許可權管理尤其重要,在1.5版的時候引入了RBAC(Role Base Access Control)的許可權控制機制。
啟用RBAC,需要在 apiserver 中添加參數--authorization-mode=RBAC,如果使用的kubeadm安裝的集群,1.6+版本都預設開啟了RBAC。
$ grep -C3 'authorization-mode' /etc/kubernetes/manifests/kube-apiserver.yaml
API Server目前支持以下幾種授權策略:
- AlwaysDeny:表示拒絕所有請求,一般用於測試。
- AlwaysAllow:允許接收所有請求。
如果集群不需要授權流程,則可以採用該策略,這也是Kubernetes的預設配置。 - ABAC(Attribute-Based Access Control):基於屬性的訪問控制。
表示使用用戶配置的授權規則對用戶請求進行匹配和控制。 - Webhook:通過調用外部REST服務對用戶進行授權。
- RBAC:Role-Based Access Control,基於角色的訪問控制(本章講解)。
- Node:是一種專用模式,用於對kubelet發出的請求進行訪問控制。
更多許可權管理,可參考:http://docs.kubernetes.org.cn/51.html#Kubernetes
二、用戶分類
K8s的用戶分兩種,一種是普通用戶,一種是ServiceAccount(服務賬戶)。
1、普通用戶
- 普通用戶是假定被外部或獨立服務管理的。管理員分配私鑰。平時常用的kubectl命令都是普通用戶執行的。
- 如果是用戶需求許可權,則將Role與User(或Group)綁定(這需要創建User/Group),是給用戶使用的。
2、ServiceAccount(服務賬戶)**
- ServiceAccount(服務帳戶)是由Kubernetes API管理的用戶。它們綁定到特定的命名空間,並由API伺服器自動創建或通過API調用手動創建。服務帳戶與存儲為Secrets的一組證書相關聯,這些憑據被掛載到pod中,以便集群進程與Kubernetes API通信。(登錄dashboard時我們使用的就是ServiceAccount)
- 如果是程式需求許可權,將Role與ServiceAccount指定(這需要創建ServiceAccount並且在deployment中指定ServiceAccount),是給程式使用的。
相當於Role是一個類,用作許可權申明,User/Group/ServiceAccount將成為類的實例。
工作流程圖
三、K8s角色&角色綁定(以ServiceAccount展開講解)
1)授權介紹
在RABC API中,通過如下的步驟進行授權:
- 定義角色:在定義角色時會指定此角色對於資源的訪問控制的規則。
- 綁定角色:將主體與角色進行綁定,對用戶進行訪問授權。
角色
- Role:授權特定命名空間的訪問許可權
- ClusterRole:授權所有命名空間的訪問許可權
角色綁定
- RoleBinding:將角色綁定到主體(即subject)
- ClusterRoleBinding:將集群角色綁定到主體
主體(subject)
- User:用戶
- Group:用戶組
- ServiceAccount:服務賬號
圖解如下:
2)角色(Role和ClusterRole)
Role是許可權的定義,在kubernetes中角色分為兩種一種是Role針對特定的命名空間,一種是ClusterRole在整個集群範圍內都生效。
Role示例如下:
cat >Role-001.yaml<<EOF
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-role
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
EOF
$ kubectl apply -f Role-001.yaml
$ kubectl get role -n default
$ kubectl describe role pod-role -n default
ClusterRole示例如下:
cat >ClusterRole-001.yaml<<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-clusterrole
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
EOF
$ kubectl apply -f ClusterRole-001.yaml
$ kubectl get clusterrole pod-clusterrole
$ kubectl describe clusterrole pod-clusterrole
相關參數
1、Role、ClsuterRole Verbs可配置參數
"get", "list", "watch", "create", "update", "patch", "delete", "exec"
2、Role、ClsuterRole Resource可配置參數
"services", "endpoints", "pods","secrets","configmaps","crontabs","deployments","jobs","nodes","rolebindings","clusterroles","daemonsets","replicasets","statefulsets","horizontalpodautoscalers","replicationcontrollers","cronjobs"
3、Role、ClsuterRole APIGroup可配置參數
"","apps", "autoscaling", "batch"
3)角色綁定(RoleBinding和ClusterRoleBinding)
定義好了角色也就是一個許可權的集合,然後創建了一個ServiceAccount也就是一個服務賬號,然後將這兩個東西綁定起來,就是授權的過程了。
1、Role角色綁定ServiceAccount
$ cat >RoleBinding-001.yaml<<EOF
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rb
namespace: default
subjects:
- kind: ServiceAccount
name: zhangsan
namespace: default
roleRef:
kind: Role
name: pod-role
apiGroup: rbac.authorization.k8s.io
EOF
$ kubectl apply -f RoleBinding-001.yaml
$ kubectl get RoleBinding
$ kubectl describe RoleBinding rb
2、ClusterRole角色綁定ServiceAccount
$ cat >ClusterRoleBinding-001.yaml<<EOF
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: crb
subjects:
- kind: ServiceAccount
name: mark
namespace: default
roleRef:
kind: ClusterRole
name: pod-clusterrole
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: mark
namespace: default
EOF
$ kubectl apply -f ClusterRoleBinding-001.yaml
$ kubectl get ClusterRoleBinding crb
$ kubectl describe ClusterRoleBinding crb
上面只是說到了綁定ServiceAccount,其實還有兩種類型:User,Group,綁定類似,把subjects.kind。
四、實戰
儘管無法通過 API 調用來添加給kubernetes增加普通用戶,Kubernetes 仍然認為能夠提供由集群的證書 機構簽名的合法證書的用戶是通過身份認證的用戶。基於這樣的配置,Kubernetes 使用證書中的 'subject' 的通用名稱(Common Name)欄位(例如,"/CN=devuser")來 確定用戶名, Kubernetes使用證書中的 'subject' 的單位名稱 (Organization Name) 欄位(例如,"/O=system:masters")來確定用戶組。接下來,基於角色訪問控制(RBAC)子系統會確定用戶是否有權針對 某資源執行特定的操作。
Kubernetes 有著以下幾個內建的用於特殊目的的組:
- system:unauthenticated :未能通過任何一個授權插件檢驗的賬號,即未通過認證測 試的用戶所屬的組 。
- system :authenticated :認證成功後的用戶自動加入的一個組,用於快捷引用所有正常通過認證的用戶賬號。
- system : serviceaccounts :當前系統上的所有 Service Account 對象。
- system :serviceaccounts :<namespace>:特定命名空間內所有的 Service Account 對象。
1)User
1、創建K8S 用戶
普通用戶並不是通過k8s來創建和維護,是通過創建證書和切換上下文環境的方式來創建和切換用戶。
a、創建證書
# 創建私鑰
$ openssl genrsa -out devuser.key 2048
# 用此私鑰創建一個csr(證書簽名請求)文件
$ openssl req -new -key devuser.key -subj "/CN=devuser" -out devuser.csr
# 拿著私鑰和請求文件生成證書
$ openssl x509 -req -in devuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out devuser.crt -days 365
b、生成賬號
$ kubectl config set-credentials devuser --client-certificate=./devuser.crt --client-key=./devuser.key --embed-certs=true
c、設置上下文參數
# # 設置上下文, 預設會保存在 $HOME/.kube/config
$ kubectl config set-context devuser@kubernetes --cluster=kubernetes --user=devuser --namespace=dev
# 查看
$ kubectl config get-contexts
d、設置 預設上下文
$ kubectl config use-context devuser@kubernetes
# 查看
$ kubectl config get-contexts
$ kubectl get nodes
發現使用我們創建的用戶查詢是失敗的,是因為賬號還沒授權,接下來就是對賬號進行授權。這裡需要先把用切回來,要不然就無法進行下一步授權了。
$ kubectl config use-context kubernetes-admin@kubernetes
$ kubectl get nodes
2、對用戶授權
$ cat >devuser-role-bind<<EOF
kind: Role # 角色
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: dev
name: devuser-role
rules:
- apiGroups: [""] # ""代表核心api組
resources: ["pods"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: RoleBinding # 角色綁定
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: devuser-rolebinding
namespace: dev
subjects:
- kind: User
name: devuser # 目標用戶
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: devuser-role # 角色信息
apiGroup: rbac.authorization.k8s.io
EOF
執行並驗證
$ kubectl apply -f devuser-role-bind
$ kubectl config use-context devuser@kubernetes
$ kubectl get pods # 不帶命名空間,這裡預設dev,也只能查看dev上面限制的命名空間的pods資源,從而也驗證了role是針對命名空間的許可權限制
#查看其它命名空間的資源
$ kubectl get pods -n default
$ kubectl get pods -n kube-system
$ kubectl get nodes
可以看到,用devuser,已經可以管理dev命名空間下的pod資源了,也只能管理dev命名空間下的pod資源,無法管理dev以外的資源類型,驗證ok。ClusterRoleBinding綁定類似,這裡就不重覆了。有興趣的小伙伴可以試試。
切回管理員用戶
$ kubectl config use-context kubernetes-admin@kubernetes
2)Group
因為跟user類型,這裡就不過多文字介紹,直接上命令和配置
1、創建K8S 用戶和用戶組
# 創建私鑰
$ openssl genrsa -out devgroupuser.key 2048
# 用此私鑰創建一個csr(證書簽名請求)文件
$ openssl req -new -key devgroupuser.key -subj "/O=devgroup/CN=devgroupuser" -out devgroupuser.csr
# 拿著私鑰和請求文件生成證書
$ openssl x509 -req -in devgroupuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out devgroupuser.crt -days 365
# 生成賬號
$ kubectl config set-credentials devgroupuser --client-certificate=./devgroupuser.crt --client-key=./devgroupuser.key --embed-certs=true
# 設置上下文參數
$ kubectl config set-context devgroupuser@kubernetes --cluster=kubernetes --user=devgroupuser --namespace=dev
# 查看
$ kubectl config get-contexts
2、對組授權
$ cat >devgroup-role-bind.yaml<<EOF
kind: Role # 角色
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: dev
name: devgroup-role
rules:
- apiGroups: [""] # ""代表核心api組
resources: ["services","pods"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: RoleBinding # 角色綁定
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: devgroup-rolebinding
namespace: dev
subjects:
- kind: Group
name: devgroup # 目標用戶組
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: devgroup-role # 角色信息
apiGroup: rbac.authorization.k8s.io
EOF
執行並驗證(命名空間預設dev,而不是系統的default)
$ kubectl apply -f devgroup-role-bind.yaml
#切用戶
$ kubectl config use-context devgroupuser@kubernetes
# 查看
$ kubectl config get-contexts
$ kubectl get pods
$ kubectl get svc
$ kubectl get nodes
$ kubectl get jobs
從上圖實驗看,只能管理dev命名空間下的pods和services了,驗證ok。
切回管理員用戶
$ kubectl config use-context kubernetes-admin@kubernetes
3)ServiceAccount
上面第四節,已經很詳細的介紹了ServiceAccount,這裡也是直接上配置和操作命令。
$ cat >RoleBinding-ServiceAccount-001.yaml<<EOF
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: role001
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rb001
namespace: default
subjects:
- kind: ServiceAccount
name: lisi
namespace: default
roleRef:
kind: Role
name: role001
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: lisi
namespace: default
EOF
執行
$ kubectl delete -f RoleBinding-ServiceAccount-001.yaml
4)為ServiceAccount生成Token
cat >ClusterRoleBinding-ServiceAccount-token-001.yaml<<EOF
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: admin
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: sa001
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa001
namespace: kube-system
EOF
獲取token
$ kubectl -n kube-system get secret|grep sa001
$ kubectl -n kube-system describe secret sa001-token-c2klg
# 也可以使用 jsonpath 的方式直接獲取 token 的值,如:
$ kubectl -n kube-system get secret sa001-token-c2klg -o jsonpath={.data.token}|base64 -d
【註意】yaml 輸出里的那個 token 值是進行 base64 編碼後的結果
5)預設的Token
每次創建了新的namespace下都會生成一個預設的token,名為default-token-xxxx。default就相當於該namespace下的一個用戶。
$ kubectl -n dev get secret
$ kubectl -n dev describe secret default-token-67wgz
# 也可以使用 jsonpath 的方式直接獲取 token 的值,如:
$ kubectl -n dev get secret default-token-67wgz -o jsonpath={.data.token}|base64 -d
可以使用下麵的命令給該用戶分配該namespace的管理員許可權
kubectl create rolebinding $ROLEBINDING_NAME --clusterrole=admin --serviceaccount=$NAMESPACE:default --namespace=$NAMESPACE
- $ROLEBINDING_NAME必須是該namespace下的唯一的
- admin表示用戶該namespace的管理員許可權,關於使用clusterrole進行更細粒度的許可權控制請參考RBAC——基於角色的訪問控制。
- 我們給預設的serviceaccount default分配admin許可權,這樣就不要再創建新的serviceaccount,當然你也可以自己創建新的serviceaccount,然後給它admin許可權
其實kubernetes-dashboard就是通過token授權的,可以不清楚的,可以看我之前的文章:Kubernetes(k8s)安裝以及搭建k8s-Dashboard詳解
五、總結
RoleBinding 和 ClusterRoleBinding:角色綁定和集群角色綁定,簡單來說就是把聲明的 Subject 和我們的 Role 進行綁定的過程(給某個用戶綁定上操作的許可權),二者的區別也是作用範圍的區別:RoleBinding 只會影響到當前namespace 下麵的資源操作許可權,而 ClusterRoleBinding 會影響到所有的namespace。
- Rule:規則,規則是一組屬於不同 API Group 資源上的一組操作的集合
- Role 和 ClusterRole:角色和集群角色,這兩個對象都包含上面的 Rules 元素,二者的區別在於,在 Role 中,定義的規則只適用於單個命名空間,也就是和namespace 關聯的,而 ClusterRole 是集群範圍內的,因此定義的規則不受命名空間的約束。另外 Role 和 ClusterRole 在Kubernetes中都被定義為集群內部的 API 資源,和我們前面學習過的 Pod、ConfigMap 這些類似,都是我們集群的資源對象,所以同樣的可以使用我們前面的kubectl相關的命令來進行操作
- Subject:主題,對應在集群中嘗試操作的對象,集群中定義了3種類型的主題資源:
- User:用戶,這是有外部獨立服務進行管理的,管理員進行私鑰的分配,用戶可以使用 KeyStone或者 Goolge 帳號,甚至一個用戶名和密碼的文件列表也可以。對於用戶的管理集群內部沒有一個關聯的資源對象,所以用戶不能通過集群內部的 API 來進行管理
- Group:組,這是用來關聯多個賬戶的,集群中有一些預設創建的組,比如cluster-admin
- ServiceAccount:服務帳號,通過Kubernetes API 來管理的一些用戶帳號,和namespace 進行關聯的,適用於集群內部運行的應用程式,需要通過 API 來完成許可權認證,所以在集群內部進行許可權操作,我們都需要使用到 ServiceAccount,這也是我們這節課的重點