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.
Linux
commandsKubernetes
commands & conceptsThere are two major ways of creating secrets in Kubernetes
kubectl create secret
command and automatically does encoding for you making it quick and easy to use especially for single secret values.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.
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
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!!
To make a comment you have to login
0 Comments