Skip to content

Commit

Permalink
Reword “Managing Service Accounts” task
Browse files Browse the repository at this point in the history
  • Loading branch information
sftim committed Aug 3, 2019
1 parent 72b3f87 commit 9668687
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 94 deletions.
215 changes: 121 additions & 94 deletions content/en/docs/reference/access-authn-authz/service-accounts-admin.md
Original file line number Diff line number Diff line change
Expand Up @@ -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: <none>
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 %}}
7 changes: 7 additions & 0 deletions content/en/examples/secret/serviceaccount/mysecretname.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
name: mysecretname
annotations:
- kubernetes.io/service-account.name: myserviceaccount

0 comments on commit 9668687

Please sign in to comment.