Керування конфігураціями віддалених систем - невід'ємна частина повсякденної роботи Адміністраторів і операційних груп. Тому актуальним залишається завдання автоматизації цього трудомісткого процесу. Для цих цілей використовується низка програмних інструментів, одним з яких виступає Ansible. Характеристики та спосіб обробки даних дають змогу говорити про очевидні переваги програми перед своїми аналогами. Розглянемо детальніше її можливості та приклади використання на практиці.
Методи управління конфігураціями віддалених систем
Суть процесу автоматизації управління великою кількістю віддалених систем полягає в реалізації двох основних завдань або етапів: приведення конфігурації систем до однакового стійкого стану; застосування одного з механізмів управління внесеними змінами. Для розв'язання зазначених завдань може бути застосовано один із двох основних підходів - імперативний або декларативний.
Імперативний підхід передбачає формування обов'язкових директив або алгоритмів для отримання потрібного стану конфігурацій і зазвичай реалізується за допомогою bash-скриптів. До недоліків підходу можна віднести складність структури програм та їх обслуговування, а також неможливість забезпечити точне виконання вимоги щодо приведення конфігурацій віддалених систем до одного стійкого стану.
Суть декларативного підходу полягає у формуванні набору специфікацій для опису потрібних станів конфігурацій віддалених систем і подальшого використання для їхнього опрацювання програмного забезпечення (ПЗ) на стороні клієнтських машин. На відміну від попереднього підходу, складання специфікацій є набагато менш трудомістким процесом порівняно з програмуванням, і тут гарантоване отримання стійкого стану конфігурації відразу для всіх систем. До недоліків можна віднести певну трудомісткість робіт зі встановлення ПЗ на клієнтах. Як приклад реалізації можна вказати добре відому програму Chef.
Одним із варіантів декларативного підходу є використання на стороні клієнта замість спеціального ПЗ стандартизованих програмних засобів, таких, наприклад, як Python. Саме цей варіант реалізовано в системі Ansible. Керування запуском обробників специфікацій на стороні клієнта тут здійснюється за допомогою push-повідомлень, які надсилаються з сервера по захищеному ssh-каналу. Таким чином додатково забезпечується надійний захист даних, що передаються по мережі.
Структурна організація програмного середовища Ansible
Робота системи зводиться до постійної взаємодії між собою трьох основних елементів:
- Керуючий вузол або сервер;
- Клієнтські машини або віддалені клієнти;
- Динамічний список хостів або Inventory (у контексті термінології розробників).
Встановлення та налаштування програми передбачено тільки на керуючому вузлі. На машинах-клієнтах достатньо наявності середовища виконання Python версії Python 3 або вище. Список Inventory постійно перебуває на керуючому вузлі, зазнаючи змін відповідно до актуального стану конфігурації обслуговуваного кластера віддалених машин.
Виконання підготовчих етапів перед встановленням Ansible на Ubuntu 22.04
Як і для будь-якого іншого ПЗ, тут необхідно виконати низку підготовчих дій, що гарантує згодом коректну роботу та встановлення програми. Сюди можна віднести такі дії:
- Створення на керуючому вузлі користувача з правами sudo;
- Створення на сервері пари ssh-ключів;
- Підготовка списку хостів кластера (Inventory);
- Копіювання відкритих ssh-ключів на клієнтські машини;
- Створення на сервері середовища виконання Python 3.
Виконаємо на нашому сервері кожну із зазначених дій.
Створення користувача
Для початку створимо на сервері обліковий запис користувача з ім'ям testing_ansible. Для цього наберемо в терміналі:
$ adduser testing_ansible
Обліковий запис було успішно створено. Після цього додамо новоствореного користувача в адміністраторську групу sudo:
$ adduser testing_ansible sudo
Результат виконання команди: "Adding user testing_ansible to group sudo Done." (користувача успішно додано до групи sudo).
Змінимо поточний акаунт на щойно створений за допомогою такої команди:
$ su -l testing_ansible
Як бачимо, ми зайшли в систему під обліковим записом користувача testing_ansible і надалі формуватимемо всі команди від його імені.
Створення ssh-ключів
Ssh-ключі надають альтернативний спосіб автентифікації користувачів віддалених систем, який має вищий рівень захисту порівняно з методом автентифікації на основі пароля. Тому він є кращим. Суть його використання полягає в передачі на віддалені машини кластера відкритого ключа, тоді як закритий ключ залишається на сервері та надається тільки за запитом віддаленого клієнта.
Згенеруємо пару ssh-ключів за допомогою такої команди:
$ ssh-keygen
У результаті виконання команди ключі були створені та збережені в каталозі /home/testing_ansible/.ssh/. Файл закритого ключа - id_rsa, відкритого - id_rsa.pub.
Підготовка списку Inventory
Список необхідний для роботи програми в автоматичному режимі. Наприклад, для розсилки мережею керуючих push-повідомлень програма бере всю потрібну інформацію про хости саме з цього списку. Тут, зокрема, мають бути вказані такі дані, як символічні імена хостів, їхні IP-адреси, а також імена користувачів для підключення до віддаленої системи. Доцільно створити на всіх хостах облікові записи користувачів із правами sudo, імена яких збігалися б. Згодом це полегшить виконання налаштувань на сервері.
У нашому випадку для підключення до всіх хостів кластера буде використовуватися обліковий запис з ім'ям alexandr75001.
Символічні імена хостів будуть такими:
server1
server2
server3
Їхні IP-адреси:
201.0.111.101
201.0.111.102
201.0.111.103
Згодом ця інформація має бути поміщена в системний файл /etc/ansible/hosts. Цим ми займемося пізніше.
Копіювання відкритого ssh-ключа на машини кластера
Для можливості безперешкодного захищеного доступу Ansible до віддалених машин кластера, необхідно забезпечити наявність на кожній з них створеного нами раніше файлу відкритого ключа id_rsa.pub. Це можна зробити різними способами, зокрема й ручним копіюванням. Однак у разі великої кількості машин такий підхід неприйнятний. Тому ми автоматизуємо цей процес за допомогою команди ssh-copy-id. Для демонстрації процесу використовуватимемо сторонній хост, що не входить до нашого списку Inventory. Введемо в терміналі:
$ ssh-copy-id alexandr75001@176.9.11.135
Зазначений у команді вузол поки що не є довіреним для нашого сервера, тому в запиті командного рядка нам потрібно підтвердити свою згоду на це за допомогою підтверджувальної мовної конструкції yes.
Після цього утиліта ініціює пошук файлу відкритого ключа для поточного облікового запису сервера, і коли його буде знайдено, запитає пароль віддаленого користувача alexandr75001, як показано нижче:
Після підключення до хоста утиліта скопіює вміст файлу id_rsa.pub у файл authorized_keys, який міститься в домашньому каталозі віддаленого користувача. Нижче показано результат виконання цієї операції - "Number of key added: 1" (Додано один ключ).
Для перевірки надійності встановленого зв'язку між хостами підключимося до віддаленої системи за допомогою такої команди:
$ ssh alexandr75001@176.9.11.135
Можна переконатися, що ми тепер перебуваємо на віддаленому хості під обліковим записом alexandr75001, що видно із запрошення командного рядка.
Такого ж типу дії ми повинні були б виконати для всіх віддалених систем списку Inventory. Це гарантувало б надалі безпомилкову роботу програми Ansible. Після такого налаштування паролі вже не будуть запитуватися при підключенні до віддалених систем.
Для повернення на сервер наберемо в терміналі команду виходу:
$ exit
Тепер ми знову на сервері, де і продовжимо свою роботу.
Підготовка програмного середовища
Для початку перевіримо версію мови Python, встановленої на сервері. Для цього введемо в терміналі:
$ python3 --version
Встановлена версія - "Python 3.10.12", що відповідає системним вимогам для роботи Ansible.
Після цього оновимо індекс програмних пакетів Ubuntu:
$ sudo apt update
Оскільки файли програми Ansible у мережі зберігаються в окремому сховищі, необхідно відкрити до нього доступ, додавши його ім'я до списку джерел для нашої системи. Це можна зробити за допомогою такої команди:
$ sudo apt-add-repository ppa:ansible/ansible
Середовище для встановлення програми підготовлено.
Встановлення Ansible
Тепер можна приступати до встановлення. Введемо в терміналі:
$ sudo apt install ansible
Підтверджуємо свою згоду на виділення 300 Mb місця на диску, і процес встановлення програми починається.
Встановлення було успішно завершено. Переконаємося в цьому за допомогою команди визначення версії та одночасно переглянемо шляхи доступу до основних компонентів програми. Введемо в терміналі:
$ ansible --version
Нижче наведено висновок команди:
ansible [core 2.15.8]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/testing_ansible/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /home/testing_ansible/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/usr/bin/python3)
jinja version = 3.0.3
libyaml = True
Як бачимо, всі компоненти програми на місці, і шляхи до них визначені. Отже, все в порядку.
Налаштування сервера Ansible
Налаштування сервера полягає у формуванні списку Inventory в системному файлі /etc/ansible/hosts, а також налаштуванні параметрів у файлі конфігурації /etc/ansible/ansible.cfg. Виконаємо все по черзі.
Налаштування параметрів файлу hosts
Як уже говорилося, список хостів кластера необхідний для можливості виконання підключення до машин в автоматичному режимі без втручання Адміністратора. Шлях до цього списку (/etc/ansible/hosts) зазвичай встановлюють за замовчуванням, однак за необхідності його можна змінити в інтересах поточного проєкту. Відкриємо файл за допомогою такої команди:
$ sudo nano /etc/ansible/hosts
Вставимо в нього наведений нижче код:
[servers]
server1 ansible_host=201.0.111.101
server2 ansible_host=201.0.111.102
server3 ansible_host=201.0.111.103
[all:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_user=alexandr75001
Код містить два розділи: [servers] і [all:vars]. У першому з них вказані псевдоніми хостів кластера та їхні IP-адреси. У другому розділі вказані загальні для всіх хостів параметри - встановлено загальний для всіх хостів інтерпретатор мови Python, а також загальне ім'я користувача.
Вставимо наш код у файл hosts, як показано вище і збережемо внесені зміни (ctrl+O, Enter). Повернемося в командний рядок терміналу (ctrl+X).
Після цього нам залишається переконатися в тому, що програма правильно ідентифікувала внесені нами до списку хости. Для цього наберемо в терміналі:
$ ansible-inventory --list -y
Висновок команди наведено нижче.
all:
children:
servers:
hosts:
server1:
ansible_host: 201.0.111.101
ansible_python_interpreter: /usr/bin/python3
ansible_user: alexandr75001
server2:
ansible_host: 201.0.111.102
ansible_python_interpreter: /usr/bin/python3
ansible_user: alexandr75001
server3:
ansible_host: 201.0.111.103
ansible_python_interpreter: /usr/bin/python3
ansible_user: alexandr75001
Можна переконатися, що всі хости ідентифіковані правильно. Для кожного з них правильно вказані IP-адреси, ім'я користувача та призначений інтерпретатор мови Python.
Налаштування файлу конфігурації ansible.cfg
Відкриємо файл за допомогою редактора nano і вставимо в нього наведений нижче код:
$ sudo nano /etc/ansible/ansible.cfg
Один із можливих варіантів налаштування конфігураційних параметрів:
[defaults]
interpreter_python = auto_silent
verbosity = 1
ANSIBLE_PIPELINING = True
retry_files_enabled = False
system_warnings = True
command_warnings = False
display_args_to_stdout = True
display_skipped_hosts = True
[ssh_connection]
ssh_args = -C -o ControlMaster=no -o ControlPersist=60s -o ConnectTimeout=10
retries = 1
sftp_batch_mode = True
transfer_method = sftp
[diff]
always = True
Після вставки коду файл конфігурації матиме вигляд, наведений вище. Збережемо внесені зміни та вийдемо з редактора.
Тестування роботи системи
Тестування системи зводиться до пінгування хостів зі списку Inventory за допомогою вбудованого в Ansible модуля ping. При цьому параметри його запуску можуть відрізнятися залежно від ситуації.
Протестуємо нашу систему за допомогою такої команди:
$ ansible all -m ping
Виведення команди:
server2 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Unable to negotiate with 201.0.111.102 port 22: no matching host key type found. Their offer: ssh-rsa",
"unreachable": true
}
server1 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: ssh: connect to host 201.0.111.101 port 22: Connection timed out",
"unreachable": true
}
server3 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: ssh: connect to host 201.0.111.103 port 22: Connection timed out",
"unreachable": true
}
ННа основі отриманих результатів зробимо остаточні висновки. Для кожного з трьох хостів видаються приблизно однакові повідомлення про недоступність хоста або ключа. І це нормально, оскільки всі ці машини дійсно недоступні в мережі, адже ми їх використовували виключно для демонстративних цілей. Однак той факт, що пінгування зазначених у списку машин було здійснено, свідчить про те, що всі налаштування програми було виконано правильно, і вона повністю готова для роботи з реальними машинами.
У разі ж повної доступності, висновок команди для кожної з машин мав би такий вигляд:
server | SUCCESS => {
"changed": false,
"ping": "pong"
}
Ключове слово тут - SUCCESS, тобто повна готовність хоста до роботи.