API Server作為Kubernetes網關,是訪問和管理資源對象的唯一入口,其各種集群組件訪問資源都需要經過網關才能進行正常訪問和管理。每一次的訪問請求都需要進行合法性的檢驗,其中包括身份驗證、操作權限驗證以及操作規范驗證等,需要通過一系列驗證通過之后才能訪問或者存儲數據到etcd當中。如下圖:
一、ServiceAccount
Service account是為了方便Pod里面的進程調用Kubernetes API或其他外部服務而設計的。它與User account不同
- User account是為人設計的,而service account則是為Pod中的進程調用Kubernetes API而設計;
- User account是跨namespace的,而service account則是僅局限它所在的namespace;
- 每個namespace都會自動創建一個default service account;
- Token controller檢測service account的創建,並為它們創建secret;
- 開啟ServiceAccount Admission Controller后
- 每個Pod在創建后都會自動設置spec.serviceAccount為default(除非指定了其他ServiceAccout)
- 驗證Pod引用的service account已經存在,否則拒絕創建
- 如果Pod沒有指定ImagePullSecrets,則把service account的ImagePullSecrets加到Pod中
- 每個container啟動后都會掛載該service account的token和ca.crt到/var/run/secrets/kubernetes.io/serviceaccount/
當創建 pod 的時候,如果沒有指定一個 service account,系統會自動在與該pod 相同的 namespace 下為其指派一個default service account。而pod和apiserver之間進行通信的賬號,稱為serviceAccountName。如下:
[root@master magedu]# kubectl get pod
NAME READY STATUS RESTARTS AGE
c2p-pod 1/1 Running 0 9d
demoapp2-677db795b4-8kx4c 1/1 Running 0 16d
demoapp2-677db795b4-9vf7x 1/1 Running 0 16d
[root@master magedu]# kubectl get pods/c2p-pod -o yaml|grep "serviceAccountName"
serviceAccountName: default
[root@master magedu]# kubectl describe pods/c2p-pod
Name: c2p-pod
Namespace: default
Priority: 0
Node: node2/192.168.1.244
..............................................
Volumes:
default-token-ckxbt:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-ckxbt
Optional: false
.............................................
從上面可以看到每個Pod無論定義與否都會有個存儲卷,這個存儲卷為default-token-*** token令牌,這就是pod和serviceaccount認證信息。通過secret進行定義,由於認證信息屬於敏感信息,所以需要保存在secret資源當中,並以存儲卷的方式掛載到Pod當中。從而讓Pod內運行的應用通過對應的secret中的信息來連接apiserver,並完成認證。每個 namespace 中都有一個默認的叫做 default 的 service account 資源。進行查看名稱空間內的secret,也可以看到對應的default-token。讓當前名稱空間中所有的pod在連接apiserver時可以使用的預制認證信息,從而保證pod之間的通信。
[root@master magedu]# kubectl get ns
NAME STATUS AGE
default Active 20d
dev-namespace Active 20d
[root@master magedu]# kubectl get sa -n dev-namespace
NAME SECRETS AGE
default 1 20d
[root@master magedu]# kubectl get secret -n dev-namespace
NAME TYPE DATA AGE
default-token-89wp8 kubernetes.io/service-account-token 3 20d
[root@master magedu]# kubectl describe secrets default-token-89wp8 -n dev-namespace
Name: default-token-89wp8
Namespace: dev-namespace
Type: kubernetes.io/service-account-token
Data
====
namespace: 13 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6ImxvTjBGUXNUNVYzUkVBVTlOdFpjZW9aMkszd3NsVjZYbkJEWE1CazlrSVEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZXYtbmFtZXNwYWNlIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tODl3cDgiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImU4YmQwMTEyLWMwNzYtNDFmMS1hMzFkLTM2ZDc0ZjNmY2UzNyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZXYtbmFtZXNwYWNlOmRlZmF1bHQifQ.BM_6tEpc4aIk_cbPY8sw1H5alnSmZXQuro5cpO2rng-rLyNZSVQLNC5enQ0IrqlA6Ei75FAXzm7XjID3uaeEwy4QpPEyFKODvILwb_FfIXhCviS0B-3UQTEjbcvyjRwduhayki6dZlEcvGIaz4EOw0dyNixZ4QcnUVkfAwXPjU--w7Vg-QHntf8xbYEndlWtYAUlmHqeWxf9WzYYJAyLNfisDbTZBq_0_04IBzRATzqYRi1rx-93luXftdetMkpCsV2ditASNatWcIxTiIeruYBv42fVZLHhM27GREEO3RnbdTWYohk0evN-Ua1DMfZs4BLyLrgr1NBQnAR7xFj-aw
ca.crt: 1066 bytes
而默認的service account 僅僅只能獲取當前Pod自身的相關屬性,無法觀察到其他名稱空間Pod的相關屬性信息。如果想要擴展Pod,假設有一個Pod需要用於管理其他Pod或者是其他資源對象,是無法通過自身的名稱空間的serviceaccount進行獲取其他Pod的相關屬性信息的,此時就需要進行手動創建一個serviceaccount,並在創建Pod時進行定義。那么serviceaccount該如何進行定義呢???實際上,service accout也屬於一個k8s資源,如下查看service account的定義方式:
[root@master magedu]# kubectl explain serviceaccount
KIND: ServiceAccount
VERSION: v1
DESCRIPTION:
ServiceAccount binds together: * a name, understood by users, and perhaps
by peripheral systems, for an identity * a principal that can be
authenticated and authorized * a set of secrets
FIELDS:
apiVersion <string>
APIVersion defines the versioned schema of this representation of an
object. Servers should convert recognized schemas to the latest internal
value, and may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
automountServiceAccountToken <boolean>
AutomountServiceAccountToken indicates whether pods running as this service
account should have an API token automatically mounted. Can be overridden
at the pod level.
imagePullSecrets <[]Object>
ImagePullSecrets is a list of references to secrets in the same namespace
to use for pulling any images in pods that reference this ServiceAccount.
ImagePullSecrets are distinct from Secrets because Secrets can be mounted
in the pod, but ImagePullSecrets are only accessed by the kubelet. More
info:
https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod
kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
metadata <Object>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
secrets <[]Object>
Secrets is the list of secrets allowed to be used by pods running using
this ServiceAccount. More info:
https://kubernetes.io/docs/concepts/configuration/secret
service account的創建
[root@k8s-master mainfests]# kubectl create serviceaccount mysa -o yaml --dry-run #不執行查看定義方式
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: null
name: mysa
[root@k8s-master mainfests]# kubectl create serviceaccount mysa -o yaml --dry-run > serviceaccount.yaml #直接導出為yaml定義文件,可以節省敲鍵盤的時間
[root@k8s-master mainfests]# kubectl apply -f serviceaccount.yaml
serviceaccount/mysa created
[root@k8s-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
。
serviceaccount的自定義使用
這里在default名稱空間創建了一個sa為admin,可以看到已經自動生成了一個Tokens:admin-token-7k5nr。
[root@k8s-master mainfests]# kubectl create serviceaccount admin
serviceaccount/admin created
[root@k8s-master mainfests]# kubectl get sa
NAME SECRETS AGE
admin 1 3s
default 1 50d
[root@k8s-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@k8s-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@k8s-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@k8s-master mainfests]# kubectl apply -f pod-sa-demo.yaml
pod/pod-sa-demo created
[root@k8s-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@k8s-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)生成證書
[root@k8s-master pki]# cd /etc/kubernetes/pki/magedu
[root@k8s-master pki]# (umask 077;openssl genrsa -out magedu.key 2048)
Generating RSA private key, 2048 bit long modulus
............................................................................................+++
...................................................................................+++
e is 65537 (0x10001)
[root@k8s-master pki]# ll magedu.key
-rw------- 1 root root 1675 Oct 12 23:52 magedu.key
(2)使用ca.crt進行簽署
[root@k8s-master pki]# openssl req -new -key magedu.key -out magedu.csr -subj "/CN=magedu" 證書簽署請求
[root@k8s-master pki]# openssl x509 -req -in magedu.csr -CA ../ca.crt -CAkey ../ca.key -CAcreateserial -out magedu.crt -days 3650 #證書簽署
Signature ok
subject=/CN=magedu
Getting CA Private Key
[root@k8s-master pki]# openssl x509 -in magedu.crt -text -noout
(3)添加到用戶認證
[root@k8s-master pki]# kubectl config set-cluster kubernetes --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.1.242:6443 --kubeconfig=/tmp/magedu.conf
[root@k8s-master pki]# kubectl config set-credentials magedu --client-certificate=./magedu.crt --client-key=./magedu.key --embed-certs=true --kubeconfig=/tmp/magedu.conf
User "magedu" set.
[root@k8s-master pki]# kubectl config set-context magedu@kubernetes --cluster=kubernetes --user=magedu --kubeconfig=/tmp/magedu.conf
Context "magedu@kubernetes" created.
[root@k8s-master pki]# kubectl config use-context magedu@kubernetes --kubeconfig=/tmp/magedu.conf
[root@master magedu]# cat /tmp/magedu.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeE1EZ3dNekEyTURBeE9Gb1hEVE14TURnd01UQTJNREF4T0Zvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTkVwCnNZZ0ZIRG5sejdCRFF5d2JnT2FrZk13YnVhZW1QcEZnbmxhd2ZHOVdUZnU2aHJ0bVNlZVkvckxMRkNac2tmd2kKLzIyVkZjODRtTU1TcDN3UDA0ejl5eEM2anoxclg0SUlvczJvYjlEUWErUWZoRXJpWWNzYzMvMGJ1aEgrUGVSMApIRWI4WitockRwTGdLVnF1eE5Wb010TlB4S2tSTTE3ekQ4Y1pXdmpaWlFXR0xBYXZ6YmwySGRFQmltaWQyMi9CCnE4a2szVmpTNmhsL1hqNTBHS3VxREpKcm1WTFlSL1l0WDR4Zm5QcitnaFJwd3FTY0xaN2w0REJXTUREL1RDbnQKcjhqcU9PTGdCc0xVcFRwdmhpVnNHOGtXckExRXBWWCtsZ3BFOTN6NFdCcjlnMGk2bDZ1MUI5MUZHTElRaG9vRgp2czl1UVdFMzJ2Y2dKYzdpMTY4Q0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZLU1k4aUhYQzRtWDZCSzFpM01ZVDNFdHF6MHNNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFCQ0R4SDNENXlIUHB4b1NJQTNmdHY3cGNDK2Rhd05XZTlsK25kRDhmQ0tSaVJRNkNmNgpPMnpOWXJtYitVa1RqY1JiN3k2bi9GbDdWQmt1L2thS1RETTZEZUlqK2djMVdMTk1wN0FHdEhPdWF1anNPNVRPCkhuVGVEdEIxRzJDOGhlclFJZ0NZSW1UMWVwWmlSU1ZYMVBoc0lqVWV6MWk1WkFrdlZNeGhvQi9FUWpGVmFrRGgKMVN0RWxNNU9IZDBydHFOTnNIU1RRd2lUYmRNRVFrSDgzaEcydmJLejVHZzNPNHFmdWQ5cGQwM24yd1BPL3ZPTgpjeUE0Y2s4eVowVXN1TVY5YkZWZHVPdzY3emtwdUNGYmpGY1RlWVZGb2Z5dVMrZlUxM3lPeG9JYWM5QXQ3b1FLCnU3cjFrUW1mZXhNeC9GbDh3M3dBclV4MEVlZlByTElKaU9tTwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
server: https://192.168.1.242:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: magedu
name: magedu@kubernetes
current-context: magedu@kubernetes
kind: Config
preferences: {}
users:
- name: magedu
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNvakNDQVlvQ0NRREJMOE5XVW9lM2lEQU5CZ2txaGtpRzl3MEJBUXNGQURBVk1STXdFUVlEVlFRREV3cHIKZFdKbGNtNWxkR1Z6TUI0WERUSXhNRGd5TkRBeE5Ea3lORm9YRFRNeE1EZ3lNakF4TkRreU5Gb3dFVEVQTUEwRwpBMVVFQXd3R2JXRm5aV1IxTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF3cnBiCkJLWlFkNXYzbGtMWWZoa2ZFc00rNGgzcmhIVldGODFJSStuZjZzMEZ1RUViSUJNdHlRN2d6aDhoTGZLOExsd1MKVk5DTXhMNVczbkRuUWF6YUtVbVl6MktvOEMyMVpCcDFNU0l0dWlNY0JBK2F5Z2NzQXhzTHdQMWxha0l4eDNOcgpOV0pkeG9Eci9HN3MzenZkV1hzNXFtM2U0OEJMd29CTkFPM0dpNEplN0FxMjVxVG92aHpxRXpyNnMyaEtiZ1dNCjcxNkovNm1XcENCUndtNlJQQ0NiNDRjb2o4UERHWTE3TzZHanVHMVArdUlkVmRrbmZoUWltSkVteHhUd0U3akMKcFcwS2UwTDQ2M0g1R3BHaURTeXhHWDdqaGVmbklKTElLL0pacDN0UUp5ekxGS1VmOU1yMnV1aTdaUlBjOWo4eApCZDFUcjBEd3B4QUcrdEIwS1FJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUFGNk5RK1p6TUkrYjd6CmxLMHRsczd3QzlLTkdUQ3RkVkpRR05ycnNZc2g2NmptMEg1eWNwZzBwZHJCZ04xTklzNEJ0OWdBbjQyVFJYSFAKaWpOOVRBeEVBMVVZZTAwSTVoWWRUeFlZUW9uVTlSZ3RsdHJwVUV1ei8rdWZ0eGhwTFc0bjBENGp6eFFWeWw5NwpiNjFNVjg5WWhqT1F5azVjWFpYSmJqdDY3MUM0ZGZuMVJUMkNoeFBWMFZzN3dEQU5LVDFpbDNJZ0pWSU0rSHhoCkw0V0paTGlkY0F5L2dKcWpUa0VJR2dQSU5FRC9zWFFkREpKZ2MyR0JRMnlNMk44VmUxNGkvQ3dreml5UmZsamkKdklMeFJrcUs1eitya1d2RnQ3K01qbGViL1JTRkQ1MFYzMERMeVF0WURzTkFCbG5WVS9hVDlDMkJZVElJdmhBcwpzT2lLQnFFNAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBd3JwYkJLWlFkNXYzbGtMWWZoa2ZFc00rNGgzcmhIVldGODFJSStuZjZzMEZ1RUViCklCTXR5UTdnemg4aExmSzhMbHdTVk5DTXhMNVczbkRuUWF6YUtVbVl6MktvOEMyMVpCcDFNU0l0dWlNY0JBK2EKeWdjc0F4c0x3UDFsYWtJeHgzTnJOV0pkeG9Eci9HN3MzenZkV1hzNXFtM2U0OEJMd29CTkFPM0dpNEplN0FxMgo1cVRvdmh6cUV6cjZzMmhLYmdXTTcxNkovNm1XcENCUndtNlJQQ0NiNDRjb2o4UERHWTE3TzZHanVHMVArdUlkClZka25maFFpbUpFbXh4VHdFN2pDcFcwS2UwTDQ2M0g1R3BHaURTeXhHWDdqaGVmbklKTElLL0pacDN0UUp5ekwKRktVZjlNcjJ1dWk3WlJQYzlqOHhCZDFUcjBEd3B4QUcrdEIwS1FJREFRQUJBb0lCQVFDTVZUek81d1RLamk0cApyZGJUV1V0WmZEZlBRUHpBSXNkK3M4UXZqWlovWW0yaTBkaTRqdG5LTWR5MDd4NDhQTmg5R0lGbGVqNVljMHVyClZ2WnlFQjNRNzJjZTNkMGQ2ZkwxUjFQNXFzWUZoTlBsNFZFT0U0a1dXK0ZtbmJiK2t1SEkrVmJqekJZRXZsaFQKUGFXYlkwc3I5M0FoY0xqV3JYaHJuWWJoQ25xeGdtcmtRbjUvbmdRa3B0eXVERytkeFRTRHdQWTZuamYzQWgyTQpnVHpDZzFLWGUvVUtSMzZ6Wmc5LzRyVklWZlBIQm0vUE9aNVhWVDJ4STU4OWdnQVJMK0F2QjZ1VzBVMkRFU0ozCmhZdlhhTC9WaDBoK1Z1OHRxR0hJeHk2RkgzZGhJT3V5NDdwNlpnek1nWmtxWjF4RUJLRUNtSVNubHNUdmFZdVkKaVRraG5YY0JBb0dCQU9iWWU3Y1Y0WE1CQkEySXBhVkZ2ZEd4MzhpUmVEVStFRmFKZ2dzVXFIZTRoTm9JeVVDWApkaEk3ZWM4aE1wM2pWdEhTVUM4TzQzTzlLa2I4NU95T3IwaVY4bWFUNGpiMjlPYUxDNExjVzY5NzhaTlo3UmFQCnVlZjRvQy9qSmgvQjJQY0h0bC8yU2U1M2hCZnAxSEM2K3VGaE9DekJ5Uy9aeFRhbzZwM2hjL3Z4QW9HQkFOZnkKVzNXSVdJSVg0YVNzeWtVZmdENytMaVdiNVA2WmY3cUxlYU9TcnN3YnFvVHQzMTJiWDc4VWEyTklFTmJkb1Fxawpxa1VyaGtuQW4rRTNwcVdXOWF5ellkcDNob2dXRFlwWWR3SVBPWG1OYzgwcFhhQ3A4NEVIMVNmYTdiNFNwSUE4Cm1DTFNlQ25sNEJUM0lIWkV3VTg3YnNQVU9wUHAzeTdyTG5tZGxKTzVBb0dBZk1NcnVmdmRhU1ozWmtrZ0hYN2YKNUdGYUxUQlI0NVN6aDlHeHN3TnJPYWxFUkFMVG9sRTV3d2phQUpSVW92aW5oNmMvSnUvSkJsaUtiT3RwWG1DUApZNCtHL3VHV05WYXJiWjVnamsxQ1VFbVFlcTd6Y0dvbGM3WHYvWEdxdlNjcmQvZDNIYzRpanZ1UkxNdDN3YVdNCnlocWRIYk51WktveDZDVExDS0U4NmtFQ2dZRUExRmhoVHdXdjR0MFE2Umx3SE9DSS8yaDZnRWozdU5QQUlmT2MKdlJnMEFra0NPSXlnSkMvd3lyaU5rS2NBeUFoUG4yT2tlemY5YVBDZFJwMnVwUTM0cnNZRjV3bTVwSC9xK0t0YwordzExZXUxNWZiaTdkSTBxQVN0dWt5NVlzWnNyWDE0MlM2ZWl1YkJ0MUsvZG4rNmtHQUZkUGZ1blRtT2ZMMGZiCi80TFE0eUVDZ1lBSFFRdm9hcklZYTVYZytyQjdUanZkN1V0c3hhaXlzNjYrS3NLZ2dPRkJBdjN6R1NhTHJqK0YKNlVreXZtRDBvMldmZjZhWW9KYzBsaVdyb3pXaGdwK091cDNLVmxTOEtpbnFPZ0pKUVRsckh5ZFBkNlJDamNOMwpOQ1ZKd1RYdHJsWlhPRVAxSXFma2hxSjk5T3JUVmpKZXk2Y0xEV1dkZ2lJVk5zNERTNkgwTUE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
[root@k8s-master pki]# kubectl config use-context magedu@kubernetes
Switched to context "magedu@kubernetes".
[root@k8s-master pki]# kubectl get pods
No resources found.
Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "default"
從上面的演示,當切換成magedu用戶進行訪問集群時,由於magedu該賬戶沒有管理集群的權限,所以在獲取pods資源信息時,會提示Forrbidden。那么下面就再來了解一下怎么對賬戶進行授權!!!
二、RBAC----基於角色的訪問控制
Kubernetes的授權是基於插件形式的,其常用的授權插件有以下幾種:
- Node(節點認證)
- ABAC(基於屬性的訪問控制)
- RBAC(基於角色的訪問控制)
- Webhook(基於http回調機制的訪問控制)
讓一個用戶(Users)扮演一個角色(Role),角色擁有權限,從而讓用戶擁有這樣的權限,隨后在授權機制當中,只需要將權限授予某個角色,此時用戶將獲取對應角色的權限,從而實現角色的訪問控制。如圖:
基於角色的訪問控制(Role-Based Access Control, 即”RBAC”)使用”rbac.authorization.k8s.io” API Group實現授權決策,允許管理員通過Kubernetes API動態配置策略。
在k8s的授權機制當中,采用RBAC的方式進行授權,其工作邏輯是 把對對象的操作權限定義到一個角色當中,再將用戶綁定到該角色,從而使用戶得到對應角色的權限。此種方式僅作用於名稱空間當中,這是什么意思呢?當User1綁定到Role角色當中,User1就獲取了對該NamespaceA的操作權限,但是對NamespaceB是沒有權限進行操作的,如get,list等操作。
另外,k8s為此還有一種集群級別的授權機制,就是定義一個集群角色(ClusterRole),對集群內的所有資源都有可操作的權限,從而將User2,User3通過ClusterRoleBinding到ClusterRole,從而使User2、User3擁有集群的操作權限。Role、RoleBinding、ClusterRole和ClusterRoleBinding的關系如下圖:
但是這里有2種綁定ClusterRoleBinding
、RoleBinding
。也可以使用RoleBinding
去綁定ClusterRole
。
當使用這種方式進行綁定時,用戶僅能獲取當前名稱空間的所有權限。為什么這么繞呢??舉例有10個名稱空間,每個名稱空間都需要一個管理員,而該管理員的權限都是一致的。那么此時需要去定義這樣的管理員,使用RoleBinding就需要創建10個Role,這樣顯得更加繁重。為此當使用RoleBinding
去綁定一個ClusterRole
時,該User僅僅擁有對當前名稱空間的集群操作權限,換句話說,此時只需要創建一個ClusterRole
就解決了以上的需求。
這里要注意的是:RoleBinding僅僅對當前名稱空間有對應的權限。
在RBAC API中,一個角色包含了一套表示一組權限的規則。 權限以純粹的累加形式累積(沒有”否定”的規則)。 角色可以由命名空間(namespace)內的Role對象定義,而整個Kubernetes
集群范圍內有效的角色則通過ClusterRole
對象實現。
三、Kubernetes RBAC的演示
1、User --> Rolebinding --> Role
(1)角色的創建
一個`Role`對象只能用於授予對某一單一命名空間中資源的訪問權限
[root@k8s-master ~]# kubectl create role -h #查看角色創建幫助
Create a role with single rule.
Examples:
# Create a Role named "pod-reader" that allows user to perform "get", "watch" and "list" on pods
kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods
# Create a Role named "pod-reader" with ResourceName specified
kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
# Create a Role named "foo" with API Group specified
kubectl create role foo --verb=get,list,watch --resource=rs.extensions
# Create a Role named "foo" with SubResource specified
kubectl create role foo --verb=get,list,watch --resource=pods,pods/status
Options:
--allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
--dry-run=false: If true, only print the object that would be sent, without sending it.
-o, --output='': Output format. One of:
json|yaml|name|go-template|go-template-file|templatefile|template|jsonpath|jsonpath-file.
--resource=[]: Resource that the rule applies to
--resource-name=[]: Resource in the white list that the rule applies to, repeat this flag for multiple items
--save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--validate=true: If true, use a schema to validate the input before sending it
--verb=[]: Verb that applies to the resources contained in the rule
Usage:
kubectl create role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run]
[options]
使用kubectl create進行創建角色,指定角色名稱,--verb指定權限,--resource指定資源或者資源組,--dry-run單跑模式並不會創建
Use "kubectl options" for a list of global command-line options (applies to all commands).
[root@k8s-master ~]# kubectl create role pods-reader --verb=get,list,watch --resource=pods --dry-run -o yaml #干跑模式查看role的定義
apiVersion: rbac.authorization.k8s.io/v1
kind: Role #資源類型
metadata:
creationTimestamp: null
name: pods-reader
rules:
- apiGroups: #對那些api組內的資源進行操作
- ""
resources: #對那些資源定義
- pods
verbs: #操作權限定義
- get
- list
- watch
[root@k8s-master ~]# cd mainfests/
[root@k8s-master mainfests]# kubectl create role pods-reader --verb=get,list,watch --resource=pods --dry-run -o yaml > role-demo.yaml
[root@k8s-master mainfests]# vim 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@k8s-master mainfests]# kubectl apply -f role-demo.yaml #角色創建
role.rbac.authorization.k8s.io/pods-reader created
[root@k8s-master mainfests]# kubectl get role
NAME AGE
pods-reader 3s
[root@k8s-master mainfests]# kubectl describe role pods-reader
Name: pods-reader
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1","kind":"Role","metadata":{"annotations":{},"name":"pods-reader","namespace":"default"},"rules":[{"apiGroup...
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
pods [] [] [get list watch] #此處已經定義了pods-reader這個角色對pods資源擁有get、list、watch的權限
(2)角色的綁定
RoleBinding可以引用在同一命名空間內定義的Role對象。
[root@k8s-master ~]# kubectl create rolebinding -h #角色綁定創建幫助
Create a RoleBinding for a particular Role or ClusterRole.
Examples:
# Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole
kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1
Options:
--allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
--clusterrole='': ClusterRole this RoleBinding should reference
--dry-run=false: If true, only print the object that would be sent, without sending it.
--generator='rolebinding.rbac.authorization.k8s.io/v1alpha1': The name of the API generator to use.
--group=[]: Groups to bind to the role
-o, --output='': Output format. One of:
json|yaml|name|templatefile|template|go-template|go-template-file|jsonpath-file|jsonpath.
--role='': Role this RoleBinding should reference
--save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--serviceaccount=[]: Service accounts to bind to the role, in the format <namespace>:<name>
--template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--validate=true: If true, use a schema to validate the input before sending it
Usage:
kubectl create rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname]
[--serviceaccount=namespace:serviceaccountname] [--dry-run] [options]
使用kubectl create進行創建角色綁定,指定角色綁定的名稱,--role|--clusterrole指定綁定哪個角色,--user指定哪個用戶
Use "kubectl options" for a list of global command-line options (applies to all commands).
[root@k8s-master mainfests]# kubectl create rolebinding magedu-read-pods --role=pods-reader --user=magedu --dry-run -o yaml > rolebinding-demo.yaml
[root@k8s-master mainfests]# cat rolebinding-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: magedu-read-pods
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pods-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: magedu
[root@k8s-master mainfests]# kubectl apply -f rolebinding-demo.yaml #創建角色綁定
rolebinding.rbac.authorization.k8s.io/magedu-read-pods created
[root@k8s-master mainfests]# kubectl describe rolebinding magedu-read-pods #查看角色綁定的信息,這里可以看到user:magedu綁定到了pods-reader這個角色上
Name: magedu-read-pods
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1","kind":"RoleBinding","metadata":{"annotations":{},"creationTimestamp":null,"name":"magedu-read-pods","name...
Role:
Kind: Role
Name: pods-reader
Subjects:
Kind Name Namespace
---- ---- ---------
User magedu
[root@k8s-master ~]# kubectl config use-context magedu@kubernetes #切換magedu這個用戶,並使用get獲取pods資源信息
Switched to context "magedu@kubernetes".
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
filebeat-ds-hxgdx 1/1 Running 1 36d
filebeat-ds-s466l 1/1 Running 2 36d
myapp-0 1/1 Running 0 2d
myapp-1 1/1 Running 0 2d
myapp-2 1/1 Running 0 2d
myapp-3 1/1 Running 0 2d
pod-sa-demo 1/1 Running 0 1d
pod-vol-demo 2/2 Running 0 3d
redis-5b5d6fbbbd-q8ppz 1/1 Running 1 4d
[root@k8s-master ~]# kubectl get pods -n ingress-nginx #測試獲取ingress-nginx這個名稱空間的pods信息
No resources found.
Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "ingress-nginx"
從上面的操作,可以總結出,role的定義和綁定,僅作用於當前名稱空間,在獲取ingress-nginx名稱空間時,一樣會出現Forbidden!!!
2、User --> Clusterrolebinding --> Clusterrole
####(1)clusterrole定義
ClusterRole對象可以授予與Role對象相同的權限,但由於它們屬於集群范圍對象, 也可以使用它們授予對以下幾種資源的訪問權限:
* 集群范圍資源(例如節點,即node)
* 非資源類型endpoint(例如”/healthz”)
* 跨所有命名空間的命名空間范圍資源(例如pod,需要運行命令kubectl get pods --all-namespaces來查詢集群中所有的pod)
[root@k8s-master mainfests]# kubectl config use-context kubernetes-admin@kubernetes #切換會kubernetes-admin用戶
Switched to context "kubernetes-admin@kubernetes".
[root@k8s-master mainfests]# kubectl create clusterrole cluster-read --verb=get,list,watch --resource=pods -o yaml > clusterrole-demo.yaml
[root@k8s-master mainfests]# vim clusterrole-demo.yaml #定義clusterrole和權限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-read
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
[root@k8s-master mainfests]# kubectl apply -f clusterrole-demo.yaml #創建clusterrole
clusterrole.rbac.authorization.k8s.io/cluster-read configured
這里我們需要切換回kubernetes-admin賬戶,是由於magedu賬戶不具備創建的權限,這也說明普通用戶是無法進行創建K8S資源的,除非進行授權。如下,我們另開一個終端,將配置到一個普通用戶ik8s上,使其使用magedu賬戶進行通信
[root@k8s-master ~]# useradd ik8s
[root@k8s-master ~]# cp -rp .kube/ /home/ik8s/
[root@k8s-master ~]# chown -R ik8s.ik8s /home/ik8s/
[root@k8s-master ~]# su - ik8s
[ik8s@k8s-master ~]$ kubectl config use-context magedu@kubernetes
Switched to context "magedu@kubernetes".
[ik8s@k8s-master ~]$ 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
- context:
cluster: kubernetes
user: magedu
name: magedu@kubernetes
current-context: magedu@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
- name: magedu
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
(2)clusterrolebinding定義
[root@k8s-master mainfests]# kubectl get rolebinding #獲取角色綁定信息
NAME AGE
magedu-read-pods 1h
[root@k8s-master mainfests]# kubectl delete rolebinding magedu-read-pods #刪除前面的綁定
rolebinding.rbac.authorization.k8s.io "magedu-read-pods" deleted
[ik8s@k8s-master ~]$ kubectl get pods #刪除后,在ik8s普通用戶上進行獲取pods資源信息,就立馬出現forbidden了
No resources found.
Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "default"
[root@k8s-master mainfests]# kubectl create clusterrolebinding magedu-read-all-pods --clusterrole=cluster-read --user=magedu --dry-run -o yaml > clusterrolebinding-demo.yaml
[root@k8s-master mainfests]# vim clusterrolebinding-demo.yaml #創建角色綁定,將magedu綁定到clusterrole:magedu-read-all-pods上
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: magedu-read-all-pods
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-read
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: magedu
[root@k8s-master mainfests]# kubectl get clusterrole
NAME AGE
admin 52d
cluster-admin 52d
cluster-read 13m
......
[root@k8s-master mainfests]# kubectl apply -f clusterrolebinding-demo.yaml
clusterrolebinding.rbac.authorization.k8s.io/magedu-read-all-pods created
[root@k8s-master mainfests]# kubectl get clusterrolebinding
NAME AGE
......
magedu-read-all-pods 10s
[root@k8s-master mainfests]# kubectl describe clusterrolebinding magedu-read-all-pods
Name: magedu-read-all-pods
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1beta1","kind":"ClusterRoleBinding","metadata":{"annotations":{},"name":"magedu-read-all-pods","namespace":""...
Role:
Kind: ClusterRole
Name: cluster-read
Subjects:
Kind Name Namespace
---- ---- ---------
User magedu
[ik8s@k8s-master ~]$ kubectl get pods #角色綁定后在ik8s終端上進行獲取pods信息,已經不會出現forbidden了
NAME READY STATUS RESTARTS AGE
filebeat-ds-hxgdx 1/1 Running 1 36d
filebeat-ds-s466l 1/1 Running 2 36d
myapp-0 1/1 Running 0 2d
myapp-1 1/1 Running 0 2d
myapp-2 1/1 Running 0 2d
myapp-3 1/1 Running 0 2d
pod-sa-demo 1/1 Running 0 1d
pod-vol-demo 2/2 Running 0 4d
redis-5b5d6fbbbd-q8ppz 1/1 Running 1 4d
[ik8s@k8s-master ~]$ kubectl get pods -n ingress-nginx #更換名稱空間進行查看也是可行的
NAME READY STATUS RESTARTS AGE
default-http-backend-7db7c45b69-nqxw9 1/1 Running 1 4d
nginx-ingress-controller-6bd7c597cb-9fzbw 1/1 Running 0 4d
[ik8s@k8s-master ~]$ kubectl delete pods pod-sa-demo #但是進行刪除pod就無法進行,因為在授權時是沒有delete權限的
Error from server (Forbidden): pods "pod-sa-demo" is forbidden: User "magedu" cannot delete pods in the namespace "default"
從上面的實驗,我們可以知道對用戶magedu進行集群角色綁定,用戶magedu將會獲取對集群內所有資源的對應權限。
####3、User --> Rolebinding --> Clusterrole
將maedu通過rolebinding到集群角色magedu-read-pods當中,此時,magedu僅作用於當前名稱空間的所有pods資源的權限
[root@k8s-master mainfests]# kubectl delete clusterrolebinding magedu-read-all-pods
clusterrolebinding.rbac.authorization.k8s.io "magedu-read-all-pods" deleted
[root@k8s-master mainfests]# kubectl create rolebinding magedu-read-pods --clusterrole=cluster-read --user=magedu --dry-run -o yaml > rolebinding-clusterrole-demo.yaml
[root@k8s-master mainfests]# vim rolebinding-clusterrole-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: magedu-read-pods
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-read
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: magedu
[root@k8s-master mainfests]# kubectl apply -f rolebinding-clusterrole-demo.yaml
rolebinding.rbac.authorization.k8s.io/magedu-read-pods created
[ik8s@k8s-master ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
filebeat-ds-hxgdx 1/1 Running 1 36d
filebeat-ds-s466l 1/1 Running 2 36d
myapp-0 1/1 Running 0 2d
myapp-1 1/1 Running 0 2d
myapp-2 1/1 Running 0 2d
myapp-3 1/1 Running 0 2d
pod-sa-demo 1/1 Running 0 1d
pod-vol-demo 2/2 Running 0 4d
redis-5b5d6fbbbd-q8ppz 1/1 Running 1 4d
[ik8s@k8s-master ~]$ kubectl get pods -n ingress-nginx
No resources found.
Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "ingress-nginx"