Secrets


  • We learned how ConfigMap helps us separate our app template and properties.
  • While that combination works for almost all scenarios, Kubernetes has one more resources to save the properties i.e Secrets
  • Secrets as name suggest should be used to store properties that should be kept secret.
  • In other words, we should keep the properties in Secret Kubernetes resource.
  • Secrets are more secure and they reduces the risk of accidental exposure.

Secret YAML

  • Secret is not different than ConfigMaps.
  • Changing the kind from ConfigMap to Secret should do the work. (But there's a catch)
  • Let's update our previous ConfigMap resource file.
apiVersion: v1
kind: Secret
metadata:
  name: web
data:
  GREETING: Namaste
  NAME: Friends!!!
  • Let's create this secret and see what happens.
kubectl create -f secrets.yaml
  • You will get an error message that says something like this.
Error from server (BadRequest): error when creating "secret-base64.yaml": 
Secret in version "v1" cannot be handled as a Secret: v1.Secret: 
Data: decode base64: illegal base64 data at input byte 4, error found in #10 byte of ...|:"Namaste","NAME":"F|..., bigger context ...|{"apiVersion":"v1","data":{"GREETING":"Namaste","NAME":"Friends!!!"},"kind":"Secret","metadata":{|...
  • If you read the error message, you can see Kubernetes is expecting base64 value for a configuration data properties. But it is a plain string.

Secrets data are base64

  • Let's convert our data to base64 and add it.
➜ echo "Namaste" | base64
TmFtYXN0ZQo=
➜ echo "Friends" | base64
RnJpZW5kcwo=
  • Our new Secrets definition
apiVersion: v1
kind: Secret
metadata:
  name: web
data:
  GREETING: TmFtYXN0ZQo=
  NAME: RnJpZW5kcwo=
  • Now let's create a Secret again.
kubectl create -f secrets.yaml
➜  kubectl get secrets web -o yaml
apiVersion: v1
data:
  GREETING: TmFtYXN0ZQo=
  NAME: RnJpZW5kcwo=
kind: Secret
metadata:
  creationTimestamp: "2019-03-02T22:53:07Z"
  name: web
  namespace: default
  resourceVersion: "102112"
  selfLink: /api/v1/namespaces/default/secrets/web
  uid: f1cf2235-3d3d-11e9-aea6-025000000001
type: Opaque

Reading as env var one at a time

  • Using Secret is easy as using ConfigMaps
  • Kubernetes when loads the Secrets values to Pods, it doesn't load encrypted value but actual value.
  • So not conversion is needed.
  • We use secretKeyRef instead of configMapKeyRef.
env:
  - name: GREETING
    valueFrom:
      secretKeyRef:
        name: web # Name of Secret
        key: GREETING
  - name: NAME
    valueFrom:
      secretKeyRef:
        name: web # Name of Secret
        key: NAME

Reading all at once

  • Like ConfigMap, instead of configRef instead of secretRef.
envFrom:
  - secretRef:
      name: web 
  • And that's it, we can access the secrets as environment variable.

Secret string value

  • As you just saw, even if you want to add a string value to a Secret it's bit hard.
  • You need to convert your value to base64.
  • This useful when you load a file on a Secret. (We will get to this when we get to know volume)
  • But Kubernetes one more property stringData, which let's you add your property value as plain text.
  • Only thing you need to remember is that stringData property is write only. You cannot read from it. You will know what I mean in a bit.
apiVersion: v1
kind: Secret
metadata:
  name: web
stringData:
  GREETING: Namaste
  NAME: Friends!!!
  • You can see using stringData we can add secret values as plain text. We can mix and match with data if you want to.
  • Create a Secrets and see YAML generated by Kubernetes
➜  kubectl get secrets web -o yaml
apiVersion: v1
data:
  GREETING: TmFtYXN0ZQ==
  NAME: RnJpZW5kcyEhIQ==
kind: Secret
metadata:
  creationTimestamp: "2019-03-02T23:48:35Z"
  name: web
  namespace: default
  resourceVersion: "105712"
  selfLink: /api/v1/namespaces/default/secrets/web
  uid: b18f158f-3d45-11e9-aea6-025000000001
type: Opaque
  • Generated YAML doesn't have stringData.
  • That's why stringData is write only property.
  • We can write it as plain text in YAML file, but you cannot read it.
  • When you load a file and create a Secret and Kubernetes will convert the value for you.

Secrets can be mounted as volume. Mostly useful when you load a file on Secrets.

Environment Variables may not be a safest way to expose the Secret values.