Системен подход към променливите в Ansible

ansible devops codestyle

Хей! Моето име е Денис Калюжни Работя като инженер в отдела за автоматизация на процесите на разработка. Всеки ден нови компилации на приложения се разпространяват на стотици сървъри на кампании. И в тази статия споделям опита си от използването на Ansible за тези цели.

Това ръководство предлага начин за организиране на променливи в внедряване. Това ръководство е предназначено за тези, които вече използват роли в своите учебници и четат Най-добри практикино срещам подобни проблеми:

  • След като намерите променлива в кода, е невъзможно веднага да разберете за какво е отговорна;
  • Има няколко роли и променливите трябва да бъдат свързани с една стойност, но това не работи;
  • Имате затруднения да обяснявате на другите как работи логиката на променливите във вашите книги-игри

Срещнахме тези проблеми при проекти в нашата компания, в резултат на което стигнахме до правилата за форматиране на променливи в нашите книги за игри, които до известна степен решиха тези проблеми.

Системен подход към променливите в Ansible

Променливи в ролите

Ролята е отделен системен обект за разполагане. Като всеки обект от системата, той трябва да има интерфейс за взаимодействие с останалата част от системата. Ролевите променливи са такъв интерфейс.

Вземете например ролята api, който инсталира Java приложение на сървъра. Какви променливи има?

Системен подход към променливите в Ansible

Ролевите променливи могат да бъдат разделени на 2 типа по вид:

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

Променливи свойства са променливи, които определят поведението на дадена роля.

Променливи на заявката са променливи, чиято стойност се използва за обозначаване на ресурси, външни за ролята.

Променливи слушатели са променливи, чиято стойност се използва за формиране на променливи на заявка.

От друга страна, 1a, 2a, 2b са променливи, които не зависят от средата (желязо, външни ресурси и т.н.) и могат да бъдат попълнени със стойности по подразбиране в ролята по подразбиране. Въпреки това, променливи като 1.b и 2.c не могат да бъдат попълнени със стойности, различни от „пример“, тъй като те ще се променят от щанд на щанд в зависимост от средата.

кодов стил

  • Името на променливата трябва да започва с името на ролята. Това ще улесни в бъдеще да разберете каква е ролята на променливата и за какво отговаря.
  • Когато използвате променливи в роли, трябва да следвате принципа на капсулиране и да използвате променливи, дефинирани или в самата роля, или в ролите, от които зависи текущата.
  • Избягвайте използването на речници за променливи. Ansible не ви позволява удобно да замените отделни стойности в речник.

    Пример за лоша променлива:

    myrole_user:
        login: admin
        password: admin

    Тук входът е средната променлива, а паролата е зависимата променлива. Но
    тъй като те са комбинирани в речник, ще трябва да го посочите изцяло
    Винаги. Което е много неудобно. По-добре така:

    myrole_user_login: admin
    myrole_user_password: admin

Променливи в ръководствата за внедряване

Когато съставяме ръководство за разгръщане (наричано по-нататък ръководство), ние се придържаме към правилото, че трябва да бъде поставено в отделно хранилище. Точно като ролите: всяка в собственото си git хранилище. Това ви позволява да разберете, че ролите и книгата за игра са различни независими обекти на системата за внедряване и промените в един обект не трябва да засягат работата на другия. Това се постига чрез промяна на стойностите по подразбиране на променливите.

Когато съставяте книга за игра, за да обобщим, е възможно да замените стойностите по подразбиране на ролевите променливи на две места: в променливите на книгата за игра и в променливите на инвентара.

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

* - Променливи и хранилища

Разликата е, че променливите на playbook винаги се използват, когато се извикват playbooks, разположени на същото ниво с него. Това означава, че тези променливи са чудесни за промяна на стойностите по подразбиране на променливи, които не зависят от средата. Обратно, променливите на инвентара ще се използват само за определена среда, което е идеално за променливи, специфични за средата.

Важно е да се отбележи, че приоритетът на променливите няма да ви позволи да предефинирате променливите първо в променливите на книгата за игра и след това отделно в същия инвентар.

Това означава, че вече на този етап трябва да решите дали променливата зависи от средата или не и да я поставите на правилното място.

Например, в един проект, променливата, отговорна за активирането на SSL, беше зависима от средата за дълго време, тъй като не можахме да активираме SSL по причини извън нашия контрол на един от щандовете. След като коригирахме този проблем, той стана средно независим и се премести в променливи на книгата за игра.

Променливи свойства за групи

Нека разширим нашия модел на Фигура 1, като добавим 2 групи сървъри с различно Java приложение, но с различни настройки.

Системен подход към променливите в Ansible

Представете си как ще изглежда книгата в този случай:

- hosts: myapi
  roles:
    - api

- hosts: bbauth
  roles:
    - auth

- hosts: ghauth
  roles:
    - auth

Имаме три групи в наръчника, така че се препоръчва да създадете възможно най-много групови файлове в променливите на инвентара group_vars и променливите на наръчника наведнъж. Един групов файл в този случай е описанието на един компонент от вашето приложение в наръчника. Когато отворите файла на групата в променливите на книгата за игра, веднага виждате всички разлики от поведението по подразбиране на ролите, присвоени на групата. В променливите на инвентара: разлики в груповото поведение от щанд до щанд.

кодов стил

  • Опитайте се изобщо да не използвате променливите host_vars, тъй като те не описват системата, а само специален случай, който в дългосрочен план ще доведе до въпроси: "Защо този хост е различен от останалите?", Отговорът на който е не винаги е лесно да се намери.

Свързване на променливи

Все пак става въпрос за променливите свойства, но какво да кажем за променливите за връзка?
Разликата им е, че те трябва да имат еднаква стойност в различните групи.

В началото имаше идеята използвайте чудовищна конструкция на формата:
hostvars[groups['bbauth'][0]]['auth_bind_port'], но веднага беше изоставен
защото има недостатъци. Първо, обемността. Второ, зависимост от конкретен хост в групата. Трето, необходимо е да се съберат факти от всички хостове, преди да започне внедряването, ако не искаме да получим грешка с недефинирана променлива.

В резултат на това беше решено да се използват променливи за връзка.

Свързване на променливи са променливи, които принадлежат на книгата и са необходими за свързване на системни обекти.

Променливите за връзка се попълват в общи системни променливи group_vars/all/vars и се формират чрез премахване на всички променливи слушател от всяка група и добавяне на името на групата, от която е премахнат слушателят, в началото на променливата.

По този начин се осигурява еднаквост и непресичане на имената.

Нека се опитаме да свържем променливи от примера по-горе:

Системен подход към променливите в Ansible

Представете си, че имаме променливи, които зависят една от друга:

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

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

Нека го поставим в общи променливи group_vars/all/vars всички слушатели и добавете името на групата към името:

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

Сега, като променим стойността на конектора, ще сме сигурни, че заявката ще отиде на същото място, където се намира портът.

кодов стил

  • Тъй като ролите и групите са различни системни обекти, те трябва да имат различни имена, така че променливите за връзка да покажат точно, че принадлежат към конкретна сървърна група, а не към роля в системата.

Файлове на околната среда

Ролите могат да използват файлове, които се различават в различните среди.

SSL сертификатите са пример за такива файлове. Съхранявайте ги като текст
в променлива не е много удобно. Но е удобно да съхранявате пътя до тях в променлива.

Например използваме променливата api_ssl_key_file: "/path/to/file".

Тъй като е очевидно, че сертификатът на ключа ще се променя от среда на среда, това е променлива, зависима от средата, което означава, че трябва да се намира във файла
group_vars/myapi/vars списък на променливите и съдържат стойността „например“.

Най-удобният начин в този случай е да поставите ключовия файл в хранилището на playbook по пътя
files/prod/certs/myapi.key, тогава стойността на променливата ще бъде:
api_ssl_key_file: "prod/certs/myapi.key". Удобството се крие във факта, че хората, отговорни за внедряването на системата на определен щанд, също имат свое специално място в хранилището, където да съхраняват своите файлове. В същото време остава възможно да се посочи абсолютният път до сертификата на сървъра, в случай че сертификатите се доставят от друга система.

Няколко стойки в една среда

Често има нужда да се разположат няколко почти идентични стойки в една и съща среда с минимални разлики. В този случай ние разделяме зависимите от средата променливи на такива, които не се променят в тази среда, и такива, които го правят. И изваждаме последното директно в самите файлове на инвентара. След тази манипулация става възможно да се създаде друг инвентар директно в директорията на средата.

Той ще използва повторно инвентара group_vars и също така ще може да предефинира някои променливи директно за себе си.

Окончателната структура на директория за проекта за внедряване:

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

Обобщаване

След организиране на променливите в съответствие със статията: всеки файл с променливи отговаря за конкретна задача. И тъй като файлът има определени задачи, стана възможно да се назначи отговорник за коректността на всеки файл. Например, разработчикът на внедряването на системата става отговорен за правилното попълване на променливите на playbook, докато администраторът, чиято позиция е описана в инвентара, е пряко отговорен за попълването на инвентара на променливите.

Ролите се превърнаха в самостоятелна единица за разработка със собствен интерфейс, което позволява на разработчика на ролята да разработва функции, вместо да приспособява ролята, за да пасне на системата. Този проблем беше особено верен за общи роли за всички системи в кампания.

Системните администратори вече не трябва да разбират кода за внедряване. Всичко, което се изисква от тях за успешно внедряване, е да попълнят файловете с променливи на средата.

Литература

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

Автор

Калюжни Денис Александрович

Източник: www.habr.com

Добавяне на нов коментар