K8S認證、受權與准入控制(RBAC)詳解

相關推薦

本文的kubernetes環境:http://www.javashuo.com/article/p-vjmoqwfx-gm.htmlnode

RBAC官方文檔:https://kubernetes.io/docs/reference/access-authn-authz/rbac/nginx


前言

  1. RBAC (Role-Based Access Control,基於角色的訪問控制)是一種新型、靈活且使用普遍的訪問控制機制,它將權限授予「角色」(role)之上,這一點有別於傳統訪問控制機制中 將權限直接賦予使用者的方式,簡單點來講就是將權限綁定到role中,而後用戶和role綁定,這樣用戶就擁有了和role同樣的權限。
  2. 在任何將資源或服務提供給有限使用者的系統上,認證和受權都是兩個必不可少的功 能,認證用於身份鑑別,而受權則實現權限分派 。 Kubemetes 以插件化的方式實現了這兩種 功能,且分別存在多種可用的插件。 另外,它還支持准入控制機制,用於補充受權機制以實現更精細的訪問控制功能 。
  3. API Server 做爲 Kubernetes 集羣系統的網關,是訪問及管理資源對象的惟一人口,全部須要訪問集羣資源的組件,以及此前使用的 kubectl 命令等都要經由此網關進行集羣訪問和管理。
  4. RBAC使用rbac.authorization.k8s.io API Group 來實現受權決策,容許管理員經過 Kubernetes API 動態配置策略,要啓用RBAC,須要在 apiserver 中添加參數--authorization-mode=RBAC,若是使用的kubeadm安裝的集羣,都默認開啓了RBAC,能夠經過查看 Master 節點上 apiserver 的靜態Pod定義文件:
    [root@node-01 ~]# cat /etc/kubernetes/manifests/kube-apiserver.yaml 
    ···
    - --authorization-mode=Node,RBAC
    ···
  5. 若是是二進制的方式搭建的集羣,添加這個參數事後,記得要重啓 apiserver 服務。

RBAC API資源對象

Kubernetes有一個很基本的特性就是它的全部資源對象都是模型化的 API 對象,容許執行增、刪、改、查等操做,好比下面的這下資源:json

  • Pods
  • ConfigMaps
  • Deployments
  • Nodes
  • Secrets
  • Namespaces

上面這些資源對象的可能存在的操做有:api

  • create
  • get
  • delete
  • list
  • update
  • edit
  • watch
  • exec

用戶帳戶和用戶組

Kubernetes 並不會存儲由認證插件從客戶端請求中提取出的用戶及所屬組的信息,它們僅僅用於檢驗用戶是否有權限執行其所請求的操做。tomcat

客戶端訪問API服務的途徑一般有三種:kubectl、客戶端庫或者直接使用 REST接口進行請求。app

而能夠執行此類請求的主體也被 Kubernetes 分爲兩類:現實中的「人」和 Pod 對象, 它們的用戶身份分別對應於常規用戶 (User Account )和服務帳號 ( Service Account) 。 ide

  • Use Account(用戶帳號):通常是指由獨立於Kubernetes以外的其餘服務管理的用 戶帳號,例如由管理員分發的密鑰、Keystone一類的用戶存儲(帳號庫)、甚至是包 含有用戶名和密碼列表的文件等。Kubernetes中不存在表示此類用戶帳號的對象, 所以不能被直接添加進 Kubernetes 系統中 。
  • Service Account(服務帳號):是指由Kubernetes API 管理的帳號,用於爲Pod 之中的服務進程在訪問Kubernetes API時提供身份標識( identity ) 。Service Account一般要綁定於特定的命名空間,它們由 API Server 建立,或者經過 API 調用於動建立 ,附帶着一組存儲爲Secret的用於訪問API Server的憑據。
    K8S認證、受權與准入控制(RBAC)詳解

Kubernetes 有着如下幾個內建的用於特殊目的的組 。測試

  • system:unauthenticated :未能經過任何一個受權插件檢驗的帳號,即未經過認證測 試的用戶所屬的組 。
  • system :authenticated :認證成功後的用戶自動加入的一個組,用於快捷引用全部正常經過認證的用戶帳號。
  • system : serviceaccounts :當前系統上的全部 Service Account 對象。
  • system :serviceaccounts :<namespace>:特定命名空間內全部的 Service Account 對象。

Role和ClusterRole

  1. Role是隻做用於命名空間級別的,用於定義命名空間內資源權限集合。
  2. ClusterRole則用於集羣級別的資源權限集合,它們都是標準的 API 資源類型 。
  3. 通常來講, ClusterRole 的許可受權做用於整個集羣,所以經常使用於控制 Role 沒法生效的資源類型,這包括集羣級別的資源(如Nodes)、非資源類型的端點(如/healthz)和做用於全部命名空間的資源(例如跨命名空間獲取任何資源的權限)。

RoleBinding和ClusterRoleBinding

  1. RoleBinding用於將Role上的許可權限綁定到一個或一組用戶之上,它隸屬於且僅能做用於一個命名空間。綁定時,能夠引用同一名稱中的Role,也能夠引用集羣級別的 ClusterRole。jsonp

  2. ClusterRoleBinding則把ClusterRole中定義的許可權限綁定在一個或一組用戶之上,它僅能夠引用集羣級別的ClusterRole。
  3. Role、RoleBinding、ClusterRole和ClusterRoleBinding 的關係如圖 所示 。
    K8S認證、受權與准入控制(RBAC)詳解spa

  4. 一個命名空間中能夠包含多個Role和RoleBinding對象,相似地,集羣級別也能夠同時存在多個ClusterRole和ClusterRoleBinding對 象。而一個帳戶也可經由RoleBinding ClusterRoleBinding關聯至多個角色,從而具備多重許可受權。

下面咱們來建立一個User Account,測試訪問某些咱們受權的資源:

建立k8s User Account

1、建立證書

  1. 建立user私鑰

    [root@node-01 ~]# cd /etc/kubernetes/pki/
    [root@node-01 pki]# (umask 077;openssl genrsa -out billy.key 2048)
    Generating RSA private key, 2048 bit long modulus
    .................................................................................+++
    ..................+++
    e is 65537 (0x10001)
  2. 建立證書籤署請求
    O=組織信息,CN=用戶名

    [root@node-01 pki]# openssl req -new -key billy.key -out billy.csr -subj "/O=jbt/CN=billy"
  3. 簽署證書
    [root@node-01 pki]# openssl  x509 -req -in billy.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out billy.crt -days 365
    Signature ok
    subject=/O=jbt/CN=billy
    Getting CA Private Key

    2、建立配置文件

    建立配置文件主要有如下幾個步驟:

    kubectl config set-cluster --kubeconfig=/PATH/TO/SOMEFILE      #集羣配置
    kubectl config set-credentials NAME --kubeconfig=/PATH/TO/SOMEFILE #用戶配置
    kubectl config set-context    #context配置
    kubectl config use-context    #切換context
  • --embed-certs=true的做用是不在配置文件中顯示證書信息。
  • --kubeconfig=/root/billy.conf用於建立新的配置文件,若是不加此選項,則內容會添加到家目錄下.kube/config文件中,可使用use-context來切換不一樣的用戶管理k8s集羣。
  • context簡單的理解就是用什麼用戶來管理哪一個集羣,即用戶和集羣的結合。

建立集羣配置

[root@node-01 pki]# kubectl config set-cluster k8s --server=https://10.31.90.200:8443 --certificate-authority=ca.crt --embed-certs=true --kubeconfig=/root/billy.conf
Cluster "k8s" set.

[root@node-01 pki]# kubectl config view --kubeconfig=/root/billy.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.31.90.200:8443
  name: k8s
contexts: []
current-context: ""
kind: Config
preferences: {}
users: []

建立用戶配置

[root@node-01 pki]# kubectl config set-credentials billy --client-certificate=billy.crt --client-key=billy.key --embed-certs=true --kubeconfig=/root/billy.conf
User "billy" set.

#查看配置文件
[root@node-01 pki]# kubectl config view --kubeconfig=/root/billy.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.31.90.200:8443
  name: k8s
contexts: []
current-context: ""
kind: Config
preferences: {}
users:
- name: billy
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

建立context配置

[root@node-01 pki]# kubectl config set-context billy@k8s --cluster=k8s --user=billy --kubeconfig=/root/billy.conf
Context "billy@k8s" created.

#查看配置文件
[root@node-01 pki]# kubectl config view --kubeconfig=/root/billy.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.31.90.200:8443
  name: k8s
contexts:
- context:
    cluster: k8s
    user: billy
  name: billy@k8s
current-context: ""
kind: Config
preferences: {}
users:
- name: billy
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

切換context

[root@node-01 pki]# kubectl config use-context billy@k8s --kubeconfig=/root/billy.conf
Switched to context "billy@k8s".

#查看配置文件
[root@node-01 pki]# kubectl config view --kubeconfig=/root/billy.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.31.90.200:8443
  name: k8s
contexts:
- context:
    cluster: k8s
    user: billy
  name: billy@k8s
current-context: billy@k8s
kind: Config
preferences: {}
users:
- name: billy
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

建立系統用戶及k8s驗證文件

[root@node-01 ~]# useradd billy     #建立什麼用戶名均可以
[root@node-01 ~]# mkdir /home/billy/.kube
[root@node-01 ~]# cp billy.conf /home/billy/.kube/config
[root@node-01 ~]# chown billy.billy -R /home/billy/.kube/
[root@node-01 ~]# su - billy
[billy@node-01 ~]$ kubectl get pod
Error from server (Forbidden): pods is forbidden: User "billy" cannot list resource "pods" in API group "" in the namespace "default"
#默認新用戶是沒有任何權限的。

建立Role

此role只有pod的get、list、watch權限

[root@node-01 rbac]# cat pods-reader.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pods-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

[root@node-01 rbac]# kubectl apply -f pods-reader.yaml 
role.rbac.authorization.k8s.io/pods-reader created

建立Rolebinding

用戶billy和role pods-reader的綁定

[root@node-01 rbac]# cat billy-pods-reader.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: billy-pods-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pods-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: billy

[root@node-01 rbac]# kubectl apply -f billy-pods-reader.yaml 
rolebinding.rbac.authorization.k8s.io/billy-pods-reader created

驗證結果

若是沒有指定命名空間的話,默認就是default命名空間。

[billy@node-01 ~]$ kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
nginx-demo-95bd675d5-66xrm   1/1     Running   0          18d
tomcat-5c5dcbc885-7vr68      1/1     Running   0          18d

[billy@node-01 ~]$ kubectl -n kube-system get pod
Error from server (Forbidden): pods is forbidden: User "billy" cannot list resource "pods" in API group "" in the namespace "kube-system"

因此咱們是能夠查看查看default命名空間的pod,可是其餘空間的pod是沒法查看的。

建立ClusterRole

[root@node-01 rbac]# cat cluster-reader.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

[root@node-01 rbac]# kubectl apply -f cluster-reader.yaml 
clusterrole.rbac.authorization.k8s.io/cluster-reader created

建立ClusterRoleBinding

[root@node-01 rbac]# cat billy-read-all-pods.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: billy-read-all-pods
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: billy

[root@node-01 rbac]# kubectl apply -f billy-read-all-pods.yaml 
clusterrolebinding.rbac.authorization.k8s.io/billy-read-all-pods created

驗證結果

建立了ClusterRole和ClusterRoleBinding後就能夠看到全部命名空間的pod了。

[billy@node-01 ~]$ kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
nginx-demo-95bd675d5-66xrm   1/1     Running   0          18d
tomcat-5c5dcbc885-7vr68      1/1     Running   0          18d

[billy@node-01 ~]$ kubectl -n kube-system get pod
NAME                                        READY   STATUS    RESTARTS   AGE
canal-gd4qn                                 2/2     Running   0          21d
cert-manager-6464494858-wqpnb               1/1     Running   0          18d
coredns-7f65654f74-89x69                    1/1     Running   0          18d
coredns-7f65654f74-bznrl                    1/1     Running   2          54d
...

ServiceAccount

至於ServiceAccount怎麼受權,其實相對user account來講更簡單,只需先建立ServiceAccount,而後建立role或者ClusterRole,最後在RoleBinding或ClusterRoleBinding綁定便可。如下簡單作一個示例,就不在顯示結果了,你們能夠本身去驗證。

建立SA

kubectl create sa billy-sa

建立Role

[root@node-01 rbac]# cat billy-sa-role.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: billy-sa-role
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

建立Rolebinding

將billy-sa和billy-sa-role的綁定

[root@node-01 rbac]# cat billy-sa-rolebinding.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: billy-sa-rolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: billy-sa-role
subjects:
- kind: ServiceAccount
  name: billy-sa

驗證結果

建立完SA以後系統會自動建立一個secret,咱們能夠獲取這個secret裏面的token去登陸dashboard,就能夠看到相應有權限的資源。

kubectl get secret billy-sa-token-9rc55 -o jsonpath={.data.token} |base64 -d

還能夠在建立pod時在pod的spec裏指定serviceAccountName,那麼這個pod就擁有了對應的權限,具體的就不在演示了。

本次的分享就到此,若有問題歡迎在下面留言交流,但願你們多多關注和點贊,謝謝!

相關文章
相關標籤/搜索