1. 程式人生 > >kubernetes認證、授權、準入控制

kubernetes認證、授權、準入控制

server lock 上下 cts cal res always out quota

1 總述

1 概述

kubernetes 中的資源訪問類型有兩種,一種是由POD提供的服務資源,其可通過service或 ingress提供接口以供外部訪問,這種訪問不需要經過API server的認證,而另一種對集群內部資源的操作則需要經過一定的認證授權操作才能完成。

2 認證,授權,準入控制概述

1 概述

任何客戶端在操作相關資源對象時必須經過三個步驟:
認證: 身份鑒別,正確的賬號,能夠通過認證,其只能證明其是合法的賬戶。
授權: 權限檢查,對資源進行相應的操作。其可操作某些資源,其某些資源需要關聯其他資源,其對此種相關關聯的資源的操作則無相關權限,此時便需要準入控制了。
準入控制: 用於補充授權機制以實現更加精細的訪問控制功能。這次操作會關聯到其他資源或影響其他操作。一般在創建,修改,刪除和代理方面做某些限制操作。

其認證,授權、準入控制是有各種插件實現,其可經由管理員用戶選擇確認使用哪種插件來完成對其的操作。及何種控制方式。

2 API serever

API server 是kubernetes 集群系統的網管,是訪問及管理資源對象的唯一入口,其余的資源都必須經由網關進行集群訪問和管理,這些客戶端需要經由 API server防護或改變集群狀態並完成數據存儲,並經由它對每一次訪問進行合法性驗證,包括身份鑒別,操作權限鑒別以及操作是否符合全局規範約束等,所有檢查正常後且對象配置信息合法性校驗無誤後才能訪問或存儲數據存入etcd系統中。


API server依次調用為其配置的認證插件來驗證客戶端的身份,直到其中一個插件可識別出請求者身份才允許進入。

kubernetes 中內建的用於特殊目的的組。
system : unauthenicated: 未能通過任何一個授權插件檢驗的賬戶,及未通過認證測試的用戶所屬的組。

system: authenticationd: 認證成功後的用戶會自動加入一個組,用於快捷引用所有正常通過認證的用戶賬號。

system: serviceaccount : 當前系統上所有service account對象

system serviceaccount: <namespace>: 特定名稱空間內所有service account對象A

3 API 請求類型及相關內容

1 api 請求需要驗證的信息

客戶端發起對API SERVER的請求,其API server需要驗證客戶端用戶的那些身份:

1 user: username userid
2 group :組信息
3 extra : 額外字段

2 API 相關概述

其發起對API server的請求是請求某些API 資源,其具體是請求那個版本的那個API資源對象,需要進行標識,而標識則需要通過用戶在HTTP請求中的URL 和 PATH 來識別。
其允許同一個服務下的版本並存,其可實現相關的兼容

[[email protected] ~]# kubectl api-versions
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1   
apps/v1beta1  
apps/v1beta2  

所有名稱空間級別的資源訪問都必須指定其名稱空間的名稱 (無名稱空間的資源 PV,namespace),有名稱空間的資源pod,deployment,pvc,service等其他大部分資源。

/apis/apps/v1/namespaces/default(namespaces 中default名稱空間)/deployments/nginx
其可進行相關的增刪改查操作,其kubectl的相關操作實質上是被轉換為對應的URL 進行相關的操作。

使用kubectl 不需要認證信息,但使用curl需要認證信息,原因是在創建集群時已經將相關的認證信息拷貝到了.kube/中,而需要直接進行此項操作,則需要使用本地起代理的方式進行相關的操作

kubernetes 反向代理開啟,其proxy和api server進行認證,而客戶端curl則不需要相關的認證。

 kubectl proxy  --port=8080  #其需要確保8080端口未被占用

通過kubectl 反向代理至API SERVER
訪問名稱空間

curl   http://localhost:8080/api/v1/namespaces  #其默認顯示該kubernetes集群上的所有名稱空間列表,可使用kubectl create namespace 進行創建,然後查看 ,其請求通過URL訪問,結果是一個json的相應結果。

類:
1 對象類(namespace)
2 同一類型下的所有對象的集合成為集合,成為list (namespaces) 其包含了資源下的子資源。
訪問其具體的資源。

# 獲取默認名稱空間的基本信息
curl http://localhost:8080/api/v1/namespaces/default  

其默認的,核心組查詢時使用 http://localhost:8080/api ,其他非核心群組查看使用http://localhost:8080/apis 起始。其只要不是apiversion只要不是V1,則都是apis起始。


#獲取對應default名稱空間下的deployment下的Nginx對象的信息
curl  http://localhost:8080/apis/apps/v1/namespaces/default/deployments/nginx
API SERVER 請求報文包含的信息
    1 API: 用於定義其你去的目標是否是一個API資源。
    2 requests path:請求的非資源型路徑,如/api和/healthz。
    3 API  group : 要訪問的API組,僅對資源請求有效,默認為核心API組。
    4 NameSpace:目標資源所屬的名稱空間,僅對隸屬於名稱空間的資源有效(PV無效,namespace也是集群級別的)。
    5 API request verb(動作):API請求類的操作,及資源型請求,包括get,list、create、update、patch、watch、proxy、redirect、delete和deletecollection等。
    6 HTTP request verb: HTTP 請求類的操作,及非資源型請求要執行的操作,如get、post、put和delete。使用CURL 就必須標明動作。創建的時候需要帶一個請求格式的數據,在刪除時只需要給定URL即可。
    7 Resource: 請求的目標資源ID或名稱。
    8 Subresource: 請求的子資源。
[[email protected] ~]# kubectl get svc    # POD請求API server時使用的接口
NAME                                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)         AGE
kubernetes                          ClusterIP   10.96.0.1       <none>        443/TCP         10d

[[email protected] ~]# kubectl describe  svc kubernetes  # 其是引入其中的
Name:              kubernetes
Namespace:         default
Labels:            component=apiserver
                   provider=kubernetes
Annotations:       <none>
Selector:          <none>
Type:              ClusterIP
IP:                10.96.0.1
Port:              https  443/TCP
TargetPort:        6443/TCP
Endpoints:         192.168.90.100:6443
Session Affinity:  None
Events:            <none>

API server將自己的證書發送到客戶端,客戶端去校驗服務端的身份,同時,API server還需要校驗客戶端的身份,如果在apiserver 上自己手動創建證書,則需要保證證書的持有者名稱能夠解析兩條A記錄及10.96.0.1 和 192.168.90.100

POD 客戶端需要有證書,API server 需要驗證客戶端,POD需要和API server打交道,則需要進行相關的認證操作,POD 中的某些資源需要和API server之間提供相關的認證操作,其需要通過serviceAccountName去承載相關的認證信息完成對應的交互操作。默認每一個POD在運行時都要和API server打交道

4 kubernetes 的用戶類型:

1 分類

serviceaccount (服務賬號):指由kubernetes API 管理的賬號,用於為POD中的服務進程在訪問kubernetes API 時提供身份標識,service account 通常需要綁定於特定的名稱空間,其由 API server創建,或者通過API 調用創建,其會附帶一組存儲為secret的用於訪問API server的憑據。其隸屬於名稱空房間

useraccount (用戶賬號):一般是指獨立於kubernetes之外的其他服務管理的用戶賬號,kubernetes中不存在標識此類用戶賬號的對象,因此其不能被直接添加進kubernetes系統中,其通常用於較為復雜的業務邏輯管控,作用於系統全局,其必須全局唯一。


K8S 通過三個獨立的組件鍵的相互協作來實現服務賬戶的自動化,三個組件具體是:

  1. service account 準入控制器

其是api server 一部分,負責在創建或更新POD時對其按需進行service account對象相關信息的修改。
若POD沒有明確定義使用的serviceaccount對象,則將其設置為default
確保POD明確引用的serviceaccount存在,否則請求將被拒絕
若POD對象中不包含imagepullsecrets,則吧service account 的imagepullsecret添加於其上
為帶有訪問API的令牌的POD添加一個存儲卷
為POD 對象中的每個同期添加一個volumesMounts,掛載至 /var/run/secrets/kubernetes.io/serviceaccount

2 . 令牌控制器:

其是controller-manager的子組件,工作與異步模式,負責如下
1 監控service account的創建操作,並為其添加用於訪問API的sercret 對象
2 監控 service Account 的刪除操作,並刪除相關的所有service account 令牌密鑰
3 監控sercret對象的添加操作,確保其引用的service account(賬戶)已存在,並在必要時為secret對象添加認證令牌
監控sercret對象的刪除操作,以確保刪除每個service account中對此sercret的引用
為確保完整性,必須為kube-controller-manager 使用"--service-account-private-key-file"選項指定一個私鑰文件,用於對生成的服務賬戶令牌進行簽名,此私鑰文件必須是pem格式,類似的,需要為kube-apiserver 使用 --service-account-key-file 指定與前面私鑰對的公鑰文件,以用於在認證期間進行令牌校驗

3 . service account 賬戶控制器

為名稱空間管理相應的資源,並確保每個名稱空間中都存在一個名為default 的 service account 對象。

Volumes:
  default-token-68rj7:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-68rj7
    Optional:    false

其以存儲卷的方式關聯到POD上,從而完成POD與apiserver之間的信息交互。

其名稱空間中默認的secret

[[email protected] ~]# kubectl get secret 
NAME                  TYPE                                  DATA   AGE
default-token-68rj7   kubernetes.io/service-account-token   3      10d

2 創建和使用serviceaccount

[[email protected] ~]# kubectl create namespace  data  # 創建一個名稱空間
namespace/data created
[[email protected] ~]# kubectl get secret -n data  #查看其名稱空間中的資源,因此其每一個POD都能獲取連接API server的信息。但其只能獲取當前POD自身的相關信息,其不能獲取其他POD信息和屬性
NAME                  TYPE                                  DATA   AGE
default-token-bxchn   kubernetes.io/service-account-token   3      12s

如果想要擴展POD,及管理其他POD或管理其他deployment,則需要重新創建serviceaccount。
serviceaccount 屬於標準的K8S資源。

創建serviceaccount 資源,其默認只是一個賬號,其需要通過RBAC進行相關授權

kubectl create serviceaccount   -h
kubectl create serviceaccount  web

查看
技術分享圖片
其會生成一個專門的token,查詢如下
技術分享圖片

此便是創建的token ,其是認證信息,是認證


定義pod使用自定義的SA賬號

[[email protected] all]# cat pod2.yaml 
apiVersion: v1
kind: Pod
metadata:
    name: dem-dem1
    namespace: default
spec:
    containers:
        - name: dem-po2
          image: nginx:1.14
    serviceAccountName: web  #指定上述創建的serviceaccount 

部署

kubectl apply  -f pod2.yaml

查看
技術分享圖片
此處與創建的secret相同

3 配置使用serviceaccount 中的認證拉取私有鏡像倉庫鏡像

其拉去需要認證的私有鏡像倉庫的鏡像時,除了配置pod.spec.imagePullSecrets 還可以在sa中配置相關的秘鑰來完成 。

技術分享圖片

實例如下

#[[email protected] all]# cat sa1.yaml 
apiVersion: v1
kind: Secret
metadata:
    name: web1   #配置Secret 名稱
    namespace: default
stringData:
    key: Admin  #配置私有鏡像倉庫密碼
---
apiVersion: v1
kind: ServiceAccount
metadata:
    name: web
    namespace: default
imagePullSecrets:
    - name: web1  #調用上述服務
---
apiVersion: v1
kind: Pod
metadata:
    name: nginx1
    namespace: default
spec:
    containers:
        - name: nginx1
          image: 192.168.1.10/test/nginx:1.14
          ports:
            - name: http
              containerPort: 80
    serviceAccountName: web  #調用上述serviceaccount

部署

kubectl apply -f sa1.yaml

技術分享圖片
技術分享圖片

2 認證

1 概述

kubernetes 使用身份認證插件對API 請求進行身份認證,支持包括客戶端證書、承載令牌、身份驗證代理或http basic 認證等,API server接受到訪問請求時,將調用認證插件嘗試將以下屬性與訪問請求相關聯。

username: 用戶名
UID :用戶的數字標簽符,用於確保用戶身份的唯一性
Groups:用戶所屬的組,用於權限指派和集成
extra: 鍵值數據類型的字符串,用於提供認證時所需要的額外信息。

api server 支持同是啟用多種認證機制,分為service account 和 user account ,其各自啟用一個認證插件,同時支持多種認證機制,認證過程以串行方式進行,直到一種認證機制認證通過後成功,請求者會被識別為某個具體的用戶,並隨後都以此用戶身份進行認證,若無匹配條件,則返回401。

2 API server 支持的認證方式:

1 X509 客戶端證書認證:客戶端在請求報文中攜帶X509格式的數字證書用於認證,認證通過後,證書中的主體標識 (subject)被識別為用戶標識。其中CN字段是用戶名,O 是用戶屬組。


2 靜態令牌文件 (static token file): K8S 提供的是restful 風格的接口,其所有的認證都是通過HTTP進行傳遞的,因此其認證信息只能經由HTTP的認證守護進行傳遞,這種認證守護在傳遞時,傳遞的是預共享秘鑰的編碼信息,其通常被成為認證令牌,及token,經由HTTP的守護從客戶端將其轉為HTTP的傳輸到API server進行認證,其只需要交換預共享秘鑰即可。 保存者令牌信息的文件,由kube-apiserver的命令行選項--token-auth-file 加載,且服務器啟動後不可更改,HTTP 客戶端也能使用承載令牌進行身份驗證,將令牌進行編碼後,通過請求報文中的authorization 首部承載傳遞給API SERVER 即可 像mysql一樣


3 引導令牌: 一種動態管理承載令牌進行身份認證的方式,常用於簡化新建的k8S集群的節點認證過程,需要通過--experimental-bootstrap-token-auth 選項啟用;有新的工作節點首次加入時,master使用引導令牌確認節點身份的合法性之後自動為其簽署數字證書用於後續的安全通信,使用kubeadm join 命令將節點加入 kubeadm初始化的集群時使用的及時這種認證方式。這些令牌作為secret存儲在kube-sytem名稱空間中,可以動態管理和創建,而controller manager 中包含一個tokencleaner 控制器,用於刪除過期的引導令牌


4 靜態密碼文件: 用戶名和密碼等令牌以明文格式存儲的CSV格式文件,由kube-apiserver使用 --basic-auth-file 選項進行加載,客戶端在HTTP basic 認證中加認證用戶名和密碼編碼後以承載令牌的格式進行認證。


5 服務賬戶令牌:由 kube-apiserver自動啟動,並可使用可選選項加載 --service-account-key-file 驗證承載令牌的密鑰,省略時將使用的kube-apiserver 自己的證書匹配到私鑰文件,service account通常由 API service 自動創建,並通過service account 準入控制器將其註入POD對象,包括service account上的承載領跑,容器中的應用程序請求API server的服務完成身份認證


6 OPENID 連接令牌: OAuth2 的一種認證風格,由AZURE AD,salesforce 和Google 等服務上支持。


7 webhook 令牌: HTTP身份驗證允許將對服務的URL註冊為webhook,並接受帶有令牌的POST 請求進行身份認證,客戶端使用kubeconfig 格式的配置文件,在文件中,"users"指的是API 服務器 Webhook. Cluster 指API server


8 認證代理:API server支持從請求首部中的值中識別用戶,如 X-REMOTE-USER 首部,他旨在與身份驗證代理服務相結合,並由該代理設置相應的請求頭部。


9 keystone 密碼: 借助外部的keystone 服務器進行身份驗證


10 匿名請求: 未被任何驗證機制明確拒絕的用戶及被視為匿名用戶,其被自動標識為用戶名system : anonymous,並隸屬於system: unauthorized用戶組,在API server 啟用了除alwatsallow 外的認證機制,匿名用戶處於啟動狀態,管理員可通過 --anonymous-auth=false 選項將其禁用。


API SERVER 還允許用戶通過模擬(impersonation)首部來冒充另一個用戶,這些請求可以以手動的方式覆蓋請求中用於身份驗證的用戶信息.

3 kubernetes 中的SSL/TLS 認證

kubernetes 支持https客戶端證書認證、token認證以及http basic 認證中的認證方式,基於SSL/TLS 協議的客戶端證書認證安全性更高。

SSL/TLS 最常見的是場景是將X.509證書與服務器端關聯,但不為客戶端使用證書,及客戶端認證度武器端身份,服務器端無法認證客戶端身份

kubernetes 中各個集群節點的信息狀態都是以明文的方式存儲在etcd中的,因此其etcd集群內各節點間通信,以及各節點與其客戶端之前通信都應是加密傳輸的方式進行。


1 etcd 集群內對等節點通信,etcd 集群內個節點間的集群事務通信,默認監聽TCP 的 2380 端口,基於 SSL/TLS 通信時需要peer 類型的數字證書,可實現節點間的身份認證及通信安全,這些證書需要由專用CA進行管理。

2 etcd 服務器與客戶端通信:ETCD 的rest API 服務,默認監聽與TCP 的2379 ,用於接受並發響應客戶端的請求,基於SSL/TLS 通信,支持服務端認證和雙向認證,而且要使用一個專用CA來管理此類證書,kube-apiserver就是etcd 服務的主要客戶端。

4 客戶端配置文件 kubeconfig

1 簡介

使用kubeadmin初始化集群後生成的/etc/kubernetes/admin.conf 文件就是kubernetes 格式的配置文件,其由kubeadm init 命令自動生成,可由kubectl 加載厚用於接入服務器,包括kubectl kubelet和kube-controller-manager等在內的API server的各類客戶端都可以使用kubeconfig配置文件提供接入多個集群的相關配置。

2 查看

kubectl config view

技術分享圖片

3 其包含的字段:

1 cluster : 集群列表,包含訪問API server的URL 和 所屬集群的名稱。

clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED   #認證的認證方式
    server: https://192.168.90.100:6443  #訪問服務器的API server 路徑
  name: kubernetes  # 集群名稱

2 users: 用戶列表,包含訪問API server 時的用戶名和認證信息

users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED  #客戶端證書
    client-key-data: REDACTED #客戶端私鑰,其需要被服務端認證

3 context: kubectl 的可用上下文列表,有用戶列表的某特定用戶名稱和集群列表中某特定的名稱組合而成,用於指明那個賬號能夠訪問那個集群

contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: [email protected]

4 current-context : kubectl 當前使用的上下文名稱,及當前賬戶訪問的集群環境

current-context: [email protected]

kubeconfig 是一個文本文件,但希望能夠使用kubectl config 命令進行相關設定,其能夠自動進行語法檢測等功能。

4 常用命令

kubectl  config  view  #打印kubeconfig 文件內容
kubectl  config set-cluster  #設置kubeconfig 的cluster端
kubectl  config set-credentials #設置kubeconfig的user端
kubectl  config set-context  # 設置kubeconfig的context字段,設定用戶可以訪問的集群
kubectl config use-context  #切換賬號

使用kubeadm 部署的kubernetes 集群默認提供了擁有者集群權限的kubeconfig配置文件,其可以被復制到任何有kubectl 的主機上用於管理整個集群。

技術分享圖片

5 配置kubeconfig

1 創建秘鑰

為目標賬戶web 創建私鑰及證書文件保存於/etc/kubernetes/pki目錄中,需要在master節點上以root 用戶執行

A 生成私鑰文件,其權限為600,並放置於專用目錄

cd /etc/kubernetes/pki/
(umask  077;openssl genrsa -out  web.key 2048)

B 創建證書簽署請求,-subj選項中CN將被kubeconfig作為用戶名使用,O的值將被識別為用戶組

openssl  req  -new -key web.key -out web.csr -subj "/CN=web/O=kubernetes"

C 關聯基於kubeadm 安裝kubernetes集群時生成的CA證書,並配置其有效期

openssl x509 -req -in web.csr -CA  ca.crt -CAkey ca.key -CAcreateserial -out web.crt -days 3650

D 驗證證書信息

openssl x509 -in web.crt -text -noout 

E 查看
技術分享圖片

2 配置此用戶加入當前集群

1 配置用戶加入當前集群中

格式

  kubectl config set-credentials NAME [--client-certificate=path/to/certfile] [--client-key=path/to/keyfile]
[--token=bearer_token] [--username=basic_user] [--password=basic_password] [--auth-provider=provider_name]
[--auth-provider-arg=key=value] [options]

創建

kubectl config set-credentials web --client-certificate=./web.crt --client-key=./web.key --embed-certs=true
# --embed-certs=true表示密文顯示

註:此命令需在上述創建的秘鑰文件目錄中進行,否則需指定此秘鑰文件的全局路徑

查看
技術分享圖片

2 綁定用戶和集群

格式

kubectl config set-context [NAME | --current] [--cluster=cluster_nickname] [--user=user_nickname]
[--namespace=namespace] [options]

綁定

kubectl config set-context [email protected] --cluster=kubernetes --user=web

[email protected] 表示設置的用戶名稱,其是[email protected]形式的配置。其後端--cluster指定其加入集群的名稱,--user 指定要加入該集群的用戶的用戶名

查看
技術分享圖片

3 用戶賬號切換

kubectl config use-context [email protected]

查看其環境
技術分享圖片

4 執行相關操作

技術分享圖片
提示無相關權限

5 切換回來

kubectl config use-context [email protected]

技術分享圖片

3 定義一個新集群並添加上述配置的秘鑰信息

1 創建證書

cd /etc/kubernetes/pki/
(umask  077;openssl genrsa -out  user.key 2048)
openssl req -new -key user.key -out user.csr -subj "/CN=user/O=web"
openssl  x509 -req -in user.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out user.crt -days 3650 

2 創建一個新集群,定義其名稱為web1

格式

kubectl config set-cluster NAME [--server=server] [--certificate-authority=path/to/certificate/authority]
[--insecure-skip-tls-verify=true] [options]

創建

kubectl config set-cluster  web1 --kubeconfig=/tmp/web1.conf --server="https://192.168.90.100:6443"  --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true

3 配置客戶端證書及秘鑰,用戶名信息通過命令從subject的CN值自動提取,而組名則來自於上述的O=kubernetes的定義

kubectl config set-credentials user --embed-certs=true --client-certificate=/etc/kubernetes/pki/user.crt --client-key=/etc/kubernetes/pki/user.key --kubeconfig=/tmp/web1.conf

4 配置context,用來組合cluster和credentials,及訪問的集群的上下文

kubectl config set-context [email protected] --cluster=web1 --user=user --kubeconfig=/tmp/web1.conf

5 指定上下文切換

 kubectl config use-context [email protected]  --kubeconfig=/tmp/web1.conf

3 授權

1 總述

kubernetes 自1.6 後支持基於RBAC 的認證授權,認證檢查機制,基於角色的訪問控制,其有許可授權,沒有拒絕授權,

API SERVER 支持的內建授權插件,其可以同時啟動
Node: 基於POD資源的目標調度節點來完成對kubernetes的訪問控制。

ABAC: attribute-based access control 基於屬性的訪問控制。

RBAC:role-based access control 基於角色的訪問控制。通常只有許可授權,沒有拒絕授權,其使用kubeadm默認強制使用RBAC的認證機制。

webhook: 基於http回調機制通過外部REST服務檢查用戶授權的訪問控制。

always deny: 總是拒絕,用於測試
always allow:總是允許,用於不期望進行授權檢查時直接接受檢查階段放行的所有操作,啟動api server時,"authorization-mode" 選項用於定義要啟用的授權機制,多個選項之間彼此以逗號分隔。

2 RBAC簡介

RBAC 是一種新型、靈活且使用廣泛的訪問控制機制,其是基於角色的配置,將權限授予角色之上,與傳統的權限賦予使用者的方式不同。其他為賬號賦予到多個角色從而讓其具有角色上的權限,其中賬號可以是用戶賬號、用戶組、服務賬號及相關的組等,而同時關聯至多個角色的賬號鎖擁有的權限是多個角色之上的權限集合。 其用於界定"對象用戶(subject)"能不能操作(verb)那些對象或類(object),動作的發出者即是主體,通常是以賬戶為載體,其即可是常規用戶,也可以是服務賬號,操作(verb)用於標明要執行的具體操作,包括創建、刪除、修改和查看等,對應kubectl來說,其通常由create/apply/delete/update/patch/edit和get 等子命令給出,而"客體"則是指操作施加於的目標實體,對kubernetes API 來說主要是指各類資源對象及URL。


RBAC 相比其他授權機制的優勢
1 對集群中的資源和非資源URL的權限實現了完整覆蓋
2 整個RBAC完全由少數幾個API對象實現,而且同其他API對象一樣可以通過kubectl 或 API 調用進行操作
3 支持權限運行時調整,無需重啟API server。


RBAC 授權插件支持role和clusterrole兩類角色,其中role作用於名稱空間級別,用於定義名稱空間內的資源權限集合,而clusterrole則是用於集群級別的資源權限集合,一般來說,clusterrole 的許可授權可作用與整個集群,因此常用於控制role無法生效的資源對象,這包括集群級別的資源,(如 NODES等)、非資源類型的端點(如/healthz)和作用於所有名稱空間的資源。


對於這兩中角色授權,需要用到rolebinding和clusterrolebinding,rolebinding 用於將role上的許可權限綁定到一個或一組用戶上,其隸屬於且僅能作用於一個名稱空間,綁定時,可以引用同一個名稱空間中的role,也可以引用集群級別的clusterrole,而clusterrolebinding則把clusterrole中定義的許可權限綁定在一個或一組用戶至上,它僅可以引用集群級別的clusterrole。

一個名稱空間中可以包含多個role和rolebinding對象,類似的,集群級別也可以同時存在多個clusterrole和clusterrolebinding對象,而一個賬戶也可經由rolebinding或clusterrolebinding 關聯至多個角色,從而具有多重許可授權。

3 role 和 rolebinding

1 role

1 概述

role 僅是一組許可權限的集合,其描述了對那些資源可執行哪種操作,資源配置清單中使用rules資源嵌套授權規則。


2 核心字段

role.rules.verbs: 定義對資源可執行的操作列表,包括 create/apply/delete/update/patch/edit/list/get/proxy/redirect等
role.rules.apiGroups: 包含可資源的API組名稱,空串標識核心組
role.rules.resourceNames: 規則應用的目標資源名稱組成的列表,如POD資源中的那些資源的操作等
role.rules.resources: 規則應用的目標資源類型組成的列表,如pods,deployment等
role.rules.nonResourceURLs: 用於定義用戶應該投權限訪問的網址列表,其不是名稱空間級別的資源,其只能應用於clusterrole 和 clusterrolebinding。


大多數資源均可通過其資源類型的名稱引用,如pods或services等,這些名字與他們在API endpoint中的形式相同,某些資源類型還支持子資源(subresource),如Pod對象中的/log,Node對象中的/status等,其URL格式通常如下

http://localhost:8080/api/v1/namespaces/{NAMESAPCES}/pods/{NAME}/log

在RBAC角色定義中,若要引用此類資源,則需要使用resource/subresource格式。另外,還可以通過給定資源名稱直接引用某些特定的資源,支持此類子資源的操作通常有get、delete、update和patch。

3 role配置清單配置

實例

[[email protected] all]# cat role1.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
    name: web-role
    namespace: default  #其是名稱空間級別的資源,需指定名稱空間,若不指定,則默認是default名稱空間 
rules:
    - verbs: ["get","list","create","delete","watch","patch"]  # 定義其可指定的操作。操作可指定為*,表示可以執行所有的操作
      resources: ["pods","service","deployment","pods/log"]  #定義其可對那些資源對象進行操作
      apiGroups: [""]  #"" 表示核心API組

部署

kubectl apply  -f role1.yaml 

查看
技術分享圖片

4 role命令行形式配置

其也可以使用kubectl create role 命令進行快速創建操作,相關創建如下

格式

 kubectl create role NAME --verb=verb --resource=resource.group/subresource
[--resource-name=resourcename] [--dry-run] [options]

創建可對pod 進行查看,監控和列出的角色

kubectl create role pod-list  --verb=get,list,watch --resource=pods  -n default    #pod-list 角色名稱   --verb= 角色列表 --resource 可進行操作的資源名稱  -n 指定其作用的名稱空間。默認作用於default名稱空間

查看
技術分享圖片

2 rolebinding

1 概述

用於將role中定義的權限賦予一個或一組用戶,它由一組主體,以及一個要引用來賦予這組主體的role或clusterrole組成,rolebinding僅能夠引用同一名稱空間中的role對象完成授權。

2 核心字段解析

subjects 字段,主體信息綁定字段
rolebinding.subjects.apiGroup: 要引用的主體所屬的API群組,對serviceaccount類的主體來說默認是"",而User和Group類主體的默認值為"rbac.authorization.k8s.io"
rolebinding.subjects.kind: 要應用的主體類型。有User,Group和ServiceAccount三種選擇,必選字段。
rolebinding.subjects.name: 指定要綁定的主體賬戶的賬戶名稱,必選字段 
rolebinding.subjects.namespace: 指定引用的主體的名稱空間,對於非名稱空間類的主體,如"User"和"Group",其值必須為空,否則授權插件將返回錯誤信息。
roleRef 字段 角色綁定字段
rolebinding.roleRef.apiGroup: 引用的資源(Role或ClusterRole)所屬的API群組,必選字段 。
rolebinding.roleRef.kind: 引用的資源所屬的類別,可用值為Role或ClusterRole,必選字段 。
rolebinding.roleRef.name: 引用的角色資源的名稱。

3 配置清單配置

[[email protected] all]# cat rolebind.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
    name: web-rolebind
    namespace: default
subjects:  #要綁定的用戶信息
    - kind: User
      name: web
      apiGroup: rbac.authorization.k8s.io
roleRef:  #定義要綁定的資源信息
    kind: Role
    name: web-role
    apiGroup: rbac.authorization.k8s.io

部署

kubectl apply -f rolebind.yaml 

查看
技術分享圖片

切換用戶並進行查看

技術分享圖片
其不能訪問default名稱空間外的資源

4 命令行配置

格式

kubectl create rolebinding NAME --clusterrole=NAME|--role=NAME
[--user=username] [--group=groupname]
[--serviceaccount=namespace:serviceaccountname] [--dry-run] [options]

創建綁定web

kubectl create rolebinding web-pod-lsit --role=pod-list  --user=web

查看
技術分享圖片

註 :雖然rolebinding不能跨名稱空間引用role資源,但主體中的用戶賬號,用戶組合服務賬號卻不受名稱空間限制,因此,管理員可為一個主體通過不同名稱空間的rolebinding資源綁定不同名稱空間的角色

4 clusterrole和ClusterRoleBinding

1 clusterrole

1 簡介

集群級別的角色資源除了能夠管理與role資源相同的許可權限外,還可以用於集群級組件的授權,配置方式及其在rules字段中可內嵌的字段和Role類似。

2 配置清單創建方式

[[email protected] all]# cat clusterrole1.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
    name: web-rolecluster1  #其不屬於名稱空間級別資源,因此其無namespace
rules:
    - apiGroups: [""] #定義要訪問的資源群組為核心群組
      resources: ["nodes"]  #定義要訪問的資源,可以是集群級別的資源,也可是名稱空間級別的資源
      verbs: ["get","watch","list"] #定義其可執行的操作

部署

kubectl apply -f clusterrole1.yaml

查看

技術分享圖片

3 命令行方式創建

格式

kubectl create clusterrole NAME --verb=verb --resource=resource.group
[--resource-name=resourcename] [--dry-run] [options]

創建其可以查詢,列出和監控deployment,pods和service資源

kubectl create clusterrole web-cluster --verb=get,list,watch --resource=deployment,pods,service

查看
技術分享圖片

註 :rolebindding 也能夠將主題綁定到clusterrole資源上,但僅能賦予用戶訪問rolebinding資源本身所在的名稱空間內的由clusterrole賦予的權限,如clusterrole配置了可訪問所有POD的查詢權限,而rolebinding資源的名稱空間是web,則通過rolebinding綁定clusterrole和任何一個用戶,其訪問的權限範圍是web名稱空間中的POD資源。


一種常見的做法是集群管理員在集群範圍預先定義好一組訪問名稱空間級別資源全新啊的clusterrole資源,二貨普在多個名稱空間中多次通過rolebinding引用,從而讓用戶分別具有不同名稱空間上的資源的相應訪問權限,而完成了名稱空間級別的權限的快速授予。

集群級別的資源nodes、persistentvolumes等資源,以及非資源型的URL不屬於名稱空間級別,故此不能使用rolebinding來綁定授權,所有非名稱空間級別的資源都無法通過rolebinding綁定至用戶並賦予用戶相關的權限,這寫都是屬於clusterrolebinding 的功能。


kubernetes 除了名稱空間和集群級別的資源外,還有/api、/apis、/healthz、/swaggerapi和/version 等非資源型URL,對這些URL的訪問也必須事先獲取相關的權限,同級別的資源一樣,他們也只能定義在clusterrole中,且需要基於clusterrolebinding進行授權,不過,對資源的讀取權限已經由系統默認的名稱同為system:discovery的clusterrole 和 clusterrolebinding兩個資源自動設定,相關信息如下:

技術分享圖片

Non-Resource URLs 字段給出了相關URL列表,允許訪問權限僅有一個get,引用了次資源的clusterrolebinding 的相關信息如下

技術分享圖片

system:authenticated 和 system:unauthenticated 組包含了所有的用戶賬號,因此所有的用戶默認均有權限讀取。

另外,非資源型URL的授權規則和資源權限的授權規則可定義在一個clusterrole中,他們同屬於rules字段中的對象。

2 聚合型clusterrole

kubernetes 自1.9版本來時支持rules字段中嵌套aggregationRule字段來整合其他的clusterrole兌現的規則,這種類型的clusterrole 的權限受控於控制器,它們由所有被標簽選擇器匹配到的用於聚合的clusterrole的授權規則合並生成。

實例

[[email protected] all]# cat clusterrole2.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
    name: nginx-clusterrole1
    labels:
        web: nginx-clusterrole1
rules:
    - resources: ["pod","service"]
      verbs: ["list","get"]
      apiGroups: [""]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
    name: web-clusterrole3
aggregationRule:  #引用上述配置的clusterrole
    clusterRoleSelectors:
        - matchLabels:
            web: nginx-clusterrole1

部署

kubectl apply -f clusterrole2.yaml

查看
技術分享圖片

事實上kubernetes系統上面向用戶的內建clusterrole admin 和 edit 也是聚合型clusterrole,因為這可以使默認角色中包含自定義資源的相關規則。

3 面向用戶的內建clusterrole

APIserver內建了一組默認的clusterrole和clusterrolebinding已預留系統使用,其中大多數都是以"system: "為前綴 ,另外還有一些非以"system:" 為前綴的默認的role資源,其是為面向用戶的需求設定的,包括超級用戶角色(cluster-admin)。用於授權集群級別權限的clusterrolebinding(cluster-status)以及授權特定名稱空間級別權限的rolebinding (admin、edit 和 view)。

技術分享圖片

技術分享圖片

內建的clusterrole資源cluster-admin擁有管理集群所有資源的權限,它是基於同名的clusterrolebinding綁定到了"system: master"組上的用戶都將具有集群的超級管理權限。kubeadm安裝設定集群時自動創建的配置文件admin.conf中的秘鑰的組及O是master,其CN 是 kubernetes-admin,因此,其具有管理集群的權限。


因此,為kubernetes集群額外自定義超級管理員的方式有兩種:
1 創建用戶認證證書,其subjects中的O及組為master。
2 將創建的主體綁定到clusterrolecluster-admin上。


另外,在多租戶,多項目或多環境等使用場景中,用戶通常應該獲取名稱空間級別的絕大多數資源的管理,只讀或者編輯的權限,這類權限的快速授予可通過在指定的名稱空間中創建rolebinding資源引入內建的clusterrole資源admin,view 或edit 來進行。

技術分享圖片

若需要授權的是編譯或者只讀,則僅需要創建rolebinding時引用clusterrole相應的edit和view即可。

4 clusterrolebinding

1 清單文件配置

[[email protected] all]# cat clusterrolebind.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
    name: web-rolebinding
subjects:
    - kind: User
      name: web
      apiGroup: rbac.authorization.k8s.io
roleRef:
    kind: ClusterRole
    name: web-rolecluster1
    apiGroup: rbac.authorization.k8s.io

部署

kubectl apply -f clusterrolebind.yaml

查看
技術分享圖片

2 命令行方式綁定

語法

kubectl create clusterrolebinding NAME --clusterrole=NAME [--user=username]
[--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]
[options]

1創建綁定用戶和角色

kubectl create clusterrolebinding  web-clusterrolebind  --clusterrole=web-cluster   --user=web

2 切換賬戶

kubectl config  use-context [email protected]  

3 查看其相關資源
技術分享圖片

4 準入控制

1 總述

用於在客戶端請求經過身份驗證和授權檢查後,在持久化存儲etcd之前攔截請求,用於實現在資源創建、更新和刪除操作期間強制執行對象的語義驗證等功能,讀取資源信息的操作不會經由準入控制器的檢查,API 的準入控制器

2 準入控制類型

1 always deny: 總是拒絕,用於測試
2 always allow:總是允許,用於不期望進行授權檢查時直接接受檢查階段放行的所有操作,啟動api server時,"authorization-mode" 選項用於定義要啟用的授權機制,多個選項之間彼此以逗號分隔。
3 alwaysPullmages:總是下載鏡像,用於多租戶環境中以確保私有鏡像能夠被擁有權限的用戶使用
4 namespacelifecycle:拒絕在不存在的名稱空間中創建資源,而刪除名稱空間會級聯其下的所有資源
5 limitRanger:可用資源範圍界定,用於監控對設置了limitrange的對象發出的所有請求,以確保其資源請求不會超出限制。
6 serviceaccount: 用於實現service account管控機制的自動化,實現創建POD對象時自動為其附加service account 對象。
7 persistentvolumelabel: 為那些雲計算服務商提供的PV自動附加region 或 zone標簽,以確保這些存儲卷能夠正確關聯且僅能關聯到所屬的region 或 zone
8 defaultstorageclass: 監控所有創建PVC對象的請求,以確保沒有附加任何專用storageclass的請求會自動設定一個默認值。
9 resourceQuota: 用於對名稱空間設置可用資源的上限,並確保在其中創建的任何設置了資源限額的對象都不會超出名稱空間的資源配額
10 defaultolerationseconds:如果POD對象上不存在汙點寬容期限,則為他們設置默認寬容期。
11 validatingAdmissionWebhook: 並行調用匹配當前請求的所有驗證類的webhook,任何一個校驗失敗,請求及失敗。
12 mutatingadmissionwebhook: 串行調用匹配當前請求的所有編譯類的webhook,每個調用都可能會更改對象。

kubernetes認證、授權、準入控制