Rendszerszemlélet a változókban Ansible-ben

ansible devops kódstílus

Helló! A nevem Denis Kaluzsnyij 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 BestPractices, 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.

Rendszerszemlélet a változókban Ansible-ben

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?

Rendszerszemlélet a változókban Ansible-ben

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: admin

    Itt 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) *

* — Változók és trezorok

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.

Rendszerszemlélet a változókban Ansible-ben

Képzeljük el, hogyan fog kinézni a playbook ebben az esetben:

- hosts: myapi
  roles:
    - api

- hosts: bbauth
  roles:
    - auth

- hosts: ghauth
  roles:
    - auth

Há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: ötlet 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:

Rendszerszemlélet a változókban Ansible-ben

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

  1. kódkönyvtárra lépésével érheti el.

Szerző:

Kalyuzhny Denis Alexandrovich

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster