====== Ansible ======
=== Sprawdzanie, czy dzisiejszy, "cronowy" playbook wykonał się prawidłowo ===
cat ansible.log | grep -E "^$(date "+%Y-%m-%d").*failed" | grep -Ev "failed\=0" | wc -l
Zakładając, że powyższe polecenie jest w pliku check_failed.sh i ścieżka do pliku z logami jest poprawna, można wysłać raport raport na IRC:
---
- name: Send status on IRC
hosts: my-host.ping.local
tasks:
- name: Check failed tasks
command: '/usr/bin/bash /home/lukasz/ansible/helpers/check_failed.sh'
register: fails
- name: Send a report to a fedora-pl channel
irc:
server: irc.libera.chat
port: 6667
nick: raport
channel: '#fedora-pl'
msg: "[ANSIBLE] Todays failed tasks: {{ fails['stdout_lines'][0] }}."
=== Plik konfiguracyjny ===
[defaults]
inventory=~/ansible/hosts
log_path=~/ansible/var/ansible.log
remote_user=ansemble
interpreter_python=auto_silent
[privilege_escalation]
become=True
become_ask_pass=False
become_method=sudo
[persistent_connection]
[connection]
[colors]
[selinux]
[diff]
[galaxy]
[inventory]
[netconf_connection]
[paramiko_connection]
[jinja2]
[tags]
[runas_become_plugin]
[su_become_plugin]
[sudo_become_plugin]
[callback_tree]
[ssh_connection]
ssh_args = -C -o ServerAliveInterval=33 -o ControlMaster=auto -o ControlPersist=66s
timeout=21
[winrm]
[inventory_plugins]
[inventory_plugin_script]
[inventory_plugin_yaml]
[url_lookup]
[powershell]
[vars_host_group_vars]
Ustawienie //auto_silent// usuwa ostrzeżenia o wersji Pythona z każdego przebiegu playbooków. Warto użyć nazwy użytkownika, która nie jest zbyt często zgadywana przez boty.
=== Pętle w playbookach oraz helpery ===
Przykład playbooka korzystącego z pętli:
---
- name: Enable users
hosts: all
tasks:
- name: Ensure that users exists and are in correct groups
include_tasks: helpers/users_enable.yaml
loop:
- {username: lukasz, comment: Lukasz, sshkey: "{{ lookup('file', 'ssh_keys/lukasz') }}"}
# - name: Ensure that users can not login
# include_tasks: helpers/users_disable.yaml
# loop:
# - {username: qwerty, comment: QWERTY, sshkey: "{{ lookup('file', 'ssh_keys/QWERTY') }}"}
Plik helpers/user_enable.yaml:
- debug:
msg: user - {{ item.username }}
- name: Ensure user exists and is in correct groups on FreeBSD
user:
name: "{{ item.username }}"
comment: "{{ item.comment }}"
shell: /usr/local/bin/bash
groups: wheel
append: yes
when: ansible_os_family == 'FreeBSD'
- name: Ensure user exists and is in correct groups on Gentoo and RedHat-like hosts
user:
name: "{{ item.username }}"
comment: "{{ item.comment }}"
shell: /bin/bash
groups: wheel
append: yes
when: ansible_os_family == 'Gentoo' or ansible_os_family == 'RedHat'
- name: Ensure user exists and is in correct groups on Debian-like hosts
user:
name: "{{ item.username }}"
comment: "{{ item.comment }}"
shell: /bin/bash
groups: sudo
append: yes
when: ansible_os_family == 'Debian'
- name: Set authorized SSH keys for user
authorized_key:
user: "{{ item.username }}"
key: "{{ item.sshkey }}"
state: present
exclusive: True
- name: Ensure user is able to log in
user:
name: "{{ item.username }}"
password_lock: no
- name: Set permissions to home directory
file:
path: /home/{{ item.username }}
owner: "{{ item.username }}"
group: "{{ item.username }}"
mode: '700'
Plik helpers/user_disable.yaml:
- debug:
msg: user - {{ item.username }}
- name: Ensure user is not able to log in
user:
name: "{{ item.username }}"
password_lock: yes
- name: Unset authorized SSH keys for user
authorized_key:
user: "{{ item.username }}"
key: "{{ item.sshkey }}"
state: absent
- name: Set permissions to home directory on Linux
file:
owner: root
group: root
path: /home/{{ item.username }}
mode: '700'
when: ansible_os_family == 'Gentoo' or ansible_os_family == 'RedHat' or ansible_os_family == 'Debian'
- name: Set permissions to home directory on FreeBSD
file:
owner: root
group: wheel
path: /home/{{ item.username }}
mode: '700'
when: ansible_os_family == 'FreeBSD'
Plik w katalogu //ssh_keys// jest skopiowany z //~/.ssh/id_rsa.pub//.
=== Ansible 2.9 na CentOS Stream 8 ===
W repozytorium ósmego Streama pojawiły się pakiety ansible-core w nowych wersjach, niekompatybilne z playbookami pisanymi pod wersję 2.9. Stara wersja jest wciąż dostępna na EPEL-u:
dnf install epel-release
dnf install ansible --exclude=ansible-core
Do pliku /etc/yum.conf warto dodać wyjątek, żeby nie musieć o nim ciągle pamiętać.
exclude=ansible-core
=== Ansible 2.18 i Python ===
Nowe wersje Ansibla wymagają Pythona 3.8 na klientach. W RHEL8 domyślnym jest Python 3.6, więc trzeba doinstalować nowszego. Błąd można wywołać nawet pingiem
ansible -m ping all -o
i wygląda on tak:
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: SyntaxError: future feature annotations
is not defined
host.local | FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"},"changed": false,"module_stder
r": "Shared connection to host.local closed.\r\n","module_stdout": "Traceback (most recent call last):\r\n File \"/home/antik
/.ansible/tmp/ansible-tmp-1745649074.378917-9407-261269877273608/AnsiballZ_ping.py\", line 107, in \r\n _ansiballz_main()\r\n
File \"/home/antik/.ansible/tmp/ansible-tmp-1745649074.378917-9407-261269877273608/AnsiballZ_ping.py\", line 99, in _ansiballz_main\r\
n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n File \"/home/antik/.ansible/tmp/ansible-tmp-1745649074.378917-9407-2612
69877273608/AnsiballZ_ping.py\", line 44, in invoke_module\r\n from ansible.module_utils import basic\r\n File \"\", line 971, in _find_and_load\r\n File \"\", line 951, in _find_and_load_unlocked\r\n File \"
\", line 894, in _find_spec\r\n File \"\", line 1157, in find_spec\r
\n File \"\", line 1131, in _get_spec\r\n File \"\", line
1112, in _legacy_get_spec\r\n File \"\", line 441, in spec_from_loader\r\n File \"\", line 544, in spec_from_file_location\r\n File \"/tmp/ansible_ping_payload_598r6p8l/ansible_ping_payload.zip/ansible/
module_utils/basic.py\", line 5\r\nSyntaxError: future feature annotations is not defined\r\n","msg": "MODULE FAILURE: No start of json
char found\nSee stdout/stderr for the exact error","rc": 1}
Na maszynie //host.local// trzeba zainstalować nowszego Pythona:
# dnf module enable python39
# dnf install python39
i w inwentarzu Ansibla poprawić każde wystąpienia //host.local// na:
host.local ansible_python_interpreter=/usr/bin/python3.9