140 lines
6.7 KiB
Markdown
140 lines
6.7 KiB
Markdown
# Ansible + PatchMon — zarządzanie flotą serwerów
|
||
|
||
Inwentarz jest pobierany dynamicznie z PatchMon (`patchmon_inventory.yml`, plugin
|
||
`patchmon.dynamic_inventory`). Grupy hostów pochodzą wprost z grup przypisanych
|
||
w PatchMon — filtrowanie na potrzeby playbooków (`--limit`) odbywa się przez te grupy,
|
||
nie przez ręczne listy hostów.
|
||
|
||
## Pierwsze uruchomienie (świeży klon repozytorium)
|
||
|
||
Sekrety nie są trzymane w gicie — trzeba je uzupełnić lokalnie:
|
||
|
||
```bash
|
||
cp patchmon_inventory.yml.example patchmon_inventory.yml
|
||
# uzupełnij api_url / api_key / api_secret w patchmon_inventory.yml
|
||
|
||
mkdir -p ssh_keys && chmod 700 ssh_keys
|
||
cp /ścieżka/do/twojego/klucza ssh_keys/id_rsa && chmod 600 ssh_keys/id_rsa
|
||
```
|
||
|
||
## Grupy PatchMon używane w tym projekcie
|
||
|
||
| Grupa | Znaczenie |
|
||
|---|---|
|
||
| `root` | Hosty logowane bezpośrednio na konto `root`. |
|
||
| `mgmt` | Hosty logowane na konto `mgmt` (z `sudo`). |
|
||
| `Update-now` | Wszystkie hosty dopuszczone do automatycznej aktualizacji (`root` ∪ `mgmt`). Domyślny cel dla crona/autopilota. |
|
||
| `Type-HOST` | Fizyczne hosty Proxmox — traktuj ostrożniej (restart hosta restartuje też jego VM/CT). |
|
||
| `Type-VM` / `Type-CT` | Maszyny wirtualne / kontenery LXC. |
|
||
| `Site-nni` / `Site-on` | Lokalizacje. |
|
||
|
||
Konto logowania (`ansible_user`) **nie** jest już podawane ręcznie przez `-e` — jest
|
||
ustawiane automatycznie przez `group_vars/root.yml` i `group_vars/mgmt.yml` na
|
||
podstawie grupy PatchMon danego hosta. Dzięki temu jedno uruchomienie playbooka na
|
||
grupie mieszanej (np. `Update-now`) obsłuży poprawnie oba typy kont.
|
||
|
||
## Struktura projektu
|
||
|
||
```
|
||
ssh_keys/
|
||
id_rsa # klucz prywatny SSH (poza gitem, patrz sekcja "Sekrety")
|
||
group_vars/
|
||
all.yml # klucz SSH, become, próg dysku, lista kluczy admina
|
||
root.yml / mgmt.yml # ansible_user per grupa PatchMon
|
||
playbooks/
|
||
playbook_upgrade.yml # apt update + dist-upgrade
|
||
playbook_cleanup.yml # autoremove/autoclean, czyszczenie journala, alarm dysku
|
||
playbook_docker_cleanup.yml # czyszczenie nieużywanych obrazów Docker (tylko hosty z Dockerem)
|
||
playbook_fleet_report.yml # raport: OS, uptime, dysk, liczba aktualizacji, reboot-required
|
||
playbook_security_baseline.yml # unattended-upgrades + wyłączenie logowania hasłem SSH
|
||
playbook_ssh.yml # blokada pustych haseł SSH
|
||
playbook_ssh_keys.yml # zarządzanie kluczami publicznymi na koncie logowania
|
||
playbook_autopilot.yml # orkiestracja pod cron: upgrade -> cleanup -> fleet_report
|
||
templates/
|
||
50unattended-upgrades.j2
|
||
fleet_report.j2
|
||
cron/
|
||
run-autopilot.sh # wrapper do crona (flock + log)
|
||
crontab.example
|
||
ansible-autopilot.logrotate
|
||
reports/ # tu trafiają wygenerowane raporty floty
|
||
```
|
||
|
||
## Użycie
|
||
|
||
```bash
|
||
# Aktualizacja pakietów na całej flocie dopuszczonej do auto-update
|
||
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_upgrade.yml --limit "Update-now"
|
||
|
||
# Sprzątanie/kondycja systemu (autoremove, journal, alarm zajętości dysku)
|
||
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_cleanup.yml --limit "Update-now"
|
||
|
||
# Czyszczenie nieużywanych obrazów Docker (tylko hosty, na których jest Docker)
|
||
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_docker_cleanup.yml --limit "Update-now"
|
||
|
||
# Raport stanu floty -> plik w reports/
|
||
# WAŻNE: dopisz ",localhost" do --limit, inaczej faza renderowania raportu
|
||
# zostanie pominięta ("skipping: no hosts matched").
|
||
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_fleet_report.yml --limit "Update-now,localhost"
|
||
|
||
# Baza bezpieczeństwa: unattended-upgrades + wyłączenie logowania hasłem SSH
|
||
# (dotyka sshd_config — uruchamiaj świadomie, ręcznie, nie z crona)
|
||
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_security_baseline.yml --limit "Update-now"
|
||
|
||
# Blokada logowania na puste hasła
|
||
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_ssh.yml --limit "Update-now"
|
||
|
||
# Zarządzanie kluczami SSH konta logowania (uzupełnij admin_ssh_keys w group_vars/all.yml)
|
||
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_ssh_keys.yml --limit "Update-now"
|
||
|
||
# Pełny przebieg autopilot ręcznie (to samo co robi cron)
|
||
ansible-playbook -i patchmon_inventory.yml playbooks/playbook_autopilot.yml --limit "Update-now,localhost"
|
||
```
|
||
|
||
Można też celować w węższe grupy, np. `--limit "Site-on"`, `--limit "Type-CT"`,
|
||
albo pojedynczy host: `--limit "pve"`.
|
||
|
||
## Reboot — tylko raportowanie, nigdy automatycznie
|
||
|
||
`playbook_fleet_report.yml` sprawdza `/var/run/reboot-required` na każdym hoście
|
||
i wypisuje listę hostów wymagających restartu w raporcie (`reports/fleet_report_*.txt`).
|
||
**Żaden playbook w tym projekcie nie restartuje hostów automatycznie** — decyzję
|
||
i moment restartu (szczególnie dla `Type-HOST`, czyli fizycznego Proxmoksa) podejmuje
|
||
operator ręcznie, po przejrzeniu raportu.
|
||
|
||
## Bezobsługowe uruchamianie (cron)
|
||
|
||
`cron/run-autopilot.sh` to wrapper na `playbook_autopilot.yml`:
|
||
- blokuje się przez `flock`, żeby nie nakładały się dwa równoległe przebiegi,
|
||
- loguje przebieg (start/koniec/kod wyjścia) do `/var/log/ansible-autopilot.log`,
|
||
- domyślnie celuje w grupę `Update-now` (nadpisywalne zmienną `TARGET_GROUP`).
|
||
|
||
Instalacja:
|
||
|
||
```bash
|
||
chmod +x cron/run-autopilot.sh
|
||
crontab -e # wklej zawartość cron/crontab.example
|
||
sudo cp cron/ansible-autopilot.logrotate /etc/logrotate.d/ansible-autopilot
|
||
```
|
||
|
||
Każdy przebieg `playbook_fleet_report.yml` (w tym z crona) dokłada nowy plik do
|
||
`reports/` — warto od czasu do czasu posprzątać stare raporty, np.
|
||
`find reports/ -name 'fleet_report_*.txt' -mtime +30 -delete`.
|
||
|
||
## Sekrety
|
||
|
||
- **Klucz prywatny SSH** leży w `ssh_keys/id_rsa` (katalog `chmod 700`, plik `chmod 600`).
|
||
Katalog `ssh_keys/` jest w `.gitignore` — klucz nigdy nie trafia do repozytorium.
|
||
Ścieżka do niego jest ustawiona centralnie w `group_vars/all.yml`
|
||
(`ansible_ssh_private_key_file: "{{ playbook_dir }}/../ssh_keys/id_rsa"`), więc
|
||
wszystkie playbooki i `cron/run-autopilot.sh` korzystają z niej automatycznie —
|
||
nie trzeba nic dodatkowo konfigurować.
|
||
- **`api_key`/`api_secret`/`api_url` PatchMon** leżą w `patchmon_inventory.yml`, który
|
||
jest w `.gitignore` — nigdy nie trafia do repozytorium. Wersja do repo to
|
||
`patchmon_inventory.yml.example` (same placeholdery, bez sekretów). Przy zakładaniu
|
||
projektu od zera: `cp patchmon_inventory.yml.example patchmon_inventory.yml` i
|
||
uzupełnij `api_url`/`api_key`/`api_secret`.
|
||
(Plugin `patchmon.dynamic_inventory` wczytuje ten plik bezpośrednio, bez
|
||
templatowania Jinja2/Vault, dlatego to rozdzielenie na plik realny + `.example`,
|
||
a nie np. `{{ lookup('env', ...) }}`, jest tu jedynym niezawodnym sposobem.)
|