diff --git a/docs/accessing-the-cluster.md b/docs/accessing-the-cluster.md
index 58ca2271d52..3497b5d5f1f 100644
--- a/docs/accessing-the-cluster.md
+++ b/docs/accessing-the-cluster.md
@@ -102,10 +102,10 @@ the `kubernetes` DNS name, which resolves to a Service IP which in turn
will be routed to an apiserver.
The recommended way to authenticate to the apiserver is with a
-[service account](../docs/service_accounts.md). By default, a pod
+[service account](service_accounts.md) credential. By default, a pod
is associated with a service account, and a credential (token) for that
service account is placed into the filesystem tree of each container in that pod,
-at `/var/run/secrets/kubernetes.io/serviceaccount`.
+at `/var/run/secrets/kubernetes.io/serviceaccount/token`.
From within a pod the recommended ways to connect to API are:
- run a kubectl proxy as one of the containers in the pod, or as a background
@@ -115,6 +115,7 @@ From within a pod the recommended ways to connect to API are:
in a pod](../examples/kubectl-container/).
- use the Go client library, and create a client using the `client.NewInContainer()` factory.
This handles locating and authenticating to the apiserver.
+In each case, the credentials of the pod are used to communicate securely with the apiserver.
## Accessing services running on the cluster
diff --git a/docs/images.md b/docs/images.md
index aeefb1fc0e8..c1f7e9df03c 100644
--- a/docs/images.md
+++ b/docs/images.md
@@ -68,7 +68,7 @@ This can be used to preload certain images for speed or as an alternative to aut
All pods will have read access to any pre-pulled images.
-### Specifying ImagePullKeys on a Pod
+### Specifying ImagePullSecrets on a Pod
Kubernetes supports specifying registry keys on a pod.
First, create a `.dockercfg`, such as running `docker login `.
diff --git a/docs/secrets.md b/docs/secrets.md
index 6492b1b0a6f..d645e065adf 100644
--- a/docs/secrets.md
+++ b/docs/secrets.md
@@ -5,26 +5,45 @@ passwords, OAuth tokens, and ssh keys. Putting this information in a `secret`
is safer and more flexible than putting it verbatim in a `pod` definition or in
a docker image.
-### Creating and Using Secrets
-To make use of secrets requires at least two steps:
- 1. create a `secret` resource with secret data
- 1. create a pod that has a volume of type `secret` and a container
- which mounts that volume.
+## Overview of Secrets
-This is an example of a simple secret, in json format:
-```json
-{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata" : {
- "name": "mysecret",
- "namespace": "myns"
- },
- "data": {
- "username": "dmFsdWUtMQ0K",
- "password": "dmFsdWUtMg0K"
- }
-}
+
+Creation of secrets can be manual (done by the user) or automatic (done by
+automation built into the cluster).
+
+A secret can be used with a pod in two ways: either as files in a volume mounted on one or more of
+its containers, or used by kubelet when pulling images for the pod.
+
+To use a secret, a pod needs to reference the secret. This reference
+can likewise be added manually or automatically.
+
+A single Pod may use various combination of the above options.
+
+### Service Accounts Automatically Create and Use Secrets with API Credentials
+
+Kubernetes automatically creates secrets which contain credentials for
+accessing the API and it automatically modifies your pods to use this type of
+secret.
+
+The automatic creation and use of API credentials can be disabled or overridden
+if desired. However, if all you need to do is securely access the apiserver,
+this is the recommended workflow.
+
+See the [Service Account](service_accounts.md) documentation for more
+information on how Service Accounts work.
+
+### Creating a Secret Manually
+
+This is an example of a simple secret, in yaml format:
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: mysecret
+type: Opaque
+data:
+ password: dmFsdWUtMg0K
+ username: dmFsdWUtMQ0K
```
The data field is a map. Its keys must match
@@ -33,7 +52,15 @@ allowed. The values are arbitrary data, encoded using base64. The values of
username and password in the example above, before base64 encoding,
are `value-1` and `value-2`, respectively, with carriage return and newline characters at the end.
-This is an example of a pod that uses a secret, in json format:
+Create the secret using [`kubectl create`](kubectl-create.md).
+
+Once the secret is created, you can:
+ - create pods that automatically use it via a [Service Account](service_accounts.md).
+ - modify your pod specification to use the secret
+
+### Manually specifying a Secret to be Mounted on a Pod
+
+This is an example of a pod that mounts a secret in a volume:
```json
{
"apiVersion": "v1",
@@ -62,6 +89,29 @@ This is an example of a pod that uses a secret, in json format:
}
```
+Each secret you want to use needs its own `spec.volumes`.
+
+If there are multiple containers in the pod, then each container needs its
+own `volumeMounts` block, but only one `spec.volumes` is needed per secret.
+
+You can package many files into one secret, or use many secrets,
+whichever is convenient.
+
+### Manually specifying an imagePullSecret
+Use of imagePullSecrets is desribed in the [images documentation](
+images.md#specifying-imagepullsecrets-on-a-pod)
+### Automatic use of Manually Created Secrets
+
+*This feature is planned but not implemented. See [issue
+9902](https://github.com/GoogleCloudPlatform/kubernetes/issues/9902).*
+
+You can reference manually created secrets from a [service account](
+service_accounts.md).
+Then, pods which use that service account will have
+`volumeMounts` and/or `imagePullSecrets` added to them.
+The secrets will be mounted at **TBD**.
+
+## Details
### Restrictions
Secret volume sources are validated to ensure that the specified object
reference actually points to an object of type `Secret`. Therefore, a secret
@@ -106,7 +156,7 @@ versions of Kubernetes are expected to provide more automation for populating
environment variables from files.
-## Secret and Pod Lifetime interaction
+### Secret and Pod Lifetime interaction
When a pod is created via the API, there is no check whether a referenced
secret exists. Once a pod is scheduled, the kubelet will try to fetch the
@@ -327,6 +377,30 @@ Both containers will have the following files present on their filesystems:
Note how the specs for the two pods differ only in one field; this facilitates
creating pods with different capabilities from a common pod config template.
+You could further simplify the base pod specification by using two service accounts:
+one called, say, `prod-user` with the `prod-db-secret`, and one called, say,
+`test-user` with the `test-db-secret`. Then, the pod spec can be shortened to, for example:
+```json
+{
+"kind": "Pod",
+"apiVersion": "v1",
+"metadata": {
+ "name": "prod-db-client-pod",
+ "labels": {
+ "name": "prod-db-client"
+ }
+},
+"spec": {
+ "serviceAccount": "prod-db-client",
+ "containers": [
+ {
+ "name": "db-client-container",
+ "image": "myClientImage",
+ }
+ ]
+}
+```
+
### Use-case: Secret visible to one container in a pod
@@ -344,6 +418,8 @@ With this partitioned approach, an attacker now has to trick the application
server into doing something rather arbitrary, which may be harder than getting
it to read a file.
+
+
## Security Properties
### Protections
diff --git a/docs/service_accounts.md b/docs/service_accounts.md
index 335a2ea2839..bf8555d3c4c 100644
--- a/docs/service_accounts.md
+++ b/docs/service_accounts.md
@@ -1,14 +1,93 @@
# Service Accounts
-A serviceAccount provides an identity for processes that run in a Pod.
-The behavior of the the serviceAccount object is implemented via a plugin
-called an [Admission Controller]( admission_controllers.md). 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```, it modifies the pod's ```ServiceAccount``` to "default".
- 2. It ensures that the ```ServiceAccount``` referenced by a pod exists.
- 3. If ```LimitSecretReferences``` is true, it rejects the pod if the pod references ```Secret``` objects which the pods
-```ServiceAccount``` does not reference.
- 4. If the pod does not contain any ```ImagePullSecrets```, the ```ImagePullSecrets``` of the
-```ServiceAccount``` are added to the pod.
- 5. If ```MountServiceAccountToken``` is true, it adds a ```VolumeMount``` with the pod's ```ServiceAccount``` API token secret to containers in the pod.
+
+A service account provides an identity for processes that run in a Pod.
+
+*This is a user introduction to Service Accounts. See also the
+[Cluster Admin Guide to Service Accounts](service_accounts_admin.md).*
+
+*Note: This document descibes how service accounts behave in a cluster set up
+as recommended by the Kubernetes project. Your cluster administrator may have
+customized the behavior in your cluster, in which case this documentation may
+not apply.*
+
+When you (a human) access the cluster (e.g. using kubectl), you are
+authenticated by the apiserver as a particular User Account (currently this is
+usually "admin", unless your cluster administrator has customized your
+cluster). Processes in containers inside pods can also contact the apiserver.
+When they do, they are authenticated as a particular Service Account (e.g.
+"default").
+
+## Using the Default Service Account to access the API server.
+
+When you create a pod, you do not need to specify a service account. It is
+automatically assigned the `default` service account of the same namespace. If
+you get the raw json or yaml for a pod you have created (e.g. `kubectl get
+pods/podname -o yaml`), you can see the `spec.serviceAccount` field has been
+[automatically set](working_with_resources.md#resources-are-automatically-modified).
+
+You can access the API using a proxy or with a client library, as described in
+[Accessing the Cluster](accessing-the-cluster.md#accessing-the-api-from-a-pod).
+
+## Using Multiple Service Accounts
+
+Every namespace has a default service account resource called "default".
+You can list this and any other serviceAccount resources in the namespace with this command:
+```
+kubectl get serviceAccounts
+$ NAME SECRETS
+default 1
+```
+
+You can create additional serviceAccounts like this:
+```
+$ cat > serviceaccount.yaml <
+
+## Adding Secrets to a service account.
+TODO: Test and explain how to use additional non-K8s secrets with an existing service account.
+
+TODO explain:
+ - The token goes to: "/var/run/secrets/kubernetes.io/serviceaccount/$WHATFILENAME"
+
[]()
diff --git a/docs/service_accounts_admin.md b/docs/service_accounts_admin.md
new file mode 100644
index 00000000000..f371e2e90af
--- /dev/null
+++ b/docs/service_accounts_admin.md
@@ -0,0 +1,84 @@
+# Cluster Admin Guide to Service Accounts
+
+*This is a Cluster Administrator guide to service accounts. It assumes knowledge of
+the [User Guide to Service Accounts](service_accounts.md).*
+
+*Support for authorization and user accounts is planned but incomplete. Sometimes
+incomplete features are referred to in order to better describe service accounts.*
+
+## User accounts vs service accounts
+
+Kubernetes distinguished between the concept of a user account and a service accounts
+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 clusters 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](admission_controllers.md). 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`.
+ 2. It ensures that the `ServiceAccount` referenced by the pod exists, and otherwise rejects it.
+ 4. If the pod does not contain any `ImagePullSecrets`, then `ImagePullSecrets` of the
+`ServiceAccount` are added to the pod.
+ 5. It adds a `volume` to the pod which contains a token for API access.
+ 6. It adds a `volumeSource` to each container of the pod mounted at `/var/run/secrets/kubernetes.io/serviceaccount`.
+
+### 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
+- observer secret deleteion and removes a reference from the corresponding ServiceAccount if needed
+
+#### 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:
+{
+ "kind": "Secret",
+ "metadata": {
+ "name": "mysecretname",
+ "annotations": {
+ "kubernetes.io/service-account.name": "myserviceaccount"
+ }
+ }
+ "type": "kubernetes.io/service-account-token"
+}
+
+$ kubectl create -f secret.json
+$ kubectl describe secret mysecretname
+```
+
+#### To delete/invalidate a service account token:
+```
+kubectl delete secret mysecretname
+```
+
+[]()