cogini.elixir-release
elixir-release
Esta función de Ansible despliega lanzamientos de Elixir/Phoenix.
Utiliza "lanzamientos" de Erlang con systemd para la supervisión de procesos, como se describe en "Desplegando aplicaciones Elixir con Ansible" y "Mejores prácticas para desplegar aplicaciones Elixir".
Estructura de directorios
Utiliza una estructura similar a Capistrano para gestionar los archivos de lanzamiento. El directorio base se nombra según la aplicación, por ejemplo, /srv/foo
, con un directorio releases
debajo de él. Cuando la función despliega un lanzamiento, crea un directorio con una marca de tiempo, por ejemplo, /srv/foo/releases/20190603T072116
. Descomprime los archivos en él y crea un enlace simbólico de /srv/foo/current
al nuevo directorio.
Reiniciando
Después de desplegar el lanzamiento, reinicia la aplicación para que esté activa.
Por defecto, cuando elixir_release_restart_method: systemctl
, lo hace ejecutando:
sudo /bin/systemctl restart foo
La cuenta de usuario que despliega necesita permisos suficientes para reiniciar la aplicación. En lugar de dar permisos sudo completos a la cuenta de despliegue, un archivo de configuración sudo específico del usuario especifica qué comandos puede ejecutar, por ejemplo, /etc/sudoers.d/deploy-foo
:
deploy ALL=(ALL) NOPASSWD: /bin/systemctl start foo, /bin/systemctl stop foo, /bin/systemctl restart foo
Es mejor si no necesitamos permisos sudo en absoluto. Una opción es aprovechar systemd para reiniciar la aplicación.
Configura elixir_release_restart_method: systemd_flag
, el proceso de despliegue toca un archivo /srv/foo/flags/restart.flag
en el disco después de desplegar el código. Systemd lo nota y lo reinicia con el nuevo código.
Consulta mix-deploy-example para un ejemplo completo.
Ejemplo de Playbook
Un playbook mínimo para una aplicación llamada foo
:
- hosts: '*'
become: true
vars:
elixir_release_app_name: foo
roles:
- cogini.elixir-release
Coloca esto en ansible/playbooks/deploy-app.yml
.
Primero, configura la máquina de destino, por ejemplo, instalando paquetes y creando directorios. Ejecuta esto desde tu máquina de desarrollo, especificando un usuario con permisos sudo:
ansible-playbook -u $USER -v -l web_servers playbooks/deploy-app.yml --skip-tags deploy -D
Luego, despliega el código. Ejecuta esto desde el servidor de construcción, desde una cuenta de usuario con acceso ssh a la cuenta de despliegue en la máquina de destino:
ansible-playbook -u deploy -v -l web_servers playbooks/deploy-app.yml --tags deploy --extra-vars ansible_become=false -D
Un playbook más personalizado:
- hosts: '*'
become: true
vars:
elixir_release_app_name: foo
elixir_release_app_user: bar
elixir_release_deploy_user: deploy
elixir_release_mix_env: frontend
# elixir_release_release_name: "{{ elixir_release_mix_env }}"
# elixir_release_release_system: distillery
# elixir_release_start_command: foreground
elixir_release_systemd_source: mix_systemd
elixir_release_base_dir: /opt/bar
elixir_release_app_dirs:
- configuration
- runtime
- logs
- tmp
- state
- cache
elixir_release_tmp_directory_base: /var/tmp/bar
elixir_release_state_directory_base: /var/bar
elixir_release_http_listen_port: 8080
elixir_release_cache_directory_mode: 0700
elixir_release_configuration_directory_mode: 0755
elixir_release_logs_directory_mode: 0755
elixir_release_state_directory_mode: 0755
elixir_release_tmp_directory_mode: 0755
elixir_release_sudoers_file: "{{ elixir_release_app_user }}-{{ elixir_release_service_name }}"
# Ubicación de la aplicación fuente, asumiendo que los scripts de despliegue están en un repositorio separado en un directorio paralelo
elixir_release_src_dir: "{{ playbook_dir }}/../../../foo"
roles:
- cogini.elixir-release
Variables del rol
Sistema utilizado para construir los lanzamientos, ya sea "mix" o "distillery".
elixir_release_release_system: "mix"
Ubicación de la aplicación para obtener los archivos de lanzamiento. Por defecto, se asume que tienes un directorio ansible
en el código fuente de tu aplicación.
elixir_release_app_dir: "{{ role_path }}/../../.."
Nombre Erlang de la aplicación, utilizado por Distillery para nombrar directorios y scripts.
elixir_release_app_name: my_app
Nombre del lanzamiento, por defecto app_name
, pero a menudo es MIX_ENV.
elixir_release_release_name: "{{ elixir_release_app_name }}"
Nombre externo de la aplicación, utilizado para nombrar el servicio systemd y directorios. Por defecto, convierte guiones bajos en guiones:
elixir_release_service_name: "{{ elixir_release_app_name | replace('_', '-') }}"
Nombre de la aplicación en Elixir. Por defecto, es la versión CamelCase del nombre de la aplicación:
elixir_release_app_module: "{{ elixir_release_service_name.title().replace('_', '') }}"
Versión de la aplicación a lanzar. Si no se especifica, se leerá del archivo start_erl.data
en el directorio de lanzamiento.
elixir_release_version: "0.1.0"
Por motivos de seguridad, utilizamos cuentas separadas para desplegar y ejecutar la aplicación. La cuenta de despliegue posee el código y los archivos de configuración, y tiene derechos para reiniciar la aplicación. Normalmente utilizamos una cuenta separada llamada deploy
. La aplicación se ejecuta bajo una cuenta separada con los permisos mínimos necesarios. Normalmente creamos un nombre que coincida con la aplicación, por ejemplo, foo
o usamos un nombre genérico como app
.
Los archivos de lanzamiento son propiedad de deploy:app
con modo 0644 para que la aplicación pueda leerlos.
Cuenta de sistema que despliega y posee los archivos de lanzamiento:
elixir_release_deploy_user: deploy
Grupo de sistema que despliega y posee los archivos de lanzamiento:
elixir_release_deploy_group: "{{ elixir_release_deploy_user }}"
Cuenta de sistema bajo la cual se ejecuta la aplicación:
elixir_release_app_user: "{{ elixir_release_service_name }}"
Grupo de sistema bajo el cual se ejecuta la aplicación:
elixir_release_app_group: "{{ elixir_release_app_user }}"
Entorno de lanzamiento de la aplicación, es decir, la configuración de MIX_ENV
, utilizada para encontrar el archivo de lanzamiento en el directorio _build
:
elixir_release_mix_env: prod
Prefijo de directorio para los archivos de lanzamiento:
elixir_release_base_dir: /srv
Directorio base para archivos de despliegue:
elixir_release_deploy_dir: "{{ elixir_release_base_dir }}/{{ elixir_release_service_name }}"
Directorios bajo el directorio de despliegue.
Donde se descomprimen los archivos comprimidos de lanzamiento:
elixir_release_releases_dir: "{{ elixir_release_deploy_dir }}/releases"
Lanzamiento actualmente en ejecución (enlace simbólico):
elixir_release_current_dir: "{{ elixir_release_deploy_dir }}/current"
Ubicación de los scripts de despliegue:
elixir_release_scripts_dir: "{{ elixir_release_deploy_dir }}/bin"
Directorio del archivo de bandera, utilizado para señalizar el reinicio:
elixir_release_flags_dir: "{{ elixir_release_deploy_dir }}/flags"
Directorios donde la aplicación guarda sus archivos, siguiendo systemd.
elixir_release_app_dirs:
- configuration
- runtime
# - logs
# - tmp
# - state
# - cache
Si se debe usar conform:
elixir_release_conform: false
elixir_release_conform_conf_path: "{{ elixir_release_configuration_dir }}/config.conform"
Cómo debemos reiniciar la aplicación:
elixir_release_restart_method: systemctl
# elixir_release_restart_method: systemd_flag
# elixir_release_restart_method: touch
Las opciones son:
systemctl
, que ejecutasystemctl restart foo
systemd_flag
, que toca el archivo{{ elixir_release_shutdown_flags_dir }}/restart.flag
touch
, que toca el archivo{{ elixir_release_shutdown_flags_dir }}/restart.flag
. Los permisos del directorio son 0770, permitiendo que el proceso administrado se reinicie a sí mismo.
Qué usuarios están permitidos para reiniciar la aplicación usando sudo /bin/systemctl restart
cuando el método es systemctl
.
elixir_release_restart_users:
- "{{ elixir_release_deploy_user }}"
Configúralo como []
y nadie podrá reiniciar, o añade nombres adicionales, por ejemplo, - "{{ elixir_release_app_user }}"
.
systemd y scripts
Por defecto, esta función asume que estás utilizando mix_systemd para generar el archivo de unidad de systemd y mix_deploy para generar scripts de ciclo de vida.
elixir_release_systemd_source
controla la fuente del archivo de unidad de systemd.
elixir_release_systemd_source: mix_systemd
Con el valor por defecto de mix_systemd
, la función copia los archivos de unidad de systemd del directorio _build/{{ elixir_release_mix_env }}/systemd
. Configúralo como self
, y esta función generará un archivo de unidad de systemd a partir de una plantilla.
elixir_release_scripts_source
controla la fuente de los scripts.
elixir_release_scripts_source: bin
Con el valor por defecto de bin
, la función copia scripts desde el directorio bin
del proyecto a /srv/foo/bin
en el sistema de destino. Configúralo como mix_deploy
si has establecido output_dir_per_env: true
en la configuración de mix_deploy
, almacenando los scripts generados en _build
.
Las siguientes variables se usan al generar el archivo de unidad de systemd:
Puerto que la aplicación escucha para conexiones HTTP:
elixir_release_http_listen_port: 4000
Puerto que la aplicación escucha para conexiones HTTPS:
elixir_release_https_listen_port: 4001
Límite de archivos abiertos:
elixir_release_limit_nofile: 65536
Segundos a esperar entre reinicios:
elixir_release_systemd_restart_sec: 5
Variable de entorno LANG
:
elixir_release_lang: "en_US.UTF-8"
umask:
elixir_release_umask: "0027"
Versión objetivo de systemd, utilizada para habilitar características más avanzadas:
elixir_release_systemd_version: 219
Tipo de servicio systemd: simple | exec | notify | forking Consulta el Tipo de systemd.
elixir_release_service_type: simple
Comando de lanzamiento para ejecutar al iniciar la aplicación. mix usa start para simple, daemon para forking. distillery usa foreground para simple, start para forking.
elixir_release_start_command: start
Archivo PID cuando se usa el tipo de servicio forking:
elixir_release_pid_file: "{{ elixir_release_runtime_dir }}/{{ elixir_release_app_name}}.pid"
Lista de scripts ExecStartPre en el archivo de unidad de systemd:
elixir_release_exec_start_pre: []
Lista de variables de entorno a establecer en el archivo de unidad de systemd:
elixir_release_env_vars: []
Dependencias
Ninguna
Requisitos
Ninguno
Licencia
MIT
Información del Autor
Jake Morrison jake@cogini.com
ansible-galaxy install cogini.elixir-release