Kubernetes中提供了良好的多租戶認證管理機制,如RBAC、ServiceAccount還有各種Policy等。
ServiceAccount
Service Account為Pod中的進程提供身份信息。
當用戶訪問集群(例如使用kubectl命令)時,apiserver 會將用戶認證為一個特定的 User Account(目前通常是admin,除非系統管理員自定義了集群配置)。Pod 容器中的進程也可以與 apiserver 聯系。 當它們在聯系 apiserver 的時候,它們會被認證為一個特定的 Service Account(例如default)。
-
使用默認的 Service Account 訪問 API server
當創建 pod 的時候,如果沒有指定一個 service account,系統會自動得在與該pod 相同的 namespace 下為其指派一個default service account。如果獲取剛創建的 pod 的原始 json 或 yaml 信息(例如使用kubectl get pods podename -o yaml命令),將看到spec.serviceAccountName字段已經被設置為 default。
可以在 pod 中使用自動掛載的 service account 憑證來訪問 API,如 Accessing the Cluster 中所描述。
Service account 是否能夠取得訪問 API 的許可取決於您使用的 授權插件和策略。
在 1.6 以上版本中,可以選擇取消為 service account 自動掛載 API 憑證,只需在 service account 中設置 automountServiceAccountToken: false:
apiVersion: v1 kind: ServiceAccount metadata: name: build-robot automountServiceAccountToken: false ...
在 1.6 以上版本中,也可以選擇只取消單個 pod 的 API 憑證自動掛載:
apiVersion: v1 kind: Pod metadata: name: my-pod spec: serviceAccountName: build-robot automountServiceAccountToken: false ...
如果在 pod 和 service account 中同時設置了 automountServiceAccountToken , pod 設置中的優先級更高。
-
使用 Service Account 作為用戶權限管理配置 kubeconfig
創建服務賬號(serviceAccount)
kubectl create serviceaccount sample-sc
這時候將得到一個在 default namespace 的 serviceaccount 賬號;運行kubectl get serviceaccount sample-sc 將得到如下結果:
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2018-09-03T02:00:37Z
labels:
from: mofang
name: mofang-viewer-sc
namespace: default
resourceVersion: "18914458"
selfLink: /api/v1/namespaces/default/serviceaccounts/sample-sc
uid: 26e129dc-af1d-11e8-9453-00163e0efab0
secrets:
- name: sample-sc-token-9x7nk
因為在使用 serviceaccount 賬號配置 kubeconfig 的時候需要使用到 sample-sc 的 token, 該 token 保存在該 serviceaccount 保存的 secret 中;
運行kubectl get secret sample-sc-token-9x7nk 或者kubectl describe serviceaccount sample-sc將會得到如下結果:
apiVersion: v1
data:
ca.crt: Ci0tLS0tQkVHSU4gQ0VSVcvfUNBVEUtLS0tLQpNSUlDL3pDQ0FtaWdBd0lCQWdJREJzdFlNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1HSXhDekFKQmdOVkJBWVRBa05PCk1SRXdEd1lEVlFRSURBaGFhR1ZLYVdGdVp6RVJNQThHQTFVRUJ3d0lTR0Z1WjFwb2IzVXhFREFPQmdOVkJBb00KQjBGc2FXSmhZbUV4RERBS0JnTlZCQXNNQTBGRFV6RU5NQXNHQTFVRUF3d0VjbTl2ZERBZUZ3MHhPREExTWprdwpNelF3TURCYUZ3MHpPREExTWpRd016UTFOVGxhTUdveEtqQW9CZ05WQkFvVElXTTJaVGxqTm1KallUY3pZakUwClkyTTBZV0UzT1RNd1lqTTROREV4TkRaallURVFNQTRHQTFVRUN4TUhaR1ZtWVhWc2RERXFNQ2dHQTFVRUF4TWgKWXpabE9XTTJZbU5oTnpOaU1UUmpZelJoWVRjNU16QmlNemcwTVRFME5tTmhNSUdmTUEwR0NTcUdTSWIzRFFFQgpBUVVBQTRHTkFEQ0JpUUtCZ1FETGNFWmJycCtBa0taNHU4TklVM25jaFU4YkExMnhKR0pJMzlxdTd4aFFsR3lHCmZqQTFqdXV4cVMyaE4vTGpwM21XNkdIaW0zd2lJd2N1WUtUN3RGOW9UejgrTzhBQzZHYnpkWExIL1RQTWtCZ2YKOVNYaEdod1hndklMb3YzbnZlS1MzRElxU3UreS9OK1huMzhOOW53SHF6S0p2WE1ROWtJaUJuTXgwVnlzSFFJRApBUUFCbzRHNk1JRzNNQTRHQTFVZER3RUIvd1FFQXdJQ3JEQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01COEdBMVVkCkl3UVlNQmFBRklWYS85MGp6U1Z2V0VGdm5tMUZPWnRZZlhYL01Ed0dDQ3NHQVFVRkJ3RUJCREF3TGpBc0JnZ3IKQmdFRkJRY3dBWVlnYUhSMGNEb3ZMMk5sY25SekxtRmpjeTVoYkdsNWRXNHVZMjl0TDI5amMzQXdOUVlEVlIwZgpCQzR3TERBcW9DaWdKb1lrYUhSMGNEb3ZMMk5sY25SekxtRmpjeTVoYkdsNWRXNHl0TDNKdmIzUXVZM0pzCk1BMEdDU3FHU0liM0RRRUJDd1VBQTRHQkFKWFRpWElvQ1VYODFFSU5idVRTay9PanRJeDM0ckV0eVBuTytBU2oKakszaTR3d1BRMEt5MDhmTlNuU2Z4Q1EyeEY1NTIxNVNvUzMxU3dMellJVEp1WFpBN2xXT29RU1RZL2lBTHVQQgovazNCbDhOUGNmejhGNXlZNy9uY1N6WDRwTXgxOHIwY29PTE1iZlpUUXJtSHBmQ053bWRjQmVCK0JuRFJMUEpGCmgzSUQKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQoKCg==
namespace: ZGVmYXAsdA==
token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJblI1Y0NJNklrcFhppppppo5LmV5SnBjM01pT2lKcmRXSmxjbTVsZddekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZVzFsYzNCaFkyVWlPaUprWldaaGRXeDBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5elpXTnlaWFF1Ym1GdFpTSTZJbTF2Wm1GdVp5MTJhV1YzWlhJdGMyTXRkRzlyWlc0dE9YZzNibXNpTENKcmRXSmxjbTVsZEdWekxtbHZMM05sY25acFkyVmhZMk52ZFc1MEwzTmxjblpwWTJVdFlXTmpiM1Z1ZEM1dVlXMWxJam9pYlc5bVlXNW5MWFpwWlhkbGNpMXpZeUlzSW10MVltVnlibVYwWlhNdWFXOHZjMlZ5ZG1salpXRmpZMjkxYm5RdmMyVnlkbWxqWlMxaFkyTnZkVzUwTG5WcFpDSTZJakkyWlRFeU9XUmpMV0ZtTVdRdE1URmxPQzA1TkRVekxUQXdNVFl6WlRCbFptRmlNQ0lzSW5OMVlpSTZJbk41YzNSbGJUcHpaWEoyYVdObFlXTmpiM1Z1ZERwa1pXWmhkV3gwT20xdlptRnVaeTEyYVdWM1pYSXRjMk1pZlEuQWpudnZueXRaWHJ1UndSdEJ3S3RFdzZWNzJpWU1vOUI2LVh3VmkzRWhReXNOM21PLXJvdGFJQnZHUFlNMGZNVDlWRzVjTFFKYmJWUmhLR0FyclUyQ1FNVl9JQ3NpbjFzMjFxTXJ5dngzNm9abzFYZkpWZlVVMEtqeWxndEQ0NTNmWU84SlFfWFF3OGNwVWc5NGE2WnZvcDZHcXNGNGhzT0sxTjFMaGRrSFBpWHA4TzRQUzJ6eDFXNklfeGs2ZUNBcjUxRVpwSktEWTZHMmhmZ1A5emxROGdPV21nbS1EVjZPZzNobjJ4UFprZUktVk1nYUF3amdFUGtVZFJDSndYRk9QRG5UcXlqUmtZVzdLVU1GLTVDTHdBNDZMNk5PYjJ6YUR0Uy16Zm5hdVFwLVdIcFNQdDNEdFc0UmRLZDVDZzE3Z3RGaWhRZzI3dnVqYWJNMGpmQmp3
kind: Secret
metadata:
annotations:
kubernetes.io/service-account.name: sample-sc
kubernetes.io/service-account.uid: 26e129dc-af1d-11e8-9453-00163e0efab0
creationTimestamp: 2018-09-03T02:00:37Z
name: mofang-viewer-sc-token-9x7nk
namespace: default
resourceVersion: "18914310"
selfLink: /api/v1/namespaces/default/secrets/sample-sc-token-9x7nk
uid: 26e58b7c-af1d-11e8-9453-00163e0efab0
type: kubernetes.io/service-account-token
其中 {data.token} 就會是我們的用戶 token 的 base64 編碼,之后我們配置 kubeconfig 的時候將會用到它;
創建角色
比如想創建一個只可以查看集群deployments,services,pods 相關的角色,應該使用如下配置
apiVersion: rbac.authorization.k8s.io/v1
## 這里也可以使用 Role
kind: ClusterRole
metadata:
name: mofang-viewer-role
labels:
from: mofang
rules:
- apiGroups:
- ""
resources:
- pods
- pods/status
- pods/log
- services
- services/status
- endpoints
- endpoints/status
- deployments
verbs:
- get
- list
- watch
創建角色綁定
apiVersion: rbac.authorization.k8s.io/v1
## 這里也可以使用 RoleBinding
kind: ClusterRoleBinding
metadata:
name: sample-role-binding
labels:
from: mofang
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: mofang-viewer-role #這里即綁定上面創建的clusterrole
subjects:
- kind: ServiceAccount #將clusterrole綁定到這個服務賬戶上
name: sample-sc
namespace: default
配置 kubeconfig
經過以上的步驟,最開始創建的 serviceaccount 就可以用來訪問我們的集群了, 同時我們可以動態更改 ClusterRole 的授權來及時控制某個賬號的權限(這也是使用 serviceaccount 的好處);
配置應該如下:
apiVersion: v1
clusters:
- cluster:
## 這個是集群的 TLS 證書,與授權無關,使用同一的就可以
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvekNDQW1pZ0F3SUJBZ0lEQnN0WU1BMEdDU3FHU0liM0RRRUJDd1VBTUdJeEN6QUpCZ05WQkFZVEFrTk8KTVJFd0R3WURWUVFJREFoYWFHVkthV0Z1WnpFUk1BOEdBMVVFQnd3SVNHRnVaMXBvYjNVeEVEQU9CZ05WQkFvTQpCMEZzYVdKaFltRXhEREFLQmdOVkJBc01BMEZEVXpFTk1Bc0dBMVVFQXd3RWNtOXZkREFlRncweE9EQTFNamt3Ck16UXdNREJhRncwek9EQTFNalF3TXpRMU5UbGFNR294S2pBb0JnTlZCQW9USVdNMlpUbGpObUpqWVRjellqRTAKWTJNMFlXRTNPVE13WWpNNE5ERXhORFpqWVRFUU1BNEdBMVVFQ3hNSFpHVm1ZWFZzZERFcU1DZ0dBMVVFQXhNaApZelpsT1dNMlltTmhOek5pTVRSall6UmhZVGM1TXpCaU16ZzBNVEUwTm1OaE1JR2ZNQTBHQ1NxR1NJYjNEUUVCCkFRVUFBNEdOQURDQmlRS0JnUURMY0VaYnJwK0FrS1o0dThOSVUzbmNoVThiQTEyeEpHSkkzOXF1N3hoUWxHeUcKZmpBMWp1dXhxUzJoTi9ManAzbVc2R0hpbTN3aUl3Y3VZS1Q3dEY5b1R6OCtPOEFDNkdiemRYTEgvVFBNa0JnZgo5U1hoR2h3WGd2SUxvdjNudmVLUzNESXFTdSt5L04rWG4zOE45bndIcXpLSnZYTVE5a0lpQm5NeDBWeXNIUUlECkFRQUJvNEc2TUlHM01BNEdBMVVkRHdFQi93UUVBd0lDckRBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUI4R0ExVWQKSXdRWU1CYUFGSVZhLzkwanpTVnZXRUZ2bm0xRk9adFlmWFgvTUR3R0NDc0dBUVVGQndFQkJEQXdMakFzQmdncgpCZ0VGQlFjd0FZWWdhSFIwY0RvdkwyTmxjblJ6TG1GamN5NWhiR2w1ZFc0dVkyOXRMMjlqYzNBd05RWURWUjBmCkJDNHdMREFxb0NpZ0pvWWthSFIwY0RvdkwyTmxjblJ6TG1GamN5NWhiR2w1ZFc0dVkyOXRMM0p2YjNRdVkzSnMKTUEwR0NTcUdTSWIzRFFFQkN3VUFBNEdCQUpYVGlYSW9DVVg4MUVJTmJ1VFNrL09qdEl4MzRyRXR5UG5PK0FTagpqSzNpNHd3UFEwS3kwOGZOU25TZnhDUTJ4RjU1MjE1U29TMzFTd0x6WUlUSnVYWkE3bFdPb1FTVFkvaUFMdVBCCi9rM0JsOE5QY2Z6OEY1eVk3L25jU3pYNHBNeDE4cjBjb09MTWJmWlRRcm1IcGZDTndtZGNCZUIrQm5EUkxQSkYKaDNJRAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
server: https://10.10.10.165:6443
name: beta
contexts:
- context:
cluster: beta
user: beta-viewer
name: beta-viewer
current-context: beta-viewer
kind: Config
preferences: {}
users:
- name: beta-viewer
user:
## 這個使我們在創建 serviceaccount 生成相關 secret 之后的 data.token 的 base64 解碼字符,它本質是一個 jwt token
token: eyJhbGciOiJSUzI1NiIsInR5dffg6IkpXVCJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6Im1vZmFuZy12aWV3ZXItc2MtdG9rZW4tOXg3bmsiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoibW9mYW5nLXZpZXdlci1zYyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjxZTEyOWRjLWFmMWQtMTFlOC05NDUzLTAwMTYzZTBlZmFiMCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0Om1vZmFuZy12aWV3ZXItc2MifQ.AjnvvnytZXruRwRtBwKtEw6V72iYMo9B6-XwVi3EhQysN3mO-rotaIBvGPYM0fMT9VG5cLQJbbVRhKGArrU2CQMV_ICsin1s21qMryvx36oZo1XfJVfUU0KjylgtD453fYO8JQ_XQw8cpUg94a6Zvop6GqsF4hsOK1N1LhdkHPiXp8O4PS2zx1W6I_xk6eCAr51EZpJKDY6G2hfgP9zlQ8gOWmgm-DV6Og3hn2xPZkeI-VMgaAwjgEPkUdRCJwXFOPDnTqyjRkYW7KUMF-5CLwA46L6NOb2zaDtS-zfnauQp-WHpSPt3DtW4RdKd5Cg17gtFihQg27vujabM0jfBjw
-
使用多個Service Account
每個 namespace 中都有一個默認的叫做 default 的 service account 資源。
可以使用以下命令列出 namespace 下的所有 serviceAccount 資源。
$ kubectl get serviceAccounts NAME SECRETS AGE default 1 1d [root@bogon ingress-test]# kubectl get serviceaccounts --all-namespaces NAMESPACE NAME SECRETS AGE default default 1 26d ingress-nginx default 1 11d ingress-nginx nginx-ingress-serviceaccount 1 3d kube-public default 1 26d kube-system dashboard 1 22d kube-system default 1 26d kube-system heapster 1 21d kube-system jenkins-admin 1 3d kube-system kube-dns 1 23d
可以像這樣創建一個 ServiceAccount 對象:
$ cat > /tmp/serviceaccount.yaml <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: build-robot EOF
$ kubectl create -f /tmp/serviceaccount.yaml serviceaccount "build-robot" created
如果看到如下的 service account 對象的完整輸出信息:
$ kubectl get serviceaccounts/build-robot -o yaml apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: 2015-06-16T00:12:59Z name: build-robot namespace: default resourceVersion: "272500" selfLink: /api/v1/namespaces/default/serviceaccounts/build-robot uid: 721ab723-13bc-11e5-aec2-42010af0021e secrets: - name: build-robot-token-bvbk5
然后將看到有一個 token 已經被自動創建,並被 service account 引用。可以使用授權插件來 設置 service account 的權限
在 pod 創建之初 service account 就必須已經存在,否則創建將被拒絕。設置非默認的 service account,只需要在 pod 的spec.serviceAccountName 字段中將name設置為想要用的 service account 名字即可。
不能更新已創建的 pod 的 service account。可以清理 service account,如下所示:
$ kubectl delete serviceaccount/build-robot
-
手動創建 service account 的 API token
假設已經有了一個如上文提到的名為 ”build-robot“ 的 service account,現在手動創建一個新的 secret。
$ cat > /tmp/build-robot-secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
name: build-robot-secret
annotations:
kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token
EOF
$ kubectl create -f /tmp/build-robot-secret.yaml
secret "build-robot-secret" created
現在可以確認下新創建的 secret 取代了 “build-robot” 這個 service account 原來的 API token。
所有已不存在的 service account 的 token 將被 token controller 清理掉。獲取token內容命令如下
[root@bogon tmp]# kubectl describe secrets/build-robot-secret
Name: build-robot-secret
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name=build-robot
kubernetes.io/service-account.uid=fcf67da4-cd58-11e8-8e6e-00505693e5c6
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1359 bytes
namespace: 7 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImJ1aWxkLXJvYm90LXNlY3JldCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJidWlsZC1yb2JvdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImZjZjY3ZGE0LWNkNTgtMTFlOC04ZTZlLTAwNTA1NjkzZTVjNiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmJ1aWxkLXJvYm90In0.dH-Xxj0drOjhvQlWF37n2Q61fGXG26xRkklIWw6wHH0s8Msdf5FIOfD_E9OFez9nbIPO4efMG5ZK79Rc1vtmdBIfHUSi_tsHhsoGJwqtkoj1wXTJTaum4RtXQVyaVxqLsPjFaP0EL-5_YTy2Q9Ay5hBBqjUGRJ1KiuRKHNoLuSO3L7oYZcPXX0BCrSFyTqlYfvcNqv3P-hT-TKLB25uBw2eE90iguDk1cGCCfCeKtLVuZ6iFNOBEZOYCErOiboPAH55e3wl98Uuze6MOAbsZRIaALISCxyR0W_heyYES90MU8IOvgQW7Z0WkxSNLTsknPL7nMykvkHXJay1J-18ZGw
-
為 service account 添加 ImagePullSecret
ImagePullSecret用於從私有倉庫pull鏡像
$ kubectl create secret docker-registry myregistrykey --docker-server=10.10.10.12 --docker-username=admin --docker-password=HarBor12345 --docker-email=xxxx secret/myregistrykey created.
說明 : --docker 開頭的參數分別指定了私有倉庫的地址用戶和密碼
首先,創建一個 imagePullSecret,詳見這里(或者上面)。然后,確認已創建。如:
$ kubectl get secrets myregistrykey NAME TYPE DATA AGE myregistrykey kubernetes.io/.dockerconfigjson 1 1d
然后,修改 namespace 中的默認 service account 使用該 secret 作為 imagePullSecret。
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
或者使用Vi 交互過程中需要手動編輯:
$ kubectl get serviceaccounts default -o yaml > ./sa.yaml
$ cat sa.yaml apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: 2015-08-07T22:02:39Z name: default namespace: default resourceVersion: "243024" selfLink: /api/v1/namespaces/default/serviceaccounts/default uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6 secrets: - name: default-token-uudge
$ vi sa.yaml [editor session not shown] [delete line with key "resourceVersion"] [add lines with "imagePullSecret:"]
$ cat sa.yaml apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: 2015-08-07T22:02:39Z name: default namespace: default selfLink: /api/v1/namespaces/default/serviceaccounts/default uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6 secrets: - name: default-token-uudge imagePullSecrets: - name: myregistrykey
$ kubectl replace serviceaccount default -f ./sa.yaml serviceaccounts/default
現在,所有當前 namespace 中新創建的 pod 的 spec 中都會增加如下內容:
spec: imagePullSecrets: - name: myregistrykey
RBAC——基於角色的訪問控制
基於角色的訪問控制(Role-Based Access Control, 即”RBAC”)使用”rbac.authorization.k8s.io” API Group實現授權決策,允許管理員通過Kubernetes API動態配置策略。
要啟用RBAC,請使用--authorization-mode=RBAC啟動API Server。
-
Role與ClusterRole
在RBAC API中,一個角色包含了一套表示一組權限的規則。 權限以純粹的累加形式累積(沒有”否定”的規則)。 角色可以由命名空間(namespace)內的Role對象定義,而整個Kubernetes集群范圍內有效的角色則通過ClusterRole對象實現。
一個Role對象只能用於授予對某一單一命名空間中資源的訪問權限。 以下示例描述了”default”命名空間中的一個Role對象的定義,用於授予對pod的讀訪問權限:
kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: namespace: default name: pod-reader rules: - apiGroups: [""] # 空字符串""表明使用core API group resources: ["pods"] verbs: ["get", "watch", "list"]
下面示例中的ClusterRole定義可用於授予用戶對某一特定命名空間,或者所有命名空間中的secret(取決於其綁定方式)的讀訪問權限:
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: # 鑒於ClusterRole是集群范圍對象,所以這里不需要定義"namespace"字段 name: secret-reader rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"]
-
RoleBinding與ClusterRoleBinding
角色綁定將一個角色中定義的各種權限授予一個或者一組用戶。 角色綁定包含了一組相關主體(即subject, 包括用戶——User、用戶組——Group、或者服務賬戶——Service Account)以及對被授予角色的引用。 在命名空間中可以通過RoleBinding對象授予權限,而集群范圍的權限授予則通過ClusterRoleBinding對象完成。
RoleBinding可以引用在同一命名空間內定義的Role對象。 下面示例中定義的RoleBinding對象在”default”命名空間中將”pod-reader”角色授予用戶”jane”。 這一授權將允許用戶”jane”從”default”命名空間中讀取pod。
# 以下角色綁定定義將允許用戶"jane"從"default"命名空間中讀取pod。
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: read-pods namespace: default subjects: - kind: User #賦予用戶jane pod-reader角色權限 name: jane apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader #引用上面定義的role apiGroup: rbac.authorization.k8s.io
RoleBinding對象也可以引用一個ClusterRole對象用於在RoleBinding所在的命名空間內授予用戶對所引用的ClusterRole中 定義的命名空間資源的訪問權限。這一點允許管理員在整個集群范圍內首先定義一組通用的角色,然后再在不同的命名空間中復用這些角色。
例如,盡管下面示例中的RoleBinding引用的是一個ClusterRole對象,但是用戶”dave”(即角色綁定主體)還是只能讀取”development” 命名空間中的secret(即RoleBinding所在的命名空間)。
# 以下角色綁定允許用戶"dave"讀取"development"命名空間中的secret。
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: read-secrets namespace: development # 這里表明僅授權讀取"development"命名空間中的資源。 subjects: - kind: User name: dave apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader #引用上面定義的clusterRole 名稱(clusterRole沒有指定命名空間,默認可以應用所有,但是在rolebinding時,指定了命名空間,所以只能讀取本命名空間的文件) apiGroup: rbac.authorization.k8s.io
最后,可以使用ClusterRoleBinding在集群級別和所有命名空間中授予權限。下面示例中所定義的ClusterRoleBinding 允許在用戶組”manager”中的任何用戶都可以讀取集群中任何命名空間中的secret。
# 以下`ClusterRoleBinding`對象允許在用戶組"manager"中的任何用戶都可以讀取集群中任何命名空間中的secret。
kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: read-secrets-global subjects: - kind: Group name: manager apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io
-
對資源的引用
大多數資源由代表其名字的字符串表示,例如”pods”,就像它們出現在相關API endpoint的URL中一樣。然而,有一些Kubernetes API還 包含了”子資源”,比如pod的logs。在Kubernetes中,pod logs endpoint的URL格式為:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
在這種情況下,”pods”是命名空間資源,而”log”是pods的子資源。為了在RBAC角色中表示出這一點,我們需要使用斜線來划分資源 與子資源。如果需要角色綁定主體讀取pods以及pod log,您需要定義以下角色:
kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: namespace: default name: pod-and-pod-logs-reader rules: - apiGroups: [""] resources: ["pods", "pods/log"] #根據上面意思表示授予讀取pods下log的權限 verbs: ["get", "list"]
通過resourceNames列表,角色可以針對不同種類的請求根據資源名引用資源實例。當指定了resourceNames列表時,不同動作 種類的請求的權限,如使用”get”、”delete”、”update”以及”patch”等動詞的請求,將被限定到資源列表中所包含的資源實例上。 例如,如果需要限定一個角色綁定主體只能”get”或者”update”一個configmap時,您可以定義以下角色:
kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: namespace: default name: configmap-updater rules: - apiGroups: [""] resources: ["configmap"] resourceNames: ["my-configmap"] verbs: ["update", "get"]
值得注意的是,如果設置了resourceNames,則請求所使用的動詞不能是list、watch、create或者deletecollection。 由於資源名不會出現在create、list、watch和deletecollection等API請求的URL中,所以這些請求動詞不會被設置了resourceNames 的規則所允許,因為規則中的resourceNames部分不會匹配這些請求。
-
-
角色定義的例子
-
在以下示例中,僅截取展示了rules部分的定義。
允許讀取core API Group中定義的資源”pods”:
rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"]
允許讀寫在”extensions”和”apps” API Group中定義的”deployments”:
rules: - apiGroups: ["extensions", "apps"] resources: ["deployments"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
允許讀取”pods”以及讀寫”jobs”:
rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"] - apiGroups: ["batch", "extensions"] resources: ["jobs"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
允許讀取一個名為”my-config”的ConfigMap實例(需要將其通過RoleBinding綁定從而限制針對某一個命名空間中定義的一個ConfigMap實例的訪問):
rules: - apiGroups: [""] resources: ["configmaps"] resourceNames: ["my-config"] verbs: ["get"]
允許讀取core API Group中的”nodes”資源(由於Node是集群級別資源,所以此ClusterRole定義需要與一個ClusterRoleBinding綁定才能有效):
rules: - apiGroups: [""] resources: ["nodes"] verbs: ["get", "list", "watch"]
允許對非資源endpoint “/healthz”及其所有子路徑的”GET”和”POST”請求(此ClusterRole定義需要與一個ClusterRoleBinding綁定才能有效):
rules: - nonResourceURLs: ["/healthz", "/healthz/*"] # 在非資源URL中,'*'代表后綴通配符 verbs: ["get", "post"]
-
對角色綁定主體(Subject)的引用
RoleBinding或者ClusterRoleBinding將角色綁定到角色綁定主體(Subject)。 角色綁定主體(kind指定)可以是用戶組(Group)、用戶(User)或者服務賬戶(Service Accounts)。
用戶由字符串表示。可以是純粹的用戶名,例如”alice”、電子郵件風格的名字,如 “bob@example.com” 或者是用字符串表示的數字id。由Kubernetes管理員配置認證模塊 以產生所需格式的用戶名。對於用戶名,RBAC授權系統不要求任何特定的格式。然而,前綴system:是 為Kubernetes系統使用而保留的,所以管理員應該確保用戶名不會意外地包含這個前綴。
Kubernetes中的用戶組信息由授權模塊提供。用戶組與用戶一樣由字符串表示。Kubernetes對用戶組 字符串沒有格式要求,但前綴system:同樣是被系統保留的。
服務賬戶(serviceAccount)擁有包含 system:serviceaccount:前綴的用戶名,並屬於擁有system:serviceaccounts:前綴的用戶組。
-
-
角色綁定例子
-
以下示例中,僅截取展示了RoleBinding的subjects字段。
一個名為”alice@example.com”的用戶:
subjects: - kind: User name: "alice@example.com" apiGroup: rbac.authorization.k8s.io
一個名為”frontend-admins”的用戶組:
subjects: - kind: Group name: "frontend-admins" apiGroup: rbac.authorization.k8s.io
kube-system命名空間中的默認服務賬戶:
subjects: - kind: ServiceAccount name: default namespace: kube-system
名為”qa”命名空間中的所有服務賬戶:
subjects: - kind: Group name: system:serviceaccounts:qa apiGroup: rbac.authorization.k8s.io
在集群中的所有服務賬戶:
subjects: - kind: Group name: system:serviceaccounts apiGroup: rbac.authorization.k8s.io
所有認證過的用戶(version 1.5+):
subjects: - kind: Group name: system:authenticated apiGroup: rbac.authorization.k8s.io
所有未認證的用戶(version 1.5+):
subjects: - kind: Group name: system:unauthenticated apiGroup: rbac.authorization.k8s.io
所有用戶(version 1.5+):
subjects: - kind: Group name: system:authenticated apiGroup: rbac.authorization.k8s.io - kind: Group name: system:unauthenticated apiGroup: rbac.authorization.k8s.io
-
默認角色與默認角色綁定
API Server會創建一組默認的ClusterRole和ClusterRoleBinding對象。 這些默認對象中有許多包含system:前綴,表明這些資源由Kubernetes基礎組件”擁有”。 對這些資源的修改可能導致非功能性集群(non-functional cluster)。一個例子是system:node ClusterRole對象。 這個角色定義了kubelets的權限。如果這個角色被修改,可能會導致kubelets無法正常工作。
所有默認的ClusterRole和ClusterRoleBinding對象都會被標記為kubernetes.io/bootstrapping=rbac-defaults。
每次啟動時,API Server都會更新默認ClusterRole所缺乏的各種權限,並更新默認ClusterRoleBinding所缺乏的各個角色綁定主體。 這種自動更新機制允許集群修復一些意外的修改。由於權限和角色綁定主體在新的Kubernetes釋出版本中可能變化,這也能夠保證角色和角色 綁定始終保持是最新的。
如果需要禁用自動更新,請將默認ClusterRole以及ClusterRoleBinding的rbac.authorization.kubernetes.io/autoupdate 設置成為false。 請注意,缺乏默認權限和角色綁定主體可能會導致非功能性集群問題。
自Kubernetes 1.6+起,當集群RBAC授權器(RBAC Authorizer)處於開啟狀態時,可以啟用自動更新功能
-
-
發現類角色
-
| 默認ClusterRole | 默認ClusterRoleBinding | 描述 |
|---|---|---|
| system:basic-user | system:authenticated and system:unauthenticatedgroups | 允許用戶只讀訪問有關自己的基本信息。 |
| system:discovery | system:authenticated and system:unauthenticatedgroups | 允許只讀訪問API discovery endpoints, 用於在API級別進行發現和協商。 |
-
-
面向用戶的角色
-
一些默認角色並不包含system:前綴,它們是面向用戶的角色。 這些角色包含超級用戶角色(cluster-admin),即旨在利用ClusterRoleBinding(cluster-status)在集群范圍內授權的角色, 以及那些使用RoleBinding(admin、edit和view)在特定命名空間中授權的角色。
| 默認ClusterRole | 默認ClusterRoleBinding | 描述 |
|---|---|---|
| cluster-admin | system:mastersgroup | 超級用戶權限,允許對任何資源執行任何操作。 在ClusterRoleBinding中使用時,可以完全控制集群和所有命名空間中的所有資源。 在RoleBinding中使用時,可以完全控制RoleBinding所在命名空間中的所有資源,包括命名空間自己。 |
| admin | None | 管理員權限,利用RoleBinding在某一命名空間內部授予。 在RoleBinding中使用時,允許針對命名空間內大部分資源的讀寫訪問, 包括在命名空間內創建角色與角色綁定的能力。 但不允許對資源配額(resource quota)或者命名空間本身的寫訪問。 |
| edit | None | 允許對某一個命名空間內大部分對象的讀寫訪問,但不允許查看或者修改角色或者角色綁定。 |
| view | None | 允許對某一個命名空間內大部分對象的只讀訪問。 不允許查看角色或者角色綁定。 由於可擴散性等原因,不允許查看secret資源。 |
-
Core Component Roles
-
核心組件角色
-
| 默認ClusterRole | 默認ClusterRoleBinding | 描述 |
|---|---|---|
| system:kube-scheduler | system:kube-scheduler user | 允許訪問kube-scheduler組件所需要的資源。 |
| system:kube-controller-manager | system:kube-controller-manageruser | 允許訪問kube-controller-manager組件所需要的資源。 單個控制循環所需要的權限請參閱控制器(controller)角色. |
| system:node | system:nodesgroup (deprecated in 1.7) | 允許對kubelet組件所需要的資源的訪問,包括讀取所有secret和對所有pod的寫訪問。 自Kubernetes 1.7開始, 相比較於這個角色,更推薦使用Node authorizer 以及NodeRestriction admission plugin, 並允許根據調度運行在節點上的pod授予kubelets API訪問的權限。 自Kubernetes 1.7開始,當啟用Node授權模式時,對system:nodes用戶組的綁定將不會被自動創建。 |
| system:node-proxier | system:kube-proxyuser | 允許對kube-proxy組件所需要資源的訪問。 |
-
-
其它組件角色
-
| 默認ClusterRole | 默認ClusterRoleBinding | 描述 |
|---|---|---|
| system:auth-delegator | None | 允許委托認證和授權檢查。 通常由附加API Server用於統一認證和授權。 |
| system:heapster | None | Heapster組件的角色。 |
| system:kube-aggregator | None | kube-aggregator組件的角色。 |
| system:kube-dns | kube-dns service account in the kube-systemnamespace | kube-dns組件的角色。 |
| system:node-bootstrapper | None | 允許對執行Kubelet TLS引導(Kubelet TLS bootstrapping)所需要資源的訪問. |
| system:node-problem-detector | None | node-problem-detector組件的角色。 |
| system:persistent-volume-provisioner | None | 允許對大部分動態存儲卷創建組件(dynamic volume provisioner)所需要資源的訪問。 |
-
-
控制器(Controller)角色
-
Kubernetes controller manager負責運行核心控制循環。 當使用--use-service-account-credentials選項運行controller manager時,每個控制循環都將使用單獨的服務賬戶啟動。 而每個控制循環都存在對應的角色,前綴名為system:controller:。 如果不使用--use-service-account-credentials選項時,controller manager將會使用自己的憑證運行所有控制循環,而這些憑證必須被授予相關的角色。 這些角色包括:
- system:controller:attachdetach-controller
- system:controller:certificate-controller
- system:controller:cronjob-controller
- system:controller:daemon-set-controller
- system:controller:deployment-controller
- system:controller:disruption-controller
- system:controller:endpoint-controller
- system:controller:generic-garbage-collector
- system:controller:horizontal-pod-autoscaler
- system:controller:job-controller
- system:controller:namespace-controller
- system:controller:node-controller
- system:controller:persistent-volume-binder
- system:controller:pod-garbage-collector
- system:controller:replicaset-controller
- system:controller:replication-controller
- system:controller:resourcequota-controller
- system:controller:route-controller
- system:controller:service-account-controller
- system:controller:service-controller
- system:controller:statefulset-controller
- system:controller:ttl-controller
-
初始化與預防權限升級
RBAC API會阻止用戶通過編輯角色或者角色綁定來升級權限。 由於這一點是在API級別實現的,所以在RBAC授權器(RBAC authorizer)未啟用的狀態下依然可以正常工作。
用戶只有在擁有了角色所包含的所有權限的條件下才能創建/更新一個角色,這些操作還必須在角色所處的相同范圍內進行(對於ClusterRole來說是集群范圍,對於Role來說是在與角色相同的命名空間或者集群范圍)。 例如,如果用戶”user-1”沒有權限讀取集群范圍內的secret列表,那么他也不能創建包含這種權限的ClusterRole。為了能夠讓用戶創建/更新角色,需要:
- 授予用戶一個角色以允許他們根據需要創建/更新
Role或者ClusterRole對象。 - 授予用戶一個角色包含他們在
Role或者ClusterRole中所能夠設置的所有權限。如果用戶嘗試創建或者修改Role或者ClusterRole以設置那些他們未被授權的權限時,這些API請求將被禁止。
用戶只有在擁有所引用的角色中包含的所有權限時才可以創建/更新角色綁定(這些操作也必須在角色綁定所處的相同范圍內進行)或者用戶被明確授權可以在所引用的角色上執行綁定操作。 例如,如果用戶”user-1”沒有權限讀取集群范圍內的secret列表,那么他將不能創建ClusterRole來引用那些授予了此項權限的角色。為了能夠讓用戶創建/更新角色綁定,需要:
- 授予用戶一個角色以允許他們根據需要創建/更新
RoleBinding或者ClusterRoleBinding對象。 - 授予用戶綁定某一特定角色所需要的權限:
-
隱式地,通過授予用戶所有所引用的角色中所包含的權限
-
顯式地,通過授予用戶在特定Role(或者ClusterRole)對象上執行
bind操作的權限
例如,下面例子中的ClusterRole和RoleBinding將允許用戶”user-1”授予其它用戶”user-1-namespace”命名空間內的admin、edit和view等角色和角色綁定。
apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: role-grantor rules: - apiGroups: ["rbac.authorization.k8s.io"] resources: ["rolebindings"] verbs: ["create"] - apiGroups: ["rbac.authorization.k8s.io"] resources: ["clusterroles"] verbs: ["bind"] resourceNames: ["admin","edit","view"] --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: RoleBinding metadata: name: role-grantor-binding namespace: user-1-namespace roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: role-grantor subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: user-1
當初始化第一個角色和角色綁定時,初始用戶需要能夠授予他們尚未擁有的權限。 初始化初始角色和角色綁定時需要:
- 使用包含
system:masters用戶組的憑證,該用戶組通過默認綁定綁定到cluster-admin超級用戶角色。 - 如果您的API Server在運行時啟用了非安全端口(
--insecure-port),您也可以通過這個沒有施行認證或者授權的端口發送角色或者角色綁定請求。
-
一些命令行工具
有兩個kubectl命令可以用於在命名空間內或者整個集群內授予角色。
kubectl create rolebinding
在某一特定命名空間內授予Role或者ClusterRole。示例如下:
-
在名為”acme”的命名空間中將
adminClusterRole授予用戶”bob”:kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
-
在名為”acme”的命名空間中將
viewClusterRole授予服務賬戶”myapp”:kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme
kubectl create clusterrolebinding
在整個集群中授予ClusterRole,包括所有命名空間。示例如下:
-
在整個集群范圍內將
cluster-adminClusterRole授予用戶”root”:kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
-
在整個集群范圍內將
system:nodeClusterRole授予用戶”kubelet”:kubectl create clusterrolebinding kubelet-node-binding --clusterrole=system:node --user=kubelet
-
在整個集群范圍內將
viewClusterRole授予命名空間”acme”內的服務賬戶”myapp”:kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp
-
服務賬戶(Service Account)權限
默認的RBAC策略將授予控制平面組件(control-plane component)、節點(node)和控制器(controller)一組范圍受限的權限, 但對於”kube-system”命名空間以外的服務賬戶,則不授予任何權限(超出授予所有認證用戶的發現權限)。
從最安全到最不安全可以排序以下方法:
-
-
對某一特定應用程序的服務賬戶授予角色(最佳實踐)
要求應用程序在其pod規范(pod spec)中指定
serviceAccountName字段,並且要創建相應服務賬戶(例如通過API、應用程序清單或者命令kubectl create serviceaccount等)。例如,在”my-namespace”命名空間中授予服務賬戶”my-sa”只讀權限:
kubectl create rolebinding my-sa-view \ --clusterrole=view \ --serviceaccount=my-namespace:my-sa \ --namespace=my-namespace
換成yaml文件大概如下
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: my-sa-view namespace: my-namespace subjects: - kind: ServiceAccount name: my-sa apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: view #這里view為clusterrole名稱,其中berbs需要給view apiGroup: rbac.authorization.k8s.io
-
-
在某一命名空間中授予”default”服務賬號一個角色
如果一個應用程序沒有在其pod規范中指定
serviceAccountName,它將默認使用”default”服務賬號。注意:授予”default”服務賬號的權限將可用於命名空間內任何沒有指定
serviceAccountName的pod。下面的例子將在”my-namespace”命名空間內授予”default”服務賬號只讀權限:
kubectl create rolebinding default-view \ --clusterrole=view \ --serviceaccount=my-namespace:default \ --namespace=my-namespace
目前,許多加載項(addon)作為”kube-system”命名空間中的”default”服務帳戶運行。 要允許這些加載項使用超級用戶訪問權限,請將cluster-admin權限授予”kube-system”命名空間中的”default”服務帳戶。 注意:啟用上述操作意味着”kube-system”命名空間將包含允許超級用戶訪問API的秘鑰。
kubectl create clusterrolebinding add-on-cluster-admin \ --clusterrole=cluster-admin \ --serviceaccount=kube-system:default
-
為命名空間中所有的服務賬號授予角色
如果您希望命名空間內的所有應用程序都擁有同一個角色,無論它們使用什么服務賬戶,您可以為該命名空間的服務賬戶用戶組授予角色。
下面的例子將授予”my-namespace”命名空間中的所有服務賬戶只讀權限:
kubectl create rolebinding serviceaccounts-view \ --clusterrole=view \ --group=system:serviceaccounts:my-namespace \ --namespace=my-namespace
-
對集群范圍內的所有服務賬戶授予一個受限角色(不鼓勵)
如果您不想管理每個命名空間的權限,則可以將集群范圍角色授予所有服務帳戶。
下面的例子將所有命名空間中的只讀權限授予集群中的所有服務賬戶:
kubectl create clusterrolebinding serviceaccounts-view \ --clusterrole=view \ --group=system:serviceaccounts
-
授予超級用戶訪問權限給集群范圍內的所有服務帳戶(強烈不鼓勵)
如果您根本不關心權限分塊,您可以對所有服務賬戶授予超級用戶訪問權限。
警告:這種做法將允許任何具有讀取權限的用戶訪問secret或者通過創建一個容器的方式來訪問超級用戶的憑據。
kubectl create clusterrolebinding serviceaccounts-cluster-admin \ --clusterrole=cluster-admin \ --group=system:serviceaccounts
-
並行授權器(authorizer)
同時運行RBAC和ABAC授權器,並包括舊版ABAC策略:
--authorization-mode=RBAC,ABAC --authorization-policy-file=mypolicy.jsonl
RBAC授權器將嘗試首先授權請求。如果RBAC授權器拒絕API請求,則ABAC授權器將被運行。這意味着RBAC策略或者ABAC策略所允許的任何請求都是可通過的。
當以日志級別為2或更高(--v = 2)運行時,您可以在API Server日志中看到RBAC拒絕請求信息(以RBAC DENY:為前綴)。 您可以使用該信息來確定哪些角色需要授予哪些用戶,用戶組或服務帳戶。 一旦授予服務帳戶角色,並且服務器日志中沒有RBAC拒絕消息的工作負載正在運行,您可以刪除ABAC授權器。

