ansible. Работа с проверками (debug/when/jinja2)

===========================================================================

Thank you for reading this post, don't forget to subscribe!

 

Про­ве­ря­ем нали­чие 2х уста­нов­лен­ных паке­тов python и tcpdump  исполь­зу­ем модуль package_facts

 

========================================

 

====================================

Делегирование задачи другому хосту

Ино­гда тре­бу­ет­ся выпол­нить зада­чу на опре­де­лён­ном узле, но в кон­тек­сте дру­го­го узла. Напри­мер, во вре­мя обнов­ле­ния узла может воз­ник­нуть необ­хо­ди­мость отклю­чить для него мони­то­ринг, нахо­дя­щий­ся на отдель­ном сер­ве­ре. Для это­го исполь­зу­ет­ся управ­ля­ю­щая дирек­ти­ва delegate_to. При­ве­дём пример:

Резуль­та­том выпол­не­ния этой зада­чи будет отклю­че­ние сооб­ще­ний для сер­ви­са dnsserver в Nagios.

====================================================

Выражение ‘When’ в Ansible: Проверка Переменных

Узнать опре­де­ле­на ли (суще­ству­ет ли) пере­мен­ная в Ansible:

Про­ве­рить явля­ет­ся ли пере­мен­ная в Ansible пустой:

Убе­дить­ся что пере­мен­ная в Ansible опре­де­ле­на и не явля­ет­ся пустой:

Узнать име­ет ли пере­мен­ная в Ansible зна­че­ние True или False:

выпол­не­ние зада­чи на опре­де­лён­ной груп­пе из группы:
cat /etc/ansible/hosts
[nfs:children]
nfsmaster
nfsclient

[nfsmaster]
192.168.1.112
[nfsclient]
192.168.1.111
192.168.1.110

Печать Переменных & Вывод Всех Переменных — Playbook

Во вре­мя отлад­ки плей­бу­ка в Ansible, полез­но знать как, отоб­ра­зить задан­ные пере­мен­ные или извест­ные о хосте факты.

В Ansible, для печа­ти сооб­ще­ний из плей­бу­ка, а так­же для выво­да зна­че­ний пере­мен­ных, мы можем исполь­зо­вать модуль debug.

В сле­ду­ю­щих при­ме­рах я пока­зы­ваю, как напе­ча­тать кон­крет­ные пере­мен­ные в Ansible и как выве­сти спи­сок всех извест­ных фак­тов и пере­мен­ных в Ansible с помо­щью плейбука.

Debug Ansible Playbook — Печать Переменных

Выве­сти зна­че­ние переменной:

Напе­ча­тать пере­мен­ную толь­ко если она определена:

Печать несколь­ких переменных:

Выве­сти спи­сок всех извест­ных фак­тов и переменных:

Jinja2: Проверка Существования и Значения Переменной

В Jinja2-тем­плей­тах явля­ет­ся хоро­шей прак­ти­кой зара­нее про­ве­рять суще­ству­ет ли пере­мен­ная и какое у нее значение.

Суще­ству­ет несколь­ко полез­ных про­ве­рок, кото­рые вы може­те сде­лать с помо­щью встро­ен­ных в Jinja2 тестов и филь­тров.

В этой ста­тье я пока­жу, как про­ве­рить, суще­ству­ет ли пере­мен­ная, явля­ет­ся ли она пустой или она уста­нов­ле­на в зна­че­ние True.

Проверка Переменной в Jinja2

Про­ве­рить суще­ству­ет ли (опре­де­ле­на ли) переменная:

Про­ве­рить явля­ет­ся ли пустой переменная:

Про­ве­рить уста­нов­ле­на ли в зна­че­ние true переменная:

Про­ве­рить что пере­мен­ная суще­ству­ет и не явля­ет­ся пустой:

Про­ве­рить что пере­мен­ная суще­ству­ет и уста­нов­ле­на в зна­че­ние true:

 

======================================================================================

Ещё немно­го о WHEN

Использование когда с фактами

Вы може­те исполь­зо­вать услов­ные выра­же­ния when для запус­ка зада­чи, толь­ко если выпол­ня­ет­ся опре­де­лен­ное усло­вие. Для демон­стра­ции создай­те новую кни­гу вос­про­из­ве­де­ния с име­нем ubuntu-server.yml со сле­ду­ю­щим содержимым:

[codesyntax lang="php"]

[/codesyntax]

Теперь запу­сти­те playbook:

Обра­ти­те вни­ма­ние, как мы исполь­зо­ва­ли факт Ansible ansible_facts[‘distribution’] в усло­вии when, что­бы про­ве­рить, на каких узлах рабо­та­ет Ubuntu. Так­же обра­ти­те вни­ма­ние, что вам не нуж­но заклю­чать пере­мен­ные в фигур­ные скоб­ки при исполь­зо­ва­нии услов­ных выра­же­ний when.

В выход­ных дан­ных playbook обра­ти­те вни­ма­ние, как TASK [Detect Ubuntu Servers] про­пу­ще­ны пер­вые три узла, посколь­ку все они рабо­та­ют под CentOS и рабо­та­ют толь­ко на node4, посколь­ку он рабо­та­ет под управ­ле­ни­ем Ubuntu.

 

Использование when с регистрами

Вы так­же може­те исполь­зо­вать услов­ные выра­же­ния с заре­ги­стри­ро­ван­ны­ми пере­мен­ны­ми. Напри­мер, сле­ду­ю­щая кни­га centos-servers.yml пока­жет, на каких узлах рабо­та­ет CentOS:

[codesyntax lang="php"]

[/codesyntax]

Плей­бук сна­ча­ла начи­на­ет­ся с сохра­не­ния содер­жи­мо­го фай­ла /etc/os-release в регистр os_release . Затем вто­рая зада­ча отоб­ра­жа­ет сооб­ще­ние «Запуск CentOS…», толь­ко если сло­во «CentOS» встре­ча­ет­ся в   стан­дарт­ном выво­де os_release .

Иди­те впе­ред и запу­сти­те playbook:

Обра­ти­те вни­ма­ние, как рабо­та­ет TASK [Detect CentOS Servers] толь­ко на пер­вых трех узлах и про­пус­ка­ет­ся node4 (Ubuntu).

 

Тестирование нескольких условий с помощью when

Вы так­же може­те про­ве­рить несколь­ко усло­вий одно­вре­мен­но, исполь­зуя логи­че­ские опе­ра­то­ры. Напри­мер, сле­ду­ю­щая перезагрузка-centos8.yml Playbook исполь­зу­ет логи­че­ский и опе­ра­то­ра для пере­за­груз­ки сер­ве­ров, рабо­та­ю­щих под управ­ле­ни­ем CentOS вер­сии 8:

[codesyntax lang="php"]

[/codesyntax]

Вы так­же може­те исполь­зо­вать логи­че­ский опе­ра­тор или для запус­ка зада­чи, если выпол­ня­ет­ся какое-либо из усло­вий. Напри­мер, сле­ду­ю­щая зада­ча будет пере­за­гру­жать сер­ве­ры , на кото­рых рабо­та­ет CentOS или RedHat :

[codesyntax lang="php"]

[/codesyntax]

Использование when с петлями

Если вы объ­еди­ни­те услов­ный опе­ра­тор when с цик­лом, Ansible про­ве­рит усло­вие для каж­до­го эле­мен­та в цик­ле отдельно.

Напри­мер, сле­ду­ю­щий сце­на­рий print-even.yml напе­ча­та­ет все чет­ные чис­ла в диа­па­зоне (1,11):

[codesyntax lang="php"]

[/codesyntax]

Про­дол­жай­те и запу­сти­те playbook, что­бы уви­деть спи­сок всех чет­ных чисел в диа­па­зоне (1,11):

 

Использование when с переменными

Вы так­же може­те исполь­зо­вать услов­ные опе­ра­то­ры when с ваши­ми соб­ствен­ны­ми опре­де­лен­ны­ми пере­мен­ны­ми. Помни­те, что услов­ные выра­же­ния тре­бу­ют логи­че­ских вход­ных дан­ных; то есть, для сра­ба­ты­ва­ния усло­вия тест дол­жен быть истин­ным, поэто­му вам нуж­но исполь­зо­вать фильтр bool с небу­ле­вы­ми переменными.

Что­бы про­де­мон­стри­ро­вать это, взгля­ни­те на сле­ду­ю­щий сбор­ник сце­на­ри­ев isfree.yml :

[codesyntax lang="php"]

[/codesyntax]

Обра­ти­те вни­ма­ние, что здесь я исполь­зо­вал фильтр bool для пре­об­ра­зо­ва­ния зна­че­ния on_call в его логи­че­ский экви­ва­лент (no -> false).

Кро­ме того, вы долж­ны знать, что not false – это исти­на, и поэто­му в этом слу­чае все усло­вие будет оце­ни­вать­ся как true; ты свободен!

Вы так­же може­те про­ве­рить, уста­нов­ле­на ли пере­мен­ная или нет; напри­мер, сле­ду­ю­щая зада­ча будет выпол­нять­ся, толь­ко если опре­де­ле­на пере­мен­ная car :

[codesyntax lang="php"]

[/codesyntax]

Сле­ду­ю­щая зада­ча исполь­зу­ет сбой моду­ля потер­петь неуда­чу , если клю­чи пере­мен­ная не определена:

[codesyntax lang="php"]

[/codesyntax]

Обработка исключений с помощью блоков

Пого­во­рим об обра­бот­ке исключений.

Группировка задач с блоками

Вы може­те исполь­зо­вать бло­ки для груп­пи­ров­ки свя­зан­ных задач. Для демон­стра­ции взгля­ни­те на сле­ду­ю­щую кни­гу install-apache.yml :

[codesyntax lang="php"]

[/codesyntax]

Playbook запус­ка­ет­ся на хостах груп­пы веб-сер­ве­ров и име­ет один блок с име­нем Уста­но­вить и запу­стить Apache, кото­рый вклю­ча­ет в себя две задачи:

  1. Уста­но­вить httpd
  2. Запу­стить и вклю­чить httpd

Пер­вая зада­ча Install httpd исполь­зу­ет модуль yum для уста­нов­ки паке­та httpd apache. Вто­рая зада­ча исполь­зу­ет слу­жеб­ный модуль для запус­ка и раз­ре­ша­ет запуск httpd при загрузке.

Обра­ти­те вни­ма­ние, что в playbook есть тре­тья зада­ча, кото­рая не при­над­ле­жит бло­ку Install and start Apache.

Теперь запу­сти­те playbook, что­бы уста­но­вить и запу­стить httpd на узлах веб-серверов:

 

Вы так­же може­те выпол­нить спе­ци­аль­ную коман­ду, что­бы убе­дить­ся, что httpd дей­стви­тель­но запу­щен и работает:

 

Обработка сбоев с помощью блоков

Вы так­же може­те исполь­зо­вать бло­ки для обра­бот­ки оши­бок задач, исполь­зуя раз­де­лы rescue и always. Это очень похо­же на обра­бот­ку исклю­че­ний в язы­ках про­грам­ми­ро­ва­ния, таких как try-catch в Java или try-except в Python.

Вы може­те исполь­зо­вать раз­дел вос­ста­нов­ле­ния, что­бы вклю­чить все зада­чи, кото­рые вы хоти­те запу­стить в слу­чае сбоя одной или несколь­ких задач в блоке.

Для демон­стра­ции давай­те взгля­нем на сле­ду­ю­щий пример:

[codesyntax lang="php"]

[/codesyntax]

Обра­ти­те вни­ма­ние, как вто­рая зада­ча в бло­ке run a bad command гене­ри­ру­ет ошиб­ку, и, в свою оче­редь, тре­тья зада­ча в бло­ке нико­гда не полу­ча­ет воз­мож­но­сти запу­стить. Зада­чи внут­ри спа­са­тель­ной сек­ции будут рабо­тать , пото­му что вто­рая зада­ча в бло­ке не удалась.

Вы так­же може­те исполь­зо­вать ignore_errors: yes, что­бы гаран­ти­ро­вать, что Ansible про­дол­жит выпол­не­ние задач в playbook, даже если зада­ча не удалась:

[codesyntax lang="php"]

[/codesyntax]

Обра­ти­те вни­ма­ние, что в этом при­ме­ре вы про­игно­ри­ро­ва­ли ошиб­ки во вто­рой зада­че в бло­ке run a bad command, и поэто­му тре­тья зада­ча была запу­ще­на. Кро­ме того, спа­са­тель­ный раз­дел не будет рабо­тать , как вы игно­ри­ро­ва­ли ошиб­ку во вто­рой зада­че в блоке.

Вы так­же може­те доба­вить в блок раз­дел все­гда. Зада­чи в раз­де­ле все­гда будут выпол­нять­ся все­гда, неза­ви­си­мо от того, про­изо­шел сбой бло­ка или нет.

Что­бы про­де­мон­стри­ро­вать это, взгля­ни­те на сле­ду­ю­щую кни­гу вос­про­из­ве­де­ния handle-errors.yml, в кото­рой есть все три раз­де­ла бло­ка (block, rescue, always):

[codesyntax lang="php"]

[/codesyntax]

Иди­те впе­ред и запу­сти­те playbook:

Как вы виде­те; спа­са­тель­ный раз­дел ли рабо­тать как 2 – й зада­ча в бло­ке про­изо­шел сбой, и вы не игно­ри­ро­вать ошиб­ки. Кро­ме того, все­гда выпол­нял­ся (и будет все­гда) раз­дел всегда.

 

Запуск задач при изменении с помощью обработчиков

Посмот­рим, как менять обра­бот­чи­ки и запус­кать задачи.

 

Запуск вашего первого обработчика

Вы може­те исполь­зо­вать обра­бот­чи­ки для запус­ка задач при изме­не­нии на ваших управ­ля­е­мых узлах. Что­бы про­де­мон­стри­ро­вать это, взгля­ни­те на сле­ду­ю­щий сбор­ник handler-example.yml:

[codesyntax lang="php"]

[/codesyntax]

Пер­вая зада­ча Create engineers group­со­зда­ет груп­пу инже­не­ров, а так­же уве­дом­ля­ет обра­бот­чи­ка add destroyer.

Давай­те запу­стим сце­на­рий, что­бы уви­деть, что произойдет:

 

Обра­ти­те вни­ма­ние, что созда­ние инже­не­ров вызва­ло изме­не­ние на node1 и в резуль­та­те запу­сти­ло add destroyerобработчик.

Вы так­же може­те запу­стить быст­рую спе­ци­аль­ную коман­ду, что­бы убе­дить­ся, что поль­зо­ва­тель destroyer дей­стви­тель­но явля­ет­ся чле­ном груп­пы инженеров:

 

Плей­бу­ки и моду­ли Ansible явля­ют­ся идем­по­тент­ны­ми, что озна­ча­ет, что если на управ­ля­е­мых узлах про­изо­шло изме­не­ние кон­фи­гу­ра­ции; он боль­ше не повторится!

Что­бы пол­но­стью понять кон­цеп­цию идем­по­тент­но­сти Ansible; запу­сти­те playbook handler-example.yml еще раз:

 

Как вы виде­те; на этот раз Create engineers group зада­ча не вызва­ла и не сооб­щи­ла об изме­не­нии, пото­му что груп­па инже­не­ров уже суще­ству­ет на node1 и, как резуль­тат; обра­бот­чик add destroyer не запустился.

 

Контроль, когда сообщать об изменении

Вы може­те исполь­зо­вать клю­че­вое сло­во changed_when, что­бы ука­зать, когда зада­ча долж­на сооб­щать об изме­не­нии. Что­бы про­де­мон­стри­ро­вать это, взгля­ни­те на сле­ду­ю­щий сце­на­рий control-change.yml:

[codesyntax lang="php"]

[/codesyntax]

Обра­ти­те вни­ма­ние, как пер­вая зада­ча Run the date command­за­пус­ка­ет handler1. А теперь запу­сти­те playbook:

 

Обе зада­чи Run the date command и Run the uptime command заре­ги­стри­ро­ван­ные изме­не­ния, и обра­бот­чик handler1 был запу­щен. Вы може­те утвер­ждать, что выпол­не­ние команд date и uptime на самом деле ниче­го не меня­ет на управ­ля­е­мом узле, и вы совер­шен­но правы!

Теперь давай­те отре­дак­ти­ру­ем playbook, что­бы зада­ча не сооб­ща­ла об изменениях:

[codesyntax lang="php"]

[/codesyntax]

Теперь сно­ва запу­сти­те playbook:

 

Как види­те, на этот раз зада­ча не сооб­щи­ла об изме­не­нии, и в резуль­та­те handler1 не был запущен.

 

Настройка сервисов с обработчиками

Обра­бот­чи­ки осо­бен­но полез­ны, когда вы редак­ти­ру­е­те кон­фи­гу­ра­ции служб с помо­щью Ansible. Это пото­му, что вы хоти­те пере­за­пу­стить служ­бу толь­ко при изме­не­нии ее кон­фи­гу­ра­ции службы.

Что­бы про­де­мон­стри­ро­вать это, взгля­ни­те на сле­ду­ю­щую инструк­цию configure-ssh.yml :

[codesyntax lang="php"]

[/codesyntax]

Обра­ти­те вни­ма­ние, что мы исполь­зо­ва­ли модуль blockinfile для встав­ки несколь­ких строк тек­ста в файл кон­фи­гу­ра­ции /etc/ssh/sshd_config. Зада­ча так­же вызы­ва­ет обра­бот­чик restart ssh по изменению.

Иди­те впе­ред и запу­сти­те playbook:

 

Все хоро­шо! Теперь давай­те быст­ро взгля­нем на послед­ние несколь­ко строк в файле/etc/ssh/sshd_config:

 

Уди­ви­тель­но! Точ­но так, как вы ожи­да­ли. Имей­те в виду, что если вы повтор­но запу­сти­те playbook configure-ssh.yml, Ansible не будет редак­ти­ро­вать (или добав­лять) файл /etc/ssh/sshd_config. Вы може­те попро­бо­вать это сами.

Мы так­же реко­мен­ду­ем вам взгля­нуть на стра­ни­цы доку­мен­та­ции blockinfile и lineinfile, что­бы понять раз­ли­чия и исполь­зо­ва­ние каж­до­го модуля: