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 }}/../../.."
Distilleryがディレクトリやスクリプトの名前を付けるために使用するアプリケーションのErlang名。
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アプリケーション名。デフォルトではアプリ名のCamelCaseバージョンになります。
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
を使ってアプリを再起動できるか(method == 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
にコピーします。output_dir_per_env: true
を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を参照してください。
elixir_release_service_type: simple
アプリを起動するために実行するリリースコマンド。mixはsimpleのためにstart、forkingのためにdaemonを使用します。 distileryはsimpleのためにforeground、forkingのためにstartを使用します。
elixir_release_start_command: start
forkingサービスタイプを使用する場合の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