Kubernetes: Env, ConfigMaps, Secrets

created:

updated:

tags: kubernetes

Environment Variables

env

We can environment variables for the containers that run in the Pod.

# In a pod definition file
apiVersion: v1
kind: Pod
metadata:
  name: <name_of_pod>
spec:
  containers:
  - name: <name_of_container>
    image: <image_to_use>
    env:
    - name: EXAMPLE_ENV1
      value: "This is value of EXAMPLE_ENV1"
    - name: EXAMPLE_ENV2
      value: "The value of EXAMPLE_ENV2"

ConfigMaps

How to Create configMaps

# Directly specify key-value on the command line
kubectl create configmap <name_of_configmap> --from-literal=<key>=<value>
# Alternatively, use a file
kubectl create configmap <name_of_configmap> --from-file=<path_to_file>

ConfigMap file

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_COLOR: red
  APP_MODE: dev 

Commands for a ConfigMap

kubectl create -f <config_map_file_path>
kubectl get configmaps
# Alternatively,
kubectl get cm
kubectl describe configmaps

We can create multiple config map files as needed for different purposes. It’s important to name each configMap file as appropriate to the purpose.

ConfigMaps in Pods

# in a pod definition file
apiVersion: v1
kind: Pod
metadata:
  name: <name_of_pod>
spec:
  containers:
  - name: <name_of_container>
    image: <name_of_image>
    ports:
      - containerPort: 8080
    envFrom:
      - configMapRef:
          name: <name_of_configmap_we_created>

Alternatively, we can inject individual environment variables:

# in a pod definition file
apiVersion: v1
kind: Pod
...
spec:
  containers:
  - name: <name_of_container>
    image: <name_of_image>
    env:
      - name: APP_COLOR
        valueFrom:
          configMapKeyRef:
            name: <name_of_configmap>
            key: APP_COLOR 

Or using volumes:

apiVersion: v1
kind: Pod
...
spec:
  containers:
  - name: <name_of_container>
    image: <name_of_image>
    volumes:
    - name: <name_of_volume_in_configmap>
      configMap:
        name: <name_configmap>

Secrets

Secrets are used to store sensitive information such as passwords. They are similar to ConfigMap but they are store in an encoded or hashed format.

  • Secrets are encoded in base64 format. Since anyone can easily decode it, secrets are not considered very safe.
  • Secrets are not encrypted.

Good Practices with Secrets

  • Do not push secret object files to repositories
  • Configure encryption at rest
  • Configure least-privilege access to Secrets
  • Configure access to external Secrets

How to use Secrets

  • Create a secret
    • Imperative way:

      • kubectl create secret generic <secret_name> --from-literal=<key1>=<value1> --from-literal=<key2>=<value2>
      # secret file
      DB_HOST: mysql
      DB_USER: user
      DB_PASSWORD: password
      
      • kubectl create secret generic <secret_name> --from-file=<path_to_secret_file>
    • Declarative way:

      • kubectl create -f secret-data.yaml
      # secret-data.yaml
      apiVersion: v1
      kind: Secret
      metadata:
        name: app-secret
      data:
        # We must specify the secret values in an encoded format for security
        DB_HOST: mysql
        DB_USER: user
        DB_PASSWORD: password
      
      • How do we convert data from plain text to an encoded format?
        • On Linux machine, we can use the following: echo -n "text" | base64
      • How to view secrets:
        • kubectl get secrets
        • kubectl describe secrets
      • In order to view values as well, we can get secret information with yaml format:
        • kubectl get secret <name_of_secret> -o yaml
      • How to decode the encoded secret value?
        • echo -n "encoded_Text" | base64 --decode
  • Inject to a Pod:
    # in a pod-definition yaml file
    apiVersion: v1
    kind: Pod
    metadata:
      name: <name_of_pod>
      labels:
        name: <name_of_pod>
    spec:
      containers:
      - name: <container_name>
        image: <image_name>
        ports:
          - containerPort: 8080
        envFrom:
          - secretRef:
              name: <name_of_secret>
        # alternatively, single env
        env:
          - name: DB_PASSWORD
            valueFrom:
              secretKeyRef:
                name: <name_of_secret>
                key: DB_PASSWORD
        # or volume
        volumes:
          - name: <name_of_volume_for_secret>
            secret:
              secretName: <name_of_secret>
    
    • kubectl create -f pod-defintion.yaml

Notes on Secret

  • Secrets are not encrypted. They are only encoded.
    • Therefore, do not push secret objects to Git or other repositories along with code
  • Secrets are not encrypted in etcd. None of data in ectd is encrypted.
    • We can enable encryption at rest through Kubernetes.
  • Anyone who can create pods / deployments in the same namespace can access the secrets.
    • We can configure least-privilege access to Secrets (role-based access control)
  • There are third-party secrets store providers such as AWS, Azure, GCP, Vault

Encryption of Secrets at rest

etcdctl (etcd-client)

# to view what's stored in etcd
ETCDCTL_API=3 etcdctl --<name_of_secret>=<filepath_of_key_or_crt>
  • Under etcd/ we have certificate files etc.
  • Anyone who has access to etcd will be able to see what’s in etcd

Reference