Ansible instalacja i konfiguracja kontenera LXC Debian 11 do zarządzania serwerami

Opis Ansible

Ansible to narzędzie do automatyzacji typu open source, które upraszcza zarządzanie i orkiestrację infrastruktury IT. Został zaprojektowany w celu automatyzacji powtarzalnych zadań, usprawnienia złożonych przepływów pracy oraz umożliwienia konfiguracji i wdrażania systemów na dużą skalę. Ansible używa deklaratywnego języka, znanego jako YAML, do opisywania pożądanego stanu systemów i wykorzystuje architekturę klient-serwer do komunikacji.

Kluczowe funkcje i koncepcje Ansible obejmują:

  • Bez agenta: Ansible działa bez agenta, co oznacza, że nie wymaga instalowania żadnego oprogramowania ani demonów na zarządzanych hostach. Łączy się z hostami za pomocą protokołów SSH (Secure Shell) lub WinRM (Windows Remote Management), umożliwiając zdalne zarządzanie i automatyzację.
  • Playbooki: Ansible używa playbooków , które są plikami zapisanymi w formacie YAML, aby zdefiniować pożądany stan systemów. Playbooki zawierają szereg zadań, które Ansible wykonuje na hostach docelowych. Mogą definiować konfiguracje, przeprowadzać konfigurację systemu, wdrażać aplikacje i nie tylko.
  • Moduły: Ansible wykorzystuje ogromną kolekcję modułów do wykonywania określonych zadań na zarządzanych hostach. Moduły to małe programy, które Ansible wykonuje na hostach docelowych w celu osiągnięcia określonej akcji, takiej jak zarządzanie pakietami, konfigurowanie usług, manipulowanie plikami i interakcja z dostawcami usług w chmurze.
  • Inwentarz: Inwentarz Ansible to plik zawierający listę hostów lub grup hostów zarządzanych przez Ansible. Pozwala organizować infrastrukturę w logiczne grupy i przypisywać zmienne do hostów lub grup. Plik inwentaryzacji może być statyczny lub dynamiczny, w zależności od Twoich potrzeb.
  • Polecenia ad-hoc: oprócz korzystania z podręczników, Ansible zapewnia możliwość uruchamiania poleceń ad-hoc bezpośrednio z wiersza poleceń. Polecenia ad-hoc umożliwiają wykonywanie szybkich i jednorazowych zadań na zdalnych hostach bez konieczności tworzenia podręcznika.
  • Orkiestracja: Ansible umożliwia orkiestrację aplikacji wielowarstwowych poprzez zdefiniowanie zależności między różnymi podręcznikami i rolami. Umożliwia definiowanie złożonych przepływów pracy i wykonywanie zadań w określonej kolejności, dzięki czemu nadaje się do wdrażania i zarządzania złożonymi konfiguracjami infrastruktury.

Ansible jest szeroko stosowany do automatyzacji infrastruktury, zarządzania konfiguracją, wdrażania aplikacji i ciągłego dostarczania. Oferuje prostą składnię, łatwość użycia i rozszerzalność, co czyni go popularnym wyborem zarówno dla małych, jak i dużych projektów automatyzacji.

Więcej ciekawych informacji o Ansible można znaleźć na stronie https://docs.ansible.com/

Instalacja Ansible w kontenerze LXC

Przygotowanie kontenera LXC z Debian 11

Więcej informacji o tworzeniu kontenerów LXC z użyciem szablonów można znaleźć na stronie https://itadmin.vblog.ovh/proxmox-ve-zarzadzanie-kontenerami-lxc/. Na podstawie szablonu debian-11-standard_11.6-1_amd64 utworzony został kontener LXC o następujących parametrach:

  • nazwa hosta: ansible
  • 2 vCPU
  • 1 GB RAM
  • 8 GB HDD
  • unprivileged aby można było swobodnie korzystać z klientów sieciowych NFS, SMB/CIFS, FUSE
  • statyczny adres 192.168.20.10/24 i karta sieciowa eth0 przypięta do mostka sieciowego vmbr2 na Proxmoxie wskazującego na sieć 192.168.20.0/24. Więcej o konfiguracji sieci w Proxmox i dlaczego jest tutaj mostek vmbr2 można przeczytać na stronie https://itadmin.vblog.ovh/proxmox-konfiguracja-i-podzial-sieci/

Wstępna konfiguracja systemu Debian 11 w kontenerze LXC

Więcej informacji na temat wstępnej konfiguracji systemu Debian 11 w kontenerze LXC można znaleźć na stronie https://itadmin.vblog.ovh/proxmox-ve-zarzadzanie-kontenerami-lxc/. Najważniejsze kroki to:

# instalacja pakietu sudo w systemie 
apt install sudo

# dodanie nowego użytkownika o nazwie np. ansible
adduser ansible

Adding user `ansible' ...
Adding new group `ansible' (1000) ...
Adding new user `ansible' (1000) with group `ansible' ...
Creating home directory `/home/ansible' ...
Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for ansible
Enter the new value, or press ENTER for the default
Full Name []: Ansible User
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n] y

# dodanie uprawnień dla użytkownia ansible do wykonania polecenia sudo
usermod -aG sudo ansible

# sprawdzenie czy prawidłowo dodano do grupy sudo
getent group sudo
sudo:x:27:ansible

# sprawdzenie działania sudo z poziomu użytkownika ansible
sudo su --

Instalacja Ansible w systemie Debian 11

# dodanie repozytorium ansible do systemu na końcu pliku
nano /etc/apt/sources.list

deb http://ppa.launchpad.net/ansible/ansible/ubuntu focal main

# dodanie klucza repozytorium
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367

# aktualizacja pakietów
apt-get update

# instalacja ansible
apt-get install ansible -y

# sprawdzenie wersji ansible
ansible --version

ansible [core 2.12.10]
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/dist-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.9.2 (default, Feb 28 2021, 17:03:44) [GCC 10.2.1 20210110]
jinja version = 2.11.3
libyaml = True

Konfiguracja Ansible

Utworzenie pliku domyślnej konfiguracji Ansible

ansible-config init --disabled > /home/ansible/ansible.cfg
sudo cp -f /home/ansible/ansible.cfg /etc/ansible/ansible.cfg

Włączenie możliwości automatycznego wykonywania poleceń jako root na serwerach

# edcyja domyślnej konfiguracji Ansible
sudo nano /etc/ansible/ansible.cfg

[privilege_escalation]
;become=False
become=True
# (string) Privilege escalation method to use when `become` is enabled.
become_method=sudo
# (string) The user your login/remote user 'becomes' when using privilege escalation, most systems will use 'root' when no user is specified.
become_user=root

Dodanie nowego hosta do zarządzania w konfiguracji Ansible

# jednorazowo (tylko pierwszy raz) utworzyć parę kluczy publicznego i prywatnego
# będąc zalogowanym jako zwykły użytkownik ansible w kontenerze LXC ansible
ssh-keygen

Generating public/private rsa key pair.
Enter file in which to save the key (/home/ansible/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ansible/.ssh/id_rsa
Your public key has been saved in /home/ansible/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ansible@ansible

# dla każdego hosta którego chcemy dodać do zarządzania przez Ansible
# będąc zalogowanym jako zwykły użytkownik ansible w kontenerze LXC ansible

ssh [email protected]

# powstanie /home/ansible/.ssh/known_hosts zawierający klucze publiczne 
# wszystkich serwerów z którymi łączyliśmy się przez protokół SSH

# kopiujemy klucz publiczny użytkownika ansible na zdalny serwer np.192.168.8.20
ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/ansible/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
Number of key(s) added: 1
Now try logging into the machine, with:   "ssh '[email protected]'"
and check to make sure that only the key(s) you wanted were adde

# weryfikujemy logowanie bez hasła
ssh [email protected]

W powyższy sposób dodajemy wszystkie serwery, którymi chcemy zarządzać przez Ansible .W pliku /etc/ansible/hosts dodajemy odpowiednie wpisy jak w poniższym przykładzie

sudo nano /etc/ansible/hosts

[proxmox]
pve ansible_host=192.168.8.20 ansible_user=root ansible_port=22

[all:vars]

Weryfikujemy czy możemy wykonać podstawowe polecenie ping sprawdzające łączność Ansible ze zdefiniowanymi hostami

# z poziomu użytkownika ansible w kontenerze LXC ansible
# albo ping na nazwę hosta:pve  albo na nazwę grupy: proxmox
ansible -m ping proxmox
pve | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

ansible@ansible:~$ ansible -m ping pve

pve | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

Dodanie nowego hosta do zarządzania w konfiguracji Ansible poprzez sudo

Jeśli zarządzanie serwerem np. 192.168.10.22 poprzez Ansible wymaga podniesienia uprawnień czyli przejścia na root-a przez sudo, możemy w pliku /etc/ansible/hosts dodać następujący wpis

sudo nano /etc/ansible/hosts

[ubuntu]
remote ansible_host=192.168.10.22 ansible_user=linuser ansible_port=22 ansible_become=yes ansible_become_pass=haslo_roota

Na serwer 192.168.10.22 skopiowano wcześniej klucz publiczny użytkownika ansible.

ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

Dodanie nowego hosta do zarządzania w konfiguracji Ansible bez kopiowania klucza publicznego

Jeśli logowaliśmy się już przez SSH użytkownikiem ansible do serwera np. 192.168.10.23 i nie chcemy lub nie możemy wysłać tam swojego klucza publicznego to możemy w pliku /etc/ansible/hosts dodać następujący wpis

sudo nano /etc/ansible/hosts

[ubuntu]
nut ansible_host=192.168.10.23 ansible_user=linuser ansible_port=22 ansible_ssh_pass=haslo_linuser ansible_become=yes ansible_become_pass=haslo_roota

Dodanie kontenera LXC z Ansible do zarządzania w konfiguracji Ansible

Jeśli chcemy zarządzać kontenerem ansible również przez zainstalowany w nim Ansible to możemy w pliku /etc/ansible/hosts dodać następujący wpis

sudo nano /etc/ansible/hosts

[lxc]
ansible ansible_connection=local ansible_user=ansible ansible_ssh_pass=haslo_ansible ansible_become=yes ansible_become_pass=haslo_roota

Przykład listy moich serwerów zarządzanych przez Ansible w pliku /etc/ansible/hosts

[servers]
pve ansible_host=192.168.8.20 ansible_user=root ansible_port=22
pbs ansible_host=192.168.10.21 ansible_user=root ansible_port=22
unifi ansible_host=192.168.8.24 ansible_port=22 ansible_user=linuser ansible_become=yes ansible_become_pass=haslo_roota
remote ansible_host=192.168.10.22 ansible_port=22 ansible_user=linuser ansible_become=yes ansible_become_pass=haslo_roota
nut ansible_host=192.168.10.23 ansible_port=22 ansible_user=linuser ansible_become=yes ansible_become_pass=haslo_roota
zoneminder ansible_host=192.168.10.31 ansible_port=22 ansible_user=linuser ansible_become=yes ansible_become_pass=haslo_roota
cloud ansible_host=192.168.10.29 ansible_port=22 ansible_user=linuser ansible_become=yes ansible_become_pass=haslo_roota
icinga ansible_host=192.168.10.27 ansible_port=22 ansible_user=linuser ansible_become=yes ansible_become_pass=haslo_roota
kibana ansible_host=192.168.60.30 ansible_port=22 ansible_user=linuser ansible_become=yes ansible_become_pass=haslo_roota
ansible ansible_connection=local ansible_user=ansible ansible_ssh_pass=haslo_ansible ansible_become=yes ansible_become_pass=haslo_roota
dnsmasq ansible_host=192.168.20.2 ansible_port=22 ansible_user=root
certbot ansible_host=192.168.20.35 ansible_port=22 ansible_user=root
omv ansible_host=192.168.10.28 ansible_user=root ansible_port=22
docker ansible_host=192.168.10.30 ansible_user=root ansible_port=22
crc ansible_host=192.168.30.75 ansible_port=22 ansible_user=linuser ansible_become=yes ansible_become_pass=haslo_roota
jns ansible_host=192.168.60.40 ansible_port=22 ansible_user=root
web ansible_host=192.168.70.20 ansible_user=linuser ansible_port=22 ansible_become=yes ansible_become_pass=haslo_roota

[proxmox]
pve
pbs

[debian]
pve
pbs
omv
docker
ansible
dnsmasq

[ubuntu]
unifi
remote
nut
zoneminder
cloud
icinga
kibana
certbot
web

[lxc]
ansible
dnsmasq
certbot

[centos]
crc
jns

[nas]
omv
pbs
zoneminder

[all:vars]

Przykładowe polecenia Ansible

Podstawowe polecenia do wyświetlenia zasobów (inventory)

# wyświetl wszystkie hosty

ansible all --list-hosts
  hosts (17):
    pve
    pbs
    unifi
    remote
    nut
    zoneminder
    cloud
    icinga
    kibana
    ansible
    dnsmasq
    certbot
    omv
    docker
    crc
    jns
    web

# wyświetl wszystkie hosty z grupy ubuntu 
ansible ubuntu --list-hosts
  hosts (9):
    unifi
    remote
    nut
    zoneminder
    cloud
    icinga
    kibana
    certbot
    web

# wyświetlenie inventory w formacie yaml
ansible-inventory --list --yaml

Polecenia z wykorzystaniem modułu ping

Więcej informacji na temat modułu ping można znaleźć na stronie https://docs.ansible.com/ansible/latest/collections/ansible/builtin/ping_module.html

# sprawdzenie komunikacji przez ping z wszystkimi / wybraną grupą / pojedynczym hostem
ansible all -m ping
ansible ubuntu -m ping
ansible pve -m ping

Polecenia z wykorzystaniem modułu command

W Ansible moduł command i moduł shell są używane do wykonywania poleceń na zarządzanych hostach, ale różnią się zachowaniem i sposobem obsługi wykonywania poleceń. Moduł command służy do uruchamiania poleceń na zdalnym hoście. Wykonuje polecenie bezpośrednio bez użycia powłoki. Oto kilka kluczowych punktów dotyczących modułu command:

  • Polecenie jest wykonywane z ograniczonym przetwarzaniem powłoki. Nadaje się do prostych poleceń bez składni specyficznej dla powłoki lub złożonego potokowania/przekierowania.
  • Wyjście polecenia jest zwracane bezpośrednio przez moduł, które można wykorzystać w kolejnych zadaniach lub zarejestrować jako zmienną.
  • Ponieważ nie wywołuje powłoki, polecenie nie ma dostępu do zmiennych środowiskowych ani funkcji specyficznych dla powłoki.
  • Znaki charakterystyczne dla powłoki, takie jak zmienne powłoki ($VAR), interpretacja symboli wieloznacznych (*, ?) i zastępowanie poleceń ($(command)) nie są przetwarzane przez moduł poleceń.

Więcej informacji na temat modułu command można znaleźć na stronie https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html

# sprawdzenie na grupie ubuntu z jakiego konta jest uruchomione whoami (powinno być w tym przypadku wszędzie root)
ansible ubuntu -m command -a "whoami"

nut | CHANGED | rc=0 >>
root
zoneminder | CHANGED | rc=0 >>
root
remote | CHANGED | rc=0 >>
root
cloud | CHANGED | rc=0 >>
root
unifi | CHANGED | rc=0 >>
root
icinga | CHANGED | rc=0 >>
root
kibana | CHANGED | rc=0 >>
root
certbot | CHANGED | rc=0 >>
root
web | CHANGED | rc=0 >>
root

# sprawdzenie uptime na grupie hostów debian
ansible debian -m command -a "uptime"

# sprawdzenie zajętości / na grupie hostów lxc
ansible lxc -m command -a "df -h /"

Polecenia z wykorzystaniem modułu shell (powłoki)

Moduł powłoki: Moduł powłoki umożliwia uruchamianie poleceń na zdalnym hoście za pomocą powłoki. Zapewnia większą elastyczność i może obsługiwać polecenia ze składnią specyficzną dla powłoki. Oto kilka kluczowych punktów dotyczących modułu powłoki:

Polecenie jest wykonywane w powłoce, zwykle /bin/sh w systemach typu Unix.
Obsługiwane są funkcje powłoki, takie jak rozwijanie zmiennych środowiskowych, rozwijanie symboli wieloznacznych i zastępowanie poleceń.
Dane wyjściowe polecenia są zwracane w postaci ciągu znaków, który można wykorzystać w kolejnych zadaniach lub zarejestrować jako zmienną.
Moduł powłoki jest potężniejszy, ale może być wolniejszy niż moduł poleceń, ponieważ wymaga uruchomienia procesu powłoki.

Ogólnie rzecz biorąc, zaleca się używanie modułu poleceń do prostych poleceń, które nie wymagają funkcji specyficznych dla powłoki, podczas gdy moduł powłoki jest odpowiedni do bardziej złożonych poleceń lub gdy konieczne jest przetwarzanie powłoki. Jednak ważne jest, aby zachować ostrożność podczas korzystania z modułu powłoki, aby uniknąć zagrożeń bezpieczeństwa, takich jak luki w zabezpieczeniach wstrzykiwania poleceń, przez odpowiednie oczyszczanie danych wejściowych lub używanie zapytań sparametryzowanych.

Więcej informacji na temat modułu shell można znaleźć na stronie https://docs.ansible.com/ansible/latest/collections/ansible/builtin/shell_module.html

# wyświetlenie wersji systemu i zajętości pamięci
ansible all -m shell -a "cat /etc/*release"
ansible all -m shell -a "cat /proc/meminfo|head -2" -u root --become

# sprawdzenie nazwy dystrybucji i wersji 
ansible all -m shell -a "lsb_release -a|grep "Description:""

# wykonanie skryptu z parametrami jako root gdybyśmy nie mieli w pliku /etc/ansible/hosts zdefiniowanego parametru ansible_become=yes
ansible all -m shell -a "/usr/local/sbin/backup.sh -d no -f no -r no -n no" -u root --become

Polecenia z wykorzystaniem modułu service

Więcej informacji na temat modułu service można znaleźć na stronie https://docs.ansible.com/ansible/latest/collections/ansible/builtin/service_module.html

# zatrzymanie usługi nginx na hoście web
ansible web -m service -a "name=nginx state=stopped"

# uruchomienie usługi nginx na hoście web
ansible web -m service -a "name=nginx state=started"

# sprawdzenie stanu usługi nginx na hoście web
ansible web -m service -a "name=nginx"

 Polecenia z wykorzystaniem modułu apt

Więcej informacji na temat modułu apt można znaleźć na stronie https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_module.html

# zaktulizuj grupę hostów o nazwie ubuntu
ansible ubuntu -m apt -a "update_cache=yes upgrade=dist autoremove=yes autoclean=yes"

Ansible Playbooks

Ansible playbook to plik napisany w formacie YAML (Yet Another Markup Language), który definiuje zestaw zadań do wykonania na zdalnych hostach. Pozwala zdefiniować pożądany stan systemu, określić kroki wymagane do osiągnięcia tego stanu oraz zautomatyzować konfigurację i zarządzanie infrastrukturą.

Playbook składa się z jednego lub więcej zadań  do wykonania na określonej grupie gospodarzy. Zadania są definiowane za pomocą modułów Ansible, które są małymi programami wykonującymi określone działania na zarządzanych hostach.

Playbook wykorzystujący moduł apt do instalacji programu

mkdir -p /home/ansible/playbooks
nano /home/ansible/playbooks/install_cool_soft.yml
- name: cool software installation playbook
  hosts: dnsmasq

  tasks:
  - name: install program hwinfo
    apt:
     name: hwinfo
     state: present
     update_cache: yes

Uruchomienie przykładowego playbooka

ansible-playbook install_cool_soft.yml

PLAY [cool software installation playbook] *******************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************
ok: [dnsmasq]

TASK [install program hwinfo] ********************************************************************************************************************************
changed: [dnsmasq]

PLAY RECAP ***************************************************************************************************************************************************
dnsmasq                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 Moja kolekcja Ansible Playbooks

Przykłady Ansible Playbooks, których używam w swojej sieci można znaleźć na stronie https://itadmin.vblog.ovh/category/skrypty/ansible-playbooks/