Niet zo lang geleden moest ik enkele Ansible-playbooks schrijven om een server voor te bereiden op de deploy van een Rails-applicatie. Tot mijn verbazing kon ik geen eenvoudige stapsgewijze handleiding vinden. Ik wilde geen bestaand playbook kopiƫren zonder te begrijpen wat er aan de hand was, dus moest ik de documentatie lezen en alles zelf samenstellen. Misschien kan ik iemand helpen dit proces te versnellen met behulp van dit artikel.
Allereerst is het belangrijk om te begrijpen dat Ansible je een gebruiksvriendelijke interface biedt om een vooraf gedefinieerde lijst met acties op een of meerdere externe servers via SSH uit te voeren. Hier is geen enkele magie, je kunt geen plugin installeren en direct een zero downtime deploy van je applicatie met Docker, monitoring en andere voordelen krijgen. Om een playbook te schrijven moet je weten wat je precies wilt doen en hoe je dat kunt doen. Daarom ben ik niet tevreden met kant-en-klare playbooks van GitHub, of artikelen zoals: 'Kopieer en voer uit, het zal werken.'
Wat hebben we nodig?
Zoals ik al zei, om een playbook te schrijven moet je weten wat je wilt doen en hoe je dat kunt doen. Laten we bepalen wat we nodig hebben. Voor een Rails-applicatie hebben we een aantal systeem pakketten nodig: nginx, postgresql (redis, enz.). Daarnaast hebben we Ruby van een bepaalde versie nodig. Het installeren van Ruby gaat het beste via rbenv (rvm, asdfā¦). Alles onder de root-gebruiker draaien is altijd een slechte idee, daarom moeten we een aparte gebruiker aanmaken en rechten instellen. Daarna moeten we onze code naar de server uploaden, configuratiebestanden voor nginx, postgres, enz. kopiĆ«ren en al deze services opstarten.
Uiteindelijk is de volgorde van de acties als volgt:
- Inloggen als root
- Installeer de systeem pakketten
- Maak een nieuwe gebruiker aan, stel rechten en een SSH-sleutel in
- Stel de systeem pakketten in (nginx enz.) en start ze op
- Maak een gebruiker aan in de database (je kunt ook gelijk een database aanmaken)
- Log in als nieuwe gebruiker
- Installeer rbenv en Ruby
- Installeer Bundler
- Upload de applicatiecode
- Start de Puma-server
Deze laatste stappen kunnen ook met Capistrano worden uitgevoerd, in ieder geval kan Capistrano out-of-the-box de code naar de release-directories kopiƫren, de release-switch met een symlink bij een succesvolle deploy uitvoeren, configuraties uit de gedeelde directory kopiƫren, Puma herstarten, enz. Dit kan ook met Ansible, maar waarom?
Bestandsstructuur
Ansible heeft een strikte voor al zijn bestanden, daarom is het het beste om dit in een aparte directory te houden. Het maakt niet zo veel uit of dit in de rails applicatie zelf is, of apart. Je kunt bestanden in een aparte git-repository opslaan. Persoonlijk vond ik het het handigst om een directory ansible aan te maken in de /config directory van de rails applicatie en alles in ƩƩn repository op te slaan.
Eenvoudige Playbook
Een Playbook is een yml-bestand waarin met behulp van een speciale syntaxis is beschreven wat en hoe ansible moet doen. Laten we ons eerste playbook maken dat niets doet:
---
- naam: Eenvoudig playbook
hosts: allHier geven we gewoon aan dat ons playbook wordt genoemd Eenvoudige Playbook en dat de inhoud ervan uitgevoerd moet worden voor alle hosts. We kunnen het opslaan in de /ansible directory met de naam playbook.yml en proberen het uit te voeren:
ansible-playbook ./playbook.yml
PLAY [Eenvoudig Playbook] ************************************************************************************************************************************
skipping: geen hosts gevondenAnsible zegt dat het geen hosts kent die overeenkomen met de lijst all. Ze moeten worden opgesomd in een speciale .
Laten we het aanmaken in dezelfde ansible directory:
123.123.123.123Zo geven we eenvoudig een host op (bij voorkeur de host van je VPS voor tests, of je kunt localhost opgeven) en slaan het op onder de naam inventaris.
Je kunt proberen ansible uit te voeren met het inventory bestand:
ansible-playbook ./playbook.yml -i inventory
PLAY [Eenvoudig Playbook] ************************************************************************************************************************************
TAKEN [Verzamelen van Feiten] ************************************************************************************************************************************
PLAY SAMENVATTING ************************************************************************************************************************************Als je toegang hebt via ssh tot de opgegeven host, dan maakt ansible verbinding en verzamelt het informatie over het externe systeem. (standaard TAKEN [Verzamelen van Feiten]) waarna het een kort verslag geeft van de uitvoering (PLAY SAMENVATTING).
Standaard wordt de gebruikersnaam gebruikt waarmee je ingelogd bent in het systeem voor de verbinding. Op de host is deze, waarschijnlijk, niet aanwezig. In het playbook bestand kun je opgeven welke gebruiker gebruikt moet worden voor de verbinding met de directive remote_user. Ook is informatie over het externe systeem voor jou vaak niet nodig en kun je tijd besparen door de verzameling ervan uit te schakelen:
---
- naam: Eenvoudig playbook
hosts: all
remote_user: root
become: true
gather_facts: neeProbeer het playbook opnieuw uit te voeren en zorg ervoor dat de verbinding werkt. (Als je de root-gebruiker hebt opgegeven, moet je ook de directive become: true opgeven voor hogere rechten. Zoals in de documentatie staat: become ingesteld op 'true'/'yes' om privilege-escalatie te activeren. hoewel het niet helemaal duidelijk is waarom).
Mogelijk ontvang je een fout die wordt veroorzaakt doordat Ansible de Python-interpreter niet kan bepalen, dit kun je handmatig opgeven:
ansible_python_interpreter: /usr/bin/python3 waar je Python hebt staan, kun je te weten komen met het commando whereis python.
Installatie van systeem pakketten
De standaardversie van Ansible bevat veel modules voor het werken met verschillende systeem pakketten, waardoor we niet voor elk probleem bash-scripts hoeven te schrijven. Nu hebben we een van deze modules nodig om het systeem bij te werken en systeem pakketten te installeren. Ik gebruik Ubuntu Linux op mijn VPS, dus voor het installeren van pakketten gebruik ik apt-get en . Als je een ander operating systeem gebruikt, heb je mogelijk een andere module nodig (vergeet niet dat ik in het begin zei dat je van tevoren moet weten wat en hoe je het gaat doen). De syntaxis zal echter waarschijnlijk vergelijkbaar zijn.
Laten we ons playbook aanvullen met de eerste taken:
---
- name: Eenvoudig playbook
hosts: all
remote_user: root
become: true
gather_facts: no
taken:
- name: Systeem bijwerken
apt: update_cache=yes
- name: Installeer systeemafhankelijkheden
apt:
naam: git,nginx,redis,postgresql,postgresql-contrib
status: aanwezigTaak ā dit is de taak die Ansible op de externe servers zal uitvoeren. We geven de taak een naam om het uitvoeren ervan in de log bij te houden. En beschrijven, met behulp van de syntaxis van de specifieke module, wat hij moet doen. In dit geval apt: update_cache=yes ā zegt dat de pakketten van het systeem moeten worden bijgewerkt met de apt-module. De tweede opdracht is iets ingewikkelder. We geven de apt-module een lijst met pakketten en vertellen dat hun state moet worden present, dat wil zeggen we zeggen deze pakketten te installeren. Op een vergelijkbare manier kunnen we zeggen dat ze moeten worden verwijderd of bijgewerkt door eenvoudigweg te veranderen state. Let op dat we voor Rails met PostgreSQL het pakket postgresql-contrib nodig hebben, dat we nu installeren. Dit moet je opnieuw weten en doen, Ansible doet dit niet automatisch.
Probeer het playbook opnieuw uit te voeren en te controleren of de pakketten worden geĆÆnstalleerd.
Nieuwe gebruikers aanmaken.
Voor het werken met gebruikers heeft Ansible ook een module - user. Laten we nog een taak toevoegen (ik heb de al bekende delen van het playbook verborgen achter opmerkingen, zodat ik het niet elke keer helemaal hoef te kopiƫren):
---
- name: Eenvoudig playbook
# ...
tasks:
# ...
- name: Voeg een nieuwe gebruiker toe
user:
name: my_user
shell: /bin/bash
password: "{{ 123qweasd | password_hash('sha512') }}"We creƫren een nieuwe gebruiker, stellen zijn shell en wachtwoord in. En dan stoten we al snel op verschillende problemen. Wat als gebruikersnamen verschillend moeten zijn voor verschillende hosts? En het is ook een heel slecht idee om het wachtwoord in platte tekst in het playbook op te slaan. Laten we beginnen met het extraheren van de gebruikersnaam en het wachtwoord naar variabelen, en aan het eind van het artikel laat ik zien hoe we het wachtwoord kunnen versleutelen.
---
- name: Eenvoudig playbook
# ...
tasks:
# ...
- name: Voeg een nieuwe gebruiker toe
user:
name: "{{ user }}"
shell: /bin/bash
password: "{{ user_password | password_hash('sha512') }}"Met behulp van dubbele accolades worden variabelen in playbooks ingesteld.
We zullen de waarden van de variabelen in het inventory-bestand opgeven:
123.123.123.123
[all:vars]
user=my_user
user_password=123qweasdLet op de directive [all:vars] ā dit geeft aan dat de volgende tekstblock variabelen (vars) zijn en dat ze toepasbaar zijn voor alle hosts (all).
Ook interessant is de constructie "{{ user_password | password_hash('sha512') }}". Het punt is dat Ansible de gebruiker niet toevoegt via user_add zoals je dat handmatig zou doen. Maar slaat alle gegevens direct op, waardoor we het wachtwoord ook van tevoren in een hash moeten omzetten, wat deze opdracht doet.
Laten we onze gebruiker aan de sudo-groep toevoegen. Maar voordat we dit doen, moeten we ervoor zorgen dat zo'n groep bestaat, want niemand zal dat voor ons doen:
---
- name: Eenvoudig playbook
# ...
tasks:
# ...
- name: Zorg ervoor dat er een 'sudo' groep is
group:
name: sudo
state: present
- name: Voeg een nieuwe gebruiker toe
user:
name: "{{ user }}"
shell: /bin/bash
password: "{{ user_password | password_hash('sha512') }}"
groups: "sudo"Het is allemaal vrij eenvoudig, we hebben ook de module group voor het aanmaken van groepen, met een syntaxis die erg lijkt op apt. Daarna is het voldoende om deze groep aan de gebruiker toe te wijzen (groups: "sudo").
Het is ook nuttig om deze gebruiker een ssh-sleutel toe te voegen, zodat we zonder wachtwoord onder deze gebruiker kunnen inloggen:
---
- naam: Simpele playbook
# ...
taken:
# ...
- naam: Zorg voor een 'sudo' groep
groep:
naam: sudo
staat: aanwezig
- naam: Voeg een nieuwe gebruiker toe
gebruiker:
naam: "{{ gebruiker }}"
shell: /bin/bash
wachtwoord: "{{ gebruiker_wachtwoord | password_hash('sha512') }}"
groepen: "sudo"
- naam: SSH Sleutel implementeren
authorized_key:
gebruiker: "{{ gebruiker }}"
sleutel: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
staat: aanwezigIn dit geval is de constructie interessant "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" ā het kopieert de inhoud van het bestand id_rsa.pub (de naam kan verschillen), dat wil zeggen, het publieke deel van de ssh-sleutel en laadt het in de lijst van geautoriseerde sleutels voor de gebruiker op de server.
Rollen
Alle drie de taken voor het aanmaken van de gebruiker kunnen eenvoudig aan ƩƩn groep taken worden toegeschreven, en het zou handig zijn om deze groep apart van de hoofdbestanden op te slaan, zodat deze niet te groot wordt. Hiervoor bestaan er in ansible .
Volgens de in het begin aangegeven mappenstructuur moeten rollen in een aparte map roles worden geplaatst, voor elke rol ā een aparte map met dezelfde naam, binnen de map taken, bestanden, sjablonen, enz.
Laten we een mappenstructuur aanmaken: ./ansible/roles/user/tasks/main.yml (main is het hoofdbestand dat zal worden geladen en uitgevoerd wanneer de rol aan de playbook wordt gekoppeld; hierin kunnen andere rolbestanden worden aangesloten). Nu kunnen we alle taken met betrekking tot de gebruiker naar dit bestand verplaatsen:
# 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: presentIn de hoofdbestanden moet worden aangegeven dat de rol gebruiker moet worden gebruikt:
---
- naam: Simpele playbook
hosts: alle
remote_user: root
gather_facts: nee
taken:
- naam: Bijwerkensysteem
apt: update_cache=yes
- naam: Installeer systeemeisen
apt:
naam: git,nginx,redis,postgresql,postgresql-contrib
staat: aanwezig
rollen:
- gebruikerHet kan ook zinvol zijn om het systeem eerder bij te werken dan de andere taken; hiervoor kunnen we het blok hernoemen tasks waarin ze zijn gedefinieerd in pre_tasks.
Configuratie van nginx
Nginx zou al geïnstalleerd moeten zijn, we moeten het configureren en starten. Laten we dit meteen in de rol doen. We creëren een mappenstructuur:
- ansible
- roles
- nginx
- bestanden
- taken
- main.yml
- sjablonenNu hebben we bestanden en sjablonen nodig. Het verschil tussen hen is dat ansible bestanden direct kopieert, zoals ze zijn. Sjablonen moeten de extensie j2 hebben en kunnen variabele waarden bevatten met behulp van dezelfde dubbele accolades.
Laten we nginx opnemen in main.yml bestand. Hiervoor hebben we de systemd-module:
# Copy nginx configs and start it
- name: enable service nginx and start
systemd:
name: nginx
state: started
enabled: yesHier zeggen we niet alleen dat nginx gestart moet worden (dat wil zeggen, we starten het), maar we geven ook meteen aan dat het ingeschakeld moet zijn.
Laten we 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 hoofdconfiguratiebestand van nginx aan (je kunt het direct van de server halen of zelf schrijven). En ook het configuratiebestand voor onze applicatie in de sites_available map (dit is niet verplicht, maar nuttig). In het eerste geval gebruiken we de copy-module om bestanden te kopiƫren (het bestand moet liggen in /ansible/roles/nginx/files/nginx.conf). In het tweede geval kopiƫren we de sjabloon, waarbij we de waarden van variabelen invullen. De sjabloon moet liggen in /ansible/roles/nginx/templates/my_app.j2). En het kan er ongeveer zo uitzien:
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 invoegingen: {{ app_name }}, {{ app_path }}, {{ server_name }}, {{ inventory_hostname }} ā dit zijn allemaal variabelen waarvan de waarden door Ansible in de sjabloon worden ingevuld voordat ze gekopieerd worden. Dit is nuttig als je de playbook voor verschillende groepen hosts gebruikt. Bijvoorbeeld, we kunnen ons inventory-bestand aanvullen:
[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_appAls we nu onze playbook uitvoeren, worden de opgegeven taken voor beide hosts uitgevoerd. Maar de variabelen voor de staging-host zullen verschillen van die voor de productie, en niet alleen in rollen en playbooks, maar ook in de nginx-configuraties. {{ inventory_hostname }} je hoeft niet in het inventory-bestand op te nemen ā dit is en daar wordt de host opgeslagen waarvoor de playbook op dat moment wordt uitgevoerd.
Als je een inventory-bestand voor meerdere hosts wilt hebben, maar alleen voor ƩƩn groep wilt uitvoeren, kun je de volgende opdracht gebruiken:
ansible-playbook -i inventory .\/playbook.yml -l "staging"een andere optie is om aparte inventory-bestanden voor verschillende groepen te hebben. Of je kunt twee benaderingen combineren als je veel verschillende hosts hebt.
Laten we teruggaan naar de nginx-configuratie. Na het kopiƫren van de configuratiebestanden moeten we een symlink in sites_enabled naar my_app.conf vanuit sites_available maken. En herstart nginx.
... # oude code in mail.yml
- name: Maak symlink naar sites-enabled
file:
src: \/etc\/nginx\/sites-available\/my_app.conf
dest: \/etc\/nginx\/sites-enabled\/my_app.conf
state: link
- name: Herstart nginx
service:
name: nginx
state: restartedHier is het eenvoudig ā weer ansible-modules met een vrij standaard syntaxis. Maar er is ƩƩn punt. Het heeft geen zin om nginx telkens opnieuw op te starten. U heeft misschien opgemerkt dat we geen opdrachten schrijven zoals: "doe dit zo", de syntaxis lijkt meer op "dit moet deze toestand hebben". En vaak werkt ansible precies zo. Als de groep al bestaat of het systeempakket al is geĆÆnstalleerd, dan zal ansible dit controleren en de taak overslaan. Evenzo zullen bestanden niet worden 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 is er de directieve register:
# 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.changedAls een van de configuratiebestanden wijzigt, zal de kopieeractie worden uitgevoerd en wordt er een variabele geregistreerd restart_nginx. En alleen als deze variabele is geregistreerd, zal de service opnieuw worden opgestart.
En natuurlijk moet de nginx-rol aan de hoofd-playbook worden toegevoegd.
Configuratie van postgresql
We moeten postgresql inschakelen via systemd, net zoals we dat met nginx deden, en ook een gebruiker aanmaken die we zullen gebruiken om toegang te krijgen tot de database, evenals de database zelf.
Laten we een rol aanmaken /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 uitleggen hoe variabelen aan inventory moeten worden toegevoegd, dat is al vele keren gedaan, net als de syntaxis van de modules postgresql_db en postgresql_user. Meer gegevens zijn te vinden in de documentatie. Het meest interessante hier is de directieve become_user: postgres. Het punt is dat standaard alleen de gebruiker postgres toegang heeft tot de postgresql-database en alleen lokaal. Deze directieve stelt ons in staat om commando's uit te voeren namens deze gebruiker (als we natuurlijk toegang hebben).
Misschien moet u ook een regel in pg_hba.conf toevoegen om toegang te geven aan de nieuwe gebruiker tot de database. Dit kan ook op dezelfde manier worden gedaan als we de nginx-configuratie wijzigden.
En natuurlijk moet de postgresql-rol aan de hoofd-playbook worden toegevoegd.
Ruby installeren via rbenv
In ansible zijn er geen modules voor het werken met rbenv, en het wordt geĆÆnstalleerd door het klonen van een git-repository. Daarom wordt deze taak de meest ongewone. Laten we een rol hiervoor aanmaken /ansible/roles/ruby_rbenv/main.yml en deze beginnen in te vullen:
# Install rbenv and ruby
- name: Install rbenv
become_user: "{{ user }}"
git: repo=https://github.com/rbenv/rbenv.git dest=~/.rbenvWe gebruiken opnieuw de become_user-directive om te werken vanuit de gebruiker die we hiervoor hebben aangemaakt. Aangezien rbenv wordt geĆÆnstalleerd in zijn home-directory en niet globaal. We gebruiken ook de git-module om de repository te klonen, waarbij we repo en dest opgeven.
Vervolgens moeten we rbenv init in bashrc schrijven en rbenv aan de PATH toevoegen. Hiervoor hebben we de module lineinfile:
- naam: Voeg rbenv toe aan PATH
become_user: "{{ user }}"
lineinfile:
path: ~\/ .bashrc
state: present
line: 'export PATH="${HOME}\/ .rbenv\/bin:${PATH}"'
- naam: Voeg rbenv init toe aan bashrc
become_user: "{{ user }}"
lineinfile:
path: ~\/ .bashrc
state: present
line: 'eval "$(rbenv init -)"'Daarna moeten we ruby_build installeren:
- naam: Installeer ruby-build
become_user: "{{ user }}"
git: repo=https:\/\/github.com\/rbenv\/ruby-build.git dest=~\/ .rbenv\/plugins\/ruby-buildEn als laatste installeren we ruby. Dit gebeurt via rbenv, eenvoudigweg met een bash-commando:
- naam: Installeer ruby
become_user: "{{ user }}"
shell: |
export PATH="${HOME}\/ .rbenv\/bin:${PATH}"
eval "$(rbenv init -)"
rbenv install {{ ruby_version }}
args:
executable: \/bin\/bashWe geven aan welke opdracht we willen uitvoeren en waarmee. Echter, hier stuiten we op het feit dat ansible geen code in bashrc uitvoert voordat het de opdrachten uitvoert. Dit betekent dat rbenv direct in hetzelfde script moet worden gedefinieerd.
Het volgende probleem is dat de shell-opdracht geen staat heeft vanuit het perspectief van ansible. Dit betekent dat er geen automatische controle zal zijn of deze versie van ruby is geĆÆnstalleerd of niet ā dat moeten we zelf doen:
- naam: Installeer 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\/bashEn dan resteert het om bundler te installeren:
- naam: Installeer bundler
become_user: "{{ user }}"
shell: |
export PATH="${HOME}\/ .rbenv\/bin:${PATH}"
eval "$(rbenv init -)"
gem install bundlerEn weer moeten we onze ruby_rbenv rol toevoegen aan de hoofdplaybook.
Gedeelde bestanden.
Over het algemeen zou de configuratie hier kunnen eindigen. Vervolgens moet capistrano worden uitgevoerd en zal het zelf de code kopiƫren, de benodigde mappen aanmaken en de applicatie starten (als alles correct is ingesteld). Echter, capistrano vereist vaak extra configuratiebestanden, zoals database.yml of .env Deze kunnen op dezelfde manier worden gekopieerd als bestanden en sjablonen voor nginx. Er is echter ƩƩn nuance. Voor het kopiƫren van de bestanden moet de mappenstructuur worden aangemaakt, iets als dit:
# Copy shared files for deploy
- name: Ensure shared dir
become_user: "{{ user }}"
file:
path: "{{ app_path }}/shared/config"
state: directorywe geven slechts ƩƩn map op en ansible zal automatisch de bovenliggende mappen aanmaken indien nodig.
Ansible Vault
We have already encountered that sensitive information such as user passwords can be found in variables. If you have created .env a file for the application, and database.yml there should be even more critical data there. It is advisable to hide them from prying eyes. For this, .
Let's create a file for the variables. /ansible/vars/all.yml (different files can be created for different host groups, just like in the inventory file: production.yml, staging.yml, etc.).
All variables that need to be encrypted must be transferred to this file using standard yml syntax:
# 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_baseAfter that, this file can be encrypted with the command:
ansible-vault encrypt ./vars/all.ymlOf course, when encrypting, you will need to set a password for decryption. You can check what will be inside the file after executing this command.
Met behulp van ansible-vault decrypt the file can be decrypted, modified, and then encrypted again.
For operation, you do not need to decrypt the file. You keep it in encrypted form and run the playbook with the argument --ask-vault-pass. Ansible will ask for the password, retrieve the variables, and execute the tasks. All data will remain encrypted.
The complete command for multiple host groups and ansible vault will look something like this:
ansible-playbook -i inventory ./playbook.yml -l "staging" --ask-vault-passAnd I won't provide you with the full text of playbooks and roles, write them yourself. Because ansible is such a thing ā if you donāt understand what you need to do, it wonāt do it for you either.
Bron: habr.com
