由於 Kubernetes 整體就是以 API 為基礎來設計的,因此要了解認證機制也就等同於要了解 k8s API server 的認證機制。
了解 Kubernetes API 認證機制
k8s 提供了多種的認證方式,管理者可以設定多種認證機制共存,只要任何一種通過就算通過。
以 k8s 中各服務之間的認證為例,是以 x509 的認證,同時也是最嚴格的認證方式。透過 Kubespray 安裝好 k8s 後,我們可以在 master node 上檢視一下 api server 的啟動設定:(/etc/kubernetes/manifests/kube-apiserver.manifest
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| apiVersion: v1 kind: Pod metadata: name: kube-apiserver namespace: kube-system ........(略) spec: hostNetwork: true dnsPolicy: ClusterFirst containers: - name: kube-apiserver image: gcr.io/google-containers/hyperkube:v1.10.4 imagePullPolicy: IfNotPresent resources: limits: cpu: 800m memory: 2000M requests: cpu: 100m memory: 256M command: - /hyperkube - apiserver - --advertise-address=10.103.10.51 - --etcd-servers=https://10.103.10.51:2379,https://10.103.10.52:2379,https://10.103.10.53:2379 - --etcd-cafile=/etc/ssl/etcd/ssl/ca.pem - --etcd-certfile=/etc/ssl/etcd/ssl/node-kube-master0.pem - --etcd-keyfile=/etc/ssl/etcd/ssl/node-kube-master0-key.pem - --insecure-bind-address=127.0.0.1 - --bind-address=0.0.0.0 ........(略) - --client-ca-file=/etc/kubernetes/ssl/ca.pem - --kubelet-client-certificate=/etc/kubernetes/ssl/node-kube-master0.pem - --kubelet-client-key=/etc/kubernetes/ssl/node-kube-master0-key.pem - --tls-cert-file=/etc/kubernetes/ssl/apiserver.pem - --tls-private-key-file=/etc/kubernetes/ssl/apiserver-key.pem - --service-account-key-file=/etc/kubernetes/ssl/service-account-key.pem - --secure-port=6443 - --insecure-port=8080 - --storage-backend=etcd3 - --authorization-mode=Node,RBAC ........(略) - --requestheader-client-ca-file=/etc/kubernetes/ssl/front-proxy-ca.pem - --proxy-client-cert-file=/etc/kubernetes/ssl/front-proxy-client.pem - --proxy-client-key-file=/etc/kubernetes/ssl/front-proxy-client-key.pem livenessProbe: ........(略) volumeMounts: ........(略) volumes: - hostPath: path: /etc/kubernetes name: kubernetes-config - name: ssl-certs-host hostPath: path: /etc/ssl - name: usr-share-ca-certificates hostPath: path: /usr/share/ca-certificates - hostPath: path: /etc/ssl/etcd/ssl name: etcd-certs
|
從上面可以看出:
與各個服務相互認證所使用的憑證 (*.pem
)
與本地端的其他服務則是透過 --insecure-bind-address=127.0.0.1
& --insecure-port=8080
來溝通
憑證存放的位置其實就是在各個 node 的本機上 (hostPath
定義)
目前此 k8s cluster 支援的認證方式為 Node & RBAC
pod 內部服務需要與 api server 互動時的認證方式,使用 Service Account Token 的方式,此處對應的設定是 --service-account-key-file=/etc/kubernetes/ssl/service-account-key.pem
Kubespray 預設設置了 X509
, Node
& RBAC
三種認證方式,但 Kubernetes 還支援了相當多其他的認證方式,例如:
以下會針對比較重要的認證機制詳細說明。
X509 Client Certs
從 Kubespray 預設的安裝設定中的 API server 啟動參數中,可以看到與 X509 相關設定參數有:
client-ca-file
tls-private-key-file
tls-cert-file
由於只有在 k8s cluster 內的 node 才會有這些憑證檔案,因此這樣的認證方式是在 cluster 內部不同 node 之間的服務相互存取時使用。
但若是與 API server 同在本地端(localhost)的服務要存取 API 呢? 就直接 pass 了…..(像是 kube-scheduler
& kube-controller-manager
都屬於這一類的服務)
可看到 --insecure-bind-address=127.0.0.1
& --insecure-port=8080
兩個設定,就可以看出在本地端內部服務存取 API server 時,使用的是 http://localhost:8080
Service Account
Service Account 本身在 k8s 中是屬於 resource 的一種。我們可以透過以下指令取得 Service Account 清單:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
root@kube-master0:~ NAMESPACE NAME SECRETS AGE default default 1 4d kube-public default 1 4d kube-system attachdetach-controller 1 4d kube-system cronjob-controller 1 4d kube-system daemon-set-controller 1 4d kube-system default 1 4d kube-system deployment-controller 1 4d .....(略)
|
從上面清單可看出,每個 namespace 中都會有一個名稱為 default
的 service account,接著可以來拆解這個 default
service account 有什麼內容:
1 2 3 4 5 6 7 8 9 10 11 12
|
root@kube-master0:~ Name: default Namespace: kube-system Labels: <none> Annotations: <none> Image pull secrets: <none> Mountable secrets: default-token-nkl69 Tokens: default-token-nkl69 Events: <none>
|
最後來看看上面 service account token 所帶的內容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
root@kube-master0:~ Name: default-token-nkl69 Namespace: kube-system Labels: <none> Annotations: kubernetes.io/service-account.name=default kubernetes.io/service-account.uid=fd2e5d64-6f9c-11e8-b6b3-065296fdbf18
Type: kubernetes.io/service-account-token
Data ==== namespace: 11 bytes token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLW5rbDY5Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJmZDJlNWQ2NC02ZjljLTExZTgtYjZiMy0wNjUyOTZmZGJmMTgiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.cMC6jKcj1vmDhQnxlsHzop1t6W3qeG-xhEAZyBuzagUgb-2f06ZxI0UvIQ-qb3mkXyjtCdhw-Hn4PpvJ56HtvCBMYwfaP-ii4ord0aZfhqIRynlFuj-cc2qvhewaGwC84Yj7awMj6rv9yQGMgFBEL0roaLgoVAyYqpbJ6B2ig4cBlQQnTbiewYXdGoWGzb3wtl2Ii6E9nZ6ANPxLI4dhwbAxVNVAR4tojRiukQldSnI0ItX-Iwx1Djd5FK3FCgxY1soo682sLE-_NJeF8KfVPAWtg1049dSXe1iNQ3k-AO3pfEGDBaAq4WACuYhMtfL2iYlZRxS5SEt8Mwz3aVW1ng ca.crt: 1090 bytes
|
Service Account 的認證方式主要是由 k8s 自行管理,當我們建立一個 namespace 時,就自動會產生一個名稱為 default
的 service account 並帶有新建立的 token;而未來在此 namespace 中所產生的 pod,都會自動使用此 token 與 API server 進行認證。
References