kubernetes 中的權限管理

Kubernetes 發展好快,在我寫這篇總結的同時,1.9.0 版本已經在昨日(2017.12.16)正式發布,而上次在正式環境中部署已經是半年前了,我花了點時間將集群升級到了 1.8.4 版本,其中變化最明顯的就是權限了,已經可以用上 RBAC 了,而我也在發現報錯的時候才意識到需要將以前 k8s 的基礎應用也全部加上了權限(當然了,1.6 其實就開始有了)。

目前,k8s 中一共有 4 種權限模式:

  • Node: 一種特殊目的的授權模式,主要用來讓 kubelets 遵從 node 的編排規則,實際上是 RBAC 的一部分,相當于只定義了 node 這個角色以及它的權限;
  • ABAC: Attribute-based access control;
  • RBAC: Role-based access control;
  • Webhook: 以 HTTP Callback 的方式,利用外部授權接口來進行權限控制;

對于大部分人來說,RBAC 就能起到很好的權限控制效果了(k8s 的 RBAC 實現是一個非常優秀的樣例,詳細研究下它的設計將對你未來對于其它系統的權限設計會有很好的啟發作用,比如你們公司管理后臺權限設計)。下面將詳細介紹下。

基礎

樣例

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: example
rules:
- apiGroups: [""] # "" 說明是 core API group
  resources: ["pods"] # 可用來操作的對象
  verbs: # 可以進行的操作
    - get
    - list
    - create
    - update
    - patch
    - watch
    - proxy
    - redirect
    - delete
    - deletecollection

Role & ClusterRole

兩種角色,很好區分,role 限定于單個 namespace,而 ClusterRole 則是沒有這個限制的,主要是用來給一些基礎服務用的。

RoleBinding & ClusterRoleBinding

這個就相當于具體的權限授權列表了,所有的 Role 會與具體的 ServiceAccount、User 以及 Group 等綁定,而他們的區別就是分別對應 Role & ClusterRole。

Aggregated ClusterRoles

這是 1.9 引入的新功能,簡而言之,你可以利用標簽來組合一些列的 ClusterRoles,具體樣例如下:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: monitoring
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.example.com/aggregate-to-monitoring: "true"
# 所有帶有 rbac.example.com/aggregate-to-monitoring: "true" 這個標簽的都會被組合
# 然后自動生成 rules
rules: [] 

實踐:生成用戶賬戶

在官方文檔中,也沒有介紹應該如何生成具體的 User 賬戶(在 設計文檔 中,提到過 userAccount,但目前還沒有實現),但其實生成賬戶很簡單,因為 User 賬戶是根據 SSL 證書生成的,你只要根據 k8s 的 ca 證書來生成對應的賬戶即可。

比如目前我需要生成一個 xizhibei 的賬戶:

# 在當前目錄下添加目錄,用來存放證書
mkdir certs
# 設置一些變量
KUBE_URL=https://k8s-master01.zs:6443
CLUSTER=k8s.cluster
CRT_DAYS=365
USER_NAME=xizhibei

# CA 證書可以在 master node 上找到
# 一般就在 /etc/kubernetes/ssl 或者 /etc/kubernetes/pki 里面
CA_CRT_PATH=/etc/kubernetes/ssl/ca.pem
CA_KEY_PATH=/etc/kubernetes/ssl/ca-key.pem

# 生成私有密鑰
openssl genrsa -out certs/$USER_NAME.key 2048

# 用私鑰生成證書,CN 表示用戶名,O 表示用戶組
openssl req -new -key certs/$USER_NAME.key -out certs/$USER_NAME.csr \
-subj "/CN=$USER_NAME/O=example"

# 然后用 CA 證書來給剛才生成的證書來簽名
# 在這個例子中,我們給 xizhibei 這個賬戶簽發了一張有效期為一年的證書
openssl x509 -req -in certs/$USER_NAME.csr -CA $CA_CRT_PATH -CAkey $CA_KEY_PATH \
-CAcreateserial -out certs/$USER_NAME.crt -days $CRT_DAYS

好了,這樣你就生成了一個賬戶,接下來,需要設置下 kubectl 的配置:

# 存放 kubectl config 的文件
export KUBECONFIG=/root/k8s-$USER_NAME.conf

# 設置 cluster
kubectl config set-cluster $CLUSTER --server="$KUBE_URL" \
--certificate-authority="$CA_CRT_PATH" --embed-certs=true

# 設置私鑰以及已簽名證書
kubectl config set-credentials $USER_NAME --client-certificate=certs/$USER_NAME.crt  \
--client-key=certs/$USER_NAME.key --embed-certs=true

# 設置 context
kubectl config set-context $USER_NAME-context --cluster=$CLUSTER --user=$USER_NAME
kubectl config use-context $USER_NAME-context

你可以使用 kubectl get pods -n example --kubeconfig /root/k8s-xizhibei.conf 來確認是否可以可用,不出所料的話,你會被告知沒有權限,因為現在只是生成了一個賬戶,你還不可以操作具體的資源。

Error from server (Forbidden): pods is forbidden: User "xizhibei" cannot list pods in the namespace "example"

下面,就需要你配置具體的 Role 以及 RoleBinding 來授權你剛剛生成的賬戶,比如我想給剛剛生成的賬戶授權只能對部署進行操作:

# new-user.yaml
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: example
  name: deployment-manager
rules:
- apiGroups: ["", "extensions", "apps"]
  resources: ["deployments", "replicasets", "pods"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: deployment-manager-binding
  namespace: example
subjects:
- kind: User
  name: xizhibei@example.com
  apiGroup: ""
roleRef:
  kind: ClusterRole
  name: admin
  apiGroup: ""

然后 kubectl create -f ./new-user.yaml(注意,你得使用管理員賬戶,而不是剛剛生成的用戶賬戶)。

接下來,這個用戶就能進行操作了,使用 kubectl get pods -n example --kubeconfig /root/k8s-xizhibei.conf,你就能看到 pods 的列表了。

P.S.

似乎又寫了一篇水文,通篇還是以介紹與總結為主,沒有具體的思考內容在里面。但是回顧起來,你會發現這對于我們設計管理后臺的權限還是挺有啟發的。比如目前管理后臺中有訂單,用戶以及付費記錄三種資源,那么對于管理員賬戶來說,我們就可以設計如下的 RBAC 模型:

Account:
    - name, type: string
    - roles, type: [string] # 這里就相當于 rolebinding 了

Role:
    - name
    - rules
      - name, type: string
      - verbs, type: [string]
      - resources, type: [string]

Resource: enum(order, user, payment)

Verb: enum(get, list, update, create, delete, deleteCollection)

對應的其中一條完整記錄:

Account:
    - xizibei
    - ['edit', 'view']

Role:
    - 'view'
    - ['get', 'list']
    - ['order', 'user', 'payment']

Ref

原鏈接:https://xizhibei.github.io/2017/12/17/authorization-in-k8s/

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容