Data Store¶
Secrets and ConfigMaps¶
- Secrets & ConfigMap are ways to store and inject configurations into your deployments.
- Secrets usually store passwords, certificates, API keys and more.
- ConfigMap usually store configuration (data).
First, Let’s play a bit with Secrets¶
01. Create namespace and clear previous data (if there is any)¶
# If the namespace already exist and contains data from previous steps, lets clean it
kubectl delete namespace codewizard
# Create the desired namespace [codewizard]
$ kubectl create namespace codewizard
namespace/codewizard created
Note
You can skip section number 02. if you don’t wish to build and push your docker container
02. Build the docker container¶
1. write the server code¶
- For this demo we will use a tiny NodeJS server which will consume the desired configuration values from the secret
- This is the code of our server server.js:
//
// server.js
//
const
// Get those values in runtime.
// The variables will be passed from the Docker file and later on from K8S ConfingMap/ecret
language = process.env.LANGUAGE,
token = process.env.TOKEN;
require("http")
.createServer((request, response) => {
response.write(`Language: ${language}`);
response.write(`Token : ${token}\n`);
response.end(`\n`);
})
// Set the default port to 5000
.listen(process.env.PORT || 5000 );
2. Write the DockerFile¶
- First, let’s wrap it up as
docker container - If you wish, you can skip this and use the existing docker image:
nirgeier/k8s-secrets-sample - In the
Dockerfilewe will set theENVfor or variables
# Base Image
FROM node
# exposed port - same port is defined in the server.js
EXPOSE 5000
# The "configuration" which we pass in runtime
# The server will "read" those variables at run time and will print them out
ENV LANGUAGE Hebrew
ENV TOKEN Hard-To-Guess
# Copy the server to the container
COPY server.js .
# start the server
ENTRYPOINT node server.js
3. Build the docker container¶
# The container name is prefixed with the Dockerhub account
# !!! You should replace the prefix to your dockerhub account
# In the sample the username is `nirgeier`
$ docker build . -t nirgeier/k8s-secrets-sample
# The output should be similar to this
Sending build context to Docker daemon 12.8kB
Step 1/6 : FROM node
latest: Pulling from library/node
2587235a7635: Pull complete
953fe5c215cb: Pull complete
d4d3f270c7de: Pull complete
ed36dafe30e3: Pull complete
00e912dd434d: Pull complete
dd25ee3ea38e: Pull complete
7e835b17ced9: Pull complete
79ae84aa9e91: Pull complete
629164f2c016: Pull complete
Digest: sha256:3a9d0636755ebcc8e24148a148b395c1608a94bb1b4a219829c9a3f54378accb
Status: Downloaded newer image for node:latest
---> d6740064592f
Step 2/6 : EXPOSE 5000
---> Running in 060220eaa65b
Removing intermediate container 060220eaa65b
---> 68262a3e6741
Step 3/6 : ENV LANGUAGE Hebrew
---> Running in c404e7e6fa16
Removing intermediate container c404e7e6fa16
---> 45fcf1fe03aa
Step 4/6 : ENV TOKEN Hard-To-Guess
---> Running in d3c1491f9de5
Removing intermediate container d3c1491f9de5
---> 71e8acdbdab2
Step 5/6 : COPY server.js .
---> 42233d2b66a8
Step 6/6 : ENTRYPOINT node server.js
---> Running in 223629e16589
Removing intermediate container 223629e16589
---> f5cbb1895d66
Successfully built f5cbb1895d66
Successfully tagged nirgeier/k8s-secrets-sample:latest
4. Test the container¶
# Run the docker container which you build earlier,
# replace the name if you used your own name
# and check the response from the server.
# It should print out the variables which were defined inside the DockerFile
$ docker run -d -p5000:5000 nirgeier/k8s-secrets-sample --name server
# Get the response from the container
# The port is the one which we exposed inside the DockerFile
curl 127.0.0.1:5000
# Response:
Language: Hebrew
Token : Hard-To-Guess
- Stop the container
# Stop the running container
# We are using the name which we passed in the `docker run` command --name <container name>
docker stop server
- Push the container to your docker hub account if you wish
03. Using K8S deployment & Secrets/ConfigMap¶
1. Writing the deployment & service file¶
- Deploy the docker container that you have prepared in the previous step with the following
Deploymentfile. - In this sample we will define the values in the
YAMLfile, later on we will use Secrets/ConfigMap variables-from-yaml.yaml
apiVersion: v1
kind: Namespace
metadata:
name: codewizard
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: secrets-app
namespace: codewizard
spec:
replicas: 1
selector:
matchLabels:
name: secrets-app
template:
metadata:
labels:
name: secrets-app
spec:
containers:
- name: secrets-app
image: nirgeier/k8s-secrets-sample
imagePullPolicy: Always
ports:
- containerPort: 5000
env:
- name: LANGUAGE
value: Hebrew
- name: TOKEN
value: Hard-To-Guess2
resources:
limits:
cpu: "500m"
memory: "256Mi"
---
apiVersion: v1
kind: Service
metadata:
name: codewizard-secrets
namespace: codewizard
spec:
selector:
app: codewizard-secrets
ports:
- protocol: TCP
port: 5000
targetPort: 5000
2. Deploy to cluster¶
$ kubectl apply -n codewizard -f variables-from-yaml.yaml
deployment.apps/codewizard-secrets configured
service/codewizard-secrets created
3. Test the app¶
- We will need a second container for executing the curl request.
- We will use a
busyBox imagefor this purpose.
# grab the name of the pod
$ kubectl get pods -n codewizard
# Output
NAME READY STATUS RESTARTS AGE
codewizard-secrets-56f556c758-2mknc 1/1 Running 0 6m27s
# Login to the container and test the reponse
# kubectl exec -it -n codewizard <pod name> -- sh
# For the above output we will use
kubectl exec -it -n codewizard codewizard-secrets-56f556c758-2mknc -- sh
# Now get the server response (from inside the container)
$ curl localhost:5000
# Response
Language: Hebrew
Token : Hard-To-Guess2
04. Using Secrets & config maps¶
1. Create the desired secret and config map for this lab¶
# Create the secret
# Key = Token
# Value = Hard-To-Guess3
$ kubectl create -n codewizard secret generic token --from-literal=TOKEN=Hard-To-Guess3
secret/token created
# Create the config map
# Key = LANGUAGE
# Value = English
$ kubectl create -n codewizard configmap language --from-literal=LANGUAGE=English
configmap/language created
# Verify that the resources have been created:
$ kubectl get secrets,cm -n codewizard
NAME TYPE DATA AGE
secret/default-token-8hzhn kubernetes.io/service-account-token 3 14m
secret/token Opaque 1 80s
NAME DATA AGE
configmap/kube-root-ca.crt 1 14m
configmap/language 1 44s
# Like other resources we can use describe to view the resource
$ kubectl describe secret token -n codewizard
Name: token
Namespace: codewizard
Labels: <none>
Annotations: <none>
Type: Opaque <----- The content is stored as BASE64
Data
====
TOKEN: 14 bytes
# Same way for the ConfigMap
$ kubectl describe cm language -n codewizard
Name: language
Namespace: codewizard
Labels: <none>
Annotations: <none>
Data
====
LANGUAGE:
----
English
Events: <none>
2. Update the deployment to read the values from Secrets & ConfigMap¶
- Change the
envsection to the following:
env:
- name: LANGUAGE
valueFrom:
configMapKeyRef: # This value will be read from the config map
name: language # The name of the ConfigMap
key: LANGUAGE # The key in the config map
- name: TOKEN
valueFrom:
secretKeyRef: # This value will be read from the secret
name: token # The name of the secret
key: TOKEN # The key in the secret
3. Update the deployment to read values from K8S resources¶
$ kubectl apply -n codewizard -f variables-from-secrets.yaml
deployment.apps/codewizard-secrets configured
service/codewizard-secrets unchanged
4. Test the changes¶
- Refer to step 3.3 for testing your server
# Login to the server
# In this sample, the pod name is: codewizard-secrets-76d99bdc54-s66vl
kubectl exec -it codewizard-secrets-76d99bdc54-s66vl -n codewizard -- sh
# Test the changes to verify that they are set from the Secret/ConfigMap
curl localhost:5000
# Out put should be
Language: English
Token : Hard-To-Guess3
Note
Pods are not recreated or updated automatically when Secrets or ConfigMaps change, so you will have to restart your pods manually
- To update existing secrets or ConfigMap:
$ kubectl create secret generic token -n codewizard --from-literal=Token=Token3 -o yaml --dry-run=client | kubectl replace -f -
secret/token replaced
- Test your server and verify that you see the old values.
- Delete the old pods so they can come back to life with the new values.
- Test your server again, now you should be able to see the changes.