Systemtilnærming til variabler i Ansible

ansible devops codestyle

Hei! Mitt navn er Denis Kalyuzhny Jeg jobber som ingeniør i utviklingsprosessautomatiseringsavdelingen. Hver dag rulles nye applikasjonsbygg ut til hundrevis av kampanjeservere. Og i denne artikkelen deler jeg min erfaring med å bruke Ansible til disse formålene.

Denne veiledningen tilbyr en måte å organisere variabler i en distribusjon. Denne veiledningen er laget for de som allerede bruker roller i lekebøkene og leser Beste praksismen får lignende problemer:

  • Etter å ha funnet en variabel i koden, er det umulig å umiddelbart forstå hva den er ansvarlig for;
  • Det er flere roller, og variablene må knyttes til én verdi, men det fungerer ikke;
  • Har problemer med å forklare andre hvordan logikken til variablene i lekebøkene dine fungerer

Vi møtte disse problemene på prosjekter i selskapet vårt, som et resultat av at vi kom til reglene for formatering av variabler i lekebøkene våre, som til en viss grad løste disse problemene.

Systemtilnærming til variabler i Ansible

Variabler i roller

En rolle er et separat distribusjonssystemobjekt. Som ethvert objekt i systemet, må det ha et grensesnitt for å samhandle med resten av systemet. Rollevariabler er et slikt grensesnitt.

Ta for eksempel rollen api, som installerer en Java-applikasjon på serveren. Hvilke variabler kan det ha?

Systemtilnærming til variabler i Ansible

Rollevariabler kan deles inn i 2 typer etter type:

1. Свойства
    a) независимые от среды
    б) зависимые от среды
2. Связи
    a) слушатели 
    б) запросы внутри системы
    в) запросы в среду

Variable egenskaper er variabler som definerer oppførselen til en rolle.

Søkevariabler er variabler hvis verdi brukes til å utpeke ressurser utenfor rollen.

Variable lyttere er variabler hvis verdi brukes til å danne spørringsvariabler.

På den annen side er 1a, 2a, 2b variabler som ikke er avhengige av miljøet (jern, eksterne ressurser, etc.) og kan fylles med standardverdier i standardrollen. Variabler som 1.b og 2.c kan imidlertid ikke fylles med andre verdier enn "eksempel", siden de vil endre seg fra stand til stand avhengig av miljøet.

kode stil

  • Navnet på variabelen må begynne med navnet på rollen. Dette vil gjøre det enkelt å finne ut i fremtiden hvilken rolle variabelen er fra og hva den er ansvarlig for.
  • Når du bruker variabler i roller, må du være sikker på å følge innkapslingsprinsippet og bruke variabler definert enten i selve rollen eller i rollene som den gjeldende er avhengig av.
  • Unngå å bruke ordbøker for variabler. Ansible lar deg ikke enkelt overstyre individuelle verdier i en ordbok.

    Et eksempel på en dårlig variabel:

    myrole_user:
        login: admin
        password: admin

    Her er pålogging medianvariabelen, og passord er den avhengige variabelen. Men
    siden de er kombinert til en ordbok, må du spesifisere den i sin helhet
    Alltid. Noe som er veldig upraktisk. Bedre på denne måten:

    myrole_user_login: admin
    myrole_user_password: admin

Variabler i distribusjonshåndbøker

Når vi kompilerer en distribusjonsspillbok (heretter referert til som en spillebok), følger vi regelen om at den skal plasseres i et eget depot. Akkurat som roller: hver i sitt eget git-lager. Dette lar deg innse at rollene og spilleboken er forskjellige uavhengige objekter i distribusjonssystemet, og endringer i ett objekt bør ikke påvirke driften av det andre. Dette oppnås ved å endre standardverdiene til variablene.

Når du kompilerer en playbook, for å oppsummere, er det mulig å overstyre standardverdiene til rollevariabler på to steder: i playbook-variabler og i inventarvariabler.

mydeploy                        # Каталог деплоя
├── deploy.yml                  # Плейбук деплоя
├── group_vars                  # Каталог переменных плейбука
│   ├── all.yml                 # Файл для переменных связи всей системы
│   └── myapi.yml               # Файл переменных свойств группы myapi
└── inventories                 #
    └── prod                    # Каталог окружения prod
        ├── prod.ini            # Инвентори файл
        └── group_vars          # Каталог для переменных инвентори
            └── myapi           #
                ├── vars.yml    # Средозависимые переменные группы myapi
                └── vault.yml   # Секреты (всегда средозависимы) *

* - Variabler og hvelv

Forskjellen er at playbook-variabler alltid brukes når du kaller playbooks som ligger på samme nivå med den. Dette betyr at disse variablene er gode for å endre standardverdiene til variabler som ikke er avhengige av miljøet. Motsatt vil inventarvariabler bare brukes for et bestemt miljø, noe som er ideelt for miljøspesifikke variabler.

Det er viktig å merke seg at variabel prioritet ikke vil tillate deg å redefinere variabler først i playbook-variabler og deretter separat i samme inventar.

Dette betyr at du allerede på dette stadiet må bestemme om variabelen er miljøavhengig eller ikke og plassere den på riktig sted.

For eksempel, i ett prosjekt, var variabelen som var ansvarlig for å aktivere SSL miljøavhengig i lang tid, siden vi ikke kunne aktivere SSL av grunner utenfor vår kontroll på en av standene. Etter at vi fikset dette problemet, ble det middels uavhengig og flyttet til playbook-variabler.

Egenskapsvariabler for grupper

La oss utvide modellen vår i figur 1 ved å legge til 2 grupper av servere med en annen Java-applikasjon, men med forskjellige innstillinger.

Systemtilnærming til variabler i Ansible

Tenk deg hvordan lekeboken vil se ut i dette tilfellet:

- hosts: myapi
  roles:
    - api

- hosts: bbauth
  roles:
    - auth

- hosts: ghauth
  roles:
    - auth

Vi har tre grupper i playbook, så det anbefales å lage så mange gruppefiler i group_vars inventarvariabler og playbookvariabler samtidig. En gruppefil i dette tilfellet er beskrivelsen av én komponent i applikasjonen din i playbook. Når du åpner gruppefilen i playbook-variablene, ser du umiddelbart alle forskjellene fra standardoppførselen til rollene som er tildelt gruppen. I inventarvariabler: forskjeller i gruppeatferd fra stand til stand.

Kodestil

  • Prøv å ikke bruke host_vars-variabler i det hele tatt, da de ikke beskriver systemet, men bare et spesielt tilfelle, som i det lange løp vil føre til spørsmål: "Hvorfor er denne verten forskjellig fra resten?", Svaret er ikke alltid lett å finne.

Koble variabler

Det handler imidlertid om egenskapsvariabler, men hva med lenkevariabler?
Forskjellen deres er at de må ha samme verdi i ulike grupper.

I begynnelsen var det ideen bruk en monstrøs konstruksjon av formen:
hostvars[groups['bbauth'][0]]['auth_bind_port'], men den ble umiddelbart forlatt
fordi den har feil. Først omfanget. For det andre avhengighet av en bestemt vert i gruppen. For det tredje er det nødvendig å samle inn fakta fra alle verter før du starter utrullingen, hvis vi ikke ønsker å få en udefinert variabelfeil.

Som et resultat ble det besluttet å bruke lenkevariabler.

Koble variabler er variabler som tilhører playbook og er nødvendige for å koble sammen systemobjekter.

Koblingsvariabler er fylt ut i generelle systemvariabler group_vars/all/vars og dannes ved å fjerne alle lyttervariabler fra hver gruppe, og legge til navnet på gruppen som lytteren ble fjernet fra, til begynnelsen av variabelen.

Dermed er enhetlighet og ikke-kryss mellom navn sikret.

La oss prøve å binde variabler fra eksemplet ovenfor:

Systemtilnærming til variabler i Ansible

Tenk deg at vi har variabler som er avhengige av hverandre:

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

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

La oss sette det i vanlige variabler group_vars/all/vars alle lyttere, og legg til navnet på gruppen til navnet:

# 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 }}"

Nå, ved å endre verdien på kontakten, vil vi være sikre på at forespørselen vil gå til samme port.

Kodestil

  • Siden roller og grupper er forskjellige objekter i systemet, må du ha forskjellige navn på dem, da vil lenkevariablene nøyaktig vise at de tilhører en bestemt gruppe servere, og ikke til en rolle i systemet.

Miljøfiler

Roller kan bruke filer som er forskjellige fra miljø til miljø.

SSL-sertifikater er et eksempel på slike filer. Lagre dem som tekst
i en variabel er ikke veldig praktisk. Men det er praktisk å lagre banen til dem i en variabel.

For eksempel bruker vi variabelen api_ssl_key_file: "/path/to/file".

Siden det er åpenbart at nøkkelsertifikatet vil endre seg fra miljø til miljø, er dette en miljøavhengig variabel, noe som betyr at den bør ligge i filen
group_vars/myapi/vars inventar av variabler, og inneholder verdien 'for eksempel'.

Den mest praktiske måten i dette tilfellet er å legge nøkkelfilen i playbook-depotet langs banen
files/prod/certs/myapi.key, vil verdien av variabelen være:
api_ssl_key_file: "prod/certs/myapi.key". Bekvemmeligheten ligger i det faktum at personene som er ansvarlige for å distribuere systemet på en bestemt stand også har sin egen dedikerte plass i depotet for å lagre filene sine. Samtidig er det fortsatt mulig å spesifisere den absolutte banen til sertifikatet på serveren, i tilfelle sertifikatene leveres av et annet system.

Flere stativer i ett miljø

Ofte er det behov for å sette ut flere nesten identiske stands i samme miljø med minimale forskjeller. I dette tilfellet deler vi opp miljøavhengige variabler i de som ikke endres innenfor dette miljøet og de som gjør det. Og vi tar ut sistnevnte direkte inn i selve inventarfilene. Etter denne manipulasjonen blir det mulig å lage en annen inventar direkte i miljøkatalogen.

Den vil gjenbruke group_vars-beholdningen og også være i stand til å redefinere noen variabler direkte for seg selv.

Den endelige katalogstrukturen for distribusjonsprosjektet:

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 в среде test

Oppsummering

Etter å ha organisert variablene i samsvar med artikkelen: hver fil med variabler er ansvarlig for en spesifikk oppgave. Og siden filen har visse oppgaver, ble det mulig å tildele en person som er ansvarlig for riktigheten av hver fil. For eksempel blir utvikleren av systemimplementeringen ansvarlig for riktig utfylling av playbook-variablene, mens administratoren, hvis stand er beskrevet i inventaret, er direkte ansvarlig for å fylle ut inventaret av variabler.

Roller ble en selvstendig utviklingsenhet med sitt eget grensesnitt, slik at rolleutvikleren kunne utvikle funksjoner i stedet for å skreddersy rollen for å passe til systemet. Dette problemet gjaldt spesielt for vanlige roller for alle systemer i en kampanje.

Systemadministratorer trenger ikke lenger å forstå distribusjonskoden. Alt som kreves av dem for en vellykket distribusjon er å fylle ut filene med miljøvariabler.

Litteratur

  1. Документация

Forfatter

Kalyuzhny Denis Alexandrovich

Kilde: www.habr.com

Legg til en kommentar