ansible devops codestyle
Ahoj! Volám sa pracujem ako inžinier v oddelení automatizácie procesov vývoja. Každý deň sú nové verzie aplikácií nasadzované na stovkách serverov spoločnosti. V tomto článku sa delím o skúsenosti s používaním Ansible na tieto účely.
Tento sprievodca ponúka spôsob organizácie premenných pri nasadení. Tento sprievodca je určený pre tých, ktorí už používajú úlohy vo svojich playbookoch a čítali , ale stretávajú sa s podobnými problémami:
- Nájsť premennú v kóde je ťažké pochopiť, za čo zodpovedá;
- Existuje niekoľko úloh a premenné je potrebné prepojiť jednou hodnotou, ale nedá sa to;
- Vznikajú ťažkosti pri vysvetľovaní iným, ako funguje logika premenných vo vašich playbookoch.
S týmito problémami sme sa stretli na projektoch v našej spoločnosti, čo nás priviedlo k pravidlám formátovania premenných v našich playbookoch, ktoré do určitej miery vyriešili tieto problémy.

Premenné v úlohách
Úloha je samostatný objekt systému nasadenia. Rovnako ako akýkoľvek objekt systému, by mala mať rozhranie na interakciu s ostatnými časťami systému. Týmto rozhraním sú premenné úlohy.
Zoberme si pre príklad úlohu api, ktorá inštaluje Java aplikáciu na server. Aké premenné by mohla mať?

Premenné úlohy môžeme rozdeliť na 2 typy podľa druhu:
1. Vlastnosti
a) nezávislé od prostredia
b) závislé od prostredia
2. Vzťahy
a) poslucháče
b) dotazy vo vnútri systému
c) dotazy do prostredia
Premenné vlastnosti — to sú premenné, ktoré určujú správanie úlohy.
Premenné dotazu — to sú premenné, ktorých hodnoty sa používajú na označenie vonkajších zdrojov vzhľadom na úlohu.
Premenné poslucháče — to sú premenné, ktorých hodnoty sa používajú na vytváranie premenných dotazu.
Na druhej strane, 1a, 2a, 2b — to sú premenné, ktoré nezávisia od prostredia (hardvér, vonkajšie zdroje atď.) a môžu byť vyplnené predvolenými hodnotami v defaults úlohy. Avšak premenné typu 1b a 2c možno vyplniť len hodnotou 'example', pretože sa budú líšiť od stánku k stánku v závislosti od prostredia.
Code style
- Názov premennej musí začínať názvom úlohy. To umožní neskôr ľahko porozumieť, z ktorej úlohy premenná pochádza a za čo zodpovedá.
- Pri používaní premenných v úlohách musíte nevyhnutne dodržiavať princíp enkapsulácie a používať premenné definované buď v samotnej úlohe, alebo v úlohách, od ktorých aktuálna závisí.
Snažte sa nepoužívať slovníky pre premenné. Ansible neumožňuje pohodlné predefinovanie jednotlivých hodnôt v slovníku.
Príklad zlej premennej:
myrole_user: login: admin password: adminTu je login nezávislá premenná, a password je závislá. Ale
keďže sú spojené v slovníku, budete musieť zadávať celú ju
neustále. Čo je veľmi nepríjemné. Lepšie to je takto:myrole_user_login: admin myrole_user_password: admin
Premenné v playbookoch nasadenia
Pri zostavovaní playbooku nasadenia (ďalej playbook) dodržiavame pravidlo, že by mal byť umiestnený v samostatnom repozitári. Rovnako ako úlohy: každá vo svojom git repozitári. To umožňuje uvedomiť si, že úlohy a playbook sú rôzne nezávislé objekty nasadzovacieho systému, a zmeny v jednom objekte by nemali ovplyvniť fungovanie druhého. Dosahuje sa to zmenou predvolených hodnôt premenných.
Pri zostavovaní playbooku, ak to zhrnieme, existuje možnosť predefinovať predvolené hodnoty premenných úlohy na dvoch miestach: v premenných playbooku a v premenných inventori.
mydeploy # Archiv nasadenia
├── deploy.yml # Playbook nasadenia
├── group_vars # Archiv premenných playbooku
│ ├── all.yml # Súbor pre premenné vzťahu celej sústavy
│ └── myapi.yml # Súbor premenných vlastností skupiny myapi
└── inventories #
└── prod # Archiv prostredia prod
├── prod.ini # Inventories súbor
└── group_vars # Archiv pre premenné inventori
└── myapi #
├── vars.yml # Závislé premenné skupiny myapi
└── vault.yml # Tajomstvá (vždy závislé) ** —
Rozdiel je v tom, že premenne playbooku sa používajú vždy pri volaní playbookov, ktoré sú umiestnené na rovnakej úrovni. To znamená, že tieto premenne sú skvelé na zmenu predvolených hodnôt premenných, ktoré nezávisia od prostredia. Naopak, inventárne premenné sa budú používať iba pre konkrétne prostredie, čo je ideálne pre premenné, ktoré závisia od prostredia.
Je dôležité poznamenať, že priorita premenných vám nedovolí predefinovať premenné najprv v premenných playbooku a potom osobitne v jednom inventári.
To znamená, že už v tomto štádiu je potrebné rozhodnúť sa, či je premenná závislá od prostredia alebo nie, a umiestniť ju na správne miesto.
Napríklad, v jednom projekte bola premenná zodpovedná za zapnutie SSL dlhodobo závislá od prostredia, keďže sme nemohli zapnúť SSL z nezávislých dôvodov na jednom z testovacích prostredí. Po odstránení tejto problémovej situácie sa stala nezávislou od prostredia a presunula sa do premenných playbooku.
Premenné vlastností pre skupiny
Rozšírime našu modelovú situáciu na obrázku 1, pridaním 2 skupín serverov s inou Java aplikáciou, ale s rôznymi nastaveniami.

Predstavme si, ako bude vyzerať playbook v tomto prípade:
- hosts: myapi
roles:
- api
- hosts: bbauth
roles:
- auth
- hosts: ghauth
roles:
- authMáme tri skupiny v playbooku, preto je okamžite odporúčané vytvoriť toľko súborov skupín v group_vars inventárnych premenných aj premenných playbooku. Jeden súbor skupiny v tomto prípade je popisom jednej zložky vyššieho aplikačného systému v playbooku. Otvorením súboru skupiny v premenných playbooku okamžite vidíte všetky rozdiely od predvoleného správania rolí nastavených na skupinu. V inventárnych premenných: rozdiely v správaní skupiny od prostredia k prostrediu.
Code Style
- Snažte sa vôbec nepoužívať host_vars premenné, pretože nepopisujú systém, ale iba špecifický prípad, čo v budúcnosti prinesie otázky: "Prečo sa tento host líši od ostatných?", na ktorú odpoveď nie je vždy ľahké nájsť.
Premenné väzby
To, čo sa týka vlastností premenných, ale čo s väzbovými premennými?
Ich rozdiel spočíva v tom, že musia mať rovnakú hodnotu v rôznych skupinách.
Na začiatku bola použiť monštruóznu konštrukciu typu:
hostvars[groups['bbauth'][0]]['auth_bind_port'], ale od nej sa hneď upustilo
pretože má nevýhody. Po prvé, objemnosť. Po druhé, závislosť od konkrétneho hostiteľa v skupine. Po tretie, je potrebné pred začiatkom nasadenia zhromaždiť fakty zo všetkých hostiteľov, ak nechceme dostať chybu neurčenej premennej.
Nakoniec sa rozhodlo použiť premenne spojenia.
Premenné väzby — to sú premenne, ktoré patria k playbooku a sú potrebné na prepojenie objektov systému.
Premenne spojenia sa vyplňujú vo všeobecných premenných systému group_vars/all/vars a vytvárajú sa prevedením všetkých premenných poslucháčov z každej skupiny a pridaním názvu skupiny, odkiaľ bol poslucháč prevedený, na začiatok premennej.
Týmto sa zabezpečuje jednotnosť a neprekrývanie názvov.
Skúsme spojiť premenne z vyššie uvedeného príkladu:

Predstavme si, že máme premenné, ktoré sú navzájom závislé:
# roles/api/defaults:
# Переменная запроса
api_auth1_address: "http://example.com:80"
api_auth2_address: "http://example2.com:80"
# roles/auth/defaults:
# Переменная слушатель
auth_bind_port: "20000"Prevedieme do všeobecných premenných group_vars/all/vars všetkých poslucháčov a pridáme do názvu meno skupiny:
# 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 }}"Teraz, keď zmeníme hodnotu konektora, budeme si istí, že požiadavka sa bude adresovať tam, kde je umiestnený port.
Code Style
- Keďže úlohy a skupiny sú rôzne objekty systému, je potrebné, aby mali rôzne názvy, potom premenné spojenia jasne ukážu, že patria konkrétnej skupine serverov, a nie úlohe v systéme.
Premenné závislé od prostredia
V úlohách môžu byť použité súbory, ktoré sa líšia od prostredia k prostrediu.
Príkladom takýchto súborov môžu byť SSL certifikáty. Skladovať ich v textovej podobe
v premennej nie je veľmi pohodlné. Ale je pohodlné uchovávať cestu k nim vo vnútri premennej.
Napríklad, použijeme premennú api_ssl_key_file: "/path/to/file".
Keďže je jasné, že certifikát kľúča sa bude meniť od prostredia k prostrediu, je to premenná závislá od prostredia, a preto by mala byť umiestnená v súbore
group_vars/myapi/vars inventár premenných a obsahovať hodnotu 'pre príklad'.
Najjednoduchšie je v tomto prípade umiestniť súbor kľúča do repozitára playbooku na ceste
files/prod/certs/myapi.key, potom bude hodnota premennej:
api_ssl_key_file: "prod/certs/myapi.key"Pohodlie spočíva v tom, že ľudia zodpovední za nasadenie systému na konkrétnom stojane majú tiež svoje vyhradené miesto v repozitári na ukladanie svojich súborov. Zároveň existuje možnosť zadať absolútnu cestu k certifikátu na serveri, v prípade ak certifikáty poskytuje iný systém.
Viac stojanov v jednom prostredí
Často sa objavuje potreba nasadiť niekoľko takmer identických stojanov v jednom prostredí s minimálnymi rozdielmi. V tomto prípade delíme prostredne závislé premenné na tie, ktoré sa nemenia v rámci tohto prostredia, a na tie, ktoré sa menia. A tieto posledné vyťahujeme priamo do samotných inventárnych súborov. Po tejto manipulácii je možné vytvoriť ešte jeden inventár priamo v adresári prostredia.
Bude opätovne používať inventárne group_vars, ako aj mať možnosť predefinovať niektoré premenné priamo pre seba.
Konečná štruktúra adresárov pre projekt nasadenia:
mydeploy # Zložka nasadenia
├── deploy.yml # Príručka nasadenia
├── files # Zložka pre súbory nasadenia
│ ├── prod # Zložka pre prostredia závislé súbory standu prod
│ │ └── certs #
│ │ └── myapi.key #
│ └── test1 # Zložka pre prostredia závislé súbory standu test1
├── group_vars # Zložka pre premenné príručky
│ ├── all.yml # Súbor pre premenné spoločné pre celý systém
│ ├── myapi.yml # Súbor premenných pre skupinu myapi
│ ├── bbauth.yml #
│ └── ghauth.yml #
└── inventories #
├── prod # Zložka prostredia prod
│ ├── group_vars # Zložka pre premenné inventára
│ │ ├── myapi #
│ │ │ ├── vars.yml # Premenné závislé na prostredí skupiny myapi
│ │ │ └── vault.yml # Tajomstvá (vždy závislé na prostredí)
│ │ ├── bbauth #
│ │ │ ├── vars.yml #
│ │ │ └── vault.yml #
│ │ └── ghauth #
│ │ ├── vars.yml #
│ │ └── vault.yml #
│ └── prod.ini # Inventár standu prod
└── test # Zložka prostredia test
├── group_vars #
│ ├── myapi #
│ │ ├── vars.yml #
│ │ └── vault.yml #
│ ├── bbauth #
│ │ ├── vars.yml #
│ │ └── vault.yml #
│ └── ghauth #
│ ├── vars.yml #
│ └── vault.yml #
├── test1.ini # Inventár standu test1 v prostredí test
└── test2.ini # Inventár standu test2 v prostredí testZhrnutie
Po organizovaní premenných v súlade s článkom: každý súbor s premennými má na starosti konkrétnu úlohu. A keďže súbor má konkrétne úlohy, je možné určiť zodpovednú osobu za správnosť každého súboru. Napríklad za správnosť vyplnenia premenných príručky je zodpovedný vývojár nasadenia systému, zatiaľ čo za vyplnenie premenných inventára je zodpovedný priamo administrátor, ktorého stand je opísaný v inventári.
Roly sa stali samostatnou jednotkou vývoja s vlastným rozhraním, čo umožnilo vývojárovi roly vyvíjať možnosti, namiesto prispôsobovania roly systému. Táto problémová otázka sa obzvlášť týkala spoločných rolí pre všetky systémy v kampani.
Správcovia systémov už nemusia rozumieť kódu nasadenia. Všetko, čo potrebujú na úspešné nasadenie, je vyplniť súbory premenných závislých od prostredia.
Literatúra
Autor
Kalužný Denis Alexandrovich
Zdroj: habr.com
