Ansible w Enterprise Linuksie – cz. I: przygotowania i pierwsze komendy

Ansible

Wiele lat temu królowały komputery będące maszynami typu mainframe. Były to olbrzymie szafy z główną jednostką liczącą, które wymagały wielu osób do zarządzania nimi. Wraz z rozwojem technologii zaczęły powstawać coraz to potężniejsze komputery, a ich rozmiar zmniejszał się wraz z liczbą ludzi, którzy musieli się nimi opiekować. Ilość administratorów na jedno stanowisko komputerowe malała, aż do momentu, w którym to jeden administrator mógł władać wieloma maszynami.

Model ten jest dziś stosowany w wielu organizacjach. Jednak ludzie związani z IT oprócz tego, że nie lubią, jak większość, wykonywać nudnych czynności, to mają niesamowitą smykałkę do rozwiązywania swoich problemów. W ten sposób narodziło się pisanie zawiłych skryptów, z reguły w bashu lub perlu, które doprowadzały maszynę do określonego stanu. Skrypty te oprócz zalet, mają z reguły także wady, np. nie sprawdzają stanu faktycznego maszyny przed wykonaniem. Bardzo rzadko sprawdzają tzw. przypadki brzegowe, co potrafi kończyć się katastrofą. Co więcej, taki model zarządzania infrastrukturą sprawdza się w co najwyżej średnich środowiskach, gdzie administrator ma czas, by zbudować swoją świadomość odnośnie każdej maszyny. Jednak wraz z rozwojem zapotrzebowania na dynamiczną infrastrukturę, ręczne lub nawet oskryptowane zarządzanie maszynami przestało być wykonalne. Problem ten rozwiązują narzędzia automatyzacji zadań. Służą one do orchiestracji, wykonywania poleceń administracyjnych, czy trzymania całej infrastruktury jako kodu.

Infrastruktura jako kod jest jedną z podstaw metodologii DevOps, gdzie dzięki utrzymywaniu infrastruktury w postaci kodu źródłowego jesteśmy w stanie zautomatyzować procesy stawiania nawet całej infrastruktury od gołych maszyn do w pełni działającego środowiska. Jest to bardzo pożądana cecha w przypadku np. potrzeby zastosowania procedury DR (Disaster Recovery). Platformy automatyzacji pokazują swoją siłę także, gdy chcemy w błyskawiczny sposób wprowadzić zmianę na wielu, lub nawet bardzo wielu, maszynach równocześnie.

Dla osób związanych ze światem twórców oprogramowania, narzędzia do automatyzacji działań IT można porównać do frameworków. Pisanie w gołym JavaScriptcie jest z reguły zdecydowanie mniej efektywne i generuje więcej problemów niż użycie gotowych rozwiązań dostarczanych przez framework. Podobnie jest z automatyzacją przy pomocy niestandardowych skryptów zamiast używania sprawdzonych, przetestowanych, a przede wszystkim działających rozwiązań.

Czym jest Ansible?

Jest to niezwykle popularne narzędzie do zarządzania stanem maszyn, zarządzaniem konfiguracją infrastruktury, automatyzacją zadań IT.
Strona projektu na githubie - https://github.com/ansible/ansible - jak widać, w projekt zaangażowało się ponad 2500 kontrybutorów.

Ansible jako platforma posiada infrastrukturę typu agentless (ang. bez agentową), czyli do jej działania nie jest wymagany dodatkowy program zainstalowany na maszynie zarządzanej. Pozwala to na używanie Ansible nawet ad-hoc. Domyślnym trybem Ansible jest tryb push, czyli wypychanie zmian z zarządcy (z reguły komputera administratora lub jump hosta) na komputery zarządzane. Istnieje także tryb pull, więcej na jego temat znajdą Państwo w następnych częściach cyklu.

W 2015 roku Red Hat wykupił firmę Ansible INC. Jednak Ansible, jako wolne oprogramowanie nic na tym nie straciło. Jednak niektóre dodatki, takie jak Ansible Tower, zostały włączone do płatnego portfolio tego producenta.

Pre rekwizyty:

Maszyny do zarządzania i zarządca:

Użyjemy Ansible do uruchomienia i skonfigurowania popularnych usług na 3 maszynach. Maszyny te należy postawić w środowisku developerskim. Sam sposób postawienia tych maszyn pomijam celowo, gdyż wykracza to poza ramy tego artykułu. Sugeruję jednak użycie maszyn wirtualnych, które można w łatwy sposób doprowadzić do stanu początkowego (np. poprzez snapshot). Jest to bardzo przydatne w przypadku popełnienia jakiegoś błędu. Używanym w przykładach systemem będzie EuroLinux w wersji 7.3. Osoby nieposiadające licencji EuroLinuksa mogą skorzystać z darmowych, niewspieranych substytutów - Scientific Linuxa lub CentOS’a.

Moja sieć wygląda następująco.
192.123.123.100 - Jump host
192.123.123.200 - storage.local
192.123.123.201 - db.local
192.123.123.202 - apps.local

Wszystkie nazwy powinny być rozwiązywane na hoście, z którego wykonujemy komendy Ansible.

Instalacja Ansible

Ansible można zainstalować na kilka sposobów. Wszystkie z nich wymagają dostępu do repozytorium EPEL. Co prawda da się to zrobić bez niego, jednak jest to gra niewarta świeczki. Host używany do zarządzania nie powinien pełnić dodatkowych funkcji i może być postawiony na zupełnie innym systemie operacyjnym.

sudo yum install ansible

- Instalacja prosto z repozytorium.

sudo pip install ansible

- Instalacja przy pomocy menadżera pakietów pythona pip, wymaga zainstalowanych narzędzi i bibliotek developerskich.

sudo easy_install install ansible

- Instalacja przy pomocy menadżera pakietów pythona easy_install. Nie wymaga EPEL’a. Jednak easy_install jest dużo mniej elastycznym menadżerem pakietów niż pip.

Instalacja bezpośrednio ze źródeł  -  w ten sposób możemy wybrać gałąź projektu, która nas interesuje, np. developerską.

Na maszynie jump host’a proponuję zainstalować EPEL’a a następnie Ansible.

sudo yum install ­-y https://dl.fedoraproject.org/pub/epel/epel­-release­-latest­-7.noarch.rpm
sudo yum install ansible ­-y

Po instalacji powinniśmy móc wykonać:

ansible -- version

w chwili pisania artykułu wersja Ansible dostępna w EPEL7 to 2.2.1.0.

Ustawienie pliku inventory.

W zależności od sposobu instalacji powinniśmy mieć główny katalog konfiguracyjny Ansible pod /etc/ansible.
Jeśli katalog nie istnieje, należy go stworzyć, wykonując:

mkdir /etc/ansible

Jeśli istnieje, możemy skopiować oryginalny plik hostów (inventory) z /etc/ansible/hosts

cp /etc/ansible/hosts /etc/ansible/hosts.bck

Plik ten posiada następującą zawartość:

cat /etc/ansible/hosts
# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
#
# ­ - Comments begin with the '#' character# ­ Blank lines are ignored
# ­ - Groups of hosts are delimited by [header] elements
# ­ - You can enter hostnames or ip addresses
# ­ - A hostname/ip can be a member of multiple groups

# Ex 1: Ungrouped hosts, specify before any group headers.

## green.example.com
## blue.example.com
## 192.168.100.1
## 192.168.100.10

# Ex 2: A collection of hosts belonging to the 'webservers' group

## [webservers]
## alpha.example.org
## beta.example.org
## 192.168.1.100
## 192.168.1.110

# If you have multiple hosts following a pattern you can specify
# them like this:

## www[001:006].example.com

# Ex 3: A collection of database servers in the 'dbservers' group

## [dbservers]
##
## db01.intranet.mydomain.net
## db02.intranet.mydomain.net
## 10.25.1.56
## 10.25.1.57

# Here's another example of host ranges, this time there are no
# leading 0s:
## db­-[99:101]­-node.example.com

Jedną za największych zalet Ansible jest to, że twórcy naprawdę postarali się, by wszystko było samo tłumaczące. Doskonale obrazuje to ten plik, gdzie na samym początku jesteśmy informowani o jego budowie oraz sposobie interpretacji.

Stworzymy teraz własny plik inventory

sudo vim /etc/ansible/hosts

o następującej zawartości

[storage]
storage.local
[db]
db.local
[apps]
apps.local

Pierwsze komendy - rejestracja w EuroManie.

Możemy teraz przetestować konfiguracje Ansible.

Większość komend Ansible wykonywana jest w następujący sposób:

ansible <wzorzec­-hostów (grupy, all, etc.)> [­-m nazwa modułu] [­-a argumenty przekazane do modułu]

Spróbujmy w takim razie użyć standardowego modułu Ansible ping - sprawdza on czy jest zainstalowany python z biblioteką json, dzięki temu będziemy mogli używać playbooków i modułów.

ansible all ­-m ping ­-u root

Jak widać, użyliśmy specjalnego wyrażenia hostów:

all

Jak sama nazwa wskazuje, są to wszystkie maszyny zdefiniowane w pliku inventory (domyślnie /etc/ansible/hosts, można jednak zmienić zaczytywany plik przy pomocy przełącznika -i lub —inventory). Przełącznik -u root, nakazuje łącznie się przez ssh na konto roota.

Klucze ssh

Komenda ta powinna wyjść z niezerowym wyjściem (nie udać się). Ansible używa ssh, ciężko jest z niego skorzystać, gdy nie stworzyliśmy klucza oraz nie skopiowaliśmy go na maszyny. Co prawda istnieje możliwość używania Ansible z podawanym hasłem, jednak na chwilę obecną pominę ten aspekt.
Wykonujemy więc:

ssh­-keygen

UWAGA: Proszę uważać, by nie nadpisać istniejącego już klucza SSH, szczególnie jeśli to jego jedyna kopia! W takim wypadku proszę o zmianę nazwy klucza z id_rsa na np. ansible_key, a następnie dodanie do agenta (ssh-add) w celu łatwego logowania. Teraz możemy skopiować klucz ssh:

ssh­-copy-id ­-i ${HOME}/.ssh/id_rsa.pub [email protected]
ssh­-copy-id ­-i ${HOME}/.ssh/id_rsa.pub [email protected]
ssh­-copy-id ­-i ${HOME}/.ssh/id_rsa.pub [email protected]

Wykonując tę samą komendę

ansible all ­-m ping ­-u root

powinniśmy otrzymać dla każdej z maszyn output wyglądający mniej więcej tak:

storage.local | SUCCESS => {
"changed": false,
"ping": "pong"
}

Wiedząc, że posiadamy Pythona wraz z biblioteką json, niezbędną do działania playbooków Ansible, możemy zarejestrować nasze maszyny w EuroManie lub innym narzędziu do dystrybucji aktualizacji (odpowiednik Satellite Server lub Suse Manager). W tym celu stworzymy naszego pierwszego playbooka (playbook to najprościej rzecz ujmując inna metoda zarządzania maszynami przez Ansible, jest to plik tekstowy definiujący jaki stan maszyna powinna przyjąć). Playbooki są pisane w bardzo przyjaznym i wyjątkowo czytelnym języku YAML.

vim first_playbook.yaml
---
- hosts: all
  remote_user: root
  tasks:
­   - name: Register to EuroManager
     rhn_register: state=present username=user password=pass server_url=https
://xmlrpc.elupdate.euro-­linux.com/XMLRPC

W związku z błędem, który jest zawarty w module rhn_register [https://github.com/ansible/ansible/issues/20652] musimy podać server_url ręcznie. Oczywiście user i pass należy wypełnić samemu.

Po uruchomieniu playbooka:

ansible­-playbook first_playbook.yaml
PLAY [all] *******************************************************************
**
TASK [setup] *****************************************************************
**
ok: [db.local]
ok: [storage.local]
ok: [apps.local]
TASK [Register to EuroManager] ***********************************************
**
ok: [storage.local]
changed: [db.local]
changed: [apps.local]
PLAY RECAP *******************************************************************
**
apps.local    : ok=2 changed=1 unreachable=0 failed=0
db.local      : ok=2 changed=1 unreachable=0 failed=0
storage.local : ok=2 changed=0 unreachable=0 failed=0

Jak widać, nasz playbook zadziałał. Zmiana została dokonana na dwóch hostach. Trzeci był już wcześniej zarejestrowany do EuroMana.

Zakończenie

Po przeczytaniu powyższego materiału czytelnik powinien lepiej rozumieć, dlaczego powstały narzędzia do automatyzacji zadań w infrastrukturze. W oparciu o przedstawione przykłady umieć zainstalować Ansible z repozytorium EPEL. Wiedzieć, gdzie znajduje się domyślny plik inventory i być w stanie dostosować go do swoich potrzeb. Powinien zarządzać maszynami ad-hoc przy pomocy komendy ansible oraz napisać pierwszego własnego playbooka w języku yaml.
W części drugiej tej serii będziemy zagłębiać się w playbooki. Zobaczymy, czym jest idempotentność oraz poznamy ansible galaxy.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *