Ansible: Podstawy i obsługa inwentarza
 

Ręczne wprowadzanie zmian jest żmudne i problematyczne pod względem dokumentowania. Ansible rozwiązuje obydwa problemy. Świetnie nadaje się do tego, czego my nie lubimy. Jest tym wykonywanie tej samej czynności na wielu elementach. Dodatkowo, powstały w ten sposób plik YAML staje się pewną formą dokumentacji. Na pewno nie zastąpi on typowej dokumentacji ze schematami, tabelami oraz dodatkowymi uwagami. Natomiast jest to dobry punkt odniesienia, kiedy chcemy sprawdzić co jak zostało skonfigurowane.

Ansible umożliwia opisanie infrastruktury oraz jej usług za pomocą kodu (ang. IoC - Infrastructure as Code). Jeżeli dodatkowo zadbamy o odpowiednie komentarze oraz porządek w strukturze plików, to Ansible może zastąpić całkiem pewne elementy typowej dokumentacji, szczególnie te dynamiczne, które wymagają częstej aktualizacji.

Stworzenie takiego kodu może wydawać się sporą inwestycją czasu, niemniej wcale tak nie jest, a długofalowo opłaci się. Kiedy będziemy potrzebowali skonfigurować kolejne elementy infrastruktury w podobny sposób, to łatwo będzie można to zrobić. Bez dokładnej analizy konfiguracji tego co już jest oraz bez obawy o to, że coś przeoczymy.

Oczywiście, w tym wszystkim istotna jest dobra znajomość tego co będziemy automatyzować. Tego nie zastąpi nam żadne narzędzie. Dlatego najlepiej, kiedy tym zajmują się doświadczeni eksperci w danej dziedzinie. Cała reszta związana z wykorzystaniem do tego Ansible jest już bardzo prosta.

O ile Ansible może być wykorzystywane do automatyzacji różnych elementów, to musi się to odbywać z systemu GNU/Linux. W naszym przykładzie będzie to dokładnie system RHEL (Red Hat Enterprise Linux).

W systemie RHEL8 wymaga to wcześniejszej aktywacji wybranego repozytorium oraz typowej instalacji pakietu:

[root@vm0-net ~]# subscription-manager repos --enable ansible-2-for-rhel-8-x86_64-rpms
[root@vm0-net ~]# yum install ansible

Narzędzie Ansible dostępne jest w systemie RHEL bez żadnych dodatkowych opłat. Niemniej, Red Hat nie udziela dla niego wsparcia i nie daje dostępu do innych komponentów platformy Red Hat Ansible Automation bez wykupienia stosownych subskrypcji. Zainteresowanych ich zakupem This email address is being protected from spambots. You need JavaScript enabled to view it..


Zanim zaczniemy automatyzować, musimy zdefiniować inwentarz (ang. inventory) na którym będziemy działać. W najprostszej postaci może być on statycznym plikiem tekstowym w formacie INI lub YAML (ang. static inventory). Istnieje także możliwość korzystania z dynamicznego inwentarza (ang. dynamic inventory). Zaciągamy wtedy dane z innych rozwiązań, jak Red Hat Satellite czy Amazon EC2 lub poprzez dynamiczne skrypty z różnych baz danych.
 
Inwentarz zawiera zbiór węzłów, jak urządzenia czy serwery, które mogą być w dowolny sposób pogrupowane. Mogą one przynależeć do wielu grup jednocześnie jak i nie przynależeć do żadnej. Członkami jednej grupy mogą być także inne grupy podrzędne. Istnieją dwie grupy wbudowane "all" i "ungrouped". Do grupy "all" niejawnie przynależą wszystkie węzły z inwentarza, a do grupy "ungrouped" niejawnie przynależą wszystkie węzły z inwentarza, które nie są członkiem żadnej innej grupy. Wewnątrz inwentarza da się definiować zmienne powiązane ze znajdującymi się w nim obiektami grup i pojedynczych węzłów. O ile posłużyliśmy się tutaj terminem węzłów, to Ansbile w jego miejscu wykorzystuje termin hostów, bez względu czy tymi węzłami są serwery, urządzenie sieciowe czy jeszcze coś innego.
 
Nie powinno się używać "-" w nazwach grup oraz tej samej nazwy hosta i grupy w pliku inwentarza. W tym drugim przypadku, nazwa grupy zostanie pominięta i uwzględniony zostanie tylko host. W nazwach grup powinno się stosować tylko litery, cyfry oraz "_", przy czym cyfra nie może być pierwszym znakiem nazwy.
 
Najczęściej do budowy inwentarza stosuje się plik w formacie INI. Nim też będziemy się posługiwać w większości przykładów. Jego najprostszą postacią jest lista adresów IP oraz nazw domenowych (jeden per wiersz).

vm1-net.int.networkers.pl
vm2-net.int.networkers.pl
vm3-net.int.networkers.pl
vm4-net.int.networkers.pl
10.8.232.61
10.8.232.62


Format INI umożliwia tworzenie sekcji poprzez użycie nawiasów kwadratowych "[]". W ten sposób definiuje się grupy. Każda sekcja jest oddzielną grupą. Nazwa sekcji odpowiada nawie grupy. Z grup korzysta się bardzo często, gdyż najczęściej chcemy wykonać konkretne zadania na konkretnej grupie hostów. Poniżej został pokazany przykładowy plik inwentarza, który umożliwia wygodne wydawanie operacji na wszystkich serwerach o określonej funkcji lub ulokowanych w danym centrum danych lub pracujących w danym środowisku.

[web_servers]
web1-net.int.networkers.pl
web2-net.int.networkers.pl

[db_servers]
db1-net.int.networkers.pl
db2-net.int.networkers.pl

[dns_servers]
10.8.232.61
10.8.232.62

[east_datacenter]
web1-net.int.networkers.pl
db1-net.int.networkers.pl
10.8.232.61

[west_datacenter]
web2-net.int.networkers.pl
db2-net.int.networkers.pl
10.8.232.62

[production]
web1-net.int.networkers.pl
web2-net.int.networkers.pl
db1-net.int.networkers.pl
db2-net.int.networkers.pl
10.8.232.61
10.8.232.62

[development]
vm1-net.int.networkers.pl
vm2-net.int.networkers.pl
10.8.232.123
10.8.232.124


Jak widać powyżej, sposób grupowania jest praktycznie dowolny. Wspomnieliśmy też o możliwości tworzenia grup zagnieżdżonych, to jest grup składających się nie tylko z hostów, ale i z innych grup. Do tego celu wykorzystywany jest sufiks ":children", który dodaje się do nazwy grupy.

Przykład wykorzystania grup zagnieżdżonych można zobaczyć poniżej, gdzie do grupy "db_and_web" przynależy grupa "web_servers" i "db_servers", a do grupy "production" przynależy grupa "web_servers" i "db_server" oraz dwa host "10.8.232.61" i "10.8.232.62".

[root@vm0-net ~]# cat inventory

vm1-net.int.networkers.pl
vm2-net.int.networkers.pl
10.8.232.123
10.8.232.124

[web_servers]
web1-net.int.networkers.pl
web2-net.int.networkers.pl

[db_servers]
db1-net.int.networkers.pl
db2-net.int.networkers.pl

[db_and_web:children]
web_servers
db_servers

[production]
10.8.232.61
10.8.232.62

[production:children]
web_servers
db_servers

[root@vm0-net ~]#


Warto zwrócić uwagę na to, że o ile grupa może zawierać hosty, jak i inne grupy, to dodaje się je w różnych sekcjach.

Użyjemy teraz polecenia ansible do weryfikacji hostów przynależących do poszczególnych grup.

$ ansible -i <inventory_file> --list-hosts <group_name>


Za pomocą opcji "-i" wskazujemy plik inwentarza o nazwie "inventory", a opcja "--list-hosts" wyświetla hosty należące do zadanej grupy. Widać poniżej, że do grupy "web_servers" i "db_servers" przynależą po 2 hosty:

[root@vm0-net ~]# ansible -i inventory --list-hosts web_servers
hosts (2):
web1-net.int.networkers.pl
web2-net.int.networkers.pl
[root@vm0-net ~]# ansible -i inventory --list-hosts db_servers
hosts (2):
db1-net.int.networkers.pl
db2-net.int.networkers.pl
[root@vm0-net ~]#


Zatem do grupy "db_and_web" przynależą 4 hosty, jako że jej członkami są grupy "db_servers" i "web_servers":

[root@vm0-net ~]# ansible -i inventory --list-hosts db_and_web
hosts (4):
web1-net.int.networkers.pl
web2-net.int.networkers.pl
db1-net.int.networkers.pl
db2-net.int.networkers.pl
[root@vm0-net ~]#


Do grupy "production" przynależy 6-hostów (2 z "web_servers", 2 z "db_servers" i 2 z "production"):

[root@vm0-net ~]# ansible -i inventory --list-hosts production
hosts (6):
10.8.232.61
10.8.232.62
web1-net.int.networkers.pl
web2-net.int.networkers.pl
db1-net.int.networkers.pl
db2-net.int.networkers.pl
[root@vm0-net ~]#


Da się także podać kilka plików inwentarzy. Wtedy działamy na zbiorze łącznym. Dotyczy to wszystkich grup.

[root@vm0-net ~]# cat inventory1
[production]
10.8.232.61
10.8.232.62

[root@vm0-net ~]# cat inventory2
[production]
10.8.232.63
10.8.232.64

[root@vm0-net ~]# ansible -i inventory1 -i inventory2 --list-hosts production
hosts (4):
10.8.232.61
10.8.232.62
10.8.232.63
10.8.232.64
[root@vm0-net ~]#


Wróćmy do wspomnianych wcześniej grup wbudowanych: "upgrouped" i "all". Pierwsza zawiera 4 hosty znajdujące się na samej górze naszego pliku inwentarza, w miejscu gdzie definiuje się hosty nieprzynależące do żadnych grup:

[root@vm0-net ~]# ansible -i inventory --list-hosts ungrouped
hosts (4):
vm1-net.int.networkers.pl
vm2-net.int.networkers.pl
10.8.232.123
10.8.232.124
[root@vm0-net ~]#


A druga zawiera wszystkie hosty jakie zostały zdefiniowane w pliku inwentarza:

[root@vm0-net ~]# ansible -i inventory --list-hosts all
hosts (10):
vm1-net.int.networkers.pl
vm2-net.int.networkers.pl
10.8.232.123
10.8.232.124
10.8.232.61
10.8.232.62
web1-net.int.networkers.pl
web2-net.int.networkers.pl
db1-net.int.networkers.pl
db2-net.int.networkers.pl
[root@vm0-net ~]#


Nasz plik można także nieco uprościć posługując się zapisem zakresu "[START:END]" w nazwie lub adresie hosta:

  • 10.8.232.12[0:9] - adresy IPv4 od 10.8.232.120 do 10.8.232.129.
  • 10.8.22[4:5].[0:255] - całą podsieć 10.8.224.0/23, czyli adresy IPv4 od 10.8.224.0 do 10.8.225.255.
  • 2001:db8:c1sc0::[a:f] - adresy IPv6 od 2001:db8:c1sc0::a do 2001:db8:c1sc0::f.
  • web[1:20].networkers.pl - FQDN od web1.networkers.pl, przez web8.networkers.pl do web20.networkers.pl.
  • web[01:20].networkers.pl - FQDN od web01.networkers.pl, przez web08.networkers.pl do web20.networkers.pl.

Porównując dwa ostatnie przykłady, warto zwrócić uwagę na to, że we wzorcu pozostawiane są przodujące zera.

Uproszczona wersja naszego poprzedniego pliku inwentarza wygląda jak poniżej:

[root@vm0-net ~]# cat inventory

vm[1:2]-net.int.networkers.pl
10.8.232.12[3:4]

[web_servers]
web[1:2]-net.int.networkers.pl

[db_servers]
db[1:2]-net.int.networkers.pl

[production]
10.8.232.6[1:2]

[production:children]
web_servers
db_servers

[db_and_web:children]
web_servers
db_servers

[root@vm0-net ~]#


Weryfikacja jego poprawności znajduje się poniżej:

[root@vm0-net ~]# ansible -i inventory --list-hosts ungrouped
hosts (4):
vm1-net.int.networkers.pl
vm2-net.int.networkers.pl
10.8.232.123
10.8.232.124
[root@vm0-net ~]# ansible -i inventory --list-hosts db_servers
hosts (2):
db1-net.int.networkers.pl
db2-net.int.networkers.pl
[root@vm0-net ~]# ansible --inventory inventory --list-hosts db_and_web
hosts (4):
web1-net.int.networkers.pl
web2-net.int.networkers.pl
db1-net.int.networkers.pl
db2-net.int.networkers.pl
[root@vm0-net ~]#


W pliku inwentarza można także dodawać komentarze. Każda linia komentarza powinna być rozpoczęta znakiem "#".

O ile domyślną lokalizacją pliku inwentarza jest "/etc/ansible/hosts", to w praktyce się go nie używa. Zwykle tworzy się plik w katalogu danego projektu, a następnie wskazuje się go za pomocą opcji "-i", "--inventory" lub ustawienia pliku konfiguracyjnego "ansible.cfg".

Lokalizację wykorzystywanego pliku konfiguracyjnego można sprawdzić za pomocą polecenia "ansible --version". Poniżej widać, że jest to plik "/etc/ansible/ansible.cfg".

[root@vm0-net ~]# ansible --version
ansible 2.9.7
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.6/site-packages/ansible
executable location = /usr/bin/ansible
python version = 3.6.8 (default, Dec 5 2019, 15:45:45) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]
[root@vm0-net ~]#


Jest to domyślny plik, którego można nadpisać plikiem "~/.ansible.cfg". Jeżeli potrzebujemy różnej konfiguracji dla każdego z projektów, to da się je nadpisać plikiem "./ansible.cfg", w katalogu w którym wydawane będzie polecenie "ansible". Istnieje też możliwość skorzystania ze zmiennej "$ANSIBLE_CONFIG". To ostatnie przydaje się, kiedy korzystamy z wielu plików konfiguracyjnych i nie chcemy przemieszczać się pomiędzy różnymi katalogami.

Kolejność wyszukiwania pliku konfiguracyjnego Ansible została zestawiona poniżej:

  1. "$ANSIBLE_CONFIG"
  2. "./ansible.cfg"
  3. "~/.ansible.cfg"
  4. "/etc/ansible/ansible.cfg"

Zatem domyślny plik konfiguracji stosowany jest tylko, jeżeli żaden inny nie zostanie znaleziony. Najlepszą praktyką jest stosowanie pliku "ansible.cfg" w katalogu, z którego uruchamiamy polecenie "ansible".

[msleczek@vm0-net projekt_A]$ pwd
/home/msleczek/projekt_A
[msleczek@vm0-net projekt_A]$ ansible --version | grep "config file"
config file = /etc/ansible/ansible.cfg
[msleczek@vm0-net projekt_A]$ touch ~/.ansible.cfg
[msleczek@vm0-net projekt_A]$ ansible --version | grep "config file"
config file = /home/msleczek/.ansible.cfg
[msleczek@vm0-net projekt_A]$ touch ansible.cfg
[msleczek@vm0-net projekt_A]$ ansible --version | grep "config file"
config file = /home/msleczek/projekt_A/ansible.cfg
[msleczek@vm0-net projekt_A]$ touch /home/msleczek/ansible-projekt_A.cfg
[msleczek@vm0-net projekt_A]$ export ANSIBLE_CONFIG=/home/msleczek/ansible-projekt_A.cfg
[msleczek@vm0-net projekt_A]$ ansible --version | grep "config file"
config file = /home/msleczek/ansible-projekt_A.cfg
[msleczek@vm0-net projekt_A]$ rm /home/msleczek/ansible-projekt_A.cfg
[msleczek@vm0-net projekt_A]$ ansible --version | grep "config file"
config file = /home/msleczek/projekt_A/ansible.cfg
[msleczek@vm0-net projekt_A]$ unset ANSIBLE_CONFIG
[msleczek@vm0-net projekt_A]$


Należy pamiętać, że plik wskazany zmienną "$ANSIBLE_CONFIG" musi istnieć. Jeżeli Ansible go nie znajdzie, to przejdzie do kolejnego miejsca, którym jest "./ansible.cfg". Widać to powyżej, kiedy plik ten usunęliśmy jeszcze przed usunięciem zmiennej "$ANSIBLE_CONFIG".

Warto nadmienić jeszcze jedną rzecz. Ansible nie załaduje pliku "ansible.cfg" z katalogu bieżącego, jeżeli katalog ten ma uprawnienia do zapisu dla każdego (ang. world-writable). Jest to dla bezpieczeństwa, gdyż inny użytkownik mógł podrzucić tam spreparowany odpowiednio plik. Jeżeli z jakiś powodów musimy korzystać z takiego katalogu, wymagane będzie umieszczenie ścieżki do niego w zmiennej "$ANSIBLE_CONFIG". Niemniej, dobrze to wcześniej przemyśleć i rozważyć wynikającego z tego ryzyko.

Plik konfiguracyjny Ansible zapisany jest w formacie INI. Składa się z sekcji definiowanych nawiasami kwadratowymi "[]", które zawierają ustawienia w formacie "klucz = wartość". Do dwóch najczęściej stosowanych sekcji należy:

  • [defaults] - domyślne ustawienia Ansible,
  • [privilege_escalation] - definiuje jak Ansible eskaluje uprawnienia na zarządzanych hostach.

W praktyce, plik ten tworzony jest w celu wskazania inwentarza oraz dostosowania sposobu łączenia się do hostów w ramach danego projektu. Przykładową zawartość pliku "ansible.cfg" w tym zakresie można zobaczyć poniżej.

[msleczek@vm0-net projekt_A]$ cat ansible.cfg 
[defaults]
inventory = ./inventory
remote_user = user
ask_pass = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
[msleczek@vm0-net projekt_A]$


Nazwy użytych parametrów są na tyle intuicyjne, że wprost wskazują swoje zastosowanie:

  • inventory - ścieżka do pliku inwentarza (można nadpisać "-i" lub "--inventory").
  • remote_user - nazwa użytkownika, jaka zostanie użyta do logowania (domyślnie bieżący użytkownik).
  • ask_pass - czy ma pytać o hasło (jeżeli używany publicznego klucza do SSH, to powinna być "false").
  • become - czy ma automatycznie eskalować uprawnienia (domyślnie "false").
  • become_method - metoda wykorzystana do eskalacji uprawnień (domyślnie "sudo").
  • become_user - użytkownika do którego odbywa się eskalacja na zarządzanym hoście (domyślnie "root").
  • become_ask_pass - czy ma pytać o hasło w trakcie eskalacji (domyślnie "false").


Dzięki odpowiedniej konfiguracji tego pliku nie trzeba podawać wszystkich parametrów, przez co wygodniej się pracuje. Dla przykładu poniżej widać, że nie musimy już wskazywać inwentarzu.

[msleczek@vm0-net projekt_A]$ ansible --list-hosts production 
hosts (6):
10.8.232.61
10.8.232.62
web1-net.int.networkers.pl
web2-net.int.networkers.pl
db1-net.int.networkers.pl
db2-net.int.networkers.pl
[msleczek@vm0-net projekt_A]$

 

Tak wygląda składnia stosowanego przez nas polecenia do weryfikacji inwentarzu:

$ ansible [pattern] --list-hosts


W miejscu "[pattern]" podawaliśmy do tej pory pojedyncze hosty lub grupy. Natomiast może być to dowolny wzorzec (ang. pattern), który będzie dalej dopasowywany do zdefiniowanych w inwentarzu obiektów. Składać się on może z wielu elementów, które separuje się ":" lub ",". Pojawić się w nim mogą także znaki specjalne, jak "!", "&" czy "*". W takich przypadkach wzorzec należy umieszczać wewnątrz pojedynczego cudzysłowu - 'pattern' - lub poprzedzić te znaki specjalne za pomocą znaku backslash "\". Można też cały wzorzec podawać zawsze w pojedynczym cudzysłowiu - 'pattern' - wtedy będzie to uniwersalne i nie natrafimy na żadne problemy.

Przykłady najczęściej stosowanych wzorców (ang. pattern) dopasowania:

  • host1:host2 lub host1,host2 - suma hostów (wiele hostów).
  • web_servers:db_servers lub web_servers,db_servers - wszystkie hosty z obu podanych grup.
  • production:!db_servers lub production,!db_servers - wszystkie hosty z production, ale bez tych z db_servers.
  • production:&db_servers lub production,&db_servers - wszystkie hosty z production, które są w db_servers.
  • *networkers.pl - wszystkie obiekty inwentarza posiadające na końcu nazwy "networkers.pl".
  • 10.8.232.* - wszystkie obiekty z inwentarza posiadające na początku nazwy "10.8.232.".

Zanim pokażemy działanie tych wzorców, sprawdźmy na jakim inwentarzu pracujemy: 

[msleczek@vm0-net projekt_A]$ grep inventory ansible.cfg 
inventory = ./inventory3
[msleczek@vm0-net projekt_A]$ cat inventory3
[web_servers]
web1-net.int.networkers.pl
web2-net.int.networkers.pl

[db_servers]
db1-net.int.networkers.pl
db2-net.int.networkers.pl

[dns_servers]
10.8.232.61
10.8.232.62

[east_datacenter]
web1-net.int.networkers.pl
db1-net.int.networkers.pl
10.8.232.61

[west_datacenter]
web2-net.int.networkers.pl
db2-net.int.networkers.pl
10.8.232.62

[production]
web1-net.int.networkers.pl
web2-net.int.networkers.pl
db1-net.int.networkers.pl
db2-net.int.networkers.pl
10.8.232.61
10.8.232.62

[development]
vm1-net.int.networkers.pl
vm2-net.int.networkers.pl
10.8.232.123
10.8.232.124

[msleczek@vm0-net projekt_A]$


Podana lista hostów lub grup we wzorcu nie musi ograniczać się do 2 obiektów:

[msleczek@vm0-net projekt_A]$ ansible 10.8.232.61,db2-net.int.networkers.pl,10.8.232.62 --list-hosts
hosts (3):
10.8.232.61
db2-net.int.networkers.pl
10.8.232.62
[msleczek@vm0-net projekt_A]$


Poniżej zobaczyć można kolejno użycie operatora sumy, różnicy i iloczynu na dwóch zbiorach grup:

[msleczek@vm0-net projekt_A]$ ansible 'production:db_servers' --list-hosts
hosts (6):
web1-net.int.networkers.pl
web2-net.int.networkers.pl
db1-net.int.networkers.pl
db2-net.int.networkers.pl
10.8.232.61
10.8.232.62
[msleczek@vm0-net projekt_A]$ ansible 'production:!db_servers' --list-hosts
hosts (4):
web1-net.int.networkers.pl
web2-net.int.networkers.pl
10.8.232.61
10.8.232.62
[msleczek@vm0-net projekt_A]$ ansible 'production:&db_servers' --list-hosts
hosts (2):
db1-net.int.networkers.pl
db2-net.int.networkers.pl
[msleczek@vm0-net projekt_A]$


Znak '*' umożliwia wygodne dopasowywanie do fragmentów zadanego wzorca. W ten sposób łatwo można odwołać się do hostów pracujących w ramach konkretnej domeny, czy posiadających określone adresy IP. Podawane wzorce muszą pasować do obiektów, jakie znajdują się w inwentarzu. Zatem, jeżeli wszystko podajemy po nazwach, to próba przeszukiwania po adresach IP nie powiedzie się i analogicznie w drugą stronę.

Poniżej widać przykład użycia '*' we wzoru z nazwą i adresem IP (należy pamiętać, że jest to znak specjalny):

[msleczek@vm0-net projekt_A]$ ansible \*networkers\* --list-hosts
hosts (6):
web1-net.int.networkers.pl
web2-net.int.networkers.pl
db1-net.int.networkers.pl
db2-net.int.networkers.pl
vm1-net.int.networkers.pl
vm2-net.int.networkers.pl
[msleczek@vm0-net projekt_A]$ ansible '*networkers*' --list-hosts
hosts (6):
web1-net.int.networkers.pl
web2-net.int.networkers.pl
db1-net.int.networkers.pl
db2-net.int.networkers.pl
vm1-net.int.networkers.pl
vm2-net.int.networkers.pl
[msleczek@vm0-net projekt_A]$ ansible '10.8.232.6*': --list-hosts
hosts (2):
10.8.232.61
10.8.232.62
[msleczek@vm0-net projekt_A]$


Otrzymane wcześniej wyniki można dalej wygodnie zawężać, tworząc bardziej rozbudowane wzorce:

[msleczek@vm0-net projekt_A]$ ansible '10.8.232.6*:&east_datacenter' --list-hosts
hosts (1):
10.8.232.61
[msleczek@vm0-net projekt_A]$


Niektóre z bardziej złożonych wzorców mogą być dość użyteczne. Dla przykładu możemy chcieć wykonać operacje na wszystkich serwerach webowych i baz danych, które pracują w środowisku produkcyjnym, ale nie są ulokowane w zachodnim centrum danych:

[msleczek@vm0-net projekt_A]$ ansible 'web_servers:db_servers:&production:!west_datacenter' --list-hosts
hosts (2):
web1-net.int.networkers.pl
db1-net.int.networkers.pl
[msleczek@vm0-net projekt_A]$


Dla bardziej wymagających, w ramach wzorca dostępne są też zaawansowane wyrażenia regularne. Aby z nich korzystać, należy poprzedzić wzorzec znakiem '~'. W takim wzorcu będzie stosowane wiele znaków specjalnych, dlatego najlepiej od razu wprowadzać go w pojedynczych znakach cudzysłowiu.

[msleczek@vm0-net projekt_A]$ ansible '~10.8.232.6[12]' --list-hosts
hosts (2):
10.8.232.61
10.8.232.62
[msleczek@vm0-net projekt_A]$ ansible '~(web|db)_*' --list-hosts
hosts (4):
web1-net.int.networkers.pl
web2-net.int.networkers.pl
db1-net.int.networkers.pl
db2-net.int.networkers.pl
[msleczek@vm0-net projekt_A]$


Ciekawa jest też możliwość odwoływania się do hostów po numerze ich pozycji w ramach zadanej grupy. Do tego celu korzysta się nawiasów kwadratowych "[]". W ten sposób można zarówno wskazać numer pozycji "[POZYCJA]", jak i zakres "[START:END]". Numery pozycji w ramach grupy zaczynają się od zera.

[msleczek@vm0-net projekt_A]$ ansible 'production' --list-hosts
hosts (6):
web1-net.int.networkers.pl
web2-net.int.networkers.pl
db1-net.int.networkers.pl
db2-net.int.networkers.pl
10.8.232.61
10.8.232.62
[msleczek@vm0-net projekt_A]$ ansible 'production[0]' --list-hosts
hosts (1):
web1-net.int.networkers.pl
[msleczek@vm0-net projekt_A]$ ansible 'production[1]' --list-hosts
hosts (1):
web2-net.int.networkers.pl
[msleczek@vm0-net projekt_A]$ ansible 'production[-1]' --list-hosts
hosts (1):
10.8.232.62
[msleczek@vm0-net projekt_A]$ ansible 'production[2:]' --list-hosts
hosts (4):
db1-net.int.networkers.pl
db2-net.int.networkers.pl
10.8.232.61
10.8.232.62
[msleczek@vm0-net projekt_A]$ ansible 'production[2:3]' --list-hosts
hosts (2):
db1-net.int.networkers.pl
db2-net.int.networkers.pl
[msleczek@vm0-net projekt_A]$


Opanowanie zasad korzystania z inwentarza oraz pliku konfiguracji Ansible jest niezbędną podstawą do dalszej pracy. Braki w tym obszarze będą ciągły się za nami przez cały czas, dlatego zalecamy poświęcenie odpowiedniej ilości czasu temu zagadnieniu przed przejściem do kolejnych artykułów.


Zapraszamy do kontaktu drogą mailową This email address is being protected from spambots. You need JavaScript enabled to view it. lub telefonicznie +48 797 004 932.