Providing sensitive data to pods
Some applications need sensitive information, such as passwords and user names, that you do not want developers to have.
As an administrator, you can use Secret
objects to provide this information without exposing that information in clear text.
Understanding secrets
The Secret
object type provides a mechanism to hold sensitive information such as passwords, OKD client configuration files, private source repository credentials, and so on. Secrets decouple sensitive content from the pods. You can mount secrets into containers using a volume plug-in or the system can use secrets to perform actions on behalf of a pod.
Key properties include:
Secret data can be referenced independently from its definition.
Secret data volumes are backed by temporary file-storage facilities (tmpfs) and never come to rest on a node.
Secret data can be shared within a namespace.
YAML Secret
object definition
apiVersion: v1
kind: Secret
metadata:
name: test-secret
namespace: my-namespace
type: Opaque (1)
data: (2)
username: dmFsdWUtMQ0K (3)
password: dmFsdWUtMg0KDQo=
stringData: (4)
hostname: myapp.mydomain.com (5)
1 | Indicates the structure of the secret’s key names and values. |
2 | The allowable format for the keys in the data field must meet the guidelines in the DNS_SUBDOMAIN value in the Kubernetes identifiers glossary. |
3 | The value associated with keys in the data map must be base64 encoded. |
4 | Entries in the stringData map are converted to base64 and the entry will then be moved to the data map automatically. This field is write-only; the value will only be returned via the data field. |
5 | The value associated with keys in the stringData map is made up of plain text strings. |
You must create a secret before creating the pods that depend on that secret.
When creating secrets:
Create a secret object with secret data.
Update the pod’s service account to allow the reference to the secret.
Create a pod, which consumes the secret as an environment variable or as a file (using a
secret
volume).
Types of secrets
The value in the type
field indicates the structure of the secret’s key names and values. The type can be used to enforce the presence of user names and keys in the secret object. If you do not want validation, use the opaque
type, which is the default.
Specify one of the following types to trigger minimal server-side validation to ensure the presence of specific key names in the secret data:
kubernetes.io/service-account-token
. Uses a service account token.kubernetes.io/basic-auth
. Use with Basic Authentication.kubernetes.io/ssh-auth
. Use with SSH Key Authentication.kubernetes.io/tls
. Use with TLS certificate authorities.
Specify type: Opaque
if you do not want validation, which means the secret does not claim to conform to any convention for key names or values. An opaque secret, allows for unstructured key:value
pairs that can contain arbitrary values.
You can specify other arbitrary types, such as |
For examples of different secret types, see the code samples in Using Secrets.
Example secret configurations
The following are sample secret configuration files.
YAML Secret
object that creates four files
apiVersion: v1
kind: Secret
metadata:
name: test-secret
data:
username: dmFsdWUtMQ0K (1)
password: dmFsdWUtMQ0KDQo= (2)
stringData:
hostname: myapp.mydomain.com (3)
secret.properties: |- (4)
property1=valueA
property2=valueB
1 | File contains decoded values. |
2 | File contains decoded values. |
3 | File contains the provided string. |
4 | File contains the provided data. |
YAML of a pod populating files in a volume with secret data
apiVersion: v1
kind: Pod
metadata:
name: secret-example-pod
spec:
containers:
- name: secret-test-container
image: busybox
command: [ "/bin/sh", "-c", "cat /etc/secret-volume/*" ]
volumeMounts:
# name must match the volume name below
- name: secret-volume
mountPath: /etc/secret-volume
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: test-secret
restartPolicy: Never
YAML of a pod populating environment variables with secret data
apiVersion: v1
kind: Pod
metadata:
name: secret-example-pod
spec:
containers:
- name: secret-test-container
image: busybox
command: [ "/bin/sh", "-c", "export" ]
env:
- name: TEST_SECRET_USERNAME_ENV_VAR
valueFrom:
secretKeyRef:
name: test-secret
key: username
restartPolicy: Never
YAML of a build config populating environment variables with secret data
apiVersion: v1
kind: BuildConfig
metadata:
name: secret-example-bc
spec:
strategy:
sourceStrategy:
env:
- name: TEST_SECRET_USERNAME_ENV_VAR
valueFrom:
secretKeyRef:
name: test-secret
key: username
Secret data keys
Secret keys must be in a DNS subdomain.
Understanding how to create secrets
As an administrator you must create a secret before developers can create the pods that depend on that secret.
When creating secrets:
Create a secret object with secret data.
Update the pod’s service account to allow the reference to the secret.
Create a pod, which consumes the secret as an environment variable or as a file (using a
secret
volume).
Secret creation restrictions
To use a secret, a pod needs to reference the secret. A secret can be used with a pod in three ways:
To populate environment variables for containers.
As files in a volume mounted on one or more of its containers.
By kubelet when pulling images for the pod.
Volume type secrets write data into the container as a file using the volume mechanism. Image pull secrets use service accounts for the automatic injection of the secret into all pods in a namespace.
When a template contains a secret definition, the only way for the template to use the provided secret is to ensure that the secret volume sources are validated and that the specified object reference actually points to a Secret
object. Therefore, a secret needs to be created before any pods that depend on it. The most effective way to ensure this is to have it get injected automatically through the use of a service account.
Secret API objects reside in a namespace. They can only be referenced by pods in that same namespace.
Individual secrets are limited to 1MB in size. This is to discourage the creation of large secrets that could exhaust apiserver and kubelet memory. However, creation of a number of smaller secrets could also exhaust memory.
Creating an opaque secret
As an administrator, you can create a opaque secret, which allows for unstructured key:value
pairs that can contain arbitrary values.
Procedure
Create a
Secret
object in a YAML file on master.For example:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque (1)
data:
username: dXNlci1uYW1l
password: cGFzc3dvcmQ=
1 Specifies an opaque secret. Use the following command to create a
Secret
object:$ oc create -f <filename>
To use the secret in a pod:
Update the service account for the pod where you want to use the secret to allow the reference to the secret.
Create the pod, which consumes the secret as an environment variable or as a file (using a
secret
volume).
Understanding how to update secrets
When you modify the value of a secret, the value (used by an already running pod) will not dynamically change. To change a secret, you must delete the original pod and create a new pod (perhaps with an identical PodSpec).
Updating a secret follows the same workflow as deploying a new Container image. You can use the kubectl rolling-update
command.
The resourceVersion
value in a secret is not specified when it is referenced. Therefore, if a secret is updated at the same time as pods are starting, the version of the secret that is used for the pod is not defined.
Currently, it is not possible to check the resource version of a secret object that was used when a pod was created. It is planned that pods will report this information, so that a controller could restart ones using a old |
About using signed certificates with secrets
To secure communication to your service, you can configure OKD to generate a signed serving certificate/key pair that you can add into a secret in a project.
A service serving certificate secret is intended to support complex middleware applications that need out-of-the-box certificates. It has the same settings as the server certificates generated by the administrator tooling for nodes and masters.
Service Pod
spec configured for a service serving certificates secret.
apiVersion: v1
kind: Service
metadata:
name: registry
annotations:
service.alpha.openshift.io/serving-cert-secret-name: registry-cert(1)
# ...
1 | Specify the name for the certificate |
Other pods can trust cluster-created certificates (which are only signed for internal DNS names), by using the CA bundle in the /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt file that is automatically mounted in their pod.
The signature algorithm for this feature is x509.SHA256WithRSA
. To manually rotate, delete the generated secret. A new certificate is created.
Generating signed certificates for use with secrets
To use a signed serving certificate/key pair with a pod, create or edit the service to add the service.alpha.openshift.io/serving-cert-secret-name
annotation, then add the secret to the pod.
Procedure
To create a service serving certificate secret:
Edit the
Pod
spec for your service.Add the
service.alpha.openshift.io/serving-cert-secret-name
annotation with the name you want to use for your secret.kind: Service
apiVersion: v1
metadata:
name: my-service
annotations:
service.alpha.openshift.io/serving-cert-secret-name: my-cert (1)
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
The certificate and key are in PEM format, stored in
tls.crt
andtls.key
respectively.Create the service:
$ oc create -f <file-name>.yaml
View the secret to make sure it was created:
View a list of all secrets:
$ oc get secrets
Example output
NAME TYPE DATA AGE
my-cert kubernetes.io/tls 2 9m
View details on your secret:
$ oc describe secret my-cert
Example output
Name: my-cert
Namespace: openshift-console
Labels: <none>
Annotations: service.alpha.openshift.io/expiry: 2023-03-08T23:22:40Z
service.alpha.openshift.io/originating-service-name: my-service
service.alpha.openshift.io/originating-service-uid: 640f0ec3-afc2-4380-bf31-a8c784846a11
service.beta.openshift.io/expiry: 2023-03-08T23:22:40Z
Type: kubernetes.io/tls
Data
====
tls.key: 1679 bytes
tls.crt: 2595 bytes
Edit your
Pod
spec with that secret.apiVersion: v1
kind: Pod
metadata:
name: my-service-pod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
volumes:
- name: foo
secret:
secretName: my-cert
items:
- key: username
path: my-group/my-username
mode: 511
When it is available, your pod will run. The certificate will be good for the internal service DNS name,
<service.name>.<service.namespace>.svc
.The certificate/key pair is automatically replaced when it gets close to expiration. View the expiration date in the
service.alpha.openshift.io/expiry
annotation on the secret, which is in RFC3339 format.In most cases, the service DNS name
<service.name>.<service.namespace>.svc
is not externally routable. The primary use of<service.name>.<service.namespace>.svc
is for intracluster or intraservice communication, and with re-encrypt routes.
Troubleshooting secrets
If a service certificate generation fails with (service’s service.alpha.openshift.io/serving-cert-generation-error
annotation contains):
secret/ssl-key references serviceUID 62ad25ca-d703-11e6-9d6f-0e9c0057b608, which does not match 77b6dd80-d716-11e6-9d6f-0e9c0057b60
The service that generated the certificate no longer exists, or has a different serviceUID
. You must force certificates regeneration by removing the old secret, and clearing the following annotations on the service service.alpha.openshift.io/serving-cert-generation-error
, service.alpha.openshift.io/serving-cert-generation-error-num
:
Delete the secret:
$ oc delete secret <secret_name>
Clear the annotations:
$ oc annotate service <service_name> service.alpha.openshift.io/serving-cert-generation-error-
$ oc annotate service <service_name> service.alpha.openshift.io/serving-cert-generation-error-num-
The command removing annotation has a |