Ukieweb

Diary

I write what I learn here

Creating & Managing Kubernetes Secrets in Production

Creating & Managing Kubernetes Secrets in Production

For my first technical blog in 2019, I will focus on kubernetes secrets having spent a lot of time trying to deploy a production application that uses sensitive keys that cannot not be hard coded in the code as clear text. Kubernetes offers you ways of managing your production-grade secrets (sensitive data such as tokens, keys, passwords, etc.) in a seamless manner regardless of the environment your application is running in.

Prerequisite

  1. You have a running Kubernetes cluster. Here is a full guide on how to set up a K8 cluster on AWS.
  2. You understand basic Linux commands
  3. You understand basic Kubernetes commands & concepts
  4. You have a running bug free application developed in a language of your choice.

There are two major ways of creating secrets in Kubernetes

  1. Using kubectl - This method uses kubectl create secret command and automatically does encoding for you making it quick and easy to use especially for single secret values.
  2. Using a .yaml file - With this method you need to create a deployment.yaml file just like when defining a service. However, you will need to encode all the secrets in base64 otherwise the secrets will not get created. Kubernetes encodes all its secrets in base64 which helps prevent any errors especially resulting from new lines and adds a level of security in case the values are exposed.

Of the two methods I personally prefer using .yaml file because it makes it easy to edit and delete the secrets. Updating new secrets in the same file also becomes easy too.

Using kubectl

Here is a sample command format to create the secrets using this method. If you need the secret to be created in a specific namespace use --namespace=your_namespace as part of the command otherwise it will be created in the default namespace. Using--from-literal tells kubectl to create a secret for the given value while using --from-file means the secret is being retrieved from the specified file.


kubectl create secret generic app-secrets \

--from-literal=db_username=root \

--from-literal=db_password=abcdef

Using .yaml File

The first step is to encode all the secrets to base64 as shown below. Note that when using the terminal you might need to use single quotes ‘secret_string’ or double quotes “secret_string’” around your secret. When using online tool to generate the encoded string don’t use any quotes otherwise the output will be incorrect.

echo -n secret_to_encode | base64 output c2VjcmV0X3RvX2VuY29kZQ==

You can decode a base64 encoded text as well in case you want to compare with the original text for similarity/errors.

echo c2VjcmV0X3RvX2VuY29kZQ== | base64 -d output secret_to_encode

Next you need to create a .yaml file with the format shown below. Note the Kind and the format of the file.

_apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
data: 
  db_username: 'cm9vdA=='
  db_password: 'YWJjZGVm'_

Finally create the secrets by running kubectl apply –f name_of_your_file.yaml

###Viewing, Updating & Deleting Your Secrets

Use kubectl describe secret app-secrets to view a summary of your secrets although this will not reveal the values of your secrets. Cool right :)

To update the secrets you can edit the existing .yaml file and run kubectl apply -f name_of_your_file.yaml and the update occurs seamlessly. To delete a secrets use kubectl delete secret app-secrets and it will be automatically removed though you want to avoid using this in production.

Now that you have created your secrets successfully and viewed them, let us configure our container to use these secrets.

###Using the Secrets as Environment Variables in Containers

The yaml file below shows the deployment of a sample application (my-app) using a replication controller. Pay attention to the env section at the bottom, name: app-secrets indicates the source of the secret as we create earlier. Make note of the namespace as well because if the namespace of the application and that of the secrets is different, the application will not run.


#Pod defination: image and secrets  
apiVersion: v1
kind: ReplicationController
metadata:
  labels:
    run: my-app
  name: my-app-controller
  namespace: default
spec:
  replicas: 2
  selector:
    app: my-app
  template:
    metadata:
      name: my-app
      labels:
        app: my-app
    spec:
      containers:
      - image: your_image:v1
        name: my-app
        ports:
        - containerPort: 80
        env:
          - name: DATABASE_USERNAME
            valueFrom:
              secretKeyRef:
                name: app-secrets
                key: db_username
          - name: DATABASE_PASSWORD
            valueFrom:
              secretKeyRef:
                name: app-secrets
                key: db_password

When you run kubectl apply –f deployment_file.yaml, kubernetes automatically makes available the two environment variables available for use in your container. That is DATABASE_USERNAME and DATABASE_PASSWORD which have been used in your code for example as PASSWORD = os.getenv(`PASSWORD ') in python.

A quick way of duplicating the same secrets into another namespace is by running the following command which copies the secret app-secrets from default namespace to production namespace.

kubectl get secret app-secrets --namespace=default --export -o yaml | kubectl apply --namespace=production -f -

Thank you for reading and hope this blog saved you some valuable time. For more questions around this topic & Kubernetes in general leave comments below, cheers!!

0 Comments

To make a comment you have to login