From 1024e1ecc582da67c5c7c1c3a60ed59c145f2b5d Mon Sep 17 00:00:00 2001 From: Tim Bannister Date: Mon, 29 Jul 2019 21:41:31 +0100 Subject: [PATCH] =?UTF-8?q?Reword=20=E2=80=9CManaging=20Service=20Accounts?= =?UTF-8?q?=E2=80=9D=20task?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service-accounts-admin.md | 215 ++++++++++-------- .../secret/serviceaccount/mysecretname.yaml | 7 + 2 files changed, 128 insertions(+), 94 deletions(-) create mode 100644 content/en/examples/secret/serviceaccount/mysecretname.yaml diff --git a/content/en/docs/reference/access-authn-authz/service-accounts-admin.md b/content/en/docs/reference/access-authn-authz/service-accounts-admin.md index 329b8a1b4aaf2..730f232ee4aca 100644 --- a/content/en/docs/reference/access-authn-authz/service-accounts-admin.md +++ b/content/en/docs/reference/access-authn-authz/service-accounts-admin.md @@ -4,115 +4,142 @@ reviewers: - davidopp - lavalamp - liggitt -title: Managing Service Accounts -content_template: templates/concept +title: Managing ServiceAccounts +content_template: templates/task weight: 50 --- {{% capture overview %}} -This is a Cluster Administrator guide to service accounts. It assumes knowledge of -the [User Guide to Service Accounts](/docs/user-guide/service-accounts). -Support for authorization and user accounts is planned but incomplete. Sometimes -incomplete features are referred to in order to better describe service accounts. +A _ServiceAccount_ provides an identity for processes that run in a Pod. + +A process inside a Pod can use the identiy of its associated service account to +authenticate to the cluster's API server. + +For an introduction to service accounts, read [configure service accounts](/docs/tasks/configure-pod-container/configure-service-account/). + +This guide explains how to add and remove tokens from ServiceAccounts. + {{% /capture %}} -{{% capture body %}} -## User accounts vs service accounts - -Kubernetes distinguishes between the concept of a user account and a service account -for a number of reasons: - - - User accounts are for humans. Service accounts are for processes, which - run in pods. - - User accounts are intended to be global. Names must be unique across all - namespaces of a cluster, future user resource will not be namespaced. - Service accounts are namespaced. - - Typically, a cluster's User accounts might be synced from a corporate - database, where new user account creation requires special privileges and - is tied to complex business processes. Service account creation is intended - to be more lightweight, allowing cluster users to create service accounts for - specific tasks (i.e. principle of least privilege). - - Auditing considerations for humans and service accounts may differ. - - A config bundle for a complex system may include definition of various service - accounts for components of that system. Because service accounts can be created - ad-hoc and have namespaced names, such config is portable. - -## Service account automation - -Three separate components cooperate to implement the automation around service accounts: - - - A Service account admission controller - - A Token controller - - A Service account controller - -### Service Account Admission Controller - -The modification of pods is implemented via a plugin -called an [Admission Controller](/docs/reference/access-authn-authz/admission-controllers/). It is part of the apiserver. -It acts synchronously to modify pods as they are created or updated. When this plugin is active -(and it is by default on most distributions), then it does the following when a pod is created or modified: - - 1. If the pod does not have a `ServiceAccount` set, it sets the `ServiceAccount` to `default`. - 1. It ensures that the `ServiceAccount` referenced by the pod exists, and otherwise rejects it. - 1. If the pod does not contain any `ImagePullSecrets`, then `ImagePullSecrets` of the `ServiceAccount` are added to the pod. - 1. It adds a `volume` to the pod which contains a token for API access. - 1. It adds a `volumeSource` to each container of the pod mounted at `/var/run/secrets/kubernetes.io/serviceaccount`. - -Starting from v1.13, you can migrate a service account volume to a projected volume when -the `BoundServiceAccountTokenVolume` feature gate is enabled. -The service account token will expire after 1 hour or the pod is deleted. See more details about [projected volume](/docs/tasks/configure-pod-container/configure-projected-volume-storage/). - -### Token Controller - -TokenController runs as part of controller-manager. It acts asynchronously. It: - -- observes serviceAccount creation and creates a corresponding Secret to allow API access. -- observes serviceAccount deletion and deletes all corresponding ServiceAccountToken Secrets. -- observes secret addition, and ensures the referenced ServiceAccount exists, and adds a token to the secret if needed. -- observes secret deletion and removes a reference from the corresponding ServiceAccount if needed. - -You must pass a service account private key file to the token controller in the controller-manager by using -the `--service-account-private-key-file` option. The private key will be used to sign generated service account tokens. -Similarly, you must pass the corresponding public key to the kube-apiserver using the `--service-account-key-file` -option. The public key will be used to verify the tokens during authentication. - -#### To create additional API tokens - -A controller loop ensures a secret with an API token exists for each service -account. To create additional API tokens for a service account, create a secret -of type `ServiceAccountToken` with an annotation referencing the service -account, and the controller will update it with a generated token: - -secret.json: - -```json -{ - "kind": "Secret", - "apiVersion": "v1", - "metadata": { - "name": "mysecretname", - "annotations": { - "kubernetes.io/service-account.name": "myserviceaccount" - } - }, - "type": "kubernetes.io/service-account-token" -} +{{% capture prerequisites %}} + +{{< include "task-tutorial-prereqs.md" >}} + + +To be able to follow these steps exactly, ensure you have a namespace named +`examplens`. +If you don't, create one by running: + +```shell +kubectl create namespace examplens ``` +You can clean it up when you're done by running: + ```shell -kubectl create -f ./secret.json -kubectl describe secret mysecretname +kubectl delete namespace examplens ``` +{{% /capture %}} + +{{% capture steps %}} + +## Create additional API tokens {#create-token} + +The control plane ensures that a Secret with a current API token exists for each +ServiceAccount. To create additional API tokens for a service account, you +can create a Secret of type `ServiceAccountToken` with an annotation referencing +the ServiceAccount. The _token controller_ then updates the relevant +ServiceAccount with a generated token. -#### To delete/invalidate a service account token +{{< codenew file="secret/serviceaccount/mysecretname.yaml" >}} + +To create a Secret based on this example, run: ```shell -kubectl delete secret mysecretname +kubectl -n examplens create -f https://k8s.io/examples/secret/serviceaccount/mysecretname.yaml +kubectl -n examplens describe secret mysecretname +``` + +The output is similar to: +``` +Name: mysecretname +Namespace: examplens +Labels: +Annotations: kubernetes.io/service-account.name=myserviceaccount + kubernetes.io/service-account.uid=8a85c4c4-8483-11e9-bc42-526af7764f64 + +Type: kubernetes.io/service-account-token + +Data +==== +ca.crt: 1362 bytes +namespace: 9 bytes +token: ... ``` -### Service Account Controller +If you launch a new Pod into the `examplens` namespace, it can use the `myserviceaccount` +service-account-token Secret that you just created. + +## Delete/invalidate a ServiceAccount token {#delete-token} + +If you know the name of the Secret that contains the token you want to remove: + +```shell +kubectl delete secret name-of-secret +``` + +Otherwise, first find the Secret for the ServiceAccount. + +```shell +# This assumes that you already have a namespace named 'examplens' +kubectl -n examplens get serviceaccount/example-automated-thing -o yaml +``` +The output is similar to: +```yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"example-automated-thing","namespace":"examplens"}} + creationTimestamp: "2019-07-21T07:07:07Z" + name: example-automated-thing + namespace: examplens + resourceVersion: "777" + selfLink: /api/v1/namespaces/examplens/serviceaccounts/example-automated-thing + uid: f23fd170-66f2-4697-b049-e1e266b7f835 +secrets: +- name: example-automated-thing-token-zyxwv +``` +Then, delete the Secret you now know the name of: +```shell +kubectl -n examplens delete secret/example-automated-thing-token-zyxwv +``` + +The control plane spots that the ServiceAccount is missing its Secret, +and creates a replacement: + +```shell +kubectl -n examplens get serviceaccount/example-automated-thing -o yaml +``` +```yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"example-automated-thing","namespace":"examplens"}} + creationTimestamp: "2019-07-21T07:07:07Z" + name: example-automated-thing + namespace: examplens + resourceVersion: "1026" + selfLink: /api/v1/namespaces/examplens/serviceaccounts/example-automated-thing + uid: f23fd170-66f2-4697-b049-e1e266b7f835 +secrets: +- name: example-automated-thing-token-4rdrh +``` -Service Account Controller manages ServiceAccount inside namespaces, and ensures -a ServiceAccount named "default" exists in every active namespace. +You can see that there is now a new associated Secret with a different name. The +old Secret is no longer valid. {{% /capture %}} diff --git a/content/en/examples/secret/serviceaccount/mysecretname.yaml b/content/en/examples/secret/serviceaccount/mysecretname.yaml new file mode 100644 index 0000000000000..e50fe72d71cd4 --- /dev/null +++ b/content/en/examples/secret/serviceaccount/mysecretname.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +type: kubernetes.io/service-account-token +metadata: + name: mysecretname + annotations: + - kubernetes.io/service-account.name: myserviceaccount