¿Cómo debo almacenar mis variables de entorno?

11

Esta es una pregunta muy amplia sobre métodos y consejos sobre variables / estructura del entorno. Pero en última instancia, estoy buscando respuestas para la pregunta muy específica de '¿Cómo debo almacenar mis variables de entorno?'

En primer lugar algunas aclaraciones:

  • Para mí, un entorno puede ser de 3 a 10 servidores y es una forma de contener la infraestructura de un cliente específico.
  • Dentro de cada entorno hay algunas variables que en su mayoría se generan automáticamente a partir de algunas entradas clave (nombre, tamaño, etc.).

Tal como está ahora, estamos almacenando todas nuestras variables de entorno en una estructura como esta:

<playbook>.yml                   # Various playbooks for deployment
roles/windows                    # Ansible role for Ubuntu
roles/ubuntu                     # Ansible role for Ubuntu
config/hosts/<name>.yml          # Ansible inventory
config/hosts/vars/<name>.json    # Environment specific variables 

En este momento, la configuración se inicializa como un submódulo en el repositorio de git anterior. Como el archivo de variables cambia con bastante frecuencia, esto ha causado problemas con el cambio de datos, una, dos o incluso tres veces entre confirmaciones, lo que hace que los cambios sean cada vez más difíciles de rastrear.

Como lo veo personalmente en el futuro, deberíamos buscar almacenar todas nuestras variables de cliente de forma centralizada / escalable y luego conectarlo con un inventario dinámico con .

Entiendo que hay algunas tecnologías que parecen hacer una parte de lo que se podría requerir, como el Cónsul, pero parecen funcionar mejor en un entorno que sirve para una gran aplicación en lugar de muchas más pequeñas y ligeramente diferentes.

Esencialmente, veo que tenemos que escribir un script de inventario y luego guardar todos nuestros datos en una base de datos construida sin fines específicos y luego continuar como si nada hubiera cambiado. Considero que esto es concebible como una forma de reducir potencialmente muchos de los datos que almacenamos actualmente y tal vez buscar diferentes formas de almacenar los datos en lugar de simplemente escalar lo que les sirve nuevamente.

Espero que alguien tenga algún tipo de experiencia en la implementación de infraestructura como código cuando tenga que lidiar con muchos entornos más pequeños en lugar de uno, dos o tres enormes.

¿Alguna sugerencia?

Nafta
fuente

Respuestas:

13

He tenido dos ejecuciones para hacer variables de entorno de forma escalable y ninguna de las dos ha resultado perfecta porque, como he descubierto, es muy complicado hacerlo bien. Daré un resumen de mis dos experiencias a continuación:

Factores comunes

  • Las variables de entorno se almacenan en un repositorio separado del código fuente original (se submódulan juntas pero aún se basan en repositorios separados)
  • Hay un proceso de "compilación" separado para el artefacto y sus variables.
  • Hay no un proceso de liberación separada para las variables de entorno. Si desea cambiar las variables de entorno, debe pasar por los mismos paneles de revisión de cambios y habituales

Usar pares de cónsul KV

Las variables de entorno se cargan desde un repositorio de artefactos (nunca el repositorio git original) y se cargan en un árbol de pares KV con espacio de nombres, por ejemplo

/env/dev1/my/application/v1.1.1

Donde dev1 anterior es el nombre del entorno, my / application es el espacio de nombres de la aplicación y v1.1.1 es la versión de las variables de entorno a utilizar.

Para los desarrolladores, todas estas cosas son invisibles. En el tiempo de ejecución, la plataforma verifica que el entorno exista en el clúster de cónsul actual (si no hay un problema y hay errores), luego verifica el subárbol para el espacio de nombres de las aplicaciones (de esta manera no puede haber contaminación cruzada donde una aplicación hace referencia a otras aplicaciones, luego el número de versión de la configuración se toma de la etiqueta conectada al artefacto desplegable. La actualización de esta etiqueta es la clave aquí porque significa que si perdemos ambos centros de datos de producción, podríamos defender el entorno nuevamente simplemente leyendo los metadatos de nuestros artefactos desplegables y cargando todas las variables de entorno en la tienda KV.

Problemas con este enfoque Los desarrolladores siempre, y quiero decir cada vez, encontraron una manera de deslizar los cambios de configuración en el entorno que tuvieron un impacto significativo en la forma en que se ejecutaría la aplicación. Porque siempre terminó siendo más fácil obtener los cambios de configuración aprobados que los cambios de código.

Almacenar un artefacto de "implementación" con variables incrustadas

Esto combina estrechamente la versión exacta del artefacto con la versión de configuración. Si cambió la configuración, tuvo que reconstruir este artefacto de implementación.

El artefacto de implementación en sí mismo era esencialmente un archivo yaml que contenía la URL del binario liberable y toda la configuración adjunta.

La plataforma contiene componentes para leer variables y luego sacarlas al árbol de procesos de la aplicación cuando se inicia.

Hasta ahora, esto ha tenido mucho más éxito porque hay un artefacto del que podemos rastrear la historia y que podemos sostener en cualquier panel de revisión y decir "este es el único artefacto que nos importa, no necesitamos mirarlo". cualquier otro cambio, solo cambios a esta cosa "(es decir. Versión de la aplicación a implementar, variables de entorno incluidas, etc.

Esto hace que sea un poco más difícil para los desarrolladores tratar de construir una lógica en su aplicación que cambie su comportamiento en función de las variables para que puedan introducir cambios sin pasar por los ciclos de prueba apropiados.

Puntos extra

Considere los secretos de la aplicación. Hasta ahora, nuestra solución a esto ha sido proporcionar una clave RSA pública que los equipos de desarrollo usan para cifrar un almacén de claves Java extendido (casi todos los idiomas tienen una biblioteca en algún lugar que pueda leer almacenes de claves Java), esto se trata como un tercer tipo de artefacto y se coloca en el servidor, se descifra con la clave privada de nuestra plataforma y se proporciona a la aplicación en tiempo de ejecución.

Es cierto que la gestión de secretos es su propia lata de gusanos. Pero probablemente valga la pena considerarlo.

hvindin
fuente
2
Re: secretos de la aplicación, sugeriría echar un vistazo a Vault ( vaultproject.io ), ya que también forma parte de la cadena de herramientas de Hashicorp y se integra de manera bastante clara con el cónsul (y otras herramientas de esa caja)
Michael Bravo
De hecho, me ha decepcionado mucho la bóveda dado lo bueno que suele ser el hashicorp. Esencialmente tres brechas importantes en su producto frente al resto del mercado: 1. "Secretos para secretos" es esencialmente a lo que se reduce el modelo. Me pongo fragmentos o uso un HSM. Pero esencialmente es solo comercio de secretos. 2. Compatibilidad de herramientas, a diferencia de sus otras herramientas, no hay soporte para complementos 3. Precio. No lo creí cuando le dije a la compañía con la que estoy que la bóveda era cara. Han rechazado los productos por ser demasiado baratos, está en mal estado. Pero la bóveda era tanto que ni siquiera lo consideraron.
hvindin
Vale la pena señalar que solo es prohibitivo si usa una versión paga . El producto principal de Vault es de código abierto. Por supuesto, no enumeran los precios de las versiones pro / empresariales en su sitio, por lo que no tengo idea de cuán razonable es para esas ediciones.
Adrian
Hm, no noté esa omisión en mi comentario, aunque para ser justos, mis dos primeros problemas con la bóveda siguen en pie. Aunque, para calificar, esos son mis pensamientos sobre la bóveda en comparación con otros productos de hashicorp, todos los cuales creo que son bastante buenos. En comparación con otros productos en el mercado, el desempeño de una función similar es probablemente igual, por alguna razón mucho más costosa de lo esperado.
hvindin
¿Puede dar un ejemplo de "construir lógica en su aplicación que cambie su comportamiento en función de las variables para que puedan introducir cambios sin pasar por los ciclos de prueba apropiados"? Suena como algo realmente común, pero no puedo imaginar un ejemplo concreto.
kenchew
3

Si sus entornos son por cliente, sugeriría en su caso específico tener un repositorio por cliente . (En general, es un repositorio por entorno). Este repositorio tendría una estructura de directorio estándar para variables de entorno, variables e inventarios, secretos fuertemente cifrados (tokens de acceso a cuentas, claves privadas, etc.). Git submodule el código en esos repositorios. Probablemente lo haría en múltiples repositorios. Uno para roles y módulos ansibles, uno para scripts de mantenimiento e implementación, uno para cada aplicación principal que se ejecute en los entornos.

Ahora, opcionalmente, puede bifurcar el código o fijar el submódulo en una etiqueta específica para su lanzamiento , asegurándose de que el código que administra el entorno del cliente no cambie a menos que se pruebe y se libere.

Si está utilizando un repositorio de artefactos , asegúrese de que los artefactos estén versionados correctamente y que esas versiones estén especificadas en las variables de entorno correctamente.

La automatización es importante porque las variables de entorno no deben ser actualizadas por humanos cuando sea posible, sino generadas por scripts. Asegúrese de que casi no hay actualizaciones manuales en el inventario por cliente y los desarrolladores solo actualizan los repositorios de código. Si quieren hacer un cambio de configuración, se debe hacer en uno de los scripts generadores, que luego se ejecuta para generar las variables y el diff se confirma en el repositorio del cliente. Vale la pena configurar la integración continua para este proceso. Sin esto, en algún momento habrá demasiados repositorios para mantener .

Jiri Klouda
fuente
Solo una objeción: los secretos no deben entrar en un repositorio de control de versiones a menos que tenga un estricto soporte de control de acceso. Git no lo hace: quien saca el repositorio puede ver los secretos, lo que puede ser un problema, ya no son secretos.
Dan Cornilescu
Buena atrapada. Es secretos encriptados. Las claves de descifrado son tradicionales.
Jiri Klouda