Kubernetes中提供了良好的多租户认证管理机制,如RBAC、ServiceAccount还有各类Policy等。html
Service Account为Pod中的进程提供身份信息。node
当用户访问集群(例如使用kubectl
命令)时,apiserver 会将用户认证为一个特定的 User Account(目前一般是admin
,除非系统管理员自定义了集群配置)。Pod 容器中的进程也能够与 apiserver 联系。 当它们在联系 apiserver 的时候,它们会被认证为一个特定的 Service Account(例如default
)。nginx
当建立 pod 的时候,若是没有指定一个 service account,系统会自动得在与该pod 相同的 namespace 下为其指派一个default
service account。若是获取刚建立的 pod 的原始 json 或 yaml 信息(例如使用kubectl get pods podename -o yaml
命令),将看到spec.serviceAccountName
字段已经被设置为 default
。git
能够在 pod 中使用自动挂载的 service account 凭证来访问 API,如 Accessing the Cluster 中所描述。github
Service account 是否可以取得访问 API 的许可取决于您使用的 受权插件和策略。docker
在 1.6 以上版本中,能够选择取消为 service account 自动挂载 API 凭证,只需在 service account 中设置 automountServiceAccountToken: false
:json
apiVersion: v1 kind: ServiceAccount metadata: name: build-robot automountServiceAccountToken: false ...
在 1.6 以上版本中,也能够选择只取消单个 pod 的 API 凭证自动挂载:bootstrap
apiVersion: v1 kind: Pod metadata: name: my-pod spec: serviceAccountName: build-robot automountServiceAccountToken: false ...
若是在 pod 和 service account 中同时设置了 automountServiceAccountToken
, pod 设置中的优先级更高。api
建立服务帐号(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
每一个 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
假设已经有了一个如上文提到的名为 ”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
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
基于角色的访问控制(Role-Based Access Control, 即”RBAC”)使用”rbac.authorization.k8s.io” API Group实现受权决策,容许管理员经过Kubernetes API动态配置策略。
要启用RBAC,请使用--authorization-mode=RBAC
启动API Server。
在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"]
角色绑定将一个角色中定义的各类权限授予一个或者一组用户。 角色绑定包含了一组相关主体(即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"]
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资源。 |
默认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)所须要资源的访问。 |
Kubernetes controller manager负责运行核心控制循环。 当使用--use-service-account-credentials
选项运行controller manager时,每一个控制循环都将使用单独的服务帐户启动。 而每一个控制循环都存在对应的角色,前缀名为system:controller:
。 若是不使用--use-service-account-credentials
选项时,controller manager将会使用本身的凭证运行全部控制循环,而这些凭证必须被授予相关的角色。 这些角色包括:
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
超级用户角色。--insecure-port
),您也能够经过这个没有施行认证或者受权的端口发送角色或者角色绑定请求。
有两个kubectl
命令能够用于在命名空间内或者整个集群内授予角色。
kubectl create rolebinding
在某一特定命名空间内授予Role
或者ClusterRole
。示例以下:
在名为”acme”的命名空间中将admin
ClusterRole
授予用户”bob”:
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme
在名为”acme”的命名空间中将view
ClusterRole
授予服务帐户”myapp”:
kubectl create rolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp --namespace=acme
kubectl create clusterrolebinding
在整个集群中授予ClusterRole
,包括全部命名空间。示例以下:
在整个集群范围内将cluster-admin
ClusterRole
授予用户”root”:
kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root
在整个集群范围内将system:node
ClusterRole
授予用户”kubelet”:
kubectl create clusterrolebinding kubelet-node-binding --clusterrole=system:node --user=kubelet
在整个集群范围内将view
ClusterRole
授予命名空间”acme”内的服务帐户”myapp”:
kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp
默认的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
同时运行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受权器。