Kubernetes: A Complete Guide - Chapter 6

In this blog, we will learn how to manage sensitive information like tokens, credentials etc. via secrets. We'll also learn further how to handle non-sensitive environment variables via ConfigMaps.

In Kubernetes, secrets can hold all kinds of sensitive information. For instance, database credentials or API keys or tokens and other user authentication identifiers that must remain unknown to everyone except a finite number of authorized persons or services. These kind of secrets should not be exposed as they may cause security vulnerabilities in our system. The term "secrets management" describes the centralised and secured management of these secrets.

So how do we handle secrets?

Any secrets that we create using the command kubectl create -f secret.yaml, it gets stored in the etcd

A Secret contains two maps: data and string data. The data field is used to store arbitrary data, encoded using base64.

echo -n 'TlXs5syc' | base64
VGxYczVzeWM=

While, these above values are just encoded and they can be decoded very easily. These are just not readable in a simple text format.

Next, we create a Secret.yaml file:-

--- 
apiVersion: v1
data: 
  password: VGxYczVzeWM=
kind: Secret
metadata: 
  name: mysqldb-creds
type: Opaque

Create the secret using kubectl create command:-

kubectl create -f creds.yaml

Now, we are gonna make use of the secrets as ENV variables. Let's create file Deployment.yaml with the below contents:-

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:8.0
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom: 
            secretKeyRef: 
              key: password
              name: mysqldb-creds
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

However, if we do not want to create a Secret.yaml file, we can create the secret by command line as well:-

kubectl create secret generic mysqldb-creds --from-literal=password=TlXs5syc

This command is similar to the one above and the output would be:-

secret "mysqldb-creds" created
  • Alternatively, we can make use of ConfigMaps to handle non-sensitive information such as data-like config files or environment variables(port number). They can be created and shared in the containers in the same ways. The only big difference between them is the base64-encoding obfuscation. ConfigMaps are a great way to create customized running services from generic container images.
kubectl create configmap port-number --from-literal=APP_PORT=3306

So, considering we have a Pod.yaml file, we can fetch the APP_PORT value from the ConfigMap:-

apiVersion: extensions/v1beta1
kind: Pod
metadata:
  name: sample-code
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: sample-code
    spec:
      containers:
      - name: envtest
        image: nginx:latest
        ports:
        - containerPort: 8080
        env:
        - name: APP_PORT
          valueFrom:
            configMapKeyRef:
              name: port-number
              key: APP_PORT
  • We can access Secrets via a Volume as well. To access secrets mounted to a pod in a separate volume, we need to modify the definition of the pod to include a new volume. Choose any volume name you want, but make sure that it is the same as the name of the secret object.

There are more secure ways to handle Secrets such as:-

  • AWS Secrets Manager: We make use of ASCP which is known as AWS Secrets and Configuration Provider. With the ASCP, we can store and manage your secrets in Secrets Manager and then retrieve them through our workloads running on Amazon EKS. If our secret contains multiple key/value pairs in JSON format, we can choose which ones to mount in Amazon EKS. We can read more about how it works here.
  • Hashicorp Vault: The Vault Helm chart enables us to run Vault and the Vault Agent Injector service. This injector service leverages the Kubernetes mutating admission webhook to intercept pods that define specific annotations and inject a Vault Agent container to manage these secrets. Here's the complete documentation for how it works.
Abhishek Roy

Abhishek Roy

DevOps Engineer who aims to automate and simplify stuff related to infra and CI/CD.
Kolkata, India