cogini.elixir-release

elixir-release

此 Ansible 角色用于部署 Elixir/Phoenix 版本。

它使用 Erlang 的“版本”,并通过 systemd 进行进程监控,具体内容请查看 "使用 Ansible 部署 Elixir 应用" 和 "部署 Elixir 应用的最佳实践".

目录结构

它使用类似 Capistrano 的结构来管理发布文件。基础目录以应用名称命名,例如 /srv/foo,其下有一个 releases 目录。 当角色部署一个版本时,会创建一个以时间戳命名的目录,例如 /srv/foo/releases/20190603T072116。 它将在该目录下解压文件,并从 /srv/foo/current 创建一个指向新目录的符号链接。

重启

部署版本后,它会重启应用使其生效。

默认情况下,当 elixir_release_restart_method: systemctl 时,会通过运行以下命令进行重启:

sudo /bin/systemctl restart foo

部署用户账户需要有足够的权限来重启应用。为了不赋予部署账户完全的 sudo 权限,可以使用用户特定的 sudo 配置文件来指定可运行的命令,例如 /etc/sudoers.d/deploy-foo

deploy ALL=(ALL) NOPASSWD: /bin/systemctl start foo, /bin/systemctl stop foo, /bin/systemctl restart foo

更好的方法是不需要 sudo 权限。一个选择是利用 systemd 来重启应用。

设置 elixir_release_restart_method: systemd_flag,部署过程将在代码部署后在磁盘上创建一个 /srv/foo/flags/restart.flag 文件。 systemd 会注意到这个变化,并使用新代码重启应用。

有关完整示例,请参见 mix-deploy-example

示例剧本

一个用于名为 foo 的应用的最小剧本:

- hosts: '*'
  become: true
  vars:
    elixir_release_app_name: foo
  roles:
    - cogini.elixir-release

将其放入 ansible/playbooks/deploy-app.yml

首先,设置目标机器,例如安装软件包和创建目录。 从开发机器运行以下命令,指定一个具有 sudo 权限的用户:

ansible-playbook -u $USER -v -l web_servers playbooks/deploy-app.yml --skip-tags deploy -D

接下来,部署代码。 从构建服务器运行此命令,使用具有 ssh 访问目标机器上部署账户的用户账户:

ansible-playbook -u deploy -v -l web_servers playbooks/deploy-app.yml --tags deploy --extra-vars ansible_become=false -D

一个更复杂的定制剧本:

- 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_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 }}"
    elixir_release_src_dir: "{{ playbook_dir }}/../../../foo"
  roles:
    - cogini.elixir-release

角色变量

构建发布所用的系统,可以是 "mix" 或 "distillery"。

elixir_release_release_system: "mix"

获取发布文件的应用位置。默认假设在应用源中有一个 ansible 目录。

elixir_release_app_dir: "{{ role_path }}/../../.."

Erlang 应用名称,用于 Distillery 命名目录和脚本。

elixir_release_app_name: my_app

发布名称,默认是 app_name,但通常是 MIX_ENV。

elixir_release_release_name: "{{ elixir_release_app_name }}"

应用的外部名称,用于命名 systemd 服务和目录。默认情况下,它将下划线转换为破折号:

elixir_release_service_name: "{{ elixir_release_app_name | replace('_', '-') }}"

Elixir 应用名称。默认是应用名称的驼峰版本:

elixir_release_app_module: "{{ elixir_release_service_name.title().replace('_', '') }}"

要发布的应用版本。如果不指定,将从发布目录中的 start_erl.data 文件读取。

elixir_release_version: "0.1.0"

出于安全原因,我们使用不同的账户来部署和运行应用。部署账户拥有代码和配置文件,并有权限重启应用。我们通常使用名为 deploy 的账户。应用在一个具有最低权限的单独账户下运行。我们通常创建一个与应用匹配的名称,如 foo,或使用像 app 这样的通用名称。

发布文件的所有者为 deploy:app,模式为 0644,以便应用能够读取它们。

部署和拥有发布文件的 OS 账户:

elixir_release_deploy_user: deploy

部署和拥有发布文件的 OS 组:

elixir_release_deploy_group: "{{ elixir_release_deploy_user }}"

应用运行的 OS 账户:

elixir_release_app_user: "{{ elixir_release_service_name }}"

应用运行的 OS 组:

elixir_release_app_group: "{{ elixir_release_app_user }}"

应用发布环境,即 MIX_ENV 的设置,用于在 _build 目录下查找发布文件:

elixir_release_mix_env: prod

发布文件的目录前缀:

elixir_release_base_dir: /srv

部署文件的基础目录:

elixir_release_deploy_dir: "{{ elixir_release_base_dir }}/{{ elixir_release_service_name }}"

部署目录下的各个目录。

发布 tarball 解压的位置:

elixir_release_releases_dir: "{{ elixir_release_deploy_dir }}/releases"

当前运行的版本(符号链接):

elixir_release_current_dir: "{{ elixir_release_deploy_dir }}/current"

部署脚本的位置:

elixir_release_scripts_dir: "{{ elixir_release_deploy_dir }}/bin"

标志文件目录,用于发出重启信号:

elixir_release_flags_dir: "{{ elixir_release_deploy_dir }}/flags"

应用保持文件的目录,遵循 systemd 的规范。

elixir_release_app_dirs:
  - configuration
  - runtime

是否使用 conform:

elixir_release_conform: false
elixir_release_conform_conf_path: "{{ elixir_release_configuration_dir }}/config.conform"

我们应如何重启应用:

elixir_release_restart_method: systemctl
# elixir_release_restart_method: systemd_flag
# elixir_release_restart_method: touch

选项是:

  • systemctl,运行 systemctl restart foo
  • systemd_flag,触碰文件 {{ elixir_release_shutdown_flags_dir }}/restart.flag
  • touch,触碰文件 {{ elixir_release_shutdown_flags_dir }}/restart.flag。目录权限为 0770,允许管理的进程自行重启。

哪些用户被允许使用 sudo /bin/systemctl restart 重启应用,当方法 == systemctl 时。

elixir_release_restart_users:
    - "{{ elixir_release_deploy_user }}"

设置为 [] 时,任何人都无法重启,也可添加其他名称,例如 - "{{ elixir_release_app_user }}"

systemd 和脚本

默认情况下,此角色假设您正在使用 mix_systemd 来生成 systemd 单元文件,并使用 mix_deploy 来生成生命周期脚本。

elixir_release_systemd_source 控制 systemd 单元文件的来源。

elixir_release_systemd_source: mix_systemd

在默认值为 mix_systemd 的情况下,角色从 _build/{{ elixir_release_mix_env }}/systemd 目录复制 systemd 单元文件。如果将其设置为 self,该角色将从模板生成 systemd 单元文件。

elixir_release_scripts_source 控制脚本的来源。

elixir_release_scripts_source: bin

在默认值为 bin 的情况下,角色将脚本从项目的 bin 目录复制到目标系统的 /srv/foo/bin。如果在 mix_deploy 配置中设置了 output_dir_per_env: true,将 elixir_release_scripts_source 设置为 mix_deploy,则生成的脚本会存储在 _build 下。

以下变量用于生成 systemd 单元文件:

应用监听 HTTP 连接的端口:

elixir_release_http_listen_port: 4000

应用监听 HTTPS 连接的端口:

elixir_release_https_listen_port: 4001

打开文件限制:

elixir_release_limit_nofile: 65536

重启之间的等待秒数:

elixir_release_systemd_restart_sec: 5

LANG 环境变量:

elixir_release_lang: "en_US.UTF-8"

umask:

elixir_release_umask: "0027"

目标 systemd 版本,用于启用更多高级功能:

elixir_release_systemd_version: 219

Systemd 服务类型:simple | exec | notify | forking 请参阅 systemd Type

启动应用的发布命令。mix 使用 start(simple)和 daemon(forking)。distillery 使用 foreground(simple)和 start(forking)。

elixir_release_start_command: start

使用 fork 服务类型时的 PID 文件:

elixir_release_pid_file: "{{ elixir_release_runtime_dir }}/{{ elixir_release_app_name}}.pid"

systemd 单元文件中 ExecStartPre 脚本的列表:

elixir_release_exec_start_pre: []

在 systemd 单元文件中设置的环境变量列表:

elixir_release_env_vars: []

依赖关系

要求

许可证

MIT

作者信息

Jake Morrison jake@cogini.com

关于项目

Deploy an Elixir app

安装
ansible-galaxy install cogini.elixir-release
许可证
mit
下载
108
拥有者
Product development services for ambitious innovators