cogini.elixir-release
elixir-release
Diese Ansible-Rolle installiert Elixir/Phoenix Releases.
Sie verwendet Erlang "Releases" mit systemd zur Prozessüberwachung, wie in "Elixir-Apps mit Ansible bereitstellen" und "Best Practices für die Bereitstellung von Elixir-Apps" beschrieben.
Verzeichnisstruktur
Es verwendet eine Struktur ähnlich wie Capistrano zur Verwaltung der Release-Dateien. Das Basisverzeichnis trägt den Namen der Anwendung, z. B. /srv/foo
, mit einem darunter liegenden releases
-Verzeichnis. Wenn die Rolle ein Release bereitstellt, erstellt sie ein Verzeichnis mit einem Zeitstempel, z. B. /srv/foo/releases/20190603T072116
. Die Dateien werden entpackt und ein Symlink von /srv/foo/current
wird auf das neue Verzeichnis gesetzt.
Neustart
Nach der Bereitstellung des Releases wird die App neu gestartet, damit sie live wird.
Standardmäßig, wenn elixir_release_restart_method: systemctl
, geschieht dies durch die Ausführung:
sudo /bin/systemctl restart foo
Das Bereitstellungsbenutzerkonto benötigt ausreichende Berechtigungen, um die App neu zu starten. Anstatt dem Bereitstellungskonto volle sudo-Rechte zu geben, wird eine benutzerspezifische sudo-Konfigurationsdatei angegeben, die festlegt, welche Befehle ausgeführt werden können, z. B. /etc/sudoers.d/deploy-foo
:
deploy ALL=(ALL) NOPASSWD: /bin/systemctl start foo, /bin/systemctl stop foo, /bin/systemctl restart foo
Es wäre besser, wenn wir überhaupt keine sudo-Rechte benötigen würden. Eine Option ist es, systemd zu verwenden, um die App neu zu starten.
Setzen Sie elixir_release_restart_method: systemd_flag
, der Bereitstellungsprozess erstellt eine
/srv/foo/flags/restart.flag
-Datei auf der Festplatte, nachdem der Code bereitgestellt wurde. Systemd bemerkt dies und startet die App mit dem neuen Code neu.
Siehe mix-deploy-example für ein vollständiges Beispiel.
Beispiel-Playbook
Ein minimales Playbook für eine App namens foo
:
- hosts: '*'
become: true
vars:
elixir_release_app_name: foo
roles:
- cogini.elixir-release
Legen Sie dies in ansible/playbooks/deploy-app.yml
ab.
Zuerst richten Sie die Zielmaschine ein, z. B. durch Installation von Paketen und Erstellen von Verzeichnissen. Führen Sie dies von Ihrem Entwicklungsrechner aus aus und geben Sie einen Benutzer mit sudo-Rechten an:
ansible-playbook -u $USER -v -l web_servers playbooks/deploy-app.yml --skip-tags deploy -D
Nächster Schritt: den Code bereitstellen. Führen Sie dies vom Build-Server aus aus, von einem Benutzerkonto mit ssh-Zugriff auf das Bereitstellungskonto auf der Zielmaschine:
ansible-playbook -u deploy -v -l web_servers playbooks/deploy-app.yml --tags deploy --extra-vars ansible_become=false -D
Ein stärker angepasstes Playbook:
- 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
Rollenvariablen
System zum Erstellen von Releases, entweder "mix" oder "distillery".
elixir_release_release_system: "mix"
Standort der App zur Abrufung der Release-Dateien. Standardmäßig wird davon ausgegangen, dass Sie ein ansible
-Verzeichnis in Ihrem Quellcode haben.
elixir_release_app_dir: "{{ role_path }}/../../.."
Erlang-Name der Anwendung, der von Distillery verwendet wird, um Verzeichnisse und Skripte zu benennen.
elixir_release_app_name: my_app
Name des Releases, standardmäßig app_name
, oft aber auch MIX_ENV.
elixir_release_release_name: "{{ elixir_release_app_name }}"
Externer Name der App, der zum Benennen des systemd-Dienstes und der Verzeichnisse verwendet wird. Standardmäßig werden Unterstriche in Bindestriche umgewandelt:
elixir_release_service_name: "{{ elixir_release_app_name | replace('_', '-') }}"
Elixir-Anwendungsname. Standardmäßig ist es die CamelCase-Version des Anwendungsnamens:
elixir_release_app_module: "{{ elixir_release_service_name.title().replace('_', '') }}"
Version der App, die bereitgestellt werden soll. Wenn nicht angegeben, wird sie aus der Datei start_erl.data
im Release-Verzeichnis gelesen.
elixir_release_version: "0.1.0"
Aus Sicherheitsgründen verwenden wir separate Konten für die Bereitstellung und Ausführung der App. Das Bereitstellungskonto besitzt den Code und die Konfigurationsdateien und hat das Recht, die App neu zu starten. Normalerweise verwenden wir ein separates Konto namens deploy
. Die App läuft unter einem separaten Konto mit den minimal erforderlichen Berechtigungen. Wir erstellen normalerweise einen Namen, der mit der App übereinstimmt, z. B. foo
oder verwenden einen generischen Namen wie app
.
Die Release-Dateien gehören deploy:app
mit Modus 0644, damit die App sie lesen kann.
OS-Konto, das die Release-Dateien bereitstellt und besitzt:
elixir_release_deploy_user: deploy
OS-Gruppe, die die Release-Dateien bereitstellt und besitzt:
elixir_release_deploy_group: "{{ elixir_release_deploy_user }}"
OS-Konto, unter dem die App läuft:
elixir_release_app_user: "{{ elixir_release_service_name }}"
OS-Gruppe, unter der die App läuft:
elixir_release_app_group: "{{ elixir_release_app_user }}"
Umgebungsvariable der Anwendungsbereitstellung, d. h. die Einstellung von MIX_ENV
, verwendet, um die Release-Datei im _build
-Verzeichnis zu finden:
elixir_release_mix_env: prod
Verzeichnisprefix für Release-Dateien:
elixir_release_base_dir: /srv
Basisverzeichnis für Bereitstellungsverzeichnisse:
elixir_release_deploy_dir: "{{ elixir_release_base_dir }}/{{ elixir_release_service_name }}"
Verzeichnisse unter dem Bereitstellungsverzeichnis.
Wo Release-Tarballs entpackt werden:
elixir_release_releases_dir: "{{ elixir_release_deploy_dir }}/releases"
Derzeitig laufendes Release (Symlink):
elixir_release_current_dir: "{{ elixir_release_deploy_dir }}/current"
Standort der Bereitstellungsskripte:
elixir_release_scripts_dir: "{{ elixir_release_deploy_dir }}/bin"
Verzeichnis für Flag-Dateien, das verwendet wird, um den Neustart zu signalisieren:
elixir_release_flags_dir: "{{ elixir_release_deploy_dir }}/flags"
Verzeichnisse, in denen die App ihre Dateien aufbewahrt, gemäß systemd.
elixir_release_app_dirs:
- configuration
- runtime
Ob conform verwendet werden soll:
elixir_release_conform: false
elixir_release_conform_conf_path: "{{ elixir_release_configuration_dir }}/config.conform"
Wie wir die App neu starten sollen:
elixir_release_restart_method: systemctl
# elixir_release_restart_method: systemd_flag
# elixir_release_restart_method: touch
Mögliche Optionen sind:
systemctl
, dassystemctl restart foo
ausführtsystemd_flag
, das die Datei{{ elixir_release_shutdown_flags_dir }}/restart.flag
berührttouch
, das die Datei{{ elixir_release_shutdown_flags_dir }}/restart.flag
berührt. Verzeichnisberechtigungen sind 0770, sodass der verwaltete Prozess sich selbst neu starten kann.
Welche Benutzer dürfen die App mit sudo /bin/systemctl restart
neu starten, wenn die Methode == systemctl
ist.
elixir_release_restart_users:
- "{{ elixir_release_deploy_user }}"
Setzen Sie auf []
, sodass niemand neu starten kann, oder fügen Sie zusätzliche Namen hinzu, z. B. - "{{ elixir_release_app_user }}"
.
systemd und Skripte
Standardmäßig geht diese Rolle davon aus, dass Sie mix_systemd zur Generierung der systemd-Einheitendatei und mix_deploy zur Generierung von Lebenszyklus-Skripten verwenden.
elixir_release_systemd_source
steuert die Quelle der systemd-Einheitendatei.
elixir_release_systemd_source: mix_systemd
Mit dem Standardwert mix_systemd
kopiert die Rolle die systemd-Einheitendateien aus dem
_build/{{ elixir_release_mix_env }}/systemd
-Verzeichnis. Stellen Sie es auf self
ein, und diese Rolle generiert eine systemd-Einheitendatei aus einer Vorlage.
elixir_release_scripts_source
steuert die Quelle der Skripte.
elixir_release_scripts_source: bin
Mit dem Standardwert bin
kopiert die Rolle Skripte aus dem bin
-Verzeichnis des Projekts nach /srv/foo/bin
auf dem Zielsystem. Stellen Sie es auf mix_deploy
ein, wenn Sie output_dir_per_env: true
in der mix_deploy
-Konfiguration gesetzt haben, wobei die generierten Skripte unter _build
gespeichert werden.
Die folgenden Variablen werden bei der Erstellung der systemd-Einheitendatei verwendet:
Port, auf dem die App auf HTTP-Verbindungen hört:
elixir_release_http_listen_port: 4000
Port, auf dem die App auf HTTPS-Verbindungen hört:
elixir_release_https_listen_port: 4001
Limit für offene Dateien:
elixir_release_limit_nofile: 65536
Sekunden warten zwischen Neustarts:
elixir_release_systemd_restart_sec: 5
LANG
-Umgebungsvariable:
elixir_release_lang: "en_US.UTF-8"
umask:
elixir_release_umask: "0027"
Zielversion von systemd, die verwendet wird, um fortgeschrittenere Funktionen zu aktivieren:
elixir_release_systemd_version: 219
Typ des systemd-Dienstes: simple | exec | notify | forking Siehe systemd Type
Befehlszeile, um die App zu starten. mix nutzt start für simple, daemon für forking. distillery nutzt foreground für simple, start für forking.
elixir_release_start_command: start
PID-Datei bei Verwendung des forsierenden Diensttyps:
elixir_release_pid_file: "{{ elixir_release_runtime_dir }}/{{ elixir_release_app_name}}.pid"
Liste von ExecStartPre-Skripten in der systemd-Einheitendatei:
elixir_release_exec_start_pre: []
Liste von Umgebungsvariablen, die in der systemd-Einheitendatei gesetzt werden sollen:
elixir_release_env_vars: []
Abhängigkeiten
Keine
Anforderungen
Keine
Lizenz
MIT
Autoreninformationen
Jake Morrison jake@cogini.com