1. 程式人生 > 實用技巧 >K8s之認證,授權及准入控制

K8s之認證,授權及准入控制

第1章 訪問認證的概述

1.1 概念的引入

API Server作為Kubernetes集群系統的閘道器,是訪問及管理資源物件的唯一人口,
餘下所有需要訪問叢集資源的元件,包括kube-controller-manager、kube- scheduler 、
kubelet和kube-proxy等叢集基礎元件、CoreDNS等叢集的附加元件以及此前使用的kubectl
命令等都要經由此閘道器進行叢集訪問和管理。這些客戶端均要經由API Server訪問或改變叢集狀態並
完成資料儲存,並由它對每一次的訪問請求進行合法性檢驗,包括使用者身份鑑別、操作許可權
驗證以及操作是否符合全域性規範的約束等。所有檢查均正常完成且物件配置資訊合法性檢驗
無誤之後才能訪問或存人資料於後端儲存系統etcd中

第2章 ServiceAccount

2.1 概述

Service account是為了方便Pod裡面的程序呼叫Kubernetes API或其他外部服務而設計的。它與User account不同
1)User account是為人設計的,而service account則是為Pod中的程序呼叫Kubernetes API而設計;
2)User account是跨namespace的,而service account則是僅侷限它所在的namespace;
3)每個namespace都會自動建立一個default service account
4)Token controller檢測service account的建立,併為它們建立secret
開啟ServiceAccount Admission Controller後
  1.每個Pod在建立後都會自動設定spec.serviceAccount為default(除非指定了其他ServiceAccout)
  2.驗證Pod引用的service account已經存在,否則拒絕建立
  3.如果Pod沒有指定ImagePullSecrets,則把service account的ImagePullSecrets加到Pod中
  4.每個container啟動後都會掛載該service account的token和ca.crt到/var/run/secrets/kubernetes.io/serviceaccount/

2.2 檢視相關資訊

當建立pod的時候,如果沒有指定一個service account,系統會自動在與該pod相同的namespace下為其指派一個default service account。
而pod和apiserver之間進行通訊的賬號,稱為serviceAccountName。如下:
[root@master ~]# kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
filebeat-ds-hxgdx        1/1       Running   1          34d
filebeat-ds-s466l        1/1       Running   2          34d
myapp-0                  1/1       Running   0          3h
myapp-1                  1/1       Running   0          3h
myapp-2                  1/1       Running   0          4h
myapp-3                  1/1       Running   0          4h
pod-vol-demo             2/2       Running   0          2d
redis-5b5d6fbbbd-q8ppz   1/1       Running   1          2d
[root@master ~]# kubectl get pods/myapp-0 -o yaml |grep "serviceAccountName"
  serviceAccountName: default
[root@k8s-master ~]# kubectl describe pods myapp-0
Name:               myapp-0
Namespace:          default
......
Volumes:
  ......
  default-token-j5pf5:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-j5pf5
    Optional:    false
從上面可以看到每個Pod無論定義與否都會有個儲存卷,這個儲存卷為default-token-*** token令牌,
這就是pod和serviceaccount認證資訊。通過secret進行定義,由於認證資訊屬於敏感資訊,所以需要儲存在secret資源當中,
並以儲存卷的方式掛載到Pod當中。從而讓Pod內執行的應用通過對應的secret中的資訊來連線apiserver,並完成認證。
每個namespace中都有一個預設的叫做default的service account資源。進行檢視名稱空間內的secret也可以看到對應的default-token。
讓當前名稱空間中所有的pod在連線apiserver時可以使用的預製認證資訊,從而保證pod之間的通訊。

2.3 service account定義的方式

[root@master ~]# kubectl explain sa
KIND:     ServiceAccount
VERSION:  v1
FIELDS:
apiVersion    <string>
automountServiceAccountToken    <boolean>
imagePullSecrets    <[]Object>
kind    <string>   
metadata    <Object>
secrets    <[]Object>

2.4 service account的建立

[root@master mainfests]# kubectl create serviceaccount mysa -o yaml --dry-run #不執行檢視定義方式
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: null
  name: mysa
[root@master mainfests]# kubectl create serviceaccount mysa -o yaml --dry-run > serviceaccount.yaml  #直接匯出為yaml定義檔案,可以節省敲鍵盤的時間
[root@master mainfests]# kubectl apply -f serviceaccount.yaml 
serviceaccount/mysa created
[root@master mainfests]# kubectl get serviceaccount/mysa -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"creationTimestamp":null,"name":"mysa","namespace":"default"}}
  creationTimestamp: 2018-10-11T08:12:25Z
  name: mysa
  namespace: default
  resourceVersion: "432865"
  selfLink: /api/v1/namespaces/default/serviceaccounts/mysa
  uid: 62fc7782-cd2d-11e8-801a-000c2972dc1f
secrets:
- name: mysa-token-h2mgk
看到有一個token已經被自動建立,並被service account引用。設定非預設的service account
只需要在pod的spec.serviceAccountName欄位中將name設定為您想要用的service account名字即可。
在pod建立之初service account就必須已經存在,否則建立將被拒絕。需要注意的是不能更新已建立的pod的service account

2.5 serviceaccount的自定義使用

這裡在default名稱空間建立了一個sa為admin,可以看到已經自動生成了一個Tokens:admin-token-7k5nr
[root@master mainfests]# kubectl create serviceaccount admin
serviceaccount/admin created
[root@master mainfests]# kubectl get sa
NAME      SECRETS   AGE
admin     1         3s
default   1         50d
[root@master mainfests]# kubectl describe sa/admin
Name:                admin
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   admin-token-7k5nr
Tokens:              admin-token-7k5nr
Events:              <none>
[root@master mainfests]# kubectl get secret
NAME                    TYPE                                  DATA      AGE
admin-token-7k5nr       kubernetes.io/service-account-token   3         31s
default-token-j5pf5     kubernetes.io/service-account-token   3         50d
mysecret                Opaque                                2         1d
tomcat-ingress-secret   kubernetes.io/tls                     2         10d
[root@master mainfests]# vim pod-sa-demo.yaml  #Pod中引用新建的serviceaccount
apiVersion: v1
kind: Pod
metadata:
  name: pod-sa-demo
  namespace: default
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
  serviceAccountName: admin
[root@master mainfests]# kubectl apply -f pod-sa-demo.yaml 
pod/pod-sa-demo created
[root@master mainfests]# kubectl describe pods pod-sa-demo
......
Volumes:
  admin-token-7k5nr:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  admin-token-7k5nr
    Optional:    false

在K8S叢集當中,每一個使用者對資源的訪問都是需要通過apiserver進行通訊認證才能進行訪問的,那麼在此機制當中,對資源的訪問可以是token,也可以是通過配置檔案的方式進行儲存和使用認證資訊,可以通過kubectl config進行檢視配置,如下:

[root@master mainfests]# kubectl config view
apiVersion: v1
clusters:  #叢集列表
- cluster:
    certificate-authority-data: REDACTED
    server: https://192.168.56.11: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

在上面的配置檔案當中,定義了叢集、上下文以及使用者。其中Config也是K8S的標準資源之一,在該配置檔案當中定義了一個叢集列表,指定的叢集可以有多個;
使用者列表也可以有多個,指明叢集中的使用者;而在上下文列表當中,是進行定義可以使用哪個使用者對哪個叢集進行訪問,以及當前使用的上下文是什麼。
如圖:定義了使用者kubernetes-admin可以對kubernetes該叢集的訪問,使用者kubernetes-user1對Clluster1叢集的訪問

上圖解析:
1. kubectl config中定義了有哪些叢集和哪些使用者(都是以列表的形式)
2. contexts就是定義哪個使用者去訪問哪個叢集(從kubectl config中選出來)
3. contexts可以是多個的(一個contexts用來包含一個賬號和一個叢集),所以用的列表的形式
4. current-context: kubernetes-admin@kubernetes 就是表示從眾多的contexts選出一個當前使用的contexts