Skip to content

Commit f9db6ae

Browse files
author
Tim Bannister
committed
Reword “Managing Service Accounts” task
1 parent 0fda59f commit f9db6ae

File tree

2 files changed

+208
-87
lines changed

2 files changed

+208
-87
lines changed

content/en/docs/reference/access-authn-authz/service-accounts-admin.md

Lines changed: 201 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,30 @@ weight: 50
1111

1212
<!-- overview -->
1313

14-
This is a Cluster Administrator guide to service accounts. You should be familiar with
15-
[configuring Kubernetes service accounts](/docs/tasks/configure-pod-container/configure-service-account/).
14+
A _ServiceAccount_ provides an identity for processes that run in a Pod.
1615

17-
Support for authorization and user accounts is planned but incomplete. Sometimes
18-
incomplete features are referred to in order to better describe service accounts.
16+
A process inside a Pod can use the identity of its associated service account to
17+
authenticate to the cluster's API server.
18+
19+
For an introduction to service accounts, read [configure service accounts](/docs/tasks/configure-pod-container/configure-service-account/).
20+
21+
This task guide explains some of the concepts behind ServiceAccounts. The
22+
guide also explains how to add and remove tokens from ServiceAccounts.
1923

2024
<!-- body -->
2125

26+
## {{% heading "prerequisites" %}}
27+
28+
{{< include "task-tutorial-prereqs.md" >}}
29+
30+
To be able to follow these steps exactly, ensure you have a namespace named
31+
`examplens`.
32+
If you don't, create one by running:
33+
34+
```shell
35+
kubectl create namespace examplens
36+
```
37+
2238
## User accounts versus service accounts
2339

2440
Kubernetes distinguishes between the concept of a user account and a service account
@@ -27,7 +43,7 @@ for a number of reasons:
2743
- User accounts are for humans. Service accounts are for processes, which run
2844
in pods.
2945
- User accounts are intended to be global. Names must be unique across all
30-
namespaces of a cluster. Service accounts are namespaced.
46+
namespaces of a cluster. In Kubernetes, service accounts are namespaced.
3147
- Typically, a cluster's user accounts might be synced from a corporate
3248
database, where new user account creation requires special privileges and is
3349
tied to complex business processes. Service account creation is intended to be
@@ -38,124 +54,222 @@ for a number of reasons:
3854
accounts for components of that system. Because service accounts can be created
3955
without many constraints and have namespaced names, such config is portable.
4056

41-
## Service account automation
42-
43-
Three separate components cooperate to implement the automation around service accounts:
44-
45-
- A `ServiceAccount` admission controller
46-
- A Token controller
47-
- A `ServiceAccount` controller
48-
49-
### ServiceAccount Admission Controller
57+
## ServiceAccount admission controller
5058

5159
The modification of pods is implemented via a plugin
5260
called an [Admission Controller](/docs/reference/access-authn-authz/admission-controllers/).
5361
It is part of the API server.
54-
It acts synchronously to modify pods as they are created or updated. When this plugin is active
55-
(and it is by default on most distributions), then it does the following when a pod is created or modified:
56-
57-
1. If the pod does not have a `ServiceAccount` set, it sets the `ServiceAccount` to `default`.
58-
1. It ensures that the `ServiceAccount` referenced by the pod exists, and otherwise rejects it.
59-
1. It adds a `volume` to the pod which contains a token for API access if neither the
60-
ServiceAccount `automountServiceAccountToken` nor the Pod's `automountServiceAccountToken`
61-
is set to `false`.
62-
1. It adds a `volumeSource` to each container of the pod mounted at
63-
`/var/run/secrets/kubernetes.io/serviceaccount`, if the previous step has created a volume
64-
for the ServiceAccount token.
65-
1. If the pod does not contain any `imagePullSecrets`, then `imagePullSecrets` of the
66-
`ServiceAccount` are added to the pod.
67-
68-
#### Bound Service Account Token Volume
62+
This admission controller acts synchronously to modify pods as they are created.
63+
When this plugin is active (and it is by default on most distributions), then
64+
it does the following when a Pod is created:
65+
66+
1. If the pod does not have a `.spec.serviceAccountName` set, the admission controller sets the name of the
67+
ServiceAccount for this incoming Pod to `default`.
68+
1. The admission controller ensures that the ServiceAccount referenced by the incoming Pod exists. If there
69+
is no ServiceAccount with a matching name, the admission controller rejects the incoming Pod. That check
70+
applies even for the `default` ServiceAccount.
71+
1. Provided that neither the ServiceAccount's `automountServiceAccountToken` field nor the
72+
Pod's `automountServiceAccountToken` field is set to `false`:
73+
- the admission controller mutates the incoming Pod, adding an extra
74+
{{< glossary_tooltip text="volume" term_id="volume" >}} that contains
75+
a token for API access.
76+
- the admission controller adds a `volumeMount` to each container in the Pod,
77+
skipping any containers that already have a volume mount defined for the path
78+
`/var/run/secrets/kubernetes.io/serviceaccount`.
79+
For Linux containers, that volume is mounted at `/var/run/secrets/kubernetes.io/serviceaccount`;
80+
on Windows nodes, the mount is at the equivalent path.
81+
1. If the spec of the incoming Pod does already contain any `imagePullSecrets`, then the
82+
admission controller adds `imagePullSecrets`, copying them from the `ServiceAccount`.
83+
84+
### Bound service account token volume mechanism {#bound-service-account-token-volume}
6985

7086
{{< feature-state for_k8s_version="v1.22" state="stable" >}}
7187

72-
The ServiceAccount admission controller will add the following projected volume instead of a
73-
Secret-based volume for the non-expiring service account token created by the Token controller.
88+
The Kubernetes control plane (specifically, the ServiceAccount admission controller)
89+
adds a projected volume to Pods, and the kubelet ensures that this volume contains a token
90+
that lets containers authenticate as the right ServiceAccount.
91+
92+
(This mechanism superseded an earlier mechanism that added a volume based on a Secret,
93+
where the Secret represented the ServiceAccount for the Pod but did not expire.)
94+
95+
Here's an example of how that looks for a launched Pod:
7496

7597
```yaml
76-
- name: kube-api-access-<random-suffix>
77-
projected:
78-
defaultMode: 420 # 0644
79-
sources:
80-
- serviceAccountToken:
81-
expirationSeconds: 3607
82-
path: token
83-
- configMap:
84-
items:
85-
- key: ca.crt
86-
path: ca.crt
87-
name: kube-root-ca.crt
88-
- downwardAPI:
89-
items:
90-
- fieldRef:
91-
apiVersion: v1
92-
fieldPath: metadata.namespace
93-
path: namespace
98+
...
99+
- name: kube-api-access-<random-suffix>
100+
projected:
101+
defaultMode: 420 # decimal equivalent of octal 0644
102+
sources:
103+
- serviceAccountToken:
104+
expirationSeconds: 3597
105+
path: token
106+
- configMap:
107+
items:
108+
- key: ca.crt
109+
path: ca.crt
110+
name: kube-root-ca.crt
111+
- downwardAPI:
112+
items:
113+
- fieldRef:
114+
apiVersion: v1
115+
fieldPath: metadata.namespace
116+
path: namespace
94117
```
95118
96-
This projected volume consists of three sources:
119+
That manifest snippet defines a projected volume that combines information from three sources:
97120
98-
1. A `serviceAccountToken` acquired from kube-apiserver via TokenRequest API. It will expire
99-
after 1 hour by default or when the pod is deleted. It is bound to the pod and it has
100-
its audience set to match the audience of the `kube-apiserver`.
101-
1. A `configMap` containing a CA bundle used for verifying connections to the kube-apiserver.
102-
1. A `downwardAPI` that references the namespace of the pod.
121+
1. A `serviceAccountToken` source, that contains a token that the kubelet acquires from kube-apiserver
122+
The kubelet fetches time-bound tokens using the TokenRequest API. A token served for a TokenRequest expires
123+
either when the pod is deleted or after a defined lifespan (by default, that is 1 hour).
124+
The token is bound to the specific Pod and has the kube-apiserver as its audience.
125+
1. A `configMap` source. The ConfigMap contains a bundle of certificate authority data. Pods can use these
126+
certificates to make sure that they are connecting to your cluster's kube-apiserver (and not to middlebox
127+
or an accidentally misconfigured peer).
128+
1. A `downwardAPI` source. This `downwardAPI` volume makes the name of the namespace container the Pod available
129+
to application code running inside the Pod.
103130

104-
See more details about [projected volumes](/docs/tasks/configure-pod-container/configure-projected-volume-storage/).
131+
Any container within the Pod that mounts this volume can access the above information.
105132

106-
### Token Controller
133+
## Create additional API tokens {#create-token}
107134

108-
TokenController runs as part of `kube-controller-manager`. It acts asynchronously. It:
135+
The control plane ensures that a Secret with an API token exists for each
136+
ServiceAccount. To create additional API tokens for a ServiceAccount, create a
137+
Secret of type `kubernetes.io/service-account-token` with an annotation
138+
referencing the ServiceAccount, and the control plane will update that Secret with a
139+
generated token.
109140

110-
- watches ServiceAccount creation and creates a corresponding
111-
ServiceAccount token Secret to allow API access.
112-
- watches ServiceAccount deletion and deletes all corresponding ServiceAccount
113-
token Secrets.
114-
- watches ServiceAccount token Secret addition, and ensures the referenced
115-
ServiceAccount exists, and adds a token to the Secret if needed.
116-
- watches Secret deletion and removes a reference from the corresponding
117-
ServiceAccount if needed.
141+
Here is a sample manifest for such a Secret:
118142

119-
You must pass a service account private key file to the token controller in
120-
the `kube-controller-manager` using the `--service-account-private-key-file`
121-
flag. The private key is used to sign generated service account tokens.
122-
Similarly, you must pass the corresponding public key to the `kube-apiserver`
123-
using the `--service-account-key-file` flag. The public key will be used to
124-
verify the tokens during authentication.
143+
{{< codenew file="secret/serviceaccount/mysecretname.yaml" >}}
125144

126-
#### To create additional API tokens
145+
To create a Secret based on this example, run:
146+
```shell
147+
kubectl -n examplens create -f https://k8s.io/examples/secret/serviceaccount/mysecretname.yaml
148+
```
127149

128-
A controller loop ensures a Secret with an API token exists for each
129-
ServiceAccount. To create additional API tokens for a ServiceAccount, create a
130-
Secret of type `kubernetes.io/service-account-token` with an annotation
131-
referencing the ServiceAccount, and the controller will update it with a
132-
generated token:
150+
To see the details for that Secret, run:
151+
152+
```shell
153+
kubectl -n examplens describe secret mysecretname
154+
```
155+
156+
The output is similar to:
157+
```
158+
Name: mysecretname
159+
Namespace: examplens
160+
Labels: <none>
161+
Annotations: kubernetes.io/service-account.name=myserviceaccount
162+
kubernetes.io/service-account.uid=8a85c4c4-8483-11e9-bc42-526af7764f64
163+
164+
Type: kubernetes.io/service-account-token
165+
166+
Data
167+
====
168+
ca.crt: 1362 bytes
169+
namespace: 9 bytes
170+
token: ...
171+
```
172+
173+
If you launch a new Pod into the `examplens` namespace, it can use the `myserviceaccount`
174+
service-account-token Secret that you just created.
175+
176+
## Delete/invalidate a ServiceAccount token {#delete-token}
133177

134-
Below is a sample configuration for such a Secret:
178+
If you know the name of the Secret that contains the token you want to remove:
135179

180+
```shell
181+
kubectl delete secret name-of-secret
182+
```
183+
184+
Otherwise, first find the Secret for the ServiceAccount.
185+
186+
```shell
187+
# This assumes that you already have a namespace named 'examplens'
188+
kubectl -n examplens get serviceaccount/example-automated-thing -o yaml
189+
```
190+
The output is similar to:
136191
```yaml
137192
apiVersion: v1
138-
kind: Secret
193+
kind: ServiceAccount
139194
metadata:
140-
name: mysecretname
141195
annotations:
142-
kubernetes.io/service-account.name: myserviceaccount
143-
type: kubernetes.io/service-account-token
196+
kubectl.kubernetes.io/last-applied-configuration: |
197+
{"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"example-automated-thing","namespace":"examplens"}}
198+
creationTimestamp: "2019-07-21T07:07:07Z"
199+
name: example-automated-thing
200+
namespace: examplens
201+
resourceVersion: "777"
202+
selfLink: /api/v1/namespaces/examplens/serviceaccounts/example-automated-thing
203+
uid: f23fd170-66f2-4697-b049-e1e266b7f835
204+
secrets:
205+
- name: example-automated-thing-token-zyxwv
206+
```
207+
Then, delete the Secret you now know the name of:
208+
```shell
209+
kubectl -n examplens delete secret/example-automated-thing-token-zyxwv
144210
```
145211

212+
The control plane spots that the ServiceAccount is missing its Secret,
213+
and creates a replacement:
214+
146215
```shell
147-
kubectl create -f ./secret.yaml
148-
kubectl describe secret mysecretname
216+
kubectl -n examplens get serviceaccount/example-automated-thing -o yaml
217+
```
218+
```yaml
219+
apiVersion: v1
220+
kind: ServiceAccount
221+
metadata:
222+
annotations:
223+
kubectl.kubernetes.io/last-applied-configuration: |
224+
{"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"example-automated-thing","namespace":"examplens"}}
225+
creationTimestamp: "2019-07-21T07:07:07Z"
226+
name: example-automated-thing
227+
namespace: examplens
228+
resourceVersion: "1026"
229+
selfLink: /api/v1/namespaces/examplens/serviceaccounts/example-automated-thing
230+
uid: f23fd170-66f2-4697-b049-e1e266b7f835
231+
secrets:
232+
- name: example-automated-thing-token-4rdrh
149233
```
150234

151-
#### To delete/invalidate a ServiceAccount token Secret
235+
You can see that there is now a new associated Secret with a different name. The
236+
old Secret is no longer valid.
152237

238+
## Clean up
239+
240+
If you created a namespace `examplens` to experiment with, you can remove it:
153241
```shell
154-
kubectl delete secret mysecretname
242+
kubectl delete namespace examplens
155243
```
156244

245+
## Control plane details
246+
157247
### ServiceAccount controller
158248

159249
A ServiceAccount controller manages the ServiceAccounts inside namespaces, and
160250
ensures a ServiceAccount named "default" exists in every active namespace.
161251

252+
### Token controller
253+
254+
The service account token controller runs as part of `kube-controller-manager`.
255+
This controller acts asynchronously. It:
256+
257+
- watches for ServiceAccount creation and creates a corresponding
258+
ServiceAccount token Secret to allow API access.
259+
- watches for ServiceAccount deletion and deletes all corresponding ServiceAccount
260+
token Secrets.
261+
- watches for ServiceAccount token Secret addition, and ensures the referenced
262+
ServiceAccount exists, and adds a token to the Secret if needed.
263+
- watches for Secret deletion and removes a reference from the corresponding
264+
ServiceAccount if needed.
265+
266+
You must pass a service account private key file to the token controller in
267+
the `kube-controller-manager` using the `--service-account-private-key-file`
268+
flag. The private key is used to sign generated service account tokens.
269+
Similarly, you must pass the corresponding public key to the `kube-apiserver`
270+
using the `--service-account-key-file` flag. The public key will be used to
271+
verify the tokens during authentication.
272+
273+
## {{% heading "whatsnext" %}}
274+
275+
- Read more details about [projected volumes](/docs/concepts/storage/projected-volumes/).
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: v1
2+
kind: Secret
3+
type: kubernetes.io/service-account-token
4+
metadata:
5+
name: mysecretname
6+
annotations:
7+
- kubernetes.io/service-account.name: myserviceaccount

0 commit comments

Comments
 (0)