Saturday, July 17, 2021

Kubernetes for Developers #19: Manage app credentials using Kubernetes Secrets

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.
  • 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
base64 encoded key-value pair

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.

apiVersionv1
kindSecret
metadata:
  namesecret-db
data:
  db_name"cmFtYQo="
  db_password"cGFzc3dvcmQK"

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.

apiVersionv1
kindSecret
metadata:
  namesecret-db
stringData:
  db_name"rama"
  db_password"password"

Types of Secret

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
  1. from YAML file
apiVersionv1
kindSecret
typeOpaque
metadata:
  namesecret-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

       In the below example, we are setting Pod container individual environment variables from “secret-db” object
apiVersionv1
kindPod
metadata:
  namesecret-pod
spec:
  containers:
    - namebusybox
      imagek8s.gcr.io/busybox
      command: ["/bin/sh""-c""env"]
      env:
        - nameDATABASE_HOST
          value"myrds.amazon.com"
        - nameDATABASE_USER_NAME
          valueFrom:
            secretKeyRef:
              namesecret-db
              keydb_name
        - nameDATABASE_PASSWORD
          valueFrom:
            secretKeyRef:
              namesecret-db
              keydb_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.
apiVersionv1
kindPod
metadata:
  namesecret-pod-env
spec:
  containers:
    - namebusybox
      imagek8s.gcr.io/busybox
      command: ["/bin/sh""-c""env"]
      envFrom:
        - secretRef:
            namesecret-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
apiVersionv1
kindPod
metadata:
  namesecret-pod-volume
spec:
  containers:
    - namebusybox
      imagek8s.gcr.io/busybox
      command: ["/bin/sh""-c""ls /etc/secret/"]
      volumeMounts:
        - namesecret-volume
          mountPath/etc/secret
  volumes:
    - namesecret-volume
      secret:
        secretNamesecret-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.
Happy Coding :)

No comments:

Post a Comment