ansible devops kódstílus
Helló! A nevem mérnökként dolgozom a fejlesztési folyamatok automatizálásával foglalkozó osztályon. Minden nap új alkalmazásverziókat telepítenek a cég több száz szerverére. Ebben a cikkben megosztom tapasztalataimat az Ansible használatáról ezekhez a célokhoz.
Ez a útmutató egy módszert javasol a változók megszervezésére a telepítések során. Az útmutató azoknak szól, akik már használják a szerepeket a playbookjaikban és olvasták a , de hasonló problémákkal szembesülnek:
- A kódban található változókat nehezen lehet azonosítani, hogy mit is jelentenek;
- Több szerep van, és a változókat egy értékhez kellene kötni, de ez nem sikerül;
- Nehezen tudjuk másoknak elmagyarázni, hogyan működnek a változók a playbookjainkban.
Ezekkel a problémákkal találkoztunk a vállalatunk projektjein, ennek következtében eljutottunk a változók formázásának szabályaihoz a playbookjainkban, amelyek részben megoldották ezeket a problémákat.

Változók a szerepekben
A szerep egy külön objektum a telepítési rendszerben. Mint minden rendszerbeli objektumnak, interakciós interfésszel kell rendelkeznie a többi rendszerrel. Ezt az interfészt a szerep változói jelentik.
Vegyünk például egy szerepet, api, amely egy Java alkalmazást telepít a szerverre. Milyen változói lehetnek?

A szerep változói két típussal oszthatók fel:
1. Tulajdonságok
a) környezettől független
b) környezettől függő
2. Kapcsolatok
a) hallgatók
b) lekérdezések a rendszeren belül
c) lekérdezések a környezetben
A tulajdonság változók — azok a változók, amelyek a szerep viselkedését határozzák meg.
A lekérdezési változók — azok a változók, amelynek értékét a szerepen kívüli erőforrások megjelölésére használják.
A hallgató változók — azok a változók, amelyek értéke a lekérdezési változók létrehozásához szolgál.
Másrészt, 1a, 2a, 2b — ezek a változók függetlenek a környezettől (hardver, külső erőforrások stb.), és alapértelmezett értékekkel kitölthetők a szerep defaultjai között. Azonban 1b és 2c típusú változók feltöltése más, mint 'example' értékekkel lehetetlen, mivel ezek az értékek környezettől függően változnak.
Kódstílus
- A változó neve mindenképpen a szerep nevével kell kezdődjön. Ez megkönnyíti a későbbi azonosítást arról, hogy melyik szerepből származik a változó és miért felelős.
- A változók szerepkörökben való használatakor mindenképpen be kell tartani a kapszulázás elvét, és olyan változókat kell használni, amelyeket vagy magában a szerepkörben, vagy a jelenlegi szerepköröktől függően határozunk meg.
Próbálja meg elkerülni a szótárak használatát a változókhoz. Az Ansible nem teszi lehetővé az egyes értékek kényelmes felülbírálását a szótárban.
Rossz változó példa:
myrole_user: login: admin password: adminItt a login egy környezettől független változó, míg a password függő. De
mivel ezek egy szótárban vannak összefogva, mindig teljesen meg kell adnia.
Ami nagyon kényelmetlen. Jobb így:myrole_user_login: admin myrole_user_password: admin
Változók a telepítési playbookokban
Telepítési playbook (a továbbiakban playbook) elkészítésekor azon elv szerint járunk el, hogy annak egy külön repozitóriumban kell lennie. Akárcsak a szerepköröknek: mindegyiknek a saját git repozitóriumában. Ez lehetővé teszi, hogy tudatosítsuk, hogy a szerepkörök és a playbook különálló, független telepítési rendszerbeli objektumok, és a módosítások az egyik objektumban nem befolyásolhatják a másikat. Ezt a változók alapértelmezett értékeinek módosításával érjük el.
A playbook elkészítésekor, ha összességében nézzük, két helyen van lehetőség a szerepkör változóinak alapértelmezett értékeinek felülbírálására: a playbook változói és az inventori változói.
mydeploy # Telepítési könyvtár
├── deploy.yml # Telepítési playbook
├── group_vars # Playbook változók könyvtára
│ ├── all.yml # A teljes rendszer változóit tartalmazó fájl
│ └── myapi.yml # A myapi csoport sajátosságainak változóit tartalmazó fájl
└── inventories #
└── prod # prod környezeti könyvtár
├── prod.ini # Inventori fájl
└── group_vars # Az inventori változók könyvtára
└── myapi #
├── vars.yml # A myapi csoport környezettől független változói
└── vault.yml # Titkok (mindig környezettől függetlenek) ** —
A különbség az, hogy a playbook változói mindig a vele egy szinten lévő playbookok meghívásakor kerülnek felhasználásra. Ezért ezek a változók tökéletesen alkalmasak az környezettől független változók alapértelmezett értékeinek módosítására. Ezzel szemben az inventori változók csak a konkrét környezetre vonatkoznak, ami tökéletes a környezettől függő változókhoz.
Fontos megjegyezni, hogy a változók prioritása nem teszi lehetővé, hogy a változókat először a playbook változóiban, majd külön egy inventory fájlban felülbírálja.
Ez azt jelenti, hogy már ezen a ponton el kell dönteni, hogy a változó környezettől függő-e vagy sem, és a megfelelő helyre kell helyezni.
Például egy projektben a változó, amely az SSL engedélyezéséért felelt, hosszú ideig környezettől függő volt, mivel egyes kiépítéseknél független okok miatt nem tudtuk engedélyezni az SSL-t. Miután ezt a problémát megoldottuk, környezettől függetlenné vált, és áthelyeztük a playbook változói közé.
Tulajdonsági változók csoportok számára
Bővítsük a modellünket az 1. ábrán, hozzávéve 2 szervercsoportot egy másik Java alkalmazással, de különböző beállításokkal.

Képzeljük el, hogyan fog kinézni a playbook ebben az esetben:
- hosts: myapi
roles:
- api
- hosts: bbauth
roles:
- auth
- hosts: ghauth
roles:
- authHárom csoportunk van a playbookban, ezért ajánlott az inventory group_vars változóiban és a playbook változóiban annyi fájlt létrehozni, ahány csoport van. Az egyik csoport fájl ebben az esetben a playbookban található alkalmazás egy összetevőjének leírása. A playbook változóiban található csoport fájl megnyitásakor azonnal láthatja a csoportot érintő szerepek alapértelmezett viselkedésének minden eltérését. Az inventory változókban: a csoport viselkedésének eltérései a kiépítésektől függően.
Kódstílus
- Próbálja meg egyáltalán nem használni a host_vars változókat, mivel ezek nem írják le a rendszert, csupán egy konkrét esetet mutatnak, ami a jövőben kérdéseket okozhat: "Miért különbözik ez a gazdagép a többitől?", aminek a válasza nem mindig könnyen megtalálható.
Kapcsolati változók
Ez azonban a tulajdonsági változókra vonatkozik, de hogyan kell eljárni a kapcsolati változókkal?
Az a különbség, hogy ezeknek az értéküknek azonosnak kell lennie a különböző csoportokban.
Kezdetben használni kellett volna a következő hatalmas szerkezetet: hostvars[groups['bbauth'][0]]['auth_bind_port']
, de ezt azonnal elvetettékmivel hátrányai voltak. Először is, körülményesség. Másodszor, a csoportban lévő adott gazdagéptől való függés. Harmadszor, a telepítés megkezdése előtt minden gazdagépről adatokat kell gyűjteni, ha nem akarunk meghatározatlan változó hibát kapni.
Végül döntés született a kapcsolati változók használatáról.
— ezek olyan változók, melyek a playbookhoz tartoznak, és a rendszerek objektumainak összekapcsolásához szükségesek.
Kapcsolati változók — ezek a változók a playbookhoz tartoznak, és szükségesek a rendszer objektumainak összekapcsolásához.
A kapcsolatváltozók a rendszer általános változóiban vannak kitöltve group_vars/all/vars és úgy jönnek létre, hogy a hallgatók összes változóját kiemeljük minden csoportból, és hozzáadjuk az elejéhez a csoport nevét, ahonnan a hallgató ki lett emelve.
Ezáltal biztosítva van a névváltoztatás egységessége és az elnevezések átfedésének elkerülése.
Próbáljuk meg összekapcsolni a fenti példából származó változókat:

Képzeljük el, hogy vannak olyan változóink, amelyek egymástól függenek:
# roles/api/defaults:
# Переменная запроса
api_auth1_address: "http://example.com:80"
api_auth2_address: "http://example2.com:80"
# roles/auth/defaults:
# Переменная слушатель
auth_bind_port: "20000"Helyezzük el a közös változók között group_vars/all/vars minden hallgatót, és adjuk hozzá a csoport nevét a címhez:
# 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 }}"Most, amikor a csatlakozó értékét megváltoztatjuk, biztosak lehetünk abban, hogy a kérés arra az helyre irányul, ahol a port található.
Kódstílus
- Mivel a szerepek és csoportok különböző objektumok a rendszerben, különböző nevekkel kell rendelkezniük, így a kapcsolatváltozók pontosan megmutatják, hogy melyik szervercsoporthoz tartoznak, nem pedig a rendszer szerepeihez.
Környezettől függő fájlok
A szerepekben olyan fájlok használhatóak, amelyek környezettől függően eltérők.
Ezek közé tartozhatnak például az SSL tanúsítványok. Szöveges formában tárolni őket
változóban nem túl kényelmes. Ellenben kényelmesebb a fájl elérési útját változóban tárolni.
Például használjuk a változót api_ssl_key_file: "/path/to/file".
Mivel nyilvánvaló, hogy a kulcstanúsítvány környezettől függően változni fog, így ez egy környezettől függő változó, tehát a
group_vars/myapi/vars változók leltárában kell szerepeljen, és a ‘példa értéket’ kell tartalmaznia.
A legkényelmesebb azonban ez esetben a kulcsfájlt a playbook repóban elhelyezni az alábbi elérési úton
files/prod/certs/myapi.key, akkor a változó értéke a következő lesz:
api_ssl_key_file: "prod/certs/myapi.key". Az előny abban rejlik, hogy azok, akik felelősek a rendszer telepítéséért az adott környezetben, szintén elérhető helyet kapnak a repóban a saját fájljaik tárolására. Ugyanakkor lehetőség van arra, hogy a tanúsítvány abszolút elérési útját is meghatározzuk a szerveren, arra az esetre, ha a tanúsítványokat egy másik rendszer biztosítja.
Több környezet egy helyen
Gyakran felmerül a szükség, hogy több gyakorlatilag azonos környezetet állítsunk fel minimális eltérésekkel. Ilyen esetben a környezethez kötődő változókat két csoportra osztjuk: azokra, amelyek nem változnak az adott környezetben, és azokra, amelyek változnak. Az utóbbiakat közvetlenül az inventory fájlokba helyezzük. Ezt a lépést követően lehetőség nyílik arra, hogy egy új inventory-t hozzunk létre közvetlenül a környezet katalógusában.
Ez újra felhasználja az inventory group_vars-okat, valamint lehetőséget biztosít arra, hogy bizonyos változókat közvetlenül saját magukra állítsanak át.
A telepítési projekt végső mappastruktúrája:
mydeploy # Telepítési mappa
├── deploy.yml # Telepítési playbook
├── files # Fájlok mappája a telepítéshez
│ ├── prod # Mappa a környezethez kötődő fájloknak a prod állomáshoz
│ │ └── certs #
│ │ └── myapi.key #
│ └── test1 # Mappa a környezethez kötődő fájloknak a test1 állomáshoz
├── group_vars # A playbook változóinak mappája
│ ├── all.yml # A rendszer összes változóját tartalmazó fájl
│ ├── myapi.yml # A myapi csoport változóinak fájlja
│ ├── bbauth.yml #
│ └── ghauth.yml #
└── inventories #
├── prod # prod környezet mappa
│ ├── group_vars # Az inventory változók mappája
│ │ ├── myapi #
│ │ │ ├── vars.yml # A myapi csoporthoz kötődő változók
│ │ │ └── vault.yml # Titkok (mindig környezethez kötöttek)
│ │ ├── bbauth #
│ │ │ ├── vars.yml #
│ │ │ └── vault.yml #
│ │ └── ghauth #
│ │ ├── vars.yml #
│ │ └── vault.yml #
│ └── prod.ini # A prod állomás inventory-ja
└── test # test környezet mappa
├── group_vars #
│ ├── myapi #
│ │ ├── vars.yml #
│ │ └── vault.yml #
│ ├── bbauth #
│ │ ├── vars.yml #
│ │ └── vault.yml #
│ └── ghauth #
│ ├── vars.yml #
│ └── vault.yml #
├── test1.ini # A test1 állomás inventory-ja a test környezetben
└── test2.ini # A test2 állomás inventory-ja a test környezetbenÖsszegzés
A változók cikk szerint történő rendezése után: minden változó fájl egy adott feladatért felel. Mivel a fájloknak konkrét feladataik vannak, lehetséges, hogy egy felelőst kijelöljünk minden fájl helyességéért. Például a playbook változók helyességéért a rendszer telepítési fejlesztője felel, míg az inventory változók kitöltéséért az adminisztrátor, akinek a standja az inventoryban van, felel.
A szerepek önálló fejlesztési egységgé váltak saját interfésszel, ami lehetővé tette a szerepkifejlesztő számára, hogy funkciókat fejlesszen, ahelyett, hogy a szerepet a rendszerhez igazítsa. Ez különösen a kampány összes rendszere számára közös szerepeknél volt probléma.
A rendszergazdáknak már nem kell a telepítési kódokkal foglalkozniuk. Minden, amit a sikeres telepítéshez szükséges, az környezeti változó fájlok kitöltése.
Irodalom
Szerző:
Kalyuzhny Denis Alexandrovich
Forrás: habr.com
