mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-30 21:30:16 +00:00 
			
		
		
		
	Secrets proposal
This commit is contained in:
		
							
								
								
									
										547
									
								
								docs/design/secrets.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										547
									
								
								docs/design/secrets.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,547 @@ | |||||||
|  | # Secret Distribution | ||||||
|  |  | ||||||
|  | ## Abstract | ||||||
|  |  | ||||||
|  | A proposal for the distribution of secrets (passwords, keys, etc) to the Kubelet and to | ||||||
|  | containers inside Kubernetes using a custom volume type. | ||||||
|  |  | ||||||
|  | ## Motivation | ||||||
|  |  | ||||||
|  | Secrets are needed in containers to access internal resources like the Kubernetes master or | ||||||
|  | external resources such as git repositories, databases, etc.  Users may also want behaviors in the | ||||||
|  | kubelet that depend on secret data (credentials for image pull from a docker registry) associated | ||||||
|  | with pods. | ||||||
|  |  | ||||||
|  | Goals of this design: | ||||||
|  |  | ||||||
|  | 1.  Describe a secret resource | ||||||
|  | 2.  Define the various challenges attendant to managing secrets on the node | ||||||
|  | 3.  Define a mechanism for consuming secrets in containers without modification | ||||||
|  |  | ||||||
|  | ## Constraints and Assumptions | ||||||
|  |  | ||||||
|  | *  This design does not prescribe a method for storing secrets; storage of secrets should be | ||||||
|  |    pluggable to accomodate different use-cases | ||||||
|  | *  Encryption of secret data and node security are orthogonal concerns | ||||||
|  | *  It is assumed that node and master are secure and that compromising their security could also | ||||||
|  |    compromise secrets: | ||||||
|  |    *  If a node is compromised, the only secrets that could potentially be exposed should be the | ||||||
|  |       secrets belonging to containers scheduled onto it | ||||||
|  |    *  If the master is compromised, all secrets in the cluster may be exposed | ||||||
|  | *  Secret rotation is an orthogonal concern, but it should be facilitated by this proposal | ||||||
|  |  | ||||||
|  | ## Use Cases | ||||||
|  |  | ||||||
|  | 1.  As a user, I want to store secret artifacts for my applications and consume them securely in | ||||||
|  |     containers, so that I can keep the configuration for my applications separate from the images | ||||||
|  |     that use them: | ||||||
|  |     1.  As a cluster operator, I want to allow a pod to access the Kubernetes master using a custom | ||||||
|  |         `.kubeconfig` file, so that I can securely reach the master | ||||||
|  |     2.  As a cluster operator, I want to allow a pod to access a Docker registry using credentials | ||||||
|  |         from a `.dockercfg` file, so that containers can push images | ||||||
|  |     3.  As a cluster operator, I want to allow a pod to access a git repository using SSH keys, | ||||||
|  |         so that I can push and fetch to and from the repository | ||||||
|  | 2.  As a user, I want to allow containers to consume supplemental information about services such | ||||||
|  |     as username and password which should be kept secret, so that I can share secrets about a | ||||||
|  |     service amongst the containers in my application securely | ||||||
|  | 3.  As a user, I want to associate a pod with a `ServiceAccount` that consumes a secret and have | ||||||
|  |     the kubelet implement some reserved behaviors based on the types of secrets the service account | ||||||
|  |     consumes: | ||||||
|  |     1.  Use credentials for a docker registry to pull the pod's docker image | ||||||
|  |     2.  Present kubernetes auth token to the pod or transparently decorate traffic between the pod | ||||||
|  |         and master service | ||||||
|  | 4.  As a user, I want to be able to indicate that a secret expires and for that secret's value to | ||||||
|  |     be rotated once it expires, so that the system can help me follow good practices | ||||||
|  |  | ||||||
|  | ### Use-Case: Configuration artifacts | ||||||
|  |  | ||||||
|  | Many configuration files contain secrets intermixed with other configuration information.  For | ||||||
|  | example, a user's application may contain a properties file than contains database credentials, | ||||||
|  | SaaS API tokens, etc.  Users should be able to consume configuration artifacts in their containers | ||||||
|  | and be able to control the path on the container's filesystems where the artifact will be | ||||||
|  | presented. | ||||||
|  |  | ||||||
|  | ### Use-Case: Metadata about services | ||||||
|  |  | ||||||
|  | Most pieces of information about how to use a service are secrets.  For example, a service that | ||||||
|  | provides a MySQL database needs to provide the username, password, and database name to consumers | ||||||
|  | so that they can authenticate and use the correct database. Containers in pods consuming the MySQL | ||||||
|  | service would also consume the secrets associated with the MySQL service. | ||||||
|  |  | ||||||
|  | ### Use-Case: Secrets associated with service accounts | ||||||
|  |  | ||||||
|  | [Service Accounts](https://github.com/GoogleCloudPlatform/kubernetes/pull/2297) are proposed as a | ||||||
|  | mechanism to decouple capabilities and security contexts from individual human users.  A | ||||||
|  | `ServiceAccount` contains references to some number of secrets.  A `Pod` can specify that it is | ||||||
|  | associated with a `ServiceAccount`.  Secrets should have a `Type` field to allow the Kubelet and | ||||||
|  | other system components to take action based on the secret's type. | ||||||
|  |  | ||||||
|  | #### Example: service account consumes auth token secret | ||||||
|  |  | ||||||
|  | As an example, the service account proposal discusses service accounts consuming secrets which | ||||||
|  | contain kubernetes auth tokens.  When a Kubelet starts a pod associated with a service account | ||||||
|  | which consumes this type of secret, the Kubelet may take a number of actions: | ||||||
|  |  | ||||||
|  | 1.  Expose the secret in a `.kubernetes_auth` file in a well-known location in the container's | ||||||
|  |     file system | ||||||
|  | 2.  Configure that node's `kube-proxy` to decorate HTTP requests from that pod to the  | ||||||
|  |     `kubernetes-master` service with the auth token, e. g. by adding a header to the request | ||||||
|  |     (see the [LOAS Daemon](https://github.com/GoogleCloudPlatform/kubernetes/issues/2209) proposal) | ||||||
|  |  | ||||||
|  | #### Example: service account consumes docker registry credentials | ||||||
|  |  | ||||||
|  | Another example use case is where a pod is associated with a secret containing docker registry | ||||||
|  | credentials.  The Kubelet could use these credentials for the docker pull to retrieve the image. | ||||||
|  |  | ||||||
|  | ### Use-Case: Secret expiry and rotation | ||||||
|  |  | ||||||
|  | Rotation is considered a good practice for many types of secret data.  It should be possible to | ||||||
|  | express that a secret has an expiry date; this would make it possible to implement a system | ||||||
|  | component that could regenerate expired secrets.  As an example, consider a component that rotates | ||||||
|  | expired secrets.  The rotator could periodically regenerate the values for expired secrets of | ||||||
|  | common types and update their expiry dates. | ||||||
|  |  | ||||||
|  | ## Deferral: Consuming secrets as environment variables | ||||||
|  |  | ||||||
|  | Some images will expect to receive configuration items as environment variables instead of files. | ||||||
|  | We should consider what the best way to allow this is; there are a few different options: | ||||||
|  |  | ||||||
|  | 1.  Force the user to adapt files into environment variables.  Users can store secrets that need to | ||||||
|  |     be presented as environment variables in a format that is easy to consume from a shell: | ||||||
|  |  | ||||||
|  |         $ cat /etc/secrets/my-secret.txt | ||||||
|  |         export MY_SECRET_ENV=MY_SECRET_VALUE | ||||||
|  |  | ||||||
|  |     The user could `source` the file at `/etc/secrets/my-secret` prior to executing the command for | ||||||
|  |     the image either inline in the command or in an init script,  | ||||||
|  |  | ||||||
|  | 2.  Give secrets an attribute that allows users to express the intent that the platform should | ||||||
|  |     generate the above syntax in the file used to present a secret.  The user could consume these | ||||||
|  |     files in the same manner as the above option. | ||||||
|  |  | ||||||
|  | 3.  Give secrets attributes that allow the user to express that the secret should be presented to | ||||||
|  |     the container as an environment variable.  The container's environment would contain the | ||||||
|  |     desired values and the software in the container could use them without accomodation the | ||||||
|  |     command or setup script. | ||||||
|  |  | ||||||
|  | For our initial work, we will treat all secrets as files to narrow the problem space.  There will | ||||||
|  | be a future proposal that handles exposing secrets as environment variables. | ||||||
|  |  | ||||||
|  | ## Flow analysis of secret data with respect to the API server | ||||||
|  |  | ||||||
|  | There are two fundamentally different use-cases for access to secrets: | ||||||
|  |  | ||||||
|  | 1.  CRUD operations on secrets by their owners | ||||||
|  | 2.  Read-only access to the secrets needed for a particular node by the kubelet | ||||||
|  |  | ||||||
|  | ### Use-Case: CRUD operations by owners | ||||||
|  |  | ||||||
|  | In use cases for CRUD operations, the user experience for secrets should be no different than for | ||||||
|  | other API resources. | ||||||
|  |  | ||||||
|  | #### Data store backing the REST API | ||||||
|  |  | ||||||
|  | The data store backing the REST API should be pluggable because different cluster operators will | ||||||
|  | have different preferences for the central store of secret data.  Some possibilities for storage: | ||||||
|  |  | ||||||
|  | 1.  An etcd collection alongside the storage for other API resources | ||||||
|  | 2.  A collocated [HSM](http://en.wikipedia.org/wiki/Hardware_security_module) | ||||||
|  | 3.  An external datastore such as an external etcd, RDBMS, etc. | ||||||
|  |  | ||||||
|  | #### Size limit for secrets | ||||||
|  |  | ||||||
|  | There should be a size limit for secrets in order to: | ||||||
|  |  | ||||||
|  | 1.  Prevent DOS attacks against the API server | ||||||
|  | 2.  Allow kubelet implementations that prevent secret data from touching the node's filesystem | ||||||
|  |  | ||||||
|  | The size limit should satisfy the following conditions: | ||||||
|  |  | ||||||
|  | 1.  Large enough to store common artifact types (encryption keypairs, certificates, small | ||||||
|  |     configuration files) | ||||||
|  | 2.  Small enough to avoid large impact on node resource consumption (storage, RAM for tmpfs, etc) | ||||||
|  |  | ||||||
|  | To begin discussion, we propose an initial value for this size limit of **1MB**. | ||||||
|  |  | ||||||
|  | #### Other limitations on secrets | ||||||
|  |  | ||||||
|  | Defining a policy for limitations on how a secret may be referenced by another API resource and how | ||||||
|  | constraints should be applied throughout the cluster is tricky due to the number of variables | ||||||
|  | involved: | ||||||
|  |  | ||||||
|  | 1.  Should there be a maximum number of secrets a pod can reference via a volume? | ||||||
|  | 2.  Should there be a maximum number of secrets a service account can reference? | ||||||
|  | 3.  Should there be a total maximum number of secrets a pod can reference via its own spec and its | ||||||
|  |     associated service account? | ||||||
|  | 4.  Should there be a total size limit on the amount of secret data consumed by a pod? | ||||||
|  | 5.  How will cluster operators want to be able to configure these limits? | ||||||
|  | 6.  How will these limits impact API server validations? | ||||||
|  | 7.  How will these limits affect scheduling? | ||||||
|  |  | ||||||
|  | For now, we will not implement validations around these limits.  Cluster operators will decide how | ||||||
|  | much node storage is allocated to secrets. It will be the operator's responsibility to ensure that | ||||||
|  | the allocated storage is sufficient for the workload scheduled onto a node. | ||||||
|  |  | ||||||
|  | ### Use-Case: Kubelet read of secrets for node | ||||||
|  |  | ||||||
|  | The use-case where the kubelet reads secrets has several additional requirements: | ||||||
|  |  | ||||||
|  | 1.  Kubelets should only be able to receive secret data which is required by pods scheduled onto | ||||||
|  |     the kubelet's node | ||||||
|  | 2.  Kubelets should have read-only access to secret data | ||||||
|  | 3.  Secret data should not be transmitted over the wire insecurely | ||||||
|  | 4.  Kubelets must ensure pods do not have access to each other's secrets | ||||||
|  |  | ||||||
|  | #### Read of secret data by the Kubelet | ||||||
|  |  | ||||||
|  | The Kubelet should only be allowed to read secrets which are consumed by pods scheduled onto that | ||||||
|  | Kubelet's node and their associated service accounts.  Authorization of the Kubelet to read this | ||||||
|  | data would be delegated to an authorization plugin and associated policy rule. | ||||||
|  |  | ||||||
|  | #### Secret data on the node: data at rest | ||||||
|  |  | ||||||
|  | Consideration must be given to whether secret data should be allowed to be at rest on the node: | ||||||
|  |  | ||||||
|  | 1.  If secret data is not allowed to be at rest, the size of secret data becomes another draw on | ||||||
|  |     the node's RAM - should it affect scheduling? | ||||||
|  | 2.  If secret data is allowed to be at rest, should it be encrypted? | ||||||
|  |     1.  If so, how should be this be done? | ||||||
|  |     2.  If not, what threats exist?  What types of secret are appropriate to store this way? | ||||||
|  |  | ||||||
|  | For the sake of limiting complexity, we propose that initially secret data should not be allowed | ||||||
|  | to be at rest on a node; secret data should be stored on a node-level tmpfs filesystem.  This | ||||||
|  | filesystem can be subdivided into directories for use by the kubelet and by the volume plugin. | ||||||
|  |  | ||||||
|  | #### Secret data on the node: resource consumption | ||||||
|  |  | ||||||
|  | The Kubelet will be responsible for creating the per-node tmpfs file system for secret storage. | ||||||
|  | It is hard to make a prescriptive declaration about how much storage is appropriate to reserve for | ||||||
|  | secrets because different installations will vary widely in available resources, desired pod to | ||||||
|  | node density, overcommit policy, and other operation dimensions.  That being the case, we propose | ||||||
|  | for simplicity that the amount of secret storage be controlled by a new parameter to the kubelet | ||||||
|  | with a default value of **64MB**.  It is the cluster operator's responsibility to handle choosing | ||||||
|  | the right storage size for their installation and configuring their Kubelets correctly. | ||||||
|  |  | ||||||
|  | Configuring each Kubelet is not the ideal story for operator experience; it is more intuitive that | ||||||
|  | the cluster-wide storage size be readable from a central configuration store like the one proposed | ||||||
|  | in [#1553](https://github.com/GoogleCloudPlatform/kubernetes/issues/1553).  When such a store | ||||||
|  | exists, the Kubelet could be modified to read this configuration item from the store. | ||||||
|  |  | ||||||
|  | When the Kubelet is modified to advertise node resources (as proposed in | ||||||
|  | [#4441](https://github.com/GoogleCloudPlatform/kubernetes/issues/4441)), the capacity calculation | ||||||
|  | for available memory should factor in the potential size of the node-level tmpfs in order to avoid | ||||||
|  | memory overcommit on the node. | ||||||
|  |  | ||||||
|  | #### Secret data on the node: isolation | ||||||
|  |  | ||||||
|  | Every pod will have a [security context](https://github.com/GoogleCloudPlatform/kubernetes/pull/3910). | ||||||
|  | Secret data on the node should be isolated according to the security context of the container.  The | ||||||
|  | Kubelet volume plugin API will be changed so that a volume plugin receives the security context of | ||||||
|  | a volume along with the volume spec.  This will allow volume plugins to implement setting the | ||||||
|  | security context of volumes they manage. | ||||||
|  |  | ||||||
|  | ## Community work: | ||||||
|  |  | ||||||
|  | Several proposals / upstream patches are notable as background for this proposal: | ||||||
|  |  | ||||||
|  | 1.  [Docker vault proposal](https://github.com/docker/docker/issues/10310) | ||||||
|  | 2.  [Specification for image/container standardization based on volumes](https://github.com/docker/docker/issues/9277) | ||||||
|  | 3.  [Kubernetes service account proposal](https://github.com/GoogleCloudPlatform/kubernetes/pull/2297) | ||||||
|  | 4.  [Secrets proposal for docker (1)](https://github.com/docker/docker/pull/6075) | ||||||
|  | 5.  [Secrets proposal for docker (2)](https://github.com/docker/docker/pull/6697) | ||||||
|  |  | ||||||
|  | ## Proposed Design | ||||||
|  |  | ||||||
|  | We propose a new `Secret` resource which is mounted into containers with a new volume type. Secret | ||||||
|  | volumes will be handled by a volume plugin that does the actual work of fetching the secret and | ||||||
|  | storing it. Secrets contain multiple pieces of data that are presented as different files within | ||||||
|  | the secret volume (example: SSH key pair). | ||||||
|  |  | ||||||
|  | In order to remove the burden from the end user in specifying every file that a secret consists of, | ||||||
|  | it should be possible to mount all files provided by a secret with a single ```VolumeMount``` entry | ||||||
|  | in the container specification. | ||||||
|  |  | ||||||
|  | ### Secret API Resource | ||||||
|  |  | ||||||
|  | A new resource for secrets will be added to the API: | ||||||
|  |  | ||||||
|  | ```go | ||||||
|  | type Secret struct { | ||||||
|  |     TypeMeta | ||||||
|  |     ObjectMeta | ||||||
|  |  | ||||||
|  |     // Keys in this map are the paths relative to the volume | ||||||
|  |     // presented to a container for this secret data. | ||||||
|  |     Data map[string][]byte | ||||||
|  |     Type SecretType | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type SecretType string | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  |     SecretTypeOpaque              SecretType = "opaque"           // Opaque (arbitrary data; default) | ||||||
|  |     SecretTypeKubernetesAuthToken SecretType = "kubernetes-auth"  // Kubernetes auth token | ||||||
|  |     SecretTypeDockerRegistryAuth  SecretType = "docker-reg-auth"  // Docker registry auth | ||||||
|  |     // FUTURE: other type values | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const MaxSecretSize = 1 * 1024 * 1024 | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | A Secret can declare a type in order to provide type information to system components that work | ||||||
|  | with secrets.  The default type is `opaque`, which represents arbitrary user-owned data. | ||||||
|  |  | ||||||
|  | Secrets are validated against `MaxSecretSize`. | ||||||
|  |  | ||||||
|  | A new REST API and registry interface will be added to accompany the `Secret` resource.  The | ||||||
|  | default implementation of the registry will store `Secret` information in etcd.  Future registry | ||||||
|  | implementations could store the `TypeMeta` and `ObjectMeta` fields in etcd and store the secret | ||||||
|  | data in another data store entirely, or store the whole object in another data store. | ||||||
|  |  | ||||||
|  | #### Other validations related to secrets | ||||||
|  |  | ||||||
|  | Initially there will be no validations for the number of secrets a pod references, or the number of | ||||||
|  | secrets that can be associated with a service account.  These may be added in the future as the | ||||||
|  | finer points of secrets and resource allocation are fleshed out. | ||||||
|  |  | ||||||
|  | ### Secret Volume Source | ||||||
|  |  | ||||||
|  | A new `SecretSource` type of volume source will be added to the ```VolumeSource``` struct in the | ||||||
|  | API: | ||||||
|  |  | ||||||
|  | ```go | ||||||
|  | type VolumeSource struct { | ||||||
|  |     // Other fields omitted | ||||||
|  |  | ||||||
|  |     // SecretSource represents a secret that should be presented in a volume | ||||||
|  |     SecretSource *SecretSource `json:"secret"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type SecretSource struct { | ||||||
|  |     Target ObjectReference | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Secret volume sources are validated to ensure that the specified object reference actually points | ||||||
|  | to an object of type `Secret`. | ||||||
|  |  | ||||||
|  | ### Secret Volume Plugin | ||||||
|  |  | ||||||
|  | A new Kubelet volume plugin will be added to handle volumes with a secret source.  This plugin will | ||||||
|  | require access to the API server to retrieve secret data and therefore the volume `Host` interface | ||||||
|  | will have to change to expose a client interface: | ||||||
|  |  | ||||||
|  | ```go | ||||||
|  | type Host interface { | ||||||
|  |     // Other methods omitted | ||||||
|  |  | ||||||
|  |     // GetKubeClient returns a client interface | ||||||
|  |     GetKubeClient() client.Interface | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | The secret volume plugin will be responsible for: | ||||||
|  |  | ||||||
|  | 1.  Returning a `volume.Builder` implementation from `NewBuilder` that: | ||||||
|  |     1.  Retrieves the secret data for the volume from the API server | ||||||
|  |     2.  Places the secret data onto the container's filesystem | ||||||
|  |     3.  Sets the correct security attributes for the volume based on the pod's `SecurityContext` | ||||||
|  | 2.  Returning a `volume.Cleaner` implementation from `NewClear` that cleans the volume from the | ||||||
|  |     container's filesystem | ||||||
|  |  | ||||||
|  | ### Kubelet: Node-level secret storage | ||||||
|  |  | ||||||
|  | The Kubelet must be modified to accept a new parameter for the secret storage size and to create | ||||||
|  | a tmpfs file system of that size to store secret data.  Rough accounting of specific changes: | ||||||
|  |  | ||||||
|  | 1.  The Kubelet should have a new field added called `secretStorageSize`; units are megabytes | ||||||
|  | 2.  `NewMainKubelet` should accept a value for secret storage size | ||||||
|  | 3.  The Kubelet server should have a new flag added for secret storage size | ||||||
|  | 4.  The Kubelet's `setupDataDirs` method should be changed to create the secret storage | ||||||
|  |  | ||||||
|  | ### Kubelet: New behaviors for secrets associated with service accounts | ||||||
|  |  | ||||||
|  | For use-cases where the Kubelet's behavior is affected by the secrets associated with a pod's | ||||||
|  | `ServiceAccount`, the Kubelet will need to be changed.  For example, if secrets of type | ||||||
|  | `docker-reg-auth` affect how the pod's images are pulled, the Kubelet will need to be changed | ||||||
|  | to accomodate this.  Subsequent proposals can address this on a type-by-type basis. | ||||||
|  |  | ||||||
|  | ## Examples | ||||||
|  |  | ||||||
|  | For clarity, let's examine some detailed examples of some common use-cases in terms of the | ||||||
|  | suggested changes.  All of these examples are assumed to be created in a namespace called | ||||||
|  | `example`. | ||||||
|  |  | ||||||
|  | ### Use-Case: Pod with ssh keys | ||||||
|  |  | ||||||
|  | To create a pod that uses an ssh key stored as a secret, we first need to create a secret: | ||||||
|  |  | ||||||
|  | ```json | ||||||
|  | { | ||||||
|  |   "apiVersion": "v1beta2", | ||||||
|  |   "kind": "Secret", | ||||||
|  |   "id": "ssh-key-secret", | ||||||
|  |   "data": { | ||||||
|  |     "id_rsa.pub": "dmFsdWUtMQ0K", | ||||||
|  |     "id_rsa": "dmFsdWUtMg0KDQo=" | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | **Note:** The values of secret data are encoded as base64-encoded strings. | ||||||
|  |  | ||||||
|  | Now we can create a pod which references the secret with the ssh key and consumes it in a volume: | ||||||
|  |  | ||||||
|  | ```json | ||||||
|  | { | ||||||
|  |   "id": "secret-test-pod", | ||||||
|  |   "kind": "Pod", | ||||||
|  |   "apiVersion":"v1beta2", | ||||||
|  |   "labels": { | ||||||
|  |     "name": "secret-test" | ||||||
|  |   }, | ||||||
|  |   "desiredState": { | ||||||
|  |     "manifest": { | ||||||
|  |       "version": "v1beta1", | ||||||
|  |       "id": "secret-test-pod", | ||||||
|  |       "containers": [{ | ||||||
|  |         "name": "ssh-test-container", | ||||||
|  |         "image": "mySshImage", | ||||||
|  |         "volumeMounts": [{ | ||||||
|  |           "name": "secret-volume", | ||||||
|  |           "mountPath": "/etc/secret-volume", | ||||||
|  |           "readOnly": true | ||||||
|  |         }] | ||||||
|  |       }], | ||||||
|  |       "volumes": [{ | ||||||
|  |         "name": "secret-volume", | ||||||
|  |         "source": { | ||||||
|  |           "secret": { | ||||||
|  |             "target": { | ||||||
|  |               "kind": "Secret", | ||||||
|  |               "namespace": "example", | ||||||
|  |               "name": "ssh-key-secret" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | When the container's command runs, the pieces of the key will be available in: | ||||||
|  |  | ||||||
|  |     /etc/secret-volume/id_rsa.pub | ||||||
|  |     /etc/secret-volume/id_rsa | ||||||
|  |  | ||||||
|  | The container is then free to use the secret data to establish an ssh connection. | ||||||
|  |  | ||||||
|  | ### Use-Case: Pods with pod / test credentials | ||||||
|  |  | ||||||
|  | Let's compare examples where a pod consumes a secret containing prod credentials and another pod | ||||||
|  | consumes a secret with test environment credentials. | ||||||
|  |  | ||||||
|  | The secrets: | ||||||
|  |  | ||||||
|  | ```json | ||||||
|  | [{ | ||||||
|  |   "apiVersion": "v1beta2", | ||||||
|  |   "kind": "Secret", | ||||||
|  |   "id": "prod-db-secret", | ||||||
|  |   "data": { | ||||||
|  |     "username": "dmFsdWUtMQ0K", | ||||||
|  |     "password": "dmFsdWUtMg0KDQo=" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "apiVersion": "v1beta2", | ||||||
|  |   "kind": "Secret", | ||||||
|  |   "id": "test-db-secret", | ||||||
|  |   "data": { | ||||||
|  |     "username": "dmFsdWUtMQ0K", | ||||||
|  |     "password": "dmFsdWUtMg0KDQo=" | ||||||
|  |   } | ||||||
|  | }] | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | The pods: | ||||||
|  |  | ||||||
|  | ```json | ||||||
|  | [{ | ||||||
|  |   "id": "prod-db-client-pod", | ||||||
|  |   "kind": "Pod", | ||||||
|  |   "apiVersion":"v1beta2", | ||||||
|  |   "labels": { | ||||||
|  |     "name": "prod-db-client" | ||||||
|  |   }, | ||||||
|  |   "desiredState": { | ||||||
|  |     "manifest": { | ||||||
|  |       "version": "v1beta1", | ||||||
|  |       "id": "prod-db-pod", | ||||||
|  |       "containers": [{ | ||||||
|  |         "name": "db-client-container", | ||||||
|  |         "image": "myClientImage", | ||||||
|  |         "volumeMounts": [{ | ||||||
|  |           "name": "secret-volume", | ||||||
|  |           "mountPath": "/etc/secret-volume", | ||||||
|  |           "readOnly": true | ||||||
|  |         }] | ||||||
|  |       }], | ||||||
|  |       "volumes": [{ | ||||||
|  |         "name": "secret-volume", | ||||||
|  |         "source": { | ||||||
|  |           "secret": { | ||||||
|  |             "target": { | ||||||
|  |               "kind": "Secret", | ||||||
|  |               "namespace": "example", | ||||||
|  |               "name": "prod-db-secret" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "id": "test-db-client-pod", | ||||||
|  |   "kind": "Pod", | ||||||
|  |   "apiVersion":"v1beta2", | ||||||
|  |   "labels": { | ||||||
|  |     "name": "test-db-client" | ||||||
|  |   }, | ||||||
|  |   "desiredState": { | ||||||
|  |     "manifest": { | ||||||
|  |       "version": "v1beta1", | ||||||
|  |       "id": "test-db-pod", | ||||||
|  |       "containers": [{ | ||||||
|  |         "name": "db-client-container", | ||||||
|  |         "image": "myClientImage", | ||||||
|  |         "volumeMounts": [{ | ||||||
|  |           "name": "secret-volume", | ||||||
|  |           "mountPath": "/etc/secret-volume", | ||||||
|  |           "readOnly": true | ||||||
|  |         }] | ||||||
|  |       }], | ||||||
|  |       "volumes": [{ | ||||||
|  |         "name": "secret-volume", | ||||||
|  |         "source": { | ||||||
|  |           "secret": { | ||||||
|  |             "target": { | ||||||
|  |               "kind": "Secret", | ||||||
|  |               "namespace": "example", | ||||||
|  |               "name": "test-db-secret" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }] | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | The specs for the two pods differ only in the value of the object referred to by the secret volume | ||||||
|  | source.  Both containers will have the following files present on their filesystems: | ||||||
|  |  | ||||||
|  |     /etc/secret-volume/username | ||||||
|  |     /etc/secret-volume/password | ||||||
		Reference in New Issue
	
	Block a user