Gestionar información sensible en Kubernetes con secretos

Otro de los objetos que debes utilizar cuando trabajas con Kubernetes es el llamado secret. Es la forma recomendada de almacenar contraseñas, tokens, etc. de manera segura en el clúster, para que tus pods utilicen información sensible sin que esté harcodeada. En este artículo te cuento cómo usarlos.

Crear secretos

Siguiendo con el mismo ejemplo del artículo anterior, voy a crear un secreto con el nombre de usuario y la contraseña para nuestro postgres, el cual hasta ahora no tenía definidos ninguno.

Lo primero que vamos a hacer es crear dos archivos: uno contendrá el nombre de usuario y el otro la nueva contraseña:

#Echo user name in a file
echo -n 'returngis' > ./username.txt
#Echo password in a file
echo -n 'MyPassw0rd!' > ./password.txt

El siguiente paso es crear el secreto con ambos archivos:

#Create secret for the user name and password
kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt

También se puede utilizar –from-literal en lugar de –from-file pero entonces debes tener en cuenta que debes tener cuidado con los caracteres especiales.

Para listar todos los secretos disponibles en tu clúster puedes invocar el siguiente comando:

#List secrets
kubectl get secrets

El resultado será parecido al siguiente:

kubectl get secrets

Este mismo proceso se puede hacer de diferentes maneras tal y como se explica en la documentación oficial, pero creo que lo interesante ahora mismo es que sepas que existe este tipo de objeto y cómo se usa en lineas generales. Un punto que sí que es importante es que estos secretos se almacenan en la base de datos etc con la única protección de estar codificados en base 64.

Cómo usar los secretos

Ahora que ya tienes al menos un secreto creado vamos a ver cómo usarlo. Existen dos maneras de consumir los secretos: montándolos como volumen y accediendo desde el pod como si de un archivo más se tratara o bien a través de las variables de entorno. En este caso vamos a usarlo como variables de entorno para definir durante la creación del pod el nombre de usuario y la contraseña que queremos utilizar para acceder:

#deploy-pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres-deployment
  labels:
    app: postgres
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: mypostgres
        image: postgres
        env:
        - name: POSTGRES_USER
          valueFrom:
            secretKeyRef:
              name: db-user-pass
              key: username.txt
        - name: POSTGRES_PASSWORD
          valueFrom:
             secretKeyRef:
              name: db-user-pass
              key: password.txt
        volumeMounts:
          - name: postgres-data
            mountPath: /var/lib/postgresql/data
            subPath: postgres
      volumes:
      - name: postgres-data
        persistentVolumeClaim:
          claimName: azure-managed-disk

Como ves, en el apartado env de la definición del pod utilizo el secreto db-user-pass para especificar tanto el nombre de usuario como la contraseña. ¿Cómo sé la key que debo utilizar dentro de mi secret db-user-pass? Puedes ver todas las claves que tienes dentro de un secreto a través del siguiente comando:

#Describe secret
kubectl describe secret db-user-pass

En el apartado Data tienes todas las claves contenidas dentro de este secreto.

kubectl describe secret db-user-pass

Ejecuta este despliegue en tu clúster a través del siguiente comando:

kubectl apply -f deploy-pod.yaml

Por último, necesitamos comprobar que puedes acceder sin problemas a tu base de datos con el usuario y contraseña que has almacenado dentro de tu secreto. Para ello debes exponer antes tu despliegue a través del siguiente comando:

kubectl expose deployment/postgres-deployment --type LoadBalancer --port 5432 --protocol TCP

En este caso, estoy utilizando Azure Kubernetes Service y necesitaré esperar unos minutos hasta que me dé una IP pública asociada a mi despliegue. Para no tener que comprobarlo manualmente puedes lanzar este otro comando:

kubectl get services --watch

Una vez que tengas una IP asignada, puedes utilizar cualquier cliente de posgres, por ejemplo DataGrip, para intentar llevar a cabo la conexión con tu base de datos con el usuario y contraseña especificado a través de tu secreto.

O bien a través de un contenedor de Docker con los siguientes parámetros:

#Using postgres client via Docker
docker run -it --rm postgres psql -h YOUR_IP -U returngis -d postgres

#List users
\du

¡Saludos!