Systematický přístup k proměnným v Ansible

ansible devops codestyle

Ahoj! Jmenuji se Denis Kaljužnyj pracuji jako inženýr v oddělení automatizace procesů vývoje. Každý den se nové verze aplikací nasazují na stovkách serverů společnosti. V tomto článku se podělím o zkušenosti s používáním Ansible pro tyto účely.

Tento průvodce nabízí způsob organizace proměnných při nasazení. Tento průvodce je určen pro ty, kteří již používají role ve svých playbících a četli BestPractices, ale čelí podobným problémům:

  • Nalezení proměnné v kódu, kdy není snadné pochopit, za co odpovídá;
  • Existuje několik rolí a proměnné je třeba spojit jednou hodnotou, ale nedaří se to;
  • Objevují se potíže při vysvětlování ostatním, jak funguje logika proměnných ve vašich playbících

S těmito problémy jsme se setkali v projektech naší společnosti, což nás přivedlo k pravidlům organizace proměnných v našich playbících, které tento problém do určité míry vyřešily.

Systematický přístup k proměnným v Ansible

Proměnné v rolích

Role je samostatný objekt nasazovacího systému. Stejně jako každý objekt v systému, musí mít rozhraní pro interakci s ostatním systémem. Tímto rozhraním jsou proměnné role.

Uvažujme například roli api, která instaluje Java aplikaci na server. Jaké proměnné by mohla mít?

Systematický přístup k proměnným v Ansible

Proměnné role lze rozdělit na 2 typy podle povahy:

1. Vlastnosti
    a) nezávislé na prostředí
    b) závislé na prostředí
2. Odkazy
    a) posluchače 
    b) dotazy uvnitř systému
    c) dotazy do prostředí

Vlastnosti proměnných – to jsou proměnné, které určují chování role.

Dotazové proměnné – to jsou proměnné, jejichž hodnoty se používají k označení externích zdrojů vůči roli.

Posluchačské proměnné – to jsou proměnné, jejichž hodnoty se používají k utváření dotazových proměnných.

Na druhou stranu, 1a, 2a, 2b – to jsou proměnné, které nezávisí na prostředí (hardware, externí zdroje atd.) a mohou být vyplněny výchozími hodnotami v defaults role. Nicméně proměnné typu 1b a 2c nelze vyplnit ničím jiným než 'example', protože se budou lišit mezi prostředími v závislosti na okolních podmínkách.

Code style

  • Název proměnné musí začínat názvem role. To usnadní později zjistit, z jaké role proměnná pochází a za co odpovídá.
  • Při používání proměnných v rolích musíte nutně dodržovat princip inkapsulace a používat proměnné definované buď v samotné roli, nebo v rolích, od kterých aktuální role závisí.
  • Snažte se nepoužívat slovníky pro proměnné. Ansible neumožňuje pohodlně přepisovat jednotlivé hodnoty ve slovníku.

    Příklad špatné proměnné:

    myrole_user:
        login: admin
        password: admin

    Zde je login - proměnná nezávislá na prostředí, zatímco password - závislá. Ale
    protože jsou sloučeny ve slovníku, budete muset vždy zadávat celou proměnnou.
    Což je velmi nepohodlné. Raději takto:

    myrole_user_login: admin
    myrole_user_password: admin

Proměnné v nasazovacích playbookách

Při sestavování nasazovacího playbooku (dále playbook) se držíme pravidla, že by měl být umístěn v samostatném repozitáři. Stejně jako role: každá ve svém git repozitáři. To umožňuje chápat, že role a playbook jsou různé nezávislé objekty nasazovacího systému a změny v jednom objektu by neměly ovlivnit funkci druhého. Toho je dosaženo změnou výchozích hodnot proměnných.

Při sestavování playbooku, pokud shrneme, existuje možnost přepisovat výchozí hodnoty proměnných role na dvou místech: v proměnných playbooku a v proměnných inventáře.

mydeploy                        # Průvodce nasazováním
├── deploy.yml                  # Nasazovací playbook
├── group_vars                  # Průvodce proměnnými playbooku
│   ├── all.yml                 # Soubor pro proměnné vztahující se k celému systému
│   └── myapi.yml               # Soubor proměnných pro skupinu myapi
└── inventories                 #
    └── prod                    # Průvodce prostředím prod
      ├── prod.ini              # Inventární soubor
      └── group_vars            # Průvodce pro proměnné inventáře
          └── myapi             #
              ├── vars.yml      # Závislé proměnné skupiny myapi
              └── vault.yml     # Tajemství (vždy závislé na prostředí) *

* — Proměnné a trezory

Rozdíl spočívá v tom, že proměnné playbooku se používají vždy při volání playbooků umístěných na stejné úrovni. To znamená, že tyto proměnné jsou skvělé pro změnu výchozích hodnot proměnných, které nezávisí na prostředí. Naopak proměnné inventáře budou použity pouze pro konkrétní prostředí, což je ideální pro proměnné závislé na prostředí.

Je důležité si uvědomit, že priorita proměnných vám neumožní nejprve přepsat proměnné v proměnných playbooku a poté zvlášť v jednom inventáři.

To znamená, že již v této fázi je třeba rozhodnout, zda je proměnná závislá na prostředí, či nikoli, a umístit ji na správné místo.

Například v jednom projektu byla proměnná odpovídající za zapnutí SSL dlouho závislá na prostředí, protože jsme nemohli zapnout SSL z důvodů, které nebyly v naší moci, na jednom z testovacích prostředí. Jakmile jsme tuto situaci vyřešili, stala se nezávislou na prostředí a byla přesunuta do proměnných playbooku.

Proměnné vlastností pro skupiny

Rozšíříme náš model na obrázku 1 přidáním 2 skupin serverů s jinou Java aplikací, ale s různými nastaveními.

Systematický přístup k proměnným v Ansible

Představme si, jak by playbook v tomto případě vypadal:

- hosts: myapi
  roles:
    - api

- hosts: bbauth
  roles:
    - auth

- hosts: ghauth
  roles:
    - auth

Máme tři skupiny v playbooku, proto je doporučeno ihned vytvořit stejné množství souborů skupin v group_vars pro proměnné inventáře a proměnné playbooku. Jeden soubor skupiny v tomto případě představuje popis jedné komponenty vašeho aplikace v playbooku. Otevřením souboru skupiny v proměnných playbooku okamžitě vidíte všechna odchylka od výchozího chování rolí nastavených pro skupinu. V proměnných inventáře: odchylky chování skupiny od testovacího prostředí k testovacímu prostředí.

Styl kódu

  • Snažte se vůbec nepoužívat proměnné host_vars, protože nepopsují systém, ale pouze konkrétní případ, což v budoucnu povede k otázkám: "Proč se tento host liší od ostatních?", na kterou není vždy snadné nalézt odpověď.

Proměnné spojení

To se týká proměnných vlastností, ale co s proměnnými spojení?
Jejich rozdíl spočívá v tom, že by měly mít stejnou hodnotu v různých skupinách.

Zpočátku byla myšlenka použít monstrózní konstrukci typu:
hostvars[groups['bbauth'][0]]['auth_bind_port'], ale od ní se ihned upustilo.
protože má své nedostatky. Za prvé, objemnost. Za druhé, závislost na konkrétním hostiteli ve skupině. Za třetí, je nutné před nasazením shromáždit fakta ze všech hostitelů, pokud nechceme dostat chybu neznámé proměnné.

Nakonec bylo rozhodnuto použít proměnné vazby.

Proměnné spojení — jsou to proměnné, které patří k playbooku a slouží pro propojení objektů systému.

Proměnné vazby se vyplňují ve sdílených proměnných systému group_vars/all/vars a vznikají vytažením všech proměnných posluchačů z každé skupiny a přidáním názvu skupiny, odkud byl posluchač vytažen, na začátek proměnné.

Tím se zajišťuje jednotnost a nepřekrývání názvů.

Zkusíme propojit proměnné z výše uvedeného příkladu:

Systematický přístup k proměnným v Ansible

Představme si, že máme proměnné, které na sobě závisí:

# roles/api/defaults:
# Переменная запроса
api_auth1_address: "http://example.com:80"
api_auth2_address: "http://example2.com:80"

# roles/auth/defaults:
# Переменная слушатель
auth_bind_port: "20000"

Vybereme do sdílených proměnných group_vars/all/vars všechny posluchače a přidáme k názvu název 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 }}"

Nyní, když změníme hodnotu konektoru, budeme si jisti, že dotaz bude směřovat tam, kde je port umístěn.

Styl kódu

  • Protože role a skupiny jsou různé objekty systému, musí mít různé názvy, aby proměnné vazby přesně ukazovaly, že patří konkrétní skupině serverů, a ne roli v systému.

Souvislé soubory

Ve rolích mohou být použity soubory, které se liší od prostředí k prostředí.

Příkladem takových souborů mohou být SSL certifikáty. Ukládat je v textové podobě
v proměnné není příliš praktické. Je však pohodlné uchovávat cestu k nim uvnitř proměnné.

Například použijeme proměnnou api_ssl_key_file: "/path/to/file".

Protože je zřejmé, že certifikát klíče se bude měnit od prostředí k prostředí, jedná se o proměnnou závislou na prostředí, a proto by měla být umístěna v souboru
group_vars/myapi/vars inventář proměnných a obsahovat hodnotu 'pro příklad'.

Nejlépe je v tomto případě uložit soubor klíče do repozitáře playbooku na cestě
files/prod/certs/myapi.key, pak bude hodnota proměnné:
api_ssl_key_file: "prod/certs/myapi.key"Výhodou je, že lidé odpovědní za nasazení systému na konkrétním standu mají také svůj vyhrazený prostor v repozitáři pro ukládání svých souborů. Zároveň je možné uvést absolutní cestu k certifikátu na serveru, pro případ, že certifikáty poskytuje jiný systém.

Více standů v jednom prostředí

Často se objevuje potřeba nasadit několik prakticky identických standů v jednom prostředí s minimálními rozdíly. V takovém případě rozdělujeme prostředí závislé proměnné na ty, které se v rámci tohoto prostředí nemění, a ty, které se mění. A ty druhé vyňáváme přímo do samotných inventárních souborů. Po této manipulaci je možné vytvořit další inventář přímo v adresáři prostředí.

Bude opětovně používat inventář group_vars a také bude mít možnost přepsat některé proměnné přímo pro sebe.

Konečná struktura adresářů pro projekt nasazení:

mydeploy                        # Katalog nasazení
├── deploy.yml                  # Hlavní skript pro nasazení
├── files                       # Katalog pro soubory nasazení
│   ├── prod                    # Katalog pro prostředí specifické soubory standu prod
│   │   └── certs               # 
│   │       └── myapi.key       #
│   └── test1                   # Katalog pro prostředí specifické soubory standu test1
├── group_vars                  # Katalog proměnných skriptu
│   ├── all.yml                 # Soubory pro systémové proměnné
│   ├── myapi.yml               # Soubory pro proměnné skupiny myapi
│   ├── bbauth.yml              # 
│   └── ghauth.yml              #
└── inventories                 #
    ├── prod                    # Katalog prostředí prod
    │   ├── group_vars          # Katalog pro proměnné inventáře
    │   │   ├── myapi           #
    │   │   │   ├── vars.yml    # Prostředí specifické proměnné skupiny myapi
    │   │   │   └── vault.yml   # Tajemství (vždy prostředí specifická)
    │   │   ├── bbauth          # 
    │   │   │   ├── vars.yml    #
    │   │   │   └── vault.yml   #
    │   │   └── ghauth          #
    │   │       ├── vars.yml    #
    │   │       └── vault.yml   #
    │   └── prod.ini            # Inventář standu prod
    └── test                    # Katalog prostředí test
        ├── group_vars          #
        │   ├── myapi           #
        │   │   ├── vars.yml    #
        │   │   └── vault.yml   #
        │   ├── bbauth          #
        │   │   ├── vars.yml    #
        │   │   └── vault.yml   #
        │   └── ghauth          #
        │       ├── vars.yml    #
        │       └── vault.yml   #
        ├── test1.ini           # Inventář standu test1 v prostředí test
        └── test2.ini           # Inventář standu test2 v prostředí test

Shrnutí

Po uspořádání proměnných v souladu s článkem: každý soubor s proměnnými odpovídá za konkrétní úkol. A jelikož má soubor konkrétní úkoly, bylo možné určit odpovědného za správnost každého souboru. Například za správnost vyplnění proměnných skriptu odpovídá vývojář nasazení systému, zatímco za vyplnění proměnných inventáře přímo odpovídá administrátor, jehož stand je popsán v inventáři.

Role se staly samostatnou jednotkou vývoje s vlastním rozhraním, což umožnilo vývojáři role vyvíjet možnosti, místo aby přizpůsoboval roli systému. Tento problém se zvlášť týkal společných rolí pro všechny systémy v kampani.

Správci systému již nemusí rozumět kódu nasazení. Vše, co potřebují k úspěšnému nasazení, je vyplnit soubory prostředkových proměnných.

Literatura

  1. Dokumentace

Autor

Kaljužnyj Denis Alexandrovich

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster