In the previous article (Kubernetes for Developers #18: Manage app settings using Kubernetes ConfigMap) we discussed about Kubernetes Configmap which is used for storing non-sensitive information. Whereas Kubernetes Secrets used for storing application sensitive information i.e. application encryption keys, certificates, database credentials and etc.
We should use “data” attribute if we want to pass all values of keys as base64 encoded strings. This is useful if the key value has binary data. These key values will be converted to plain text automatically when the pod is consuming.
Plain text key-value pair
We should use “stringData” attribute if we want to pass all values of keys as plain strings. However, internally it converted to based64 encoded string while creating.
Types of Secret
In the below example, we are setting Pod container individual environment variables from “secret-db” object
- It stores data as key-value pair.
- It stored in memory and never saved to physical disk.
- It helps us to separate application specific configurations from the code.
- Each Pod uses Secrets values as environment variables or volumes.
- It supports passing key value as base64 string or plain text.
- Key-value pair must be part of “data” or “stringData” attribute
- Key name must contain alphanumeric, dash (-), underscore (_), dot(.) only
apiVersion: v1
kind: Secret
metadata:
name: secret-db
data:
db_name: "cmFtYQo="
db_password: "cGFzc3dvcmQK"
apiVersion: v1
kind: Secret
metadata:
name: secret-db
stringData:
db_name: "rama"
db_password: "password"
Kubernetes provides different built-in secret types for handling common use cases. We use “Opaque” type for storing application related credentials.
Type |
Description |
Opaque |
used for creating user-defined
data |
kubernetes.io/service-account-token |
used for mapping service account
token |
kubernetes.io/dockercfg |
used for storing credentials for accessing private docker registry images |
kubernetes.io/basic-auth |
used for storing credentials for
basic authentication |
kubernetes.io/ssh-auth |
Used for storing SSH privatekey
for SSH tunneling |
kubernetes.io/tls |
Used for storing TLS certificate
details. |
Create Secret
There are multiple ways to create K8 Secret object- from YAML file
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: secret-db
data:
db_name: "cmFtYQo="
db_password: "cGFzc3dvcmQK"
As we are using data attribute, we should pass key values in the base64 encoded string format
Save above yaml content as "secret-db.yaml" and run following kubectl command
// create secret object from yaml file
$ kubectl apply -f secret-db.yaml
secret/secret-db created
// display all secret objects
$ kubectl get secret
NAME TYPE DATA AGE
secret-db Opaque 2 18s
// view secret object details using describe command
$ kubectl describe secret secret-db
// view secret object details as yaml file
$ kubectl get secret secret-db -o yaml
// decore base64 string
$ echo "cmFtYQo=" | base64 --decode
rama
2. from literals
In this approach, we pass key-value pair as part of kubectl command directly.
// create secret object from literals
// syntax
// kubectl create secret <secret-type> <secret-name> --from-literal=<key_name>=<key_value>
// we should use "generic" for "Opaque" secret type
$ kubectl create secret generic secret-db-test --from-literal=db_name=rama --from-literal=db_password=password
secret/secret-db-test created
// display all secret objects
$ kubectl get secret
NAME TYPE DATA AGE
secret-db-test Opaque 2 6s
// view secret object details using describe command
$ kubectl describe secret secret-db-test
// view secret object details as yaml file
$ kubectl get secret secret-db-test -o yaml
Passing Secret values to Pod
1. passing Secret values to container environment variables
apiVersion: v1
kind: Pod
metadata:
name: secret-pod
spec:
containers:
- name: busybox
image: k8s.gcr.io/busybox
command: ["/bin/sh", "-c", "env"]
env:
- name: DATABASE_HOST
value: "myrds.amazon.com"
- name: DATABASE_USER_NAME
valueFrom:
secretKeyRef:
name: secret-db
key: db_name
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: secret-db
key: db_password
save above yaml content as "secret-pod-valuefrom.yaml" and run following kubectl command
// create busybox Pod
$ kubectl apply -f secret-pod-valuefrom.yaml
pod/secret-pod created
// check environment values from busybox Pod
// secret values will be decoded to plaintext automatically when Pod is consuming
$ kubectl logs pod/secret-pod | grep DATABASE
DATABASE_USER_NAME=rama
DATABASE_PASSWORD=password
DATABASE_HOST=myrds.amazon.com
2. passing complete Secret Object as environment variables to the container
In the below example, we are passing all "secret-db" object key-value pairs as container environment variables.
apiVersion: v1
kind: Pod
metadata:
name: secret-pod-env
spec:
containers:
- name: busybox
image: k8s.gcr.io/busybox
command: ["/bin/sh", "-c", "env"]
envFrom:
- secretRef:
name: secret-db
save above yaml content as "configmap-pod-envfrom.yaml" and run following kubectl command
// create busybox Pod
$ kubectl apply -f secret-pod-envfrom.yaml
pod/secret-pod-env created
// check environment values from busybox Pod
$ kubectl logs pod/secret-pod-env | grep db
db_password=password
db_name=rama
3. Attaching Secret as container volume
In the below example, - we are first creating volumes by setting secretName property as "secret-db"
- we are accessing this volume by setting volumeMounts property
apiVersion: v1
kind: Pod
metadata:
name: secret-pod-volume
spec:
containers:
- name: busybox
image: k8s.gcr.io/busybox
command: ["/bin/sh", "-c", "ls /etc/secret/"]
volumeMounts:
- name: secret-volume
mountPath: /etc/secret
volumes:
- name: secret-volume
secret:
secretName: secret-db
save above yaml content as "secret-pod-volume.yaml" and run following kubectl command
// create busybox Pod
$ kubectl apply -f secret-pod-volume.yaml
pod/secret-pod-volume created
// check logs from busybox Pod
$ kubectl logs pod/secret-pod-volume
db_name
db_password
Kubernetes for Developers Journey.
- Kubernetes for Developers #25: PersistentVolume and PersistentVolumeClaim in-detail
- Kubernetes for Developers #24: Kubernetes Volume hostPath in-detail
- Kubernetes for Developers #23: Kubernetes Volume emptyDir in-detail
- Kubernetes for Developers #22: Access to Multiple Clusters or Namespaces using kubectl and kubeconfig
- Kubernetes for Developers #21: Kubernetes Namespace in-detail
- Kubernetes for Developers #20: Create Automated Tasks using Jobs and CronJobs
- Kubernetes for Developers #19: Manage app credentials using Kubernetes Secrets
- Kubernetes for Developers #18: Manage app settings using Kubernetes ConfigMap
- Kubernetes for Developers #17: Expose service using Kubernetes Ingress
- Kubernetes for Developers #16: Kubernetes Service Types - ClusterIP, NodePort, LoadBalancer and ExternalName
- Kubernetes for Developers #15: Kubernetes Service YAML manifest in-detail
- Kubernetes for Developers #14: Kubernetes Deployment YAML manifest in-detail
- Kubernetes for Developers #13: Effective way of using K8 Readiness Probe
- Kubernetes for Developers #12: Effective way of using K8 Liveness Probe
- Kubernetes for Developers #11: Pod Organization using Labels
- Kubernetes for Developers #10: Kubernetes Pod YAML manifest in-detail
- Kubernetes for Developers #9: Kubernetes Pod Lifecycle
- Kubernetes for Developers #8: Kubernetes Object Name, Labels, Selectors and Namespace
- Kubernetes for Developers #7: Imperative vs. Declarative Kubernetes Objects
- Kubernetes for Developers #6: Kubernetes Objects
- Kubernetes for Developers #5: Kubernetes Web UI Dashboard
- Kubernetes for Developers #4: Enable kubectl bash autocompletion
- Kubernetes for Developers #3: kubectl CLI
- Kubernetes for Developers #2: Kubernetes for Local Development
- Kubernetes for Developers #1: Kubernetes Architecture and Features
Happy Coding :)
Comments
Post a Comment