Zarządzanie, utrzymywanie oraz analizowanie dzienników zdarzeń to jedno z podstawowych zadań administratora w każdym systemie informatycznym. W przypadku nawet najmniejszej awarii lub anomalii pracujących aplikacji czy serwisów, dzienniki zdarzeń są nieocenionym źródłem informacji o tym co, kiedy i w jakich okolicznościach wydarzyło się w zarządzanym przez nas systemie.
Udostępnij!
Gdy środowisko się rozrasta, stale przybywająca liczba serwerów do skontrolowania może być kłopotliwa, warto zatem rozważyć zastosowanie centralnego logowania zdarzeń. Do uproszczenia i automatyzacji takiego zadania świetnie posłużyć może jedno z głównych narzędzi DevOps – Ansible. W tym artykule przedstawię zastosowanie Ansible przy szybkim wdrażaniu centralnego logowania w zarządzanym przez nas, opartym na systemie linuxowym CentOS v.7, środowisku.
[altkom@log-master ~]$ ansible --version
ansible 2.9.3
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/home/altkom/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /bin/ansible
python version = 2.7.5 (default, Aug 7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
[altkom@log-master ~]$ cat /etc/centos-release
CentOS Linux release 7.7.1908 (Core)
W naszym przykładzie posłużymy się prostym środowiskiem:
– jeden serwer master przyjmujący logi od pozostałych
– dwa serwery mające przesyłać logi do serwera master
Zawierający spis nodów, na których dokonamy zmian konfiguracyjnych plik inventory.cfg przedstawia się następująco:
[master]
log-master
[nodes]
log-node1
log-node2
Aby sprawdzić poprawność połączenia, wykorzystamy klasyczny moduł ping:
[altkom@log-master ansible]$ ansible master -i inventory.cfg -m ping
log-master | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
[altkom@log-master ansible]$ ansible nodes -i inventory.cfg -m ping
log-node2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
log-node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
Na potrzeby tego artykułu sięgniemy po ansiblowe playbooki. Stworzymy dwa oddzielne, a następnie scalimy je w całość.
W playbooku dla serwera master musimy skonfigurować trzy podstawowe kwestie:
– załadowanie modułu imudp, który odpowiada za przyjmowanie logów z pozostałych serwerów.
Posługujemy się tu modułem Ansible lineinfile, by zmienić zawartość pliku konfiguracyjnego /etc/rsyslog.conf – uruchomienie nasłuchiwania serwera rsyslog na porcie 514. W tym celu korzystamy także z lineinfile. Zmiana w pliku konfiguracyjnym wymaga restartu demona, używamy więc notify, by w razie zmian przechwycić status changed taska i w sekcji handlers zrestartować demon rsyslog.
Nazwa notify musi odpowiadać nazwie handlera.
– otwarcie firewalla na porcie 514, protokół UDP. Opcja immediate: yes odpowiada za otwarcie portu w czasie rzeczywistym, natomiast opcja permanent: yes zapewni dostęp do portu także
po restarcie serwera.
Postać playbooka dla mastera:
---
- name: konfiguracja centralnego logowania za pomoca Ansible
become: True
hosts: master
tasks:
- name: zaladowanie modulu imudp na serwer master
lineinfile:
path: /etc/rsyslog.conf
regexp: '#$ModLoad imudp'
line: '$ModLoad imudp'
notify: restart rsyslog
- name: konfiguracja portu 514/udp w demonie rsyslog serwer master
lineinfile:
path: /etc/rsyslog.conf
regexp: '#$UDPServerRun 514'
line: '$UDPServerRun 514'
notify: restart rsyslog
- name: konfiguracja firewalld na serwerze master
firewalld:
port: 514/udp
immediate: yes
permanent: yes
state: enabled
handlers:
- name: restart rsyslog
service:
name: rsyslog
state: restarted
Podobnie wygląda playbook dla nodów mających wysyłać logi do serwera centralnego. Tutaj za pomocą modułu lineinfile ustawiamy parametr *.* @log-master:514
Postać playbooka dla nodów:
- name: konfiguracja centralnego logowania za pomoca Ansible
become: True
hosts: nodes
tasks:
- name: transfer logow na serwer master
lineinfile:
path: /etc/rsyslog.conf
regexp: '#*.* @@remote-host:514'
line: '*.* @log-master:514'
notify: restart rsyslog
handlers:
- name: restart rsyslog
service:
name: rsyslog
state: restarted
Oba playbooki możemy wywołać w playbooku głównym za pomocą opcji import_playbook.
Postać playbooka głównego:
---
- name: konfiguracja centralnego logowania za pomoca Ansible
become: True
hosts: all
- name: wczytanie playbooka dla serwera master
import_playbook: playbook-master.yml
- name: wczytanie playbooka dla nodow
import_playbook: playbook-nodes.yml
Dzięki takiemu podziałowi możemy łatwo rozszerzyć naszą konfigurację o następne elementy – na przykład kopiowanie wzorców plików konfiguracyjnych dla poszczególnych aplikacji. Wystarczy za pomocą import_playbook dodać kolejnego playbooka do playbooka głównego.
Inny pomysł na automatyzację centralnego logowania to rozpisanie naszej konfiguracji
na bardziej złożoną strukturę – roles, ten temat wykracza jednak poza zakres tego artykułu.
Zanim uruchomimy naszego playbooka, dobrze sprawdzić w nim poprawność składni:
ansible-playbook --syntax-check -i inventory.cfg playbook.yml
oraz wykonać symulację działania playbooka, aby uniknąć nieoczekiwanych niespodzianek:
ansible-playbook -C -i inventory.cfg playbook.yml
Oto wynik:
[altkom@log-master ansible]$ ansible-playbook -i inventory.cfg playbook.yml
PLAY [konfiguracja centralnego logowania za pomoca Ansible] ********************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [log-node1]
ok: [log-master]
ok: [log-node2]
PLAY [konfiguracja centralnego logowania za pomoca Ansible] ********************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [log-master]
TASK [zaladowanie modulu imudp na serwer master] ********************************************************************************
changed: [log-master]
TASK [konfiguracja portu 514/udp w demonie rsyslog serwer master] ********************************************************************************
changed: [log-master]
TASK [konfiguracja firewalld na serwerze master] ********************************************************************************
changed: [log-master]
RUNNING HANDLER [restart rsyslog] ********************************************************************************
changed: [log-master]
PLAY [konfiguracja centralnego logowania za pomoca Ansible] ********************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [log-node2]
ok: [log-node1]
TASK [transfer logow na serwer master] ********************************************************************************
changed: [log-node1]
changed: [log-node2]
RUNNING HANDLER [restart rsyslog] ********************************************************************************
changed: [log-node1]
changed: [log-node2]
PLAY RECAP ********************************************************************************
log-master : ok=6 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
log-node1 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
log-node2 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[altkom@log-master ansible]$
Na koniec możemy sprawdzić poprawność konfiguracji za pomocą komendy ad-hoc Ansible:
ansible nodes -i inventory -m shell -a ‘logger „test konfiguracji centralnego logowania”
Ansible doskonale nadaje się do automatyzacji zmian konfiguracji w złożonych środowiskach,
a łatwość dokonania zmian w playbookach powinna pomóc w codziennej pracy każdemu administratorowi systemów.
Dla przykładu – konfiguracja następnych nodów sprowadza się do dodania ich adresów w pliku inventory.cfg:
[nodes]
log-node1
log-node2
log-node[100:150]
To tylko prosty przypadek wykorzystania Ansible, ale dzięki jego elastyczności można zaoszczędzić sporo czasu i nerwów.