Skip to Content
Last repository update 9/10/2025 🎉
DocsKubernetesEnv and Secrets Setup

Environments (ConfigMap) and Secrets

We have 3 ways to set environment variables and secrets;

  • key-value pair format
  • ConfigMap
  • Secrets

key-value pair format

pod.yml
apiVersion: v1 kind: Pod metadata: name: my-ubuntu spec: container: - name: my-ubuntu image: ubuntu env: - name: URL value: https://karchunt.com - name: APP_NAME value: karchunt-ubuntu

ConfigMap

The concept of ConfigMap is actually the same as key-value pair format, just it stores the configuration data in a Kubernetes API object.

There are two ways of creating ConfigMap;

  • Imperative
  • Declarative
# get configmap kubectl get configmap

Ways of creating ConfigMap

Imperative

# create configmap from key-valuye pairs kubectl create configmap <config-name> --from-literal=<key>=<value> kubectl create configmap api-config --from-literal=port=8080 # create configmap from file path kubectl create configmap <config-name> --from-file=<path-to-file> kubectl create configmap api-config --from-file=.env

When you create configmap from file path, make sure each line adhere to the format like this <name>=<value>

.env
port=8080 env=prod

Declarative

api-config.yaml
apiVersion: v1 kind: ConfigMap metadata: name: api-config data: port: 8080 env: prod

Apply entire ConfigMap to Pod

Make sure the configMapRef name is equal to ConfigMap file metadata name.

api-party.yaml
apiVersion: v1 kind: Pod metadata: name: api-party spec: containers: - name: api-party image: api-party:0.1.0 ports: - containerPort: 8080 envFrom: - configMapRef: name: api-config # ConfigMap file metadata name

Apply only 1 value from ConfigMap to Pod

We can also apply only 1 value from ConfigMap to Pod.

api-party.yaml
apiVersion: v1 kind: Pod metadata: name: api-party spec: containers: - name: api-party image: api-party:0.1.0 ports: - containerPort: 8080 env: - name: port valueFrom: configMapKeyRef: name: api-config # ConfigMap file metadata name key: port # ConfigMap file under data section

Apply ConfigMap to volume

In some cases, you might want to create files with the contents during runtime, but you can actually do that using ConfigMap.

special-cm.yaml
apiVersion: v1 kind: ConfigMap metadata: name: model-config data: config.py: | config = { 'url': 'http://localhost:8080' } special_file.txt: specialData
api-party.yaml
apiVersion: v1 kind: Pod metadata: name: api-party spec: containers: - name: api-party image: api-party:0.1.0 ports: - containerPort: 8080 volumeMounts: - name: config-volume mountPath: /app/src # subPath: src volumes: - name: config-volume configMap: name: model-config

In this case, two files called will be created in /app/src, so these files will present at this path:

  • /app/src/config.py
  • /app/src/special_file.txt

Secrets

Secrets are used to store confidential information like a password, key, or token.

Additional information on how Kubernetes manage secrets:

  • A secret will be only sent to a node if a pod requires it
  • When we mount secrets into pods, the kubelet will store a copy of the secret into a tmpfs (aka a disk in RAM) so that the confidential data is not written to disk storage.
  • The kubelet will delete its local copy of the secret when the pod depends on the secret is deleted.
kubectl get secrets
Built-in TypeUsage
Opaquearbitrary user-defined data
kubernetes.io/service-account-tokenServiceAccount token
kubernetes.io/dockerconfigjsonserialized ~/.docker/config.json file
kubernetes.io/basic-authcredentials for basic authentication
kubernetes.io/ssh-authcredentials for SSH authentication
kubernetes.io/tlsdata for a TLS client or server
bootstrap.kubernetes.io/tokenbootstrap token data

Ways of creating Secrets

Imperative

When you use imperative to create secret, you no need to encode your data, as the command will automatically help you to encode.

# create secret generic (opaque) from key-value pairs kubectl create secret generic <secret-name> --from-literal=<key>=<value> kubectl create secret generic api-secret --from-literal=token=yourtoken # create secret generic from file path kubectl create secret generic <secret-name> --from-file=<path-to-file> kubectl create secret generic api-secret --from-file=.env # create container registry secret kubectl create secret docker-registry secret-harbor \ --docker-email=karchun@gmail.com \ --docker-username=karchun \ --docker-password=mypassword \ --docker-server=harbor.registry.com # retrieve and decode the data for registry secret kubectl get secret secret-harbor -o jsonpath='{.data.*}' | base64 -d # Create TLS secret # the certificate for --cert must be .PEM encoded kubectl create secret tls <secret-name> --cert=<path-to-cert-file> --key=<path-to-key-file> kubectl create secret tls tls-domain --cert="path.crt" --key="key.key"

When you create secret from file path, make sure each line adhere to the format like this <name>=<value>

.env
token=yourtoken

Declarative

Make sure your secrets store with base64 format

# encode echo -n '<data>' | base64 echo -n 'password' | base64 # decode echo -n 'bXlzcWw=' | base64 --decode
Opaque
api-secret.yaml
apiVersion: v1 kind: Secret metadata: name: api-secret data: token: bXlzcWw=
Docker config
docker-config.yaml
apiVersion: v1 kind: Secret metadata: name: secret-dockercfg type: kubernetes.io/dockercfg data: .dockerconfigjson: | eqJhdXRocyd6eyJodHRwczoaL2V4YW1wbGUvdjEvcjP7ImF1dGgiOiJvcGVuc2VzYW1lIn19fQo=
Basic authentication

The data or stringData (clear text content) field of the Secret must contain one of the following two keys:

  • username
  • password
basic-authentication.yaml
apiVersion: v1 kind: Secret metadata: name: secret-basic-auth type: kubernetes.io/basic-auth data: username: bXlzcWw= password: bXlzcWw=
SSH authentication

Mandatory field: ssh-privatekey

ssh-authentication.yaml
apiVersion: v1 kind: Secret metadata: name: secret-ssh-auth type: kubernetes.io/ssh-auth data: ssh-privatekey: | abcoAI812hcnaik
TLS

Mandatory fields: tls.crt and tls.key

tls.yaml
apiVersion: v1 kind: Secret metadata: name: secret-tls type: kubernetes.io/tls data: tls.crt: | abcoAI812hcnaik UUVCQlFVQU1Jada bkkxWHgKRHanca1 tls.key: | abcoAI812hcnaikabcoAI812hcnaikabcoAI812hcnaik

Apply entire Secret to Pod

Make sure the secretRef name is equal to Secret file metadata name.

api-party.yaml
apiVersion: v1 kind: Pod metadata: name: api-party spec: containers: - name: api-party image: api-party:0.1.0 ports: - containerPort: 8080 envFrom: - secretRef: name: api-secret # Secret file metadata name

Apply only 1 value from Secret to Pod

We can also apply only 1 value from Secret to Pod.

api-party.yaml
apiVersion: v1 kind: Pod metadata: name: api-party spec: containers: - name: api-party image: api-party:0.1.0 ports: - containerPort: 8080 env: - name: token valueFrom: secretKeyRef: name: api-secret # Secret file metadata name key: token # Secret file under data section

Apply Secret to volume

In some cases, you might want to create files with the contents during runtime, but you can actually do that using Secret.

special-cm.yaml
apiVersion: v1 kind: Secret metadata: name: sample-secret data: .secret-file: bXlzcWw=
api-party.yaml
apiVersion: v1 kind: Pod metadata: name: api-party spec: containers: - name: api-party image: api-party:0.1.0 ports: - containerPort: 8080 volumeMounts: - name: secret-volume mountPath: /app/src readOnly: true # subPath: src volumes: - name: secret-volume configMap: name: sample-secret

In this case, a file called .secret-file will be created in /app/src, so this file will present at this path /app/src/.secret-file.

Last updated on