Can you keep a Secret? Kubernetes can.
https://kubernetes.io/docs/concepts/configuration/secret/
There are a few ways to create secrets within Kubernetes.
What we will learn
- Default Service Account and Secret
- Create from a literal command
- Create from a file
- Create from a folder
- Create from a YAML file
- Copy a secret from one namespace to another
- Encoding and decoding (base64)
- Pod — Mounting secrets within a pod
- Deployment — MySQL deployment using a secret as the password
Notes
- Mounted Secrets are updated automatically
- A container using a Secret as a subPath volume mount will not receive Secret updates
- All key values within a K8 cluster are base64 encoded by default
- Key values within YAML files need to be base64 encoded
Quick Reference
kubectl get secrets
kubectl get secrets SECRET_NAME -o yaml
kubectl create secret generic --help
kubectl create secret generic SECRET_NAME --from-literal=password=YOUR_PASSWORD
kubectl create secret generic SECRET_NAME --from-literal=username=YOUR_USERNAME --from-literal=password=YOUR_PASSWORD
Create namespace
This is the namespace I will be using within this blog.
kubectl create -n itsmetommy
Default Service Account and Secret
You will notice that each namespace has a default ServiceAccount and a default Secret. When you create a pod, if you do not specify a ServiceAccount, it is automatically assigned the default ServiceAccount in the same namespace, which uses the default Secret token as credentials.
kubectl -n itsmetommy get serviceaccounts
NAME SECRETS AGE
default 1 25d
kubectl -n itsmetommy get secrets
NAME TYPE DATA AGE
default-token-2p2sw kubernetes.io/service-account-token 3 25d
Create from a literal command
Create secret
kubectl -n itsmetommy create secret generic literal-example --from-literal=username=tommy --from-literal=password=123456789
Get secret
kubectl -n itsmetommy get secret literal-example -o yaml
apiVersion: v1
data:
password: MTIzNDU2Nzg5
username: dG9tbXk=
kind: Secret
metadata:
creationTimestamp: 2018-12-10T21:46:54Z
name: literal-example
namespace: itsmetommy
resourceVersion: "342825"
selfLink: /api/v1/namespaces/itsmetommy/secrets/literal-example
uid: 1bdea529-fcc5-11e8-be43-080027beeecc
type: Opaque
You’ll notice that the key values are base64 encoded.
Decode secret
echo 'MTIzNDU2Nzg5' | base64 --decode
123456789
echo 'dG9tbXk=' | base64 --decode
tommy
Clean up
kubectl -n itsmetommy delete secret literal-example
Create from a file
Create files
echo -n 'tommy' > username
echo -n '123456789' > password
Create secret
kubectl -n itsmetommy create secret generic files-example --from-file=username --from-file=password
Get secret
kubectl -n itsmetommy get secret files-example -o yaml
apiVersion: v1
data:
password: MTIzNDU2Nzg5
username: dG9tbXk=
kind: Secret
metadata:
creationTimestamp: 2018-12-10T21:53:05Z
name: files-example
namespace: itsmetommy
resourceVersion: "343235"
selfLink: /api/v1/namespaces/itsmetommy/secrets/files-example
uid: f90f0f2f-fcc5-11e8-be43-080027beeecc
type: Opaque
You’ll notice that the key values are base64 encoded.
Decode secret
echo 'MTIzNDU2Nzg5' | base64 --decode
123456789
echo 'dG9tbXk=' | base64 --decode
tommy
Clean up
kubectl -n itsmetommy delete secret files-example
Create from a folder
Create folder
mkdir folder-example
Create files within dir
echo -n tommy > folder-example/username; echo -n 123456789 > folder-example/password
Create secret
kubectl -n itsmetommy create secret generic folder-example --from-file=folder-example
Get secret
kubectl -n itsmetommy get secret folder-example -o yaml
apiVersion: v1
data:
password: MTIzNDU2Nzg5
username: dG9tbXk=
kind: Secret
metadata:
creationTimestamp: 2018-12-11T23:32:39Z
name: folder-example
namespace: itsmetommy
resourceVersion: "407456"
selfLink: /api/v1/namespaces/itsmetommy/secrets/folder-example
uid: 0c68fc51-fd9d-11e8-be43-080027beeecc
type: Opaque
Decode secret
echo 'MTIzNDU2Nzg5' | base64 --decode
123456789
echo 'dG9tbXk=' | base64 --decode
tommy
Clean up
kubectl -n itsmetommy delete secret folder-example
Create from a YAML file
IMPORTANT: Each item must be base64 encoded.
Encode values
echo 'tommy' | base64
dG9tbXk=
echo '123456789' | base64
MTIzNDU2Nzg5
Create secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: yaml-example
namespace: itsmetommy
type: Opaque
data:
username: dG9tbXk=
password: MTIzNDU2Nzg5
Create secret
kubectl -n itsmetommy create -f secret.yaml
Get secret
kubectl -n itsmetommy get secret yaml-example -o yaml
apiVersion: v1
data:
password: MTIzNDU2Nzg5
username: dG9tbXk=
kind: Secret
metadata:
creationTimestamp: 2018-12-10T23:10:20Z
name: yaml-example
namespace: itsmetommy
resourceVersion: "348464"
selfLink: /api/v1/namespaces/itsmetommy/secrets/yaml-example
uid: c3fccfda-fcd0-11e8-be43-080027beeecc
type: Opaque
Decode secret
echo 'MTIzNDU2Nzg5' | base64 --decode
123456789
echo 'dG9tbXk=' | base64 --decode
tommy
Clean up
kubectl -n itsmetommy delete secret yaml-example
Copy a secret from one namespace to another
Copy SECRET_NAME from NAMESPACE_A to NAMESPACE_B.
kubectl get secret -n NAMESPACE_A SECRET_NAME --export -o yaml \
| kubectl apply -n NAMESPACE_B -f -
OR you can use jq.
Install jq.
brew install jq
Copy SECRET_NAME from NAMESPACE_A to NAMESPACE_B.
kubectl -n NAMESPACE_A get secret SERECT_NAME -o json \
| jq '.metadata.namespace = "NAMESPACE_B"' \
| kubectl create -f -
Encoding and decoding (base64)
As you’ve seen already within this blog, I’ve decoded and encoded key values. At this point, it should be review.
- All key values are base64 encoded by default
- Key vaules within YAML files need to be base64 encoded
Decode secret
echo 'MTIzNDU2Nzg5' | base64 --decode
123456789
echo 'dG9tbXk=' | base64 --decode
tommy
Encode secret
echo 'tommy' | base64
dG9tbXk=
echo '123456789' | base64
MTIzNDU2Nzg5
Clone git repository
You may clone my repo if you’d like to follow along.
https://github.com/itsmetommy/kubernetes-secret
Pod — Mounting secrets within a pod
I am going to go over a few different options.
- pod-01 — Specify path
- pod-02 — Specify path and key value
- pod-03 — Specify permission
- pod-04 — Specify path & permission
- pod-05 — Environment variables
cd into the pods directory
cd pods
First create the secret that all pods will use.
kubectl create -f mysecret.yaml
Create pod-01 — Specify path
Apply pod
kubectl apply -f pod-01.yaml
Describe pod
Note: Notice the mount is read only.
kubectl -n itsmetommy describe pods pod-01
View secrets within pod
kubectl -n itsmetommy exec pod-01 -- cat /etc/foo/username
tommy
kubectl -n itsmetommy exec pod-01 -- cat /etc/foo/password
123456789
Create pod-02 — Specify path and key value
Apply pod
kubectl apply -f pod-02.yaml
Describe pod
Note: Notice the mount is read only.
kubectl -n itsmetommy describe pods pod-02
View secret within pod.
kubectl -n itsmetommy exec pod-02 -- cat /etc/foo/my-group/my-username
tommy
Create pod-03 — Specify permission
Apply pod
kubectl apply -f pod-03.yaml
Describe pod
kubectl -n itsmetommy describe pods pod-03
View secret file permissions within pod
kubectl -n itsmetommy exec pod-03 -it -- ls -l /etc/foo/..data/
total 8
-r-------- 1 root root 9 Dec 10 23:56 password
-r-------- 1 root root 5 Dec 10 23:56 username
Create pod-04 — Specify path & permission
Apply
kubectl apply -f pod-04.yaml
Describe pod
kubectl -n itsmetommy describe pods pod-04
View secret file permissions within pod
kubectl -n itsmetommy exec pod-04 -it -- ls -l /etc/foo/..data/my-group
total 4
-rwxrwxrwx 1 root root 5 Dec 11 00:01 my-username
Create pod-05 — Environment variables
Apply pod
kubectl apply -f pod-05.yaml
Describe pod
kubectl -n itsmetommy describe pods pod-05
View environment variables within pod
kubectl -n itsmetommy exec pod-05 -it -- env | grep SECRET
SECRET_USERNAME=tommy
SECRET_PASSWORD=123456789
kubectl -n itsmetommy exec pod-05 -it -- bash
root@pod-05:/# echo $SECRET_USERNAME
tommy
root@pod-05:/# echo $SECRET_PASSWORD
123456789
Clean up
kubectl -n itsmetommy delete pods -l app=secret-examples
kubectl -n itsmetommy delete secret mysecret
Deployment — MySQL deployment using a secret as the password
cd into the mysql directory
cd mysql
Create MySQL password secret
kubectl -n itsmetommy create secret generic mysql-pass --from-literal=password=123456789
Apply deployment
This will create a Deployment, PersistentVolume, PersistentVolumeClaim and Service.
kubectl apply -f .
Get pod
kubectl -n itsmetommy get pods | grep mysql
mysql-7844645f76-t557s 1/1 Running 0 1m
Connect to mysql
Note: Use password 123456789.
kubectl -n itsmetommy exec mysql-7844645f76-t557s -it -- mysql -p
Get secrets
kubectl -n itsmetommy get secrets mysql-pass -o yaml
apiVersion: v1
data:
password: MTIzNDU2Nzg5
kind: Secret
metadata:
creationTimestamp: 2018-12-11T00:25:23Z
name: mysql-pass
namespace: itsmetommy
resourceVersion: "353539"
selfLink: /api/v1/namespaces/itsmetommy/secrets/mysql-pass
uid: 3f9ca5ca-fcdb-11e8-be43-080027beeecc
type: Opaque
Decode secret
echo 'MTIzNDU2Nzg5' | base64 --decode
123456789
Clean up
kubectl delete -f .
kubectl -n itsmetommy delete secret mysql-pass