@@ -11,14 +11,30 @@ weight: 50
11
11
12
12
<!-- overview -->
13
13
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.
16
15
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.
19
23
20
24
<!-- body -->
21
25
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
+
22
38
## User accounts versus service accounts
23
39
24
40
Kubernetes distinguishes between the concept of a user account and a service account
@@ -27,7 +43,7 @@ for a number of reasons:
27
43
- User accounts are for humans. Service accounts are for processes, which run
28
44
in pods.
29
45
- 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.
31
47
- Typically, a cluster's user accounts might be synced from a corporate
32
48
database, where new user account creation requires special privileges and is
33
49
tied to complex business processes. Service account creation is intended to be
@@ -38,124 +54,222 @@ for a number of reasons:
38
54
accounts for components of that system. Because service accounts can be created
39
55
without many constraints and have namespaced names, such config is portable.
40
56
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
50
58
51
59
The modification of pods is implemented via a plugin
52
60
called an [ Admission Controller] ( /docs/reference/access-authn-authz/admission-controllers/ ) .
53
61
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}
69
85
70
86
{{< feature-state for_k8s_version="v1.22" state="stable" >}}
71
87
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:
74
96
75
97
``` 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
94
117
` ` `
95
118
96
- This projected volume consists of three sources:
119
+ That manifest snippet defines a projected volume that combines information from three sources:
97
120
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.
103
130
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 .
105
132
106
- # ## Token Controller
133
+ # # Create additional API tokens {#create-token}
107
134
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.
109
140
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 :
118
142
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" >}}
125
144
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
+ ` ` `
127
149
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}
133
177
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 :
135
179
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 :
136
191
` ` ` yaml
137
192
apiVersion: v1
138
- kind: Secret
193
+ kind: ServiceAccount
139
194
metadata:
140
- name: mysecretname
141
195
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
144
210
` ` `
145
211
212
+ The control plane spots that the ServiceAccount is missing its Secret,
213
+ and creates a replacement :
214
+
146
215
` ` ` 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
149
233
` ` `
150
234
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.
152
237
238
+ # # Clean up
239
+
240
+ If you created a namespace `examplens` to experiment with, you can remove it :
153
241
` ` ` shell
154
- kubectl delete secret mysecretname
242
+ kubectl delete namespace examplens
155
243
` ` `
156
244
245
+ # # Control plane details
246
+
157
247
# ## ServiceAccount controller
158
248
159
249
A ServiceAccount controller manages the ServiceAccounts inside namespaces, and
160
250
ensures a ServiceAccount named "default" exists in every active namespace.
161
251
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/).
0 commit comments