ansible devops codestyle
Hej! Jag heter Jag arbetar som ingenjör på avdelningen för utvecklingsprocessautomation. Varje dag rullas nya applikationsbyggen ut till hundratals av företagets servrar. Och i den här artikeln delar jag med mig av min erfarenhet av att använda Ansible för dessa ändamål.
Den här guiden ger ett sätt att organisera variabler i en distribution. Den här guiden är utformad för dig som redan använder roller i sina spelböcker och har läst men har liknande problem:
- Efter att ha hittat en variabel i koden är det omöjligt att omedelbart förstå vad den är ansvarig för;
- Det finns flera roller, och variablerna måste kopplas till ett värde, men det fungerar inte;
- Har problem med att förklara för andra hur logiken för variabler i dina spelböcker fungerar
Vi stötte på dessa problem i projekt i vårt företag, vilket ledde till att vi kom fram till regler för formatering av variabler i våra spelböcker, vilket till viss del löste dessa problem.

Variabler i roller
En roll är ett separat objekt i distributionssystemet. Som alla systemobjekt måste det ha ett gränssnitt för interaktion med resten av systemet. Rollvariabler är ett sådant gränssnitt.
Låt oss ta rollen som ett exempel api, som installerar en Java-applikation på servern. Vilka variabler kan det ha?

Rollvariabler kan delas in i två typer efter typ:
1. Свойства
a) независимые от среды
б) зависимые от среды
2. Связи
a) слушатели
б) запросы внутри системы
в) запросы в среду
Variabla egenskaper — det här är variabler som bestämmer rollens beteende.
Begär variabler — Dessa är variabler vars värde används för att ange resurser utanför rollen.
Varierande lyssnare — dessa är variabler vars värde används för att bilda frågevariabler.
Å andra sidan är 1a, 2a, 2b variabler som inte är beroende av miljön (hårdvara, externa resurser etc.) och kan fyllas med standardvärden i standardrollen. Variabler av typ 1.b och 2.c kan dock inte fyllas med andra värden än "exempel", eftersom de kommer att förändras från monter till monter beroende på miljön.
kodstil
- Variabelnamnet måste börja med rollnamnet. Detta kommer att göra det lättare att i framtiden förstå vilken roll variabeln tillhör och vad den ansvarar för.
- När du använder variabler i roller måste du alltid följa inkapslingsprincipen och använda variabler definierade antingen i själva rollen eller i roller som den aktuella är beroende av.
Försök att undvika att använda ordböcker för variabler. Ansible ger inte ett bekvämt sätt att åsidosätta individuella värden i en ordbok.
Exempel på en dålig variabel:
myrole_user: login: admin password: adminHär är inloggning en oberoende variabel, och lösenord är en beroende variabel. Men
eftersom de är kombinerade till en ordbok måste du ange den i sin helhet
Alltid. Vilket är väldigt obekvämt. Bättre så här:myrole_user_login: admin myrole_user_password: admin
Variabler i Deployment Playbooks
När vi kompilerar en distributionsspelbok (hädanefter kallad en spelbok) följer vi regeln att den ska placeras i ett separat arkiv. Samma som roller: var och en i sitt eget git-förråd. Detta gör att vi kan inse att roller och spelböcker är olika oberoende objekt i distributionssystemet, och ändringar i ett objekt bör inte påverka det andras funktion. Detta uppnås genom att ändra standardvärdena för variabler.
När du kompilerar en playbook, för att sammanfatta, är det möjligt att åsidosätta standardvärdena för rollvariabler på två ställen: i playbook-variabler och i inventeringsvariabler.
mydeploy # Каталог деплоя
├── deploy.yml # Плейбук деплоя
├── group_vars # Каталог переменных плейбука
│ ├── all.yml # Файл для переменных связи всей системы
│ └── myapi.yml # Файл переменных свойств группы myapi
└── inventories #
└── prod # Каталог окружения prod
├── prod.ini # Инвентори файл
└── group_vars # Каталог для переменных инвентори
└── myapi #
├── vars.yml # Средозависимые переменные группы myapi
└── vault.yml # Секреты (всегда средозависимы) ** -
Skillnaden är att playbook-variabler alltid används när man anropar playbooks som ligger på samma nivå som den. Det betyder att dessa variabler är idealiska för att ändra standardvärdena för variabler som inte är beroende av miljön. Omvänt kommer inventeringsvariabler endast att användas för en specifik miljö, vilket är idealiskt för miljöspecifika variabler.
Det är viktigt att notera att variabelprioritet inte tillåter dig att omdefiniera variabler först i playbook-variabler och sedan separat i en inventering.
Detta innebär att det redan i detta skede är nödvändigt att avgöra om variabeln är miljöberoende eller inte och placera den på lämplig plats.
Till exempel, i ett projekt var variabeln som ansvarade för att aktivera SSL miljöberoende under lång tid, eftersom vi inte kunde aktivera SSL av skäl utanför vår kontroll på en av montrarna. När vi åtgärdade det här problemet blev det miljöagnostiskt och flyttade till playbook-variabler.
Egenskapsvariabler för grupper
Låt oss utöka vår modell i figur 1 genom att lägga till 2 grupper av servrar med en annan Java-applikation, men med olika inställningar.

Låt oss föreställa oss hur spelboken kommer att se ut i det här fallet:
- hosts: myapi
roles:
- api
- hosts: bbauth
roles:
- auth
- hosts: ghauth
roles:
- authVi har tre grupper i playbook, så det rekommenderas att omedelbart skapa samma antal gruppfiler i group_vars med inventeringsvariabler och playbookvariabler. En gruppfil i det här fallet är en beskrivning av en komponent i ovanstående applikation i spelboken. När du öppnar en gruppfil i playbook-variablerna ser du omedelbart alla skillnader från standardbeteendet för rollerna som är installerade på gruppen. I inventeringsvariabler: skillnader i gruppbeteende från monter till monter.
Kodstil
- Försök att inte använda host_vars-variabler alls, eftersom de inte beskriver systemet, utan bara ett specialfall, vilket i det långa loppet kommer att leda till frågor: "Varför skiljer sig denna värd från de andra?", vars svar inte alltid är lätt att hitta.
Länkvariabler
Det är dock detta som gäller egenskapsvariabler, men hur är det med länkvariabler?
Skillnaden mellan dem är att de måste ha samma betydelse i olika grupper.
Först fanns det använd en monstruös konstruktion av formen:
hostvars[groups['bbauth'][0]]['auth_bind_port'], men de avvisade det omedelbart
eftersom det har sina nackdelar. För det första är det skrymmande. För det andra beroendet av en specifik värd i gruppen. För det tredje är det nödvändigt att samla in fakta från alla värdar innan vi startar distributionen, om vi inte vill få ett odefinierat variabelfel.
Till slut bestämde man sig för att använda länkvariabler.
Länkvariabler — det här är variabler som hör till spelboken och som behövs för att koppla ihop systemobjekt.
Länkvariabler fylls i de allmänna systemvariablerna group_vars/all/vars och bildas genom att ta bort alla lyssnarvariabler från varje grupp och lägga till namnet på gruppen från vilken lyssnaren togs bort i början av variabeln.
Detta säkerställer enhetlighet och icke-korsning av namn.
Låt oss försöka länka variablerna från exemplet ovan:

Låt oss föreställa oss att vi har variabler som är beroende av varandra:
# roles/api/defaults:
# Переменная запроса
api_auth1_address: "http://example.com:80"
api_auth2_address: "http://example2.com:80"
# roles/auth/defaults:
# Переменная слушатель
auth_bind_port: "20000"Låt oss flytta det till vanliga variabler group_vars/all/vars alla lyssnare och lägg till namnet på gruppen i titeln:
# group_vars/all/vars
bbauth_auth_bind_port: "20000"
ghauth_auth_bind_port: "30000"
# group_vars/bbauth/vars
auth_bind_port: "{{ bbauth_auth_bind_port }}"
# group_vars/ghauth/vars
auth_bind_port: "{{ ghauth_auth_bind_port }}"
# group_vars/myapi/vars
api_auth1_address: "http://{{ bbauth_auth_service_name }}:{{ bbauth_auth_bind_port }}"
api_auth2_address: "http://{{ ghauth_auth_service_name }}:{{ ghauth_auth_bind_port }}"Nu, genom att ändra anslutningsvärdet, kommer vi att vara säkra på att begäran kommer att gå till samma plats där porten finns.
Kodstil
- Eftersom roller och grupper är olika systemobjekt måste de ha olika namn, så att associationsvariablerna tydligt visar att de tillhör en specifik servergrupp och inte en roll i systemet.
Miljöberoende filer
Roller kan använda filer som skiljer sig från miljö till miljö.
Ett exempel på sådana filer är SSL-certifikat. Lagra dem i textform
i en variabel är det inte särskilt bekvämt. Men det är bekvämt att lagra sökvägen till dem i en variabel.
Vi använder till exempel en variabel api_ssl_key_file: "/path/to/file".
Eftersom det är uppenbart att nyckelcertifikatet kommer att ändras från miljö till miljö är detta en miljöberoende variabel, vilket betyder att den ska finnas i filen
group_vars/myapi/vars inventeringsvariabler och innehåller värdet "till exempel".
Det bekvämaste sättet i det här fallet är att lägga nyckelfilen i playbook-förrådet längs vägen
files/prod/certs/myapi.key, då blir variabelns värde:
api_ssl_key_file: "prod/certs/myapi.key". Bekvämligheten ligger i det faktum att personer som ansvarar för att distribuera systemet på en specifik monter också har ett eget dedikerat utrymme i förvaret för att lagra sina filer. Samtidigt är det fortfarande möjligt att ange den absoluta sökvägen till certifikatet på servern, om certifikaten levereras av ett annat system.
Flera montrar i en miljö
Det finns ofta ett behov av att distribuera flera praktiskt taget identiska montrar i en miljö med minimala skillnader. I det här fallet delar vi in miljöberoende variabler i de som inte förändras inom den här miljön och de som förändras. Och det senare tar vi direkt in i själva inventeringsfilerna. Efter denna manipulation blir det möjligt att skapa ytterligare en inventering direkt i miljökatalogen.
Den kommer att återanvända group_vars-inventeringen och har även förmågan att åsidosätta vissa variabler specifikt för sig själv.
Den slutliga katalogstrukturen för distributionsprojektet:
mydeploy # Каталог деплоя
├── deploy.yml # Плейбук деплоя
├── files # Каталог для файлов деплоя
│ ├── prod # Католог для средозависимых файлов стенда prod
│ │ └── certs #
│ │ └── myapi.key #
│ └── test1 # Каталог для средозависимых файлов стенда test1
├── group_vars # Каталог переменных плейбука
│ ├── all.yml # Файл для переменных связи всей системы
│ ├── myapi.yml # Файл переменных свойств группы myapi
│ ├── bbauth.yml #
│ └── ghauth.yml #
└── inventories #
├── prod # Каталог окружения prod
│ ├── group_vars # Каталог для переменных инвентори
│ │ ├── myapi #
│ │ │ ├── vars.yml # Средозависимые переменные группы myapi
│ │ │ └── vault.yml # Секреты (всегда средозависимы)
│ │ ├── bbauth #
│ │ │ ├── vars.yml #
│ │ │ └── vault.yml #
│ │ └── ghauth #
│ │ ├── vars.yml #
│ │ └── vault.yml #
│ └── prod.ini # Инвентори стенда prod
└── test # Каталог окружения test
├── group_vars #
│ ├── myapi #
│ │ ├── vars.yml #
│ │ └── vault.yml #
│ ├── bbauth #
│ │ ├── vars.yml #
│ │ └── vault.yml #
│ └── ghauth #
│ ├── vars.yml #
│ └── vault.yml #
├── test1.ini # Инвентори стенда test1 в среде test
└── test2.ini # Инвентори стенда test2 в среде testSammanfattningsvis
Efter att ha organiserat variablerna enligt artikeln: varje fil med variabler är ansvarig för en specifik uppgift. Och eftersom filen har vissa uppgifter blev det möjligt att tilldela en person som ansvarar för att varje fil är korrekt. Till exempel blir utvecklaren av systemimplementeringen ansvarig för korrekt ifyllning av playbook-variablerna, medan administratören vars ställning beskrivs i inventeringen är direkt ansvarig för att fylla i inventeringsvariablerna.
Roller blev en oberoende utvecklingsenhet med ett eget gränssnitt, vilket gjorde det möjligt för rollutvecklaren att utveckla kapacitet snarare än att skräddarsy rollen till systemet. Detta problem var särskilt relevant för de gemensamma rollerna för alla system i kampanjen.
Systemadministratörer behöver inte längre förstå distributionskoden. Allt som krävs av dem för en framgångsrik distribution är att fylla i de miljöberoende variabelfilerna.
Litteratur
Författare
Kalyuzhny Denis Aleksandrovich
Källa: will.com
