Secrets are Kubernetes objects that are very similar to ConfigMaps, except kubectl by default hides the values they contain. This makes them an option for storing things like passwords and API keys that you normally wouldn't want sitting in the text of a ConfigMap.
The things you store in secrets are base64-encoded, but not encrypted. Someone with the capability to run kubectl get secret <secret-name>
to your cluster could still see them. To prevent unauthorized access to your secrets, it's recommended that your cluster restricts access via kubeconfigs and Service Accounts.
Giving your app a password to use via a Secret
To add a Secret containing a password, it's recommended that you create a file containing your password, and then run kubectl create secret generic <secret-name> --from-file=<path-to-file>
. You could also define a Secret via a manifest file. But doing so may tempt you to lump it in the same version control system (e.g. git) you'll likely use for other manifests, and it's an insecure practice to have passwords hanging around in version control.
The following example will:
- Create a Redis environment that needs a password to access
- Create a Secret containing that password
- Inject that Secret into a microservice's container as a volume
Create the Redis environment by applying the below manifest:
apiVersion: v1
kind: Namespace
metadata:
name: redis-stage
---
apiVersion: v1
kind: Service
metadata:
namespace: redis-stage
name: redis-service
spec:
ports:
- port: 6379
selector:
component: redis
---
apiVersion: v1
kind: Pod
metadata:
namespace: redis-stage
name: redis-pod
labels:
component: redis
spec:
containers:
- name: redis
image: bmcase/loaded-redis:example-stage
ports:
- containerPort: 6379
(Note that these were created in their own namespace. If you want to check on their status or manage them, remember to use the -n redis-stage
option.)
The password this Redis instance needs is y3dHr34T4
. The microservice we'll be using will need to consume this password via a properties file, the property inside needs to be called redisprops.password
. So, create a file called passwords.properties
and give it the below contents:
redisprops.password=y3dHr34T4
(Note: the kind of microservice being used is Java Spring Boot. The container has its own default properties files, but also accepts properties from two other files called override.properties
and passwords.properties
, which will each override the default. )
Tell the cluster to create the Secret by running kubectl create secret generic passwords --from-file=./passwords.properties
. This command will create a Secret named "passwords", and this is how you'll refer to it in subsequent manifests. You can confirm that the secret has been added with kubectl get secrets
.
If using Rancher Desktop, now would be another time to remove any previous Ingress you're using. Then add the microservice that'll use the Secret by applying the below manifest:
apiVersion: v1
kind: ConfigMap
metadata:
name: shopping-cart-configmap-0.0.1
data:
my-conf: |
server.port=54321
redisprops.host=redis-service.redis-stage
redisprops.port=6379
---
apiVersion: v1
kind: Service
metadata:
name: shopping-cart-service
spec:
ports:
- port: 54321
selector:
component: shopping-cart
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: storefront-ingress
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: shopping-cart-service
port:
number: 54321
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: shopping-cart-dep
spec:
replicas: 1
selector:
matchLabels:
depLabel: shopping-cart
template:
metadata:
name: shoping-cart-pod
labels:
depLabel: shopping-cart
component: shopping-cart
spec:
containers:
- name: shopping-cart-ctr
image: bmcase/shopping-cart:0.0.1
ports:
- containerPort: 54321
volumeMounts:
- name: properties-volume
mountPath: /usr/local/lib/override.properties
subPath: override.properties
- name: passwords-volume
mountPath: /usr/local/lib/passwords.properties
subPath: passwords.properties
volumes:
- name: properties-volume
configMap:
name: shopping-cart-configmap-0.0.1
items:
- key: my-conf
path: override.properties
- name: passwords-volume
secret:
secretName: passwords
items:
- key: passwords.properties
path: passwords.properties
You can see that it is mounting two volumes.
- One is a ConfigMap in the same manner as in previous examples.
- The other is very much alike, except that it uses the Secret.
This Spring Boot API may take several seconds to be ready upon container creation. We'll discuss how to deal with container startup time in the introduction to probes. But for now just know that the endpoint may fail if you make a request to it immediately after applying, and you'll need to wait a short while.
Once these are deployed, access the microservice's API via localhost/api/v1/shopping-cart. If it returns a JSON having a list of shopping cart items, that means it has successfully connected to Redis and retrieved the records from there.