十. k8s--訪問控制 serviceaccount和RBAC 學習筆記

[TOC]html

用戶帳戶與服務帳戶

Kubernetes 區分用戶帳戶和服務帳戶的概念主要基於如下緣由:node

  • 用戶帳戶是針對人而言的。 服務帳戶是針對運行在pod中的進程而言的。
  • 用戶帳戶是全局性的。 其名稱在集羣各namespace中都是全局惟一的,將來的用戶資源不會作namespace隔離, 服務帳戶是namespace隔離的。
  • 一般狀況下,集羣的用戶帳戶可能會從企業數據庫進行同步,其建立須要特殊權限,而且涉及到複雜的業務流程。 服務帳戶建立的目的是爲了更輕量,容許集羣用戶爲了具體的任務建立服務帳戶 (即權限最小化原則)。
  • 對人員和服務帳戶審計所考慮的因素可能不一樣。
  • 針對複雜系統的配置可能包含系統組件相關的各類服務帳戶的定義。 由於服務帳戶能夠定製化地建立,而且有namespace級別的名稱,這種配置是很輕量的。
UserAccount經常使用於複雜業務邏輯管控,做用於系統全局,獨立於K8s以外
ServiceAccount僅用於實現某些特定操做任務,隸屬於名稱空間,由API Server管理

訪問控制過程

客戶端 → API Server → 認證插件 → 受權插件 → 准入控制插件 → 寫入成功nginx

須要注意:認證受權過程只存在HTTPS形式的API中。也就是說,若是客戶端使用HTTP鏈接到kube-apiserver,是不會進行認證受權的。因此說,能夠這麼設置,在集羣內部組件間通訊使用HTTP集羣, 外部就使用HTTPS,這樣既增長了安全性,也不至於太複雜。
### K8s內建用戶組:
  • system:unauthenticated,未經過認證測試的用戶所屬的組
  • system:authenticated,認證成功的用戶自動加入的組,用於快捷引用全部正常經過認證的用戶賬號
  • system:serviceaccounts,當前系統上全部Service Account對象
  • system:serviceaccounts:<namespace>,特定名稱空間內全部Service Account對象

認證. 受權與准入控制

  • API Server支持同時啓用多種認證機制, 但至少包括UserAccount和ServiceAccount中的一種
  • 啓用多種認證插件時, 認證過程會以串行方式進行, 直到一種成功便可, 認證失敗會返回401

認證方式

  1. X509客戶端證書認證:客戶端請求報文中攜帶X509格式證書,經過後,CN字段是用戶名,O字段是所屬的組,O能夠有多個,即屬於多個組
  2. 靜態令牌文件:由kube-apiserver 選項--token-auth-file加載,啓動後不可更改;HTTP客戶端也能使用承載令牌進行身份驗證,將令牌編碼後,請求報文中Authorization承載傳遞
  3. 引導令牌:kubeadm join將節點加入集羣時,就是這種方式
  4. 靜態密碼文件:用戶名密碼等以明文存儲的CSV格式文件,由kube-apiserver經過--basic-auth-file加載
  5. 服務賬戶令牌:由kube-apiserver自動啓用。ServiceAccount一般由API Server自動建立,並經過ServiceAccount准入控制器將其注入Pod對象,容器中應用請求API Server的服務時將以此完成身份證
  6. OpenID鏈接令牌:OAuth2認證
  7. Webhook令牌:客戶端使用kubeconfig格式的配置文件
  8. 認證代理:X-Remote-User
  9. Keystone密碼:藉助Keystone服務器進行身份認證
  10. 匿名請求:未被任何驗證機制明確拒絕的用戶即匿名用戶,system:anonymous 屬於 system:unauthenticated組;匿名用戶可經過 --anonymous-auth=false禁用

內建的受權插件:

  1. Node,基於Pod資源的目標調度節點來實現對kubelet的訪問控制shell

  2. ABAC,基於屬性的訪問控制,attribute-based access control數據庫

  3. RBAC,基於角色的訪問控制,role-based access controlapi

  4. Webhook,基於HTTP回調機制經過外部REST服務檢查確認用戶受權的訪問控制安全

  5. AlwaysDeny,老是拒絕,僅用於測試服務器

  6. AlwaysAllow,老是容許app

    啓用API Server時 --authorization-mode定義要啓用的受權機制,多個選項以逗號分隔frontend

准入控制器

在對象持久化存儲etcd前,強制執行對象的語義驗證等功能 讀取資源信息的請求不會通過准入控制器檢查

  1. AlwaysAdmit,容許全部請求
  2. AlwaysDeny,拒絕全部請求,僅用於測試
  3. AlwaysPullImages,老是下載鏡像
  4. NamespaceLifecycle,拒絕在不存在的名稱空間建立資源,刪除名稱空間會級聯刪除其下全部資源
  5. LimitRanger,可用資源範圍界定,確保資源請求不會超限
  6. ServiceAccount,實現ServiceAccount管理機制自動化,建立Pod對象時自動爲其附加相關ServiceAccount對象
  7. PersistnetVolumeLabel,爲由雲計算服務商提供的PV自動附加region或zone標籤
  8. DefaultStorageClass,監控全部建立PVC對象的請求,保證沒有附加專用StorageClass的請求會自動設定一個默認值
  9. ResourceQuota,對名稱空間設置可用資源上限,確保在其中建立的設置了資源限額的對象不會超出名稱空間的資源配額
  10. DefaultTolerationSeconds,若是Pod對象上不存在污點寬容期限,則爲它們設置默認寬容期,以寬容 notready:NoExecute 和 unreachable:NoExctute 類污點5min
  11. ValidatingAdmissionWebhook,並行調用匹配當前請求的全部驗證類Webhook,任何一個校驗失敗,請求即失敗
  12. MutatingAdmissionWebhook,串行調用匹配當前請求的全部變異類Webhook,每一個調用均可能會更改對象

ServiceAccount管理與應用

Service Account 資源通常由用戶名和相關的Secret對象組成
用於讓Pod對象內的容器進程訪問其餘服務時提供身份認證信息,這些其餘服務包括:API 調度器 Pod控制器 節點控制器 私有Registry服務等

Service Account 自動化

每一個Pod都會自動關聯一個存儲卷,掛載至 /var/run/secrets/kubernetes.io/serviceaccount

[root@master ~]# kubectl exec nginx-554b9c67f9-r5852 ls /var/run/secrets/kubernetes.io/serviceaccount
ca.crt # 這是API Server的CA公鑰證書,用於Pod中的Process對API Server的服務端數字證書進行校驗時使用的
namespace
token  # token保存了Service Account的認證token 容器中進程使用它向API Server發起鏈接請求
每一個Pod對象都只有一個服務賬戶,若建立時未明確指定,會自動附加當前名稱空間中默認服務賬戶default
``` [root@master ~]# kubectl describe serviceaccounts default Name: default Namespace: default Labels: Annotations: Image pull secrets: Mountable secrets: default-token-l5bzk Tokens: default-token-l5bzk Events: ```

K8s中的SSL/TLS認證

  • etcd集羣內對等節點通訊:默認2380端口,基於SSL/TLS通訊
  • etcd服務器與客戶端通訊:Restful API 默認2379端口,基於SSL/TLS通訊

建立一個ServiceAccount

#測試
[root@master ~]# kubectl create serviceaccount admin -o yaml --dry-run #幹跑
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: null
  name: admin

kubectl create serviceaccount admin
 
#查看以建立的service賬號
[root@master ~]# kubectl get sa
NAME      SECRETS   AGE
admin     1         6s
default   1         24d
 
#查看詳細信息
kubectl describe sa admin 
 
##簡潔輸出
kubectl get pods myapp-0 -o yaml --export

pod使用上述建立的ServiceAccount

apiVersion: v1
kind: Pod
metadata:
  name: pod-sa-demo
  namespace: default
  labels:
    app: myapp
    tier: frontend
  annotations:
    leiyan.com/reatedby: "cluster admin"
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
  serviceAccountName: admin

客戶端配置文件kubeconfig

包括kubectl、kubelet、kube-controller-manager等在內的API Server的各種客戶端均可以使用kubeconfig配置文件提供接入多個集羣的相關配置信息

包括API Server的URL及認證信息,且可設置不一樣的上下文,並在各環境之間快速切換

/etc/kubernetes/admin.conf即爲kubeconfig格式的配置文件

查看當前正在使用的配置文件, 上下文是集羣和用戶的配對
``` kubectl config view #顯示羣集列表、用戶列表、上下文列表、當前使用的上下文 ```
[root@master ~]# kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.0.0.50:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

kubeconfig配置文件可經過kubectl config命令進行設定

kubectl config view,打印文件內容
kubectl config set-cluster,設置clusters段
kubectl config set-credentials,設置users段
kubectl config set-context,設置contexts段
kubectl config set-use-context,設置current-context段

添加ServiceAccount

  1. 爲賬號kube-user1建立私鑰及證書文件,保存於/etc/kubernetes/pki目錄中 #須要在master節點以root用戶執行

    cd /etc/kubernetes/pki
    
    (umask 077; openssl genrsa -out kube-user1.key 2048)
    
    openssl req -new -key kube-user1.key -out kube-user1.csr -subj "/CN=kube-user1/O=kubeusers" # 其中 CN是用戶名,O是用戶組
    
    openssl x509 -req -in kube-user1.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kube-user1.crt -days 3650 
    
    openssl x509 -in kube-user1.crt -text -noout # 驗證證書(可選)
  2. 以默認管理員 kubernetes-admin@kubernetes爲新用戶kube-user1設定配置文件,默認保存於 .kube/config 也可以使用 --kubeconfig指定自定義路徑

    2.1 配置集羣信息,存在可省略此步驟

    kubectl config set-cluster kubernetes-new --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --server="https://10.0.0.50:6443"

    2.2 配置客戶端證書及密鑰,用戶名組名會自動提取

    kubectl config set-credentials kube-user1 --embed-certs=true --client-certificate=/etc/kubernetes/pki/kube-user1.crt --client-key=/etc/kubernetes/pki/kube-user1.key

    2.3 配置context,組合cluster和credentials

    kubectl config set-context kube-user1@kubernetes-new --cluster=kubernetes-new --user=kube-user1

    2.4 指定當前上下文

    kubectl config use-context kube-user1@kubernetes-new

    2.5 測試

    [root@master pki]# kubectl get pods
    Error from server (Forbidden): pods is forbidden: User "kube-user1" cannot list resource "pods" in API group "" in the namespace "default"
    
    #切換回來
    kubectl config use-context kubernetes-admin@kubernetes
    
    [root@master pki]# kubectl get pods
    NAME                     READY   STATUS        RESTARTS   AGE
    nginx-554b9c67f9-r5852   1/1     Running       0          89m
    pod-cm-1                 1/1     Running       0          6d
    pod-cm-2                 1/1     Running       0          6d
    pod-hostpath-demo        1/1     Terminating   0          7d21h

角色訪問控制RBAC (Role-Based Access Control)

相關概念

Role與ClusterRole

在RBAC API中,一個角色包含了一套表示一組權限的規則。 權限以純粹的累加形式累積(沒有」否認」的規則)。 角色能夠由命名空間(namespace)內的Role對象定義,而整個Kubernetes集羣範圍內有效的角色則經過ClusterRole對象實現。

一個Role對象只能用於授予對某一單一命名空間中資源的訪問權限。
如下示例描述了」default」命名空間中的一個Role對象的定義,用於授予對pod的讀訪問權限:
**建立一個`role`**
[root@master manifests]# cat role-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pods-reader
  namespace: default
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch
[root@master manifests]# kubectl apply -f role-demo.yaml
role.rbac.authorization.k8s.io/pods-reader created

將role和user綁定, 並驗證已經生效, 能夠get到pod資源

# 將kube-user1和pods-reader綁定
[root@master manifests]# kubectl create rolebinding kube-user1-read-pods --role=pods-reader --user=kube-user1
rolebinding.rbac.authorization.k8s.io/kube-user1-read-pods created

# 切換用戶到kube-user1
[root@master manifests]# kubectl config use-context kube-user1@kubernetes
Switched to context "kube-user1@kubernetes".

# 測試能夠get到pod信息
[root@master manifests]# kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
myapp-0   1/1     Running   0          5d4h
myapp-1   1/1     Running   0          5d4h
myapp-2   1/1     Running   0          5d4h
myapp-3   1/1     Running   0          5d4h
ClusterRole對象能夠授予與Role對象相同的權限,但因爲它們屬於集羣範圍對象, 也可使用它們授予對如下幾種資源的訪問權限:
- 集羣範圍資源(例如節點,即node) - 非資源類型endpoint(例如」/healthz」) - 跨全部命名空間的命名空間範圍資源(例如pod,須要運行命令`kubectl get pods --all-namespaces`來查詢集羣中全部的pod)

建立ClusterRole

[root@master manifests]# cat cluster-role-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-role
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch
[root@master manifests]# kubectl apply -f cluster-role-demo.yaml
clusterrole.rbac.authorization.k8s.io/cluster-role created

ClusterRoleUser綁定, 並驗證權限是否生效

[root@master manifests]# cat clusterrolebinding-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: user1-read-all-pods
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: kube-user1
[root@master manifests]# kubectl apply -f clusterrolebinding-demo.yaml
clusterrolebinding.rbac.authorization.k8s.io/user1-read-all-pods created

驗證權限

# 切換用戶到kube-user1
[root@master manifests]# kubectl config use-context kube-user1@kubernetes
Switched to context "kube-user1@kubernetes".

# 成功獲取到默認namespace的pod信息
[root@master manifests]# kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
myapp-0   1/1     Running   0          5d4h
myapp-1   1/1     Running   0          5d4h
myapp-2   1/1     Running   0          5d4h
myapp-3   1/1     Running   0          5d4h

# 成功獲取到其餘namespace的pod信息
[root@master manifests]# kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-7995bd9c47-crpwt   1/1     Running   0          12d

RoleBinding與ClusterRoleBinding

角色綁定將一個角色中定義的各類權限授予一個或者一組用戶。 角色綁定包含了一組相關主體(即subject, 包括用戶——User、用戶組——Group、或者服務帳戶——Service Account)以及對被授予角色的引用。 在命名空間中能夠經過RoleBinding對象授予權限,而集羣範圍的權限授予則經過ClusterRoleBinding對象完成。

RoleBinding能夠引用在同一命名空間內定義的Role對象。 下面示例中定義的RoleBinding對象在」default」命名空間中將」pod-reader」角色授予用戶」kube-user1」。 這一受權將容許用戶」kube-user1」從」default」命名空間中讀取pod。
```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: user1-read-pods namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: pod-reader subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: kube-user1 ```
RoleBinding對象也能夠引用一個ClusterRole對象用於在RoleBinding所在的命名空間內授予用戶對所引用的ClusterRole中 定義的命名空間資源的訪問權限。這一點容許管理員在整個集羣範圍內首先定義一組通用的角色,而後再在不一樣的命名空間中複用這些角色。
**將clusterrole經過rolebinding和user綁定到一塊兒, 會降級到rolebinding所在的namespace**
[root@master manifests]# cat rolebinding-clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: user1-read-pods
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: kube-user1
[root@master manifests]# kubectl apply -f rolebinding-clusterrole.yaml
rolebinding.rbac.authorization.k8s.io/user1-read-pods created

這時候發現只能獲取到RoleBinding設置的namespace中的pod

[root@master ~]# kubectl config use-context kube-user1@kubernetes
Switched to context "kube-user1@kubernetes".
[root@master ~]# kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
myapp-0   1/1     Running   0          5d4h
myapp-1   1/1     Running   0          5d4h
myapp-2   1/1     Running   0          5d4h
myapp-3   1/1     Running   0          5d4h
[root@master ~]# kubectl get pod -n ingress-nginx
Error from server (Forbidden): pods is forbidden: User "kube-user1" cannot list resource "pods" in API group "" in the namespace "ingress-nginx"

最後將ClusterRoleUser經過ClusterRoleBinding綁定到一塊兒

容許用戶kube-user1讀取全部namespace的pod信息

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: user1-read-all-pods
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: kube-user1
[root@master manifests]# kubectl apply -f clusterrolebinding-demo.yaml
clusterrolebinding.rbac.authorization.k8s.io/user1-read-all-pods created
[root@master manifests]# kubectl config use-context kube-user1@kubernetes
Switched to context "kube-user1@kubernetes".
[root@master manifests]# kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
myapp-0   1/1     Running   0          5d7h
myapp-1   1/1     Running   0          5d7h
myapp-2   1/1     Running   0          5d7h
myapp-3   1/1     Running   0          5d7h
[root@master manifests]# kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-7995bd9c47-crpwt   1/1     Running   0          13d

參考連接

https://pdf.us/2019/03/21/3061.html

https://jimmysong.io/kubernetes-handbook/concepts/rbac.html

相關文章
相關標籤/搜索