配置 Pod 的 Service Account

    本文是关于 Service Account 的用户指南,管理指南另见 Service Account 的集群管理指南 。

    注意:本文档描述的关于 Service Account 的行为只有当您按照 Kubernetes 项目建议的方式搭建起集群的情况下才有效。您的集群管理员可能在您的集群中有自定义配置,这种情况下该文档可能并不适用。

    当您(真人用户)访问集群(例如使用命令)时,apiserver 会将您认证为一个特定的 User Account(目前通常是admin,除非您的系统管理员自定义了集群配置)。Pod 容器中的进程也可以与 apiserver 联系。 当它们在联系 apiserver 的时候,它们会被认证为一个特定的 Service Account(例如default)。

    当您创建 pod 的时候,如果您没有指定一个 service account,系统会自动得在与该pod 相同的 namespace 下为其指派一个default service account。如果您获取刚创建的 pod 的原始 json 或 yaml 信息(例如使用kubectl get pods/podename -o yaml命令),您将看到spec.serviceAccountName字段已经被设置为 automatically 。

    您可以在 pod 中使用自动挂载的 service account 凭证来访问 API,如 Accessing the Cluster 中所描述。

    Service account 是否能够取得访问 API 的许可取决于您使用的 。

    在 1.6 以上版本中,您可以选择取消为 service account 自动挂载 API 凭证,只需在 service account 中设置 automountServiceAccountToken: false

    在 1.6 以上版本中,您也可以选择只取消单个 pod 的 API 凭证自动挂载:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: my-pod
    5. spec:
    6. serviceAccountName: build-robot
    7. automountServiceAccountToken: false
    8. ...

    如果在 pod 和 service account 中同时设置了 automountServiceAccountToken , pod 设置中的优先级更高。

    1. kubectl create serviceaccount sample-sc

    这时候我们将得到一个在 default namespace 的 serviceaccount 账号;我们运行kubectl get serviceaccount sample-sc 将得到如下结果:

    1. apiVersion: v1
    2. kind: ServiceAccount
    3. metadata:
    4. creationTimestamp: 2018-09-03T02:00:37Z
    5. labels:
    6. from: mofang
    7. name: mofang-viewer-sc
    8. namespace: default
    9. resourceVersion: "18914458"
    10. selfLink: /api/v1/namespaces/default/serviceaccounts/sample-sc
    11. uid: 26e129dc-af1d-11e8-9453-00163e0efab0
    12. secrets:
    13. - name: sample-sc-token-9x7nk

    因为我们在使用 serviceaccount 账号配置 kubeconfig 的时候需要使用到 sample-sc 的 token,该 token 保存在该 serviceaccount 保存的 secret 中;

    1. apiVersion: v1
    2. data:
    3. ca.crt: Ci0tLS0tQkVHSU4gQ0VSVcvfUNBVEUtLS0tLQpNSUlDL3pDQ0FtaWdBd0lCQWdJREJzdFlNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1HSXhDekFKQmdOVkJBWVRBa05PCk1SRXdEd1lEVlFRSURBaGFhR1ZLYVdGdVp6RVJNQThHQTFVRUJ3d0lTR0Z1WjFwb2IzVXhFREFPQmdOVkJBb00KQjBGc2FXSmhZbUV4RERBS0JnTlZCQXNNQTBGRFV6RU5NQXNHQTFVRUF3d0VjbTl2ZERBZUZ3MHhPREExTWprdwpNelF3TURCYUZ3MHpPREExTWpRd016UTFOVGxhTUdveEtqQW9CZ05WQkFvVElXTTJaVGxqTm1KallUY3pZakUwClkyTTBZV0UzT1RNd1lqTTROREV4TkRaallURVFNQTRHQTFVRUN4TUhaR1ZtWVhWc2RERXFNQ2dHQTFVRUF4TWgKWXpabE9XTTJZbU5oTnpOaU1UUmpZelJoWVRjNU16QmlNemcwTVRFME5tTmhNSUdmTUEwR0NTcUdTSWIzRFFFQgpBUVVBQTRHTkFEQ0JpUUtCZ1FETGNFWmJycCtBa0taNHU4TklVM25jaFU4YkExMnhKR0pJMzlxdTd4aFFsR3lHCmZqQTFqdXV4cVMyaE4vTGpwM21XNkdIaW0zd2lJd2N1WUtUN3RGOW9UejgrTzhBQzZHYnpkWExIL1RQTWtCZ2YKOVNYaEdod1hndklMb3YzbnZlS1MzRElxU3UreS9OK1huMzhOOW53SHF6S0p2WE1ROWtJaUJuTXgwVnlzSFFJRApBUUFCbzRHNk1JRzNNQTRHQTFVZER3RUIvd1FFQXdJQ3JEQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01COEdBMVVkCkl3UVlNQmFBRklWYS85MGp6U1Z2V0VGdm5tMUZPWnRZZlhYL01Ed0dDQ3NHQVFVRkJ3RUJCREF3TGpBc0JnZ3IKQmdFRkJRY3dBWVlnYUhSMGNEb3ZMMk5sY25SekxtRmpjeTVoYkdsNWRXNHVZMjl0TDI5amMzQXdOUVlEVlIwZgpCQzR3TERBcW9DaWdKb1lrYUhSMGNEb3ZMMk5sY25SekxtRmpjeTVoYkdsNWRXNHl0TDNKdmIzUXVZM0pzCk1BMEdDU3FHU0liM0RRRUJDd1VBQTRHQkFKWFRpWElvQ1VYODFFSU5idVRTay9PanRJeDM0ckV0eVBuTytBU2oKakszaTR3d1BRMEt5MDhmTlNuU2Z4Q1EyeEY1NTIxNVNvUzMxU3dMellJVEp1WFpBN2xXT29RU1RZL2lBTHVQQgovazNCbDhOUGNmejhGNXlZNy9uY1N6WDRwTXgxOHIwY29PTE1iZlpUUXJtSHBmQ053bWRjQmVCK0JuRFJMUEpGCmgzSUQKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQoKCg==
    4. namespace: ZGVmYXAsdA==
    5. token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJblI1Y0NJNklrcFhppppppo5LmV5SnBjM01pT2lKcmRXSmxjbTVsZddekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZVzFsYzNCaFkyVWlPaUprWldaaGRXeDBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5elpXTnlaWFF1Ym1GdFpTSTZJbTF2Wm1GdVp5MTJhV1YzWlhJdGMyTXRkRzlyWlc0dE9YZzNibXNpTENKcmRXSmxjbTVsZEdWekxtbHZMM05sY25acFkyVmhZMk52ZFc1MEwzTmxjblpwWTJVdFlXTmpiM1Z1ZEM1dVlXMWxJam9pYlc5bVlXNW5MWFpwWlhkbGNpMXpZeUlzSW10MVltVnlibVYwWlhNdWFXOHZjMlZ5ZG1salpXRmpZMjkxYm5RdmMyVnlkbWxqWlMxaFkyTnZkVzUwTG5WcFpDSTZJakkyWlRFeU9XUmpMV0ZtTVdRdE1URmxPQzA1TkRVekxUQXdNVFl6WlRCbFptRmlNQ0lzSW5OMVlpSTZJbk41YzNSbGJUcHpaWEoyYVdObFlXTmpiM1Z1ZERwa1pXWmhkV3gwT20xdlptRnVaeTEyYVdWM1pYSXRjMk1pZlEuQWpudnZueXRaWHJ1UndSdEJ3S3RFdzZWNzJpWU1vOUI2LVh3VmkzRWhReXNOM21PLXJvdGFJQnZHUFlNMGZNVDlWRzVjTFFKYmJWUmhLR0FyclUyQ1FNVl9JQ3NpbjFzMjFxTXJ5dngzNm9abzFYZkpWZlVVMEtqeWxndEQ0NTNmWU84SlFfWFF3OGNwVWc5NGE2WnZvcDZHcXNGNGhzT0sxTjFMaGRrSFBpWHA4TzRQUzJ6eDFXNklfeGs2ZUNBcjUxRVpwSktEWTZHMmhmZ1A5emxROGdPV21nbS1EVjZPZzNobjJ4UFprZUktVk1nYUF3amdFUGtVZFJDSndYRk9QRG5UcXlqUmtZVzdLVU1GLTVDTHdBNDZMNk5PYjJ6YUR0Uy16Zm5hdVFwLVdIcFNQdDNEdFc0UmRLZDVDZzE3Z3RGaWhRZzI3dnVqYWJNMGpmQmp3
    6. kind: Secret
    7. metadata:
    8. annotations:
    9. kubernetes.io/service-account.name: sample-sc
    10. kubernetes.io/service-account.uid: 26e129dc-af1d-11e8-9453-00163e0efab0
    11. creationTimestamp: 2018-09-03T02:00:37Z
    12. name: mofang-viewer-sc-token-9x7nk
    13. namespace: default
    14. resourceVersion: "18914310"
    15. selfLink: /api/v1/namespaces/default/secrets/sample-sc-token-9x7nk
    16. uid: 26e58b7c-af1d-11e8-9453-00163e0efab0
    17. type: kubernetes.io/service-account-token

    其中 {data.token} 就会是我们的用户 token 的 base64 编码,之后我们配置 kubeconfig 的时候将会用到它;

    比如我们想创建一个只可以查看集群deploymentsservicespods 相关的角色,应该使用如下配置

    1. apiVersion: rbac.authorization.k8s.io/v1
    2. ## 这里也可以使用 Role
    3. kind: ClusterRole
    4. metadata:
    5. name: mofang-viewer-role
    6. from: mofang
    7. - apiGroups:
    8. - ""
    9. resources:
    10. - pods
    11. - pods/status
    12. - pods/log
    13. - services
    14. - services/status
    15. - endpoints
    16. - endpoints/status
    17. - deployments
    18. verbs:
    19. - get
    20. - list
    21. - watch

    经过以上的步骤,我们最开始创建的 serviceaccount 就可以用来访问我们的集群了,同时我们可以动态更改 ClusterRole 的授权来及时控制某个账号的权限(这也是使用 serviceaccount 的好处);

    配置应该如下:

    1. apiVersion: v1
    2. clusters:
    3. - cluster:
    4. ## 这个是集群的 TLS 证书,与授权无关,使用同一的就可以
    5. certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvekNDQW1pZ0F3SUJBZ0lEQnN0WU1BMEdDU3FHU0liM0RRRUJDd1VBTUdJeEN6QUpCZ05WQkFZVEFrTk8KTVJFd0R3WURWUVFJREFoYWFHVkthV0Z1WnpFUk1BOEdBMVVFQnd3SVNHRnVaMXBvYjNVeEVEQU9CZ05WQkFvTQpCMEZzYVdKaFltRXhEREFLQmdOVkJBc01BMEZEVXpFTk1Bc0dBMVVFQXd3RWNtOXZkREFlRncweE9EQTFNamt3Ck16UXdNREJhRncwek9EQTFNalF3TXpRMU5UbGFNR294S2pBb0JnTlZCQW9USVdNMlpUbGpObUpqWVRjellqRTAKWTJNMFlXRTNPVE13WWpNNE5ERXhORFpqWVRFUU1BNEdBMVVFQ3hNSFpHVm1ZWFZzZERFcU1DZ0dBMVVFQXhNaApZelpsT1dNMlltTmhOek5pTVRSall6UmhZVGM1TXpCaU16ZzBNVEUwTm1OaE1JR2ZNQTBHQ1NxR1NJYjNEUUVCCkFRVUFBNEdOQURDQmlRS0JnUURMY0VaYnJwK0FrS1o0dThOSVUzbmNoVThiQTEyeEpHSkkzOXF1N3hoUWxHeUcKZmpBMWp1dXhxUzJoTi9ManAzbVc2R0hpbTN3aUl3Y3VZS1Q3dEY5b1R6OCtPOEFDNkdiemRYTEgvVFBNa0JnZgo5U1hoR2h3WGd2SUxvdjNudmVLUzNESXFTdSt5L04rWG4zOE45bndIcXpLSnZYTVE5a0lpQm5NeDBWeXNIUUlECkFRQUJvNEc2TUlHM01BNEdBMVVkRHdFQi93UUVBd0lDckRBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUI4R0ExVWQKSXdRWU1CYUFGSVZhLzkwanpTVnZXRUZ2bm0xRk9adFlmWFgvTUR3R0NDc0dBUVVGQndFQkJEQXdMakFzQmdncgpCZ0VGQlFjd0FZWWdhSFIwY0RvdkwyTmxjblJ6TG1GamN5NWhiR2w1ZFc0dVkyOXRMMjlqYzNBd05RWURWUjBmCkJDNHdMREFxb0NpZ0pvWWthSFIwY0RvdkwyTmxjblJ6TG1GamN5NWhiR2w1ZFc0dVkyOXRMM0p2YjNRdVkzSnMKTUEwR0NTcUdTSWIzRFFFQkN3VUFBNEdCQUpYVGlYSW9DVVg4MUVJTmJ1VFNrL09qdEl4MzRyRXR5UG5PK0FTagpqSzNpNHd3UFEwS3kwOGZOU25TZnhDUTJ4RjU1MjE1U29TMzFTd0x6WUlUSnVYWkE3bFdPb1FTVFkvaUFMdVBCCi9rM0JsOE5QY2Z6OEY1eVk3L25jU3pYNHBNeDE4cjBjb09MTWJmWlRRcm1IcGZDTndtZGNCZUIrQm5EUkxQSkYKaDNJRAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    6. server: https://47.95.24.167:6443
    7. name: beta
    8. contexts:
    9. - context:
    10. cluster: beta
    11. user: beta-viewer
    12. name: beta-viewer
    13. current-context: beta-viewer
    14. kind: Config
    15. preferences: {}
    16. users:
    17. - name: beta-viewer
    18. user:
    19. ## 这个使我们在创建 serviceaccount 生成相关 secret 之后的 data.token 的 base64 解码字符,它本质是一个 jwt token
    20. token: eyJhbGciOiJSUzI1NiIsInR5dffg6IkpXVCJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6Im1vZmFuZy12aWV3ZXItc2MtdG9rZW4tOXg3bmsiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoibW9mYW5nLXZpZXdlci1zYyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjxZTEyOWRjLWFmMWQtMTFlOC05NDUzLTAwMTYzZTBlZmFiMCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0Om1vZmFuZy12aWV3ZXItc2MifQ.AjnvvnytZXruRwRtBwKtEw6V72iYMo9B6-XwVi3EhQysN3mO-rotaIBvGPYM0fMT9VG5cLQJbbVRhKGArrU2CQMV_ICsin1s21qMryvx36oZo1XfJVfUU0KjylgtD453fYO8JQ_XQw8cpUg94a6Zvop6GqsF4hsOK1N1LhdkHPiXp8O4PS2zx1W6I_xk6eCAr51EZpJKDY6G2hfgP9zlQ8gOWmgm-DV6Og3hn2xPZkeI-VMgaAwjgEPkUdRCJwXFOPDnTqyjRkYW7KUMF-5CLwA46L6NOb2zaDtS-zfnauQp-WHpSPt3DtW4RdKd5Cg17gtFihQg27vujabM0jfBjw

    每个 namespace 中都有一个默认的叫做 default 的 service account 资源。

    您可以使用以下命令列出 namespace 下的所有 serviceAccount 资源。

    1. $ kubectl get serviceAccounts
    2. NAME SECRETS AGE
    3. default 1 1d

    您可以像这样创建一个 ServiceAccount 对象:

    1. $ cat > /tmp/serviceaccount.yaml <<EOF
    2. apiVersion: v1
    3. kind: ServiceAccount
    4. metadata:
    5. name: build-robot
    6. EOF
    7. $ kubectl create -f /tmp/serviceaccount.yaml
    8. serviceaccount "build-robot" created

    如果您看到如下的 service account 对象的完整输出信息:

    1. $ kubectl get serviceaccounts/build-robot -o yaml
    2. apiVersion: v1
    3. kind: ServiceAccount
    4. metadata:
    5. creationTimestamp: 2015-06-16T00:12:59Z
    6. name: build-robot
    7. namespace: default
    8. selfLink: /api/v1/namespaces/default/serviceaccounts/build-robot
    9. secrets:
    10. - name: build-robot-token-bvbk5

    然后您将看到有一个 token 已经被自动创建,并被 service account 引用。

    您可以使用授权插件来 设置 service account 的权限

    设置非默认的 service account,只需要在 pod 的spec.serviceAccountName 字段中将name设置为您想要用的 service account 名字即可。

    您不能更新已创建的 pod 的 service account。

    您可以清理 service account,如下所示:

    1. $ kubectl delete serviceaccount/build-robot

    假设我们已经有了一个如上文提到的名为 ”build-robot“ 的 service account,我们手动创建一个新的 secret。

    现在您可以确认下新创建的 secret 取代了 “build-robot” 这个 service account 原来的 API token。

    所有已不存在的 service account 的 token 将被 token controller 清理掉。

    1. $ kubectl describe secrets/build-robot-secret
    2. Name: build-robot-secret
    3. Namespace: default
    4. Labels: <none>
    5. Annotations: kubernetes.io/service-account.name=build-robot,kubernetes.io/service-account.uid=870ef2a5-35cf-11e5-8d06-005056b45392
    6. Type: kubernetes.io/service-account-token
    7. Data
    8. ====
    9. ca.crt: 1220 bytes
    10. token: ...
    11. namespace: 7 bytes

    首先,创建一个 imagePullSecret,详见。

    然后,确认已创建。如:

    1. $ kubectl get secrets myregistrykey
    2. NAME TYPE DATA AGE
    3. myregistrykey kubernetes.io/.dockerconfigjson 1 1d

    然后,修改 namespace 中的默认 service account 使用该 secret 作为 imagePullSecret。

    1. kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'

    Vi 交互过程中需要手动编辑:

    1. $ kubectl get serviceaccounts default -o yaml > ./sa.yaml
    2. $ cat sa.yaml
    3. apiVersion: v1
    4. kind: ServiceAccount
    5. metadata:
    6. creationTimestamp: 2015-08-07T22:02:39Z
    7. name: default
    8. namespace: default
    9. resourceVersion: "243024"
    10. selfLink: /api/v1/namespaces/default/serviceaccounts/default
    11. uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
    12. secrets:
    13. - name: default-token-uudge
    14. $ vi sa.yaml
    15. [editor session not shown]
    16. [delete line with key "resourceVersion"]
    17. [add lines with "imagePullSecret:"]
    18. $ cat sa.yaml
    19. apiVersion: v1
    20. kind: ServiceAccount
    21. metadata:
    22. creationTimestamp: 2015-08-07T22:02:39Z
    23. name: default
    24. namespace: default
    25. selfLink: /api/v1/namespaces/default/serviceaccounts/default
    26. uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
    27. secrets:
    28. - name: default-token-uudge
    29. imagePullSecrets:
    30. - name: myregistrykey
    31. $ kubectl replace serviceaccount default -f ./sa.yaml
    32. serviceaccounts/default

    现在,所有当前 namespace 中新创建的 pod 的 spec 中都会增加如下内容:

    1. spec:
    2. - name: myregistrykey