Een server opzetten om een ​​Rails-applicatie te implementeren met behulp van Ansible

Nog niet zo lang geleden moest ik verschillende Ansible-playbooks schrijven om de server voor te bereiden op de implementatie van een Rails-applicatie. En verrassend genoeg vond ik geen eenvoudige stapsgewijze handleiding. Ik wilde het draaiboek van iemand anders niet kopiëren zonder te begrijpen wat er gebeurde, en uiteindelijk moest ik de documentatie lezen en alles zelf verzamelen. Misschien kan ik iemand helpen dit proces te versnellen met behulp van dit artikel.

Het eerste dat u moet begrijpen is dat ansible u een handige interface biedt waarmee u via SSH een vooraf gedefinieerde lijst met acties op een externe server(s) kunt uitvoeren. Er is hier geen magie, u kunt geen plug-in installeren en uw applicatie zonder downtime implementeren met docker, monitoring en andere kant-en-klare goodies. Om een ​​draaiboek te schrijven, moet je weten wat je precies wilt doen en hoe je dat moet doen. Daarom ben ik niet tevreden met kant-en-klare playbooks van GitHub, of artikelen als: “Copy and run, it will work.”

Wat hebben we nodig

Zoals ik al zei, moet je, om een ​​draaiboek te schrijven, weten wat je wilt doen en hoe je dat moet doen. Laten we beslissen wat we nodig hebben. Voor een Rails-applicatie hebben we verschillende systeempakketten nodig: nginx, postgresql (redis, enz.). Daarnaast hebben we een specifieke versie van ruby ​​nodig. Je kunt het het beste installeren via rbenv (rvm, asdf...). Dit alles uitvoeren als rootgebruiker is altijd een slecht idee, dus u moet een afzonderlijke gebruiker aanmaken en zijn rechten configureren. Hierna moet u onze code naar de server uploaden, de configuraties voor nginx, postgres, enz. kopiëren en al deze services starten.

Als gevolg hiervan is de volgorde van acties als volgt:

  1. Log in als root
  2. systeempakketten installeren
  3. maak een nieuwe gebruiker aan, configureer rechten, ssh-sleutel
  4. configureer systeempakketten (nginx enz.) en voer ze uit
  5. Wij maken een gebruiker aan in de database (u kunt direct een database aanmaken)
  6. Log in als nieuwe gebruiker
  7. Installeer rbenv en ruby
  8. Het installeren van de bundelaar
  9. De applicatiecode uploaden
  10. De Puma-server starten

Bovendien kunnen de laatste fasen worden uitgevoerd met behulp van capistrano, in ieder geval kant-en-klaar kan het code naar release-mappen kopiëren, de release met een symlink omschakelen bij succesvolle implementatie, configuraties vanuit een gedeelde map kopiëren, puma opnieuw opstarten, enz. Dit alles kan worden gedaan met Ansible, maar waarom?

Bestandsstructuur

Ansible is streng bestandsstructuur voor al uw bestanden, dus u kunt ze het beste allemaal in een aparte map bewaren. Bovendien is het niet zo belangrijk of het in de railstoepassing zelf zal zijn, of afzonderlijk. Je kunt bestanden opslaan in een aparte git-repository. Persoonlijk vond ik het het handigst om een ​​anible-map te maken in de /config-map van de rails-applicatie en alles in één repository op te slaan.

Eenvoudig speelboek

Playbook is een yml-bestand dat, met behulp van een speciale syntaxis, beschrijft wat Ansible moet doen en hoe. Laten we het eerste draaiboek maken dat niets doet:

---
- name: Simple playbook
  hosts: all

Hier zeggen we simpelweg dat ons draaiboek heet Simple Playbook en dat de inhoud ervan voor alle hosts moet worden uitgevoerd. We kunnen het opslaan in de map /ansible met de naam playbook.yml en probeer uit te voeren:

ansible-playbook ./playbook.yml

PLAY [Simple Playbook] ************************************************************************************************************************************
skipping: no hosts matched

Ansible zegt dat het geen hosts kent die overeenkomen met de lijst met alle. Ze moeten in een special worden vermeld inventarisbestand.

Laten we het in dezelfde ansible-map maken:

123.123.123.123

Zo specificeren we eenvoudig de host (idealiter de host van onze VPS om te testen, of je kunt localhost registreren) en slaan deze op onder de naam inventory.
Je kunt proberen anible uit te voeren met een inventarisbestand:

ansible-playbook ./playbook.yml -i inventory
PLAY [Simple Playbook] ************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************

PLAY RECAP ************************************************************************************************************************************

Als je ssh-toegang hebt tot de opgegeven host, zal ansible verbinding maken en informatie verzamelen over het externe systeem. (standaard TASK [Feiten verzamelen]), waarna een kort rapport over de uitvoering wordt gegeven (PLAY RECAP).

Standaard gebruikt de verbinding de gebruikersnaam waarmee u bent ingelogd in het systeem. Waarschijnlijk zal het niet aan de host liggen. In het playbook-bestand kunt u opgeven welke gebruiker u wilt gebruiken om verbinding te maken met behulp van de remote_user-instructie. Bovendien kan informatie over een systeem op afstand vaak onnodig voor u zijn en moet u geen tijd verspillen met het verzamelen ervan. Deze taak kan ook worden uitgeschakeld:

---
- name: Simple playbook
  hosts: all
  remote_user: root
  become: true
  gather_facts: no

Probeer het draaiboek opnieuw uit te voeren en zorg ervoor dat de verbinding werkt. (Als u de rootgebruiker hebt opgegeven, moet u ook de richtlijn Become: True opgeven om verhoogde rechten te verkrijgen. Zoals geschreven in de documentatie: become set to ‘true’/’yes’ to activate privilege escalation. hoewel het niet helemaal duidelijk is waarom).

Misschien krijg je een foutmelding die wordt veroorzaakt doordat ansible de Python-interpreter niet kan bepalen, dan kun je deze handmatig opgeven:

ansible_python_interpreter: /usr/bin/python3 

Je kunt erachter komen waar je Python hebt met het commando whereis python.

Systeempakketten installeren

De standaarddistributie van Ansible bevat veel modules voor het werken met verschillende systeempakketten, zodat we om welke reden dan ook geen bash-scripts hoeven te schrijven. Nu hebben we een van deze modules nodig om het systeem bij te werken en systeempakketten te installeren. Ik heb Ubuntu Linux op mijn VPS, dus voor het installeren van pakketten gebruik ik apt-get и module ervoor. Als je een ander besturingssysteem gebruikt, heb je mogelijk een andere module nodig (onthoud dat ik in het begin zei dat we van tevoren moeten weten wat en hoe we gaan doen). De syntaxis zal echter hoogstwaarschijnlijk vergelijkbaar zijn.

Laten we ons draaiboek aanvullen met de eerste taken:

---
- name: Simple playbook
  hosts: all
  remote_user: root
  become: true
  gather_facts: no

  tasks:
    - name: Update system
      apt: update_cache=yes
    - name: Install system dependencies
      apt:
        name: git,nginx,redis,postgresql,postgresql-contrib
        state: present

Taak is precies de taak die Ansible zal uitvoeren op externe servers. We geven de taak een naam zodat we de uitvoering ervan in het logboek kunnen volgen. En we beschrijven, met behulp van de syntaxis van een specifieke module, wat deze moet doen. In dit geval apt: update_cache=yes - zegt dat systeempakketten moeten worden bijgewerkt met behulp van de apt-module. Het tweede commando is iets ingewikkelder. We geven een lijst met pakketten door aan de apt-module en zeggen dat dit het geval is state zou moeten worden present, dat wil zeggen dat we zeggen: installeer deze pakketten. Op een vergelijkbare manier kunnen we ze vertellen ze te verwijderen, of ze bij te werken door ze eenvoudigweg te wijzigen state. Houd er rekening mee dat we, om rails met postgresql te laten werken, het pakket postgresql-contrib nodig hebben, dat we nu installeren. Nogmaals, je moet dit weten en doen; ansible op zichzelf zal dit niet doen.

Probeer het draaiboek opnieuw uit te voeren en controleer of de pakketten zijn geïnstalleerd.

Nieuwe gebruikers aanmaken.

Om met gebruikers te werken heeft Ansible ook een module - gebruiker. Laten we nog een taak toevoegen (ik heb de reeds bekende delen van het draaiboek achter de opmerkingen verborgen om het niet elke keer helemaal te kopiëren):

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Add a new user
      user:
        name: my_user
        shell: /bin/bash
        password: "{{ 123qweasd | password_hash('sha512') }}"

We maken een nieuwe gebruiker aan, stellen er een schema en wachtwoord voor in. En dan komen we verschillende problemen tegen. Wat als gebruikersnamen voor verschillende hosts verschillend moeten zijn? En het opslaan van het wachtwoord in duidelijke tekst in het draaiboek is een heel slecht idee. Laten we om te beginnen de gebruikersnaam en het wachtwoord in variabelen plaatsen, en tegen het einde van het artikel zal ik laten zien hoe je het wachtwoord kunt coderen.

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Add a new user
      user:
        name: "{{ user }}"
        shell: /bin/bash
        password: "{{ user_password | password_hash('sha512') }}"

Variabelen worden in draaiboeken ingesteld met behulp van dubbele accolades.

We zullen de waarden van de variabelen in het inventarisbestand aangeven:

123.123.123.123

[all:vars]
user=my_user
user_password=123qweasd

Let op de richtlijn [all:vars] - er staat dat het volgende tekstblok variabelen (vars) is en dat deze van toepassing zijn op alle hosts (all).

Het ontwerp is ook interessant "{{ user_password | password_hash('sha512') }}". Het punt is dat Ansible de gebruiker niet via installeert user_add alsof je het handmatig zou doen. En het slaat alle gegevens direct op, daarom moeten we het wachtwoord ook vooraf omzetten in een hash, wat dit commando doet.

Laten we onze gebruiker toevoegen aan de sudo-groep. Voordat we dit doen, moeten we er echter voor zorgen dat zo'n groep bestaat, omdat niemand dit voor ons zal doen:

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Ensure a 'sudo' group
      group:
        name: sudo
        state: present
    - name: Add a new user
      user:
        name: "{{ user }}"
        shell: /bin/bash
        password: "{{ user_password | password_hash('sha512') }}"
        groups: "sudo"

Alles is vrij eenvoudig, we hebben ook een groepsmodule voor het maken van groepen, met een syntaxis die erg lijkt op apt. Dan volstaat het om deze groep te registreren bij de gebruiker (groups: "sudo").
Het is ook handig om een ​​ssh-sleutel aan deze gebruiker toe te voegen, zodat we ermee kunnen inloggen zonder wachtwoord:

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Ensure a 'sudo' group
      group:
      name: sudo
        state: present
    - name: Add a new user
      user:
        name: "{{ user }}"
        shell: /bin/bash
        password: "{{ user_password | password_hash('sha512') }}"
        groups: "sudo"
    - name: Deploy SSH Key
      authorized_key:
        user: "{{ user }}"
        key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
        state: present

In dit geval is het ontwerp interessant "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" — het kopieert de inhoud van het bestand id_rsa.pub (uw naam kan anders zijn), dat wil zeggen het openbare deel van de ssh-sleutel, en uploadt dit naar de lijst met geautoriseerde sleutels voor de gebruiker op de server.

rol

Alle drie de taken voor het creëren van gebruik kunnen eenvoudig in één groep taken worden ingedeeld, en het zou een goed idee zijn om deze groep apart van het hoofddraaiboek op te slaan, zodat deze niet te groot wordt. Voor dit doel heeft Ansible rol.
Volgens de bestandsstructuur die helemaal aan het begin is aangegeven, moeten rollen in een aparte rollenmap worden geplaatst. Voor elke rol is er een aparte map met dezelfde naam, binnen de map Taken, Bestanden, Sjablonen, enz.
Laten we een bestandsstructuur maken: ./ansible/roles/user/tasks/main.yml (main is het hoofdbestand dat wordt geladen en uitgevoerd wanneer een rol aan het playbook wordt gekoppeld; er kunnen ook andere rolbestanden aan worden gekoppeld). Nu kunt u alle taken gerelateerd aan de gebruiker naar dit bestand overbrengen:

# Create user and add him to groups
- name: Ensure a 'sudo' group
  group:
    name: sudo
    state: present

- name: Add a new user
  user:
    name: "{{ user }}"
    shell: /bin/bash
    password: "{{ user_password | password_hash('sha512') }}"
    groups: "sudo"

- name: Deploy SSH Key
  authorized_key:
    user: "{{ user }}"
    key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
    state: present

In het hoofddraaiboek moet u opgeven dat u de gebruikersrol wilt gebruiken:

---
- name: Simple playbook
  hosts: all
  remote_user: root
  gather_facts: no

  tasks:
    - name: Update system
      apt: update_cache=yes
    - name: Install system dependencies
      apt:
        name: git,nginx,redis,postgresql,postgresql-contrib
        state: present

  roles:
    - user

Het kan ook zinvol zijn om het systeem vóór alle andere taken bij te werken; hiervoor kunt u het blok een andere naam geven tasks waarin ze zijn gedefinieerd pre_tasks.

Nginx instellen

We zouden Nginx al geïnstalleerd moeten hebben; we moeten het configureren en uitvoeren. Laten we het meteen in de rol doen. Laten we een bestandsstructuur maken:

- ansible
  - roles
    - nginx
      - files
      - tasks
        - main.yml
      - templates

Nu hebben we bestanden en sjablonen nodig. Het verschil tussen beide is dat Ansible de bestanden rechtstreeks kopieert, zoals ze zijn. En sjablonen moeten de j2-extensie hebben en ze kunnen variabele waarden gebruiken met dezelfde dubbele accolades.

Laten we nginx inschakelen main.yml bestand. Hiervoor hebben we een systemd-module:

# Copy nginx configs and start it
- name: enable service nginx and start
  systemd:
    name: nginx
    state: started
    enabled: yes

Hier zeggen we niet alleen dat nginx moet worden gestart (dat wil zeggen, we lanceren het), maar we zeggen meteen dat het moet worden ingeschakeld.
Laten we nu de configuratiebestanden kopiëren:

# Copy nginx configs and start it
- name: enable service nginx and start
  systemd:
    name: nginx
    state: started
    enabled: yes

- name: Copy the nginx.conf
  copy:
    src: nginx.conf
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: '0644'
    backup: yes

- name: Copy template my_app.conf
  template:
    src: my_app_conf.j2
    dest: /etc/nginx/sites-available/my_app.conf
    owner: root
    group: root
    mode: '0644'

We maken het belangrijkste nginx-configuratiebestand (u kunt het rechtstreeks van de server halen of het zelf schrijven). En ook het configuratiebestand voor onze applicatie in de directory sites_available (dit is niet noodzakelijk maar wel handig). In het eerste geval gebruiken we de kopieermodule om bestanden te kopiëren (het bestand moet in /ansible/roles/nginx/files/nginx.conf). In de tweede kopiëren we de sjabloon, waarbij we de waarden van de variabelen vervangen. Het sjabloon zou binnen moeten zijn /ansible/roles/nginx/templates/my_app.j2). En het zou er ongeveer zo uit kunnen zien:

upstream {{ app_name }} {
  server unix:{{ app_path }}/shared/tmp/sockets/puma.sock;
}

server {
  listen 80;
  server_name {{ server_name }} {{ inventory_hostname }};
  root {{ app_path }}/current/public;

  try_files $uri/index.html $uri.html $uri @{{ app_name }};
  ....
}

Let op de inzetstukken {{ app_name }}, {{ app_path }}, {{ server_name }}, {{ inventory_hostname }} — dit zijn alle variabelen waarvan de waarden Ansible in de sjabloon zullen vervangen voordat ze worden gekopieerd. Dit is handig als u een draaiboek gebruikt voor verschillende groepen hosts. We kunnen bijvoorbeeld ons inventarisbestand toevoegen:

[production]
123.123.123.123

[staging]
231.231.231.231

[all:vars]
user=my_user
user_password=123qweasd

[production:vars]
server_name=production
app_path=/home/www/my_app
app_name=my_app

[staging:vars]
server_name=staging
app_path=/home/www/my_stage
app_name=my_stage_app

Als we nu ons draaiboek starten, zal het de opgegeven taken voor beide hosts uitvoeren. Maar tegelijkertijd zullen de variabelen voor een staging-host anders zijn dan die voor productie, en niet alleen in rollen en playbooks, maar ook in nginx-configuraties. {{ inventory_hostname }} hoeven niet te worden gespecificeerd in het inventarisbestand - dit speciale ansibelvariabele en de host waarvoor het playbook momenteel actief is, wordt daar opgeslagen.
Als u een inventarisbestand voor meerdere hosts wilt hebben, maar slechts voor één groep wilt draaien, kunt u dit doen met het volgende commando:

ansible-playbook -i inventory ./playbook.yml -l "staging"

Een andere optie is om afzonderlijke inventarisbestanden voor verschillende groepen te hebben. Of u kunt de twee benaderingen combineren als u veel verschillende hosts heeft.

Laten we teruggaan naar het instellen van nginx. Na het kopiëren van de configuratiebestanden moeten we een symlink maken in sitest_enabled naar my_app.conf van sites_available. En start nginx opnieuw op.

... # old code in mail.yml

- name: Create symlink to sites-enabled
  file:
    src: /etc/nginx/sites-available/my_app.conf
    dest: /etc/nginx/sites-enabled/my_app.conf
    state: link

- name: restart nginx
  service:
    name: nginx
    state: restarted

Alles is hier eenvoudig - opnieuw weerweerbare modules met een vrij standaard syntaxis. Maar er is één punt. Het heeft geen zin om nginx elke keer opnieuw op te starten. Is het je opgevallen dat we geen commando's schrijven als: "doe dit zo", de syntaxis lijkt meer op "dit zou deze status moeten hebben". En meestal is dit precies hoe weerwort werkt. Als de groep al bestaat, of als het systeempakket al is geïnstalleerd, zal ansible dit controleren en de taak overslaan. Ook worden bestanden niet gekopieerd als ze volledig overeenkomen met wat er al op de server staat. We kunnen hiervan profiteren en nginx alleen opnieuw opstarten als de configuratiebestanden zijn gewijzigd. Hiervoor bestaat een registerrichtlijn:

# Copy nginx configs and start it
- name: enable service nginx and start
  systemd:
    name: nginx
    state: started
    enabled: yes

- name: Copy the nginx.conf
  copy:
    src: nginx.conf
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: '0644'
    backup: yes
  register: restart_nginx

- name: Copy template my_app.conf
  template:
    src: my_app_conf.j2
    dest: /etc/nginx/sites-available/my_app.conf
    owner: root
    group: root
    mode: '0644'
  register: restart_nginx

- name: Create symlink to sites-enabled
  file:
    src: /etc/nginx/sites-available/my_app.conf
    dest: /etc/nginx/sites-enabled/my_app.conf
    state: link

- name: restart nginx
  service:
    name: nginx
    state: restarted
  when: restart_nginx.changed

Als een van de configuratiebestanden verandert, wordt er een kopie gemaakt en wordt de variabele geregistreerd restart_nginx. En alleen als deze variabele geregistreerd is, wordt de service opnieuw gestart.

En natuurlijk moet je de nginx-rol toevoegen aan het hoofdplaybook.

Postgresql instellen

We moeten postgresql inschakelen met systemd op dezelfde manier als we deden met nginx, en ook een gebruiker maken die we zullen gebruiken om toegang te krijgen tot de database en de database zelf.
Laten we een rol creëren /ansible/roles/postgresql/tasks/main.yml:

# Create user in postgresql
- name: enable postgresql and start
  systemd:
    name: postgresql
    state: started
    enabled: yes

- name: Create database user
  become_user: postgres
  postgresql_user:
    name: "{{ db_user }}"
    password: "{{ db_password }}"
    role_attr_flags: SUPERUSER

- name: Create database
  become_user: postgres
  postgresql_db:
    name: "{{ db_name }}"
    encoding: UTF-8
    owner: "{{ db_user }}"

Ik zal niet beschrijven hoe je variabelen aan de inventaris toevoegt, dit is al vele malen gedaan, evenals de syntaxis van de modules postgresql_db en postgresql_user. Meer informatie vindt u in de documentatie. De meest interessante richtlijn hier is become_user: postgres. Feit is dat standaard alleen de postgres-gebruiker toegang heeft tot de postgresql-database en alleen lokaal. Deze richtlijn stelt ons in staat opdrachten uit te voeren namens deze gebruiker (als we daar toegang toe hebben, uiteraard).
Mogelijk moet u ook een regel toevoegen aan pg_hba.conf om een ​​nieuwe gebruiker toegang tot de database te geven. Dit kan op dezelfde manier worden gedaan als waarop we de nginx-configuratie hebben gewijzigd.

En natuurlijk moet je de postgresql-rol toevoegen aan het hoofdplaybook.

Ruby installeren via rbenv

Ansible heeft geen modules om met rbenv te werken, maar wordt geïnstalleerd door een git-repository te klonen. Daarom wordt dit probleem het meest niet-standaard probleem. Laten we een rol voor haar creëren /ansible/roles/ruby_rbenv/main.yml en laten we beginnen met het invullen:

# Install rbenv and ruby
- name: Install rbenv
  become_user: "{{ user }}"
  git: repo=https://github.com/rbenv/rbenv.git dest=~/.rbenv

We gebruiken opnieuw de richtlijn Become_user om te werken onder de gebruiker die we voor deze doeleinden hebben gemaakt. Omdat rbenv in de thuismap is geïnstalleerd, en niet wereldwijd. En we gebruiken ook de git-module om de repository te klonen, waarbij repo en dest worden gespecificeerd.

Vervolgens moeten we rbenv init in bashrc registreren en daar rbenv aan PATH toevoegen. Hiervoor hebben we de lineinfile-module:

- name: Add rbenv to PATH
  become_user: "{{ user }}"
  lineinfile:
    path: ~/.bashrc
    state: present
    line: 'export PATH="${HOME}/.rbenv/bin:${PATH}"'

- name: Add rbenv init to bashrc
  become_user: "{{ user }}"
  lineinfile:
    path: ~/.bashrc
    state: present
    line: 'eval "$(rbenv init -)"'

Dan moet je ruby_build installeren:

- name: Install ruby-build
  become_user: "{{ user }}"
  git: repo=https://github.com/rbenv/ruby-build.git dest=~/.rbenv/plugins/ruby-build

En installeer ten slotte Ruby. Dit gebeurt via rbenv, dat wil zeggen eenvoudigweg met het bash-commando:

- name: Install ruby
  become_user: "{{ user }}"
  shell: |
    export PATH="${HOME}/.rbenv/bin:${PATH}"
    eval "$(rbenv init -)"
    rbenv install {{ ruby_version }}
  args:
    executable: /bin/bash

We zeggen welk commando we moeten uitvoeren en waarmee. Hier komen we echter het feit tegen dat ansible de code in bashrc niet uitvoert voordat de opdrachten worden uitgevoerd. Dit betekent dat rbenv rechtstreeks in hetzelfde script moet worden gedefinieerd.

Het volgende probleem is te wijten aan het feit dat het shell-commando vanuit weerbaar oogpunt geen status heeft. Dat wil zeggen dat er geen automatische controle plaatsvindt of deze versie van ruby ​​is geïnstalleerd of niet. Dit kunnen wij zelf doen:

- name: Install ruby
  become_user: "{{ user }}"
  shell: |
    export PATH="${HOME}/.rbenv/bin:${PATH}"
    eval "$(rbenv init -)"
    if ! rbenv versions | grep -q {{ ruby_version }}
      then rbenv install {{ ruby_version }} && rbenv global {{ ruby_version }}
    fi
  args:
    executable: /bin/bash

Het enige dat overblijft is het installeren van Bundler:

- name: Install bundler
  become_user: "{{ user }}"
  shell: |
    export PATH="${HOME}/.rbenv/bin:${PATH}"
    eval "$(rbenv init -)"
    gem install bundler

En nogmaals, voeg onze rol ruby_rbenv toe aan het hoofdspeelboek.

Gedeelde bestanden.

Over het algemeen kan de installatie hier worden voltooid. Vervolgens hoeft u alleen nog maar capistrano uit te voeren en het zal de code zelf kopiëren, de benodigde mappen aanmaken en de applicatie starten (als alles correct is geconfigureerd). Capistrano vereist echter vaak aanvullende configuratiebestanden, zoals database.yml of .env Ze kunnen net als bestanden en sjablonen voor nginx worden gekopieerd. Er is slechts één subtiliteit. Voordat u bestanden kopieert, moet u er een mapstructuur voor maken, ongeveer als volgt:

# Copy shared files for deploy
- name: Ensure shared dir
  become_user: "{{ user }}"
  file:
    path: "{{ app_path }}/shared/config"
    state: directory

we specificeren slechts één map en ansible zal indien nodig automatisch bovenliggende mappen maken.

Ansible kluis

We zijn al tegengekomen dat variabelen geheime gegevens kunnen bevatten, zoals het wachtwoord van de gebruiker. Als je hebt gemaakt .env dossier voor de aanvraag, en database.yml dan moeten er nog meer van dergelijke kritische gegevens zijn. Het zou goed zijn om ze te verbergen voor nieuwsgierige blikken. Voor dit doel wordt het gebruikt weerbaar gewelf.

Laten we een bestand voor variabelen maken /ansible/vars/all.yml (hier kunt u verschillende bestanden maken voor verschillende groepen hosts, net als in het inventarisbestand: production.yml, staging.yml, enz.).
Alle variabelen die moeten worden gecodeerd, moeten naar dit bestand worden overgebracht met behulp van de standaard yml-syntaxis:

# System vars
user_password: 123qweasd
db_password: 123qweasd

# ENV vars
aws_access_key_id: xxxxx
aws_secret_access_key: xxxxxx
aws_bucket: bucket_name
rails_secret_key_base: very_secret_key_base

Hierna kan dit bestand versleuteld worden met het commando:

ansible-vault encrypt ./vars/all.yml

Bij het coderen moet u uiteraard een wachtwoord instellen voor decodering. U kunt zien wat er in het bestand staat nadat u deze opdracht hebt aangeroepen.

Door middel van ansible-vault decrypt het bestand kan worden gedecodeerd, gewijzigd en vervolgens opnieuw worden gecodeerd.

U hoeft het bestand niet te decoderen om te kunnen werken. U slaat het gecodeerd op en voert het draaiboek met het argument uit --ask-vault-pass. Ansible zal om het wachtwoord vragen, de variabelen ophalen en de taken uitvoeren. Alle gegevens blijven gecodeerd.

Het volledige commando voor verschillende groepen hosts en weerwortkluis ziet er ongeveer zo uit:

ansible-playbook -i inventory ./playbook.yml -l "staging" --ask-vault-pass

Maar ik geef je niet de volledige tekst van draaiboeken en rollen, schrijf die zelf. Omdat weerwiet zo is: als je niet begrijpt wat er moet gebeuren, dan zal het het niet voor je doen.

Bron: www.habr.com

Voeg een reactie