Hi I am playing around with Kubernetes secrets. My deployment file is :
---
apiVersion: v1
kind: Secret
metadata:
name: my-secrets
labels:
app: my-app
data:
username: dXNlcm5hbWU=
password: cGFzc3dvcmQ=
I am able to create secrets and I am mounting them in my deployments as below:
---
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-service
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-service
labels:
app: spring-service
spec:
replicas: 1
selector:
matchLabels:
app: spring-service
template:
metadata:
labels:
app: spring-service
spec:
containers:
- name: spring-service
image: my-image:tag
imagePullPolicy: Always
ports:
- containerPort: 8080
volumeMounts:
- name: my-secret-vol
mountPath: "/app/secrets/my-secret"
readOnly: true
volumes:
- name: my-secret-vol
secret:
secretName: my-secrets
My question is how can I access username
and password
I created in secret in spring-boot app?
I have tried loading in with ${my-secrets.username}
and ${username}
, but it fails to find values.
I also tried adding secrets as enviroment variables as below in deployment.yml:
env:
- name: username
valueFrom:
secretKeyRef:
name: my-secrets
key: username
- name: password
valueFrom:
secretKeyRef:
name: my-secrets
key: password
In this case, values are loaded from secrets and when I change values of secrets in minikube dashboard, it does not reflect the changes.
Please help me to understand how this works.
I am using minikube
and docker
as containers
For the first approach you'll find the values on:
- /app/secrets/my-secret/username
- /app/secrets/my-secret/password
and for the second approach you can't change the value of env vars during runtime, you need to restart or redeploy the pod
You don't inject the secret into properties.yml
. Instead, you use the content of the secret as properties.yml
. The process is look like the following:
properties.yml
with the sensitive data (e.g. password)base64 properties.yml
).properties.yaml
.You should end up with a secret in the following format:
apiVersion: v1
kind: Secret
metadata:
name: my-secrets
labels:
app: my-app
data:
properties.yml: dXNlcm5hbWU=
Now when you mount this secret on your pod, Kubernetes will decrypt the secret and put the value under the relevant path and you can just mount it.
The pattern is to have 2 configuration files - one with non-sensitive configurations that is stored with the code, and the second (which includes sensitive configurations) stored as a secret. I don't know if that possible to load multiple config files using Spring Boot.
And one final comment - this process is cumbersome and error-prone. Each change to the configuration file requires decoding the original secret and repeating this manual process. Also, it's very hard to understand what changed - all you see is the entire content has changed. For that reason, we build Kamus. It let you encrypt only the sensitive value instead of the entire file. Let me know if that could be relevant for you :)