Cómo guardar secretos con Docker

Todos conocemos ya la nueva funcionalidad de docker añadida en la versión 1.13 (a.k.a. 17.03) los secretos. Esta nueva funcionalidad surge para proteger de miradas indiscretas los usuarios y passwords para las aplicaciones, montando únicamente en ejecución el contenido del objeto y así poder usarlo; no podemos recuperar su contenido salvo que sea usado en un contenedor.

Los secretos son objetos clave-valor que se almacenan en la base de datos distribuida del cluster de swarm. Podremos usar cadenas de caracteres y ficheros; lo que nos lleva rápidamente a observar que tenemos una nueva forma muy sencilla de configurar nuestros servicios en el cluster. Hasta ahora, crear un servicio sobre swarm suponía tener la configuración del mismo dentro de la imagen, disponible en todos los hosts de forma local o bien montada mediante almacenamiento de red (por ejemplo usando NFS). Pero los secretos pueden contener ficheros por lo que podemos usarlos para gestionar de forma sencilla las configuraciones de los servicios dado que la información estará disponible en todos los hosts que ejecutan alguna tarea del servicio.

Veamos esto con un sencillo ejemplo. Supongamos un servicio de publicación web con NGINX con una configuración dada en un fichero mynginx.conf con el siguiente contenido (una configuración muy sencilla para poder verificar el ejemplo).

$ cat mynginx.conf

daemon off;

worker_processes 1;

events {

worker_connections 1024;

}

http {

default_type application/octet-stream;

sendfile on;

keepalive_timeout 65;

server {

listen 80;

server_name localhost;

location / {

root /html;

index index.html index.htm;

}

error_page 500 502 503 504 /50x.html;

location = /50x.html {

root /html;

}

}

}

Crearemos un objeto de tipo secret con el fichero de configuración anterior, de la siguiente forma:

$ docker secret create mynginxconfig mynginx.conf

md7zgqht3vl91k6moi3piwdh4

Verificamos la existencia del “secreto” creado.

$ docker secret ls

md7zgqht3vl91k6moi3piwdh4 mynginxconfig 8 seconds ago 8 seconds ago

Crearemos una imagen que incluya como línea de comandos de inicio con la configuración especificada, por ejemplo “nginx -c /run/secrets/mynginx.conf”.

$ cat Dockerfile

FROM nginx:alpine

CMD nginx -c /run/secrets/mynginx.conf

VOLUME /html

Y ahora creamos un servicio con esta imagen de la siguiente forma:

$ docker service create –name mywebserver \

–replicas 5 \

–secret source=mynginxconfig,target=mynginx.conf,mode=0400 \

–publish 8080:80 mynginx

Al crear este servicio en el cluster swarm con 5 réplicas, se crearán 5 tareas para mantener el estado solicitado; lo que supone la ejecución de 1 contenedor por tarea en los diferentes hosts hasta alcanzar el número de tareas solicitado. Para poder arrancar nginx necesita el fichero de configuración especificado, que estará disponible ya que hemos usado el secreto mynginxconfig, cuyo contenido es el fichero de configuración mynginx.conf.

Pero qué ocurre si queremos modificar la configuración de mi servicio. Los objetos de tipo secreto no pueden modificarse, sólo “rotar”; lo que supone borrar y añadir su contenido de nuevo. Veamos esto con el ejemplo anterior:

Creamos primero una nueva configuración y la añadimos a la base de datos distribuida como secreto:

$ docker secret create \

mynginxconfig_NEW mynginx_NEW.conf

$ docker service update \

–secret-rm mynginxconfig mywebserver

$ docker service update \

–secret-add source=mynginxconfig_NEW,target=mynginx.conf mywebserver

La actualización del servicio supone el reinicio del mismo por lo que nuestro servidor web se iniciará con los nuevos valores.

En este ejemplo hemos pasado por alto algo que en la filosofía DevOps es fundamental, la gestión de versiones, tan importante en entornos dinámicos con gran cantidad de cambios. En el ejemplo hemos usado “_NEW” para diferenciar el cambio, pero siempre podríamos haber usado un versionado real. Además, estas configuraciones estarían gestionadas por un sistema de gestión de código como git; de manera que si añadimos nuestra herramienta favorita de ejecución de tareas en integración contínua, podríamos tener un entorno automatizado de despliegue/cambio de configuraciones con versionado y distribuidas en el cluster.

Por su parte, Docker Datacenter añade la capa de gestión de accesos necesaria para que cada grupo de usuarios sea creador y validador de las configuraciones de sus aplicativos y el resto de usuarios podría ni siquiera poder leerlos, o simplemente usar estas configuraciones sin poder cambiarlas.

En este ejemplo hemos visto lo sencillo que resulta gestionar configuraciones usando los secretos. Es posible que en un futuro cercano exista un objeto específico para almacenar configuraciones en el cluster, pero hasta que llegue ese momento esta alternativa que hemos comprobado resulta funcional.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.