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 ejecuta systemctl 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

Acerca del proyecto

Deploy an Elixir app

Instalar
ansible-galaxy install cogini.elixir-release
Licencia
mit
Descargas
108
Propietario
Product development services for ambitious innovators