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.
Kubernetescommands & concepts
There are two major ways of creating secrets in Kubernetes
kubectl create secretcommand and automatically does encoding for you making it quick and easy to use especially for single secret values.
deployment.yamlfile 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.
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
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
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!!
To make a comment you have to login