A mellékelt komponensek frissítése

Az átjáró mellé harmadik féltől jövő komponensek is szállítunk: egy címtár, egy identity provider, egy titok-tár, egy adatbázis, egy objektum-tár, egy levélcsapda és a monitoring-pár. Mindegyik olyan konténer-image-ből fut, ami digestre van pinelve, és bármelyik frissítése ugyanaz a két lépés — írd át a pint, futtasd újra a role-t. Ami komponensenként más, az az, hogy mibe kerül az újraindítás. Ez az oldal pontosan ez a lista.

Hogyan van egy komponens pinelve

A szállított automatikában minden image-hivatkozás alakja tag@sha256:…: a tag az olvasónak szól, a kötés a digest. Egy verziós tag maga nem köt — egy upstream-kiadás új bájtokra mozdíthatja a tagot anélkül, hogy ebben a repóban bármi változna —, ezért a konténer-motor a digestet húzza le. Hogy az ugyanazt az image-et megnevező helyek egyeznek-e, maga is mért: a make ansible-image-pin-check méri.

A pin a role saját defaultjában áll, komponensenként egy változóban:

Komponens Pin-változó
PostgreSQL isg_shared_store_postgres_image
OpenBao isg_shared_store_bao_image
RustFS (S3 objektum-tár) isg_shared_store_rustfs_image
OpenLDAP isg_directory_ldap_image
Keycloak isg_directory_idp_image
Mailpit isg_directory_mail_image
Prometheus isg_monitoring_prom_image
Grafana isg_monitoring_grafana_image
node_exporter isg_monitoring_node_exporter_image

Egy frissítés tehát: írd át a változót, futtasd a site.yml-t azzal a --limit-tel, ami azokat a gépeket választja ki, amiken a komponens fut, és a role handlere újraindítja a unitot. Ezekhez a komponensekhez nincs frissítő playbook — ami van, az upgrade-rolling.yml, és az magukat az ISG-brókereket frissíti (drain, csere, mérés, brókerenként egyenként), nem a körülöttük álló komponenseket.

Előtte és utána: a verzióriport

Futtasd a riportot a pin átírása előtt, és még egyszer a role futása után:

ansible-playbook -i inventory/<environment>.ini -e isg_env=<environment> \
  playbooks/component-versions.yml

Csak olvas. Gépenként konténerenként egy sort ír ki, három oszloppal — a pint, a TÉNYLEGESEN futó image-et (nevével és digestjével), és azt a verziót, amit a szoftver önmagáról mond —, majd komponensenként egy összesítő sort az egész flottára. Minden sor hordoz egy verdiktet:

Verdikt Mit jelent
match a pin tagje a mért verzió, és a futó digest a pin digestje
digest-match a pin erre a szoftverre nézve nem hordoz verzió-tagot — lebegő tag, csak digestes pin, vagy olyan image, ami a saját verzióját tageli, nem a benne csomagolt szoftverét —, tehát a digest az egyetlen állítás, a verzió pedig tájékoztatásként van kiírva
mismatch a futó digest nem a pin digestje, vagy a tag nem a mért verzió
not_measured a konténert vagy a verzió-parancsot nem sikerült megmérni; az ok ott áll a sor végén

Egy mismatch elbuktatja a futást — de azután, hogy a táblázat és az összesítő kiíródott, így egy futásból megvan a teljes kép. Egy not_measured nem buktat: egy álló gép nem verzió-eltérés.

Egy frissítés előtte-pillanatképénél — a pin már az új verziót nevezi meg, a gépen még a régi fut — a mismatch a várt állapot. Ilyenkor -e isg_cv_fail_on_mismatch=false: a riport ugyanúgy kiíródik (és fájlba is megy), a futás nem bukik.

Mibe kerül egy frissítés, komponensenként

OpenLDAP — a címtár a seedből épül újra

Az image cseréje újra létrehozza a konténert, és a címtár a seedből épül fel ismét. Azokat a csak olvasó fiókokat, amikkel az átjáró bindol, a role visszateszi; ami bejegyzés a címtár futása közben került be, az elveszik, és a brókerek bindja az újraindítás alatt rövid időre kiesik. Kétszer mérve, 2026-10-08-án.

Ennek megfelelően kezeld: ha a seedelt tartalmon kívül bármi él ebben a címtárban, előbb exportáld.

OpenBao — minden újraindítás után zárva

Egy újraindítás a titok-tárat zárva (sealed) hagyja. Ez nem egy kikerülendő hibamód: a role ezt hangosan, pirossal kimondja, és megáll, nem pedig úgy tesz, mintha a tár használható lenne. A kinyitás külön, szándékos lépés, és saját playbookja van — bao-init.yml. A kinyitást ugyanabba a karbantartási ablakba tervezd, mint a frissítést; amíg az le nem fut, minden elhasal, aminek titok kell a tárból.

PostgreSQL — a major-verzió egy dump és egy restore

A major-verzió a pin része. Az automatizálás egy telepítést nem visz át egy major-verzión: új adatkönyvtár kell, és az adat egy dumppal és egy restore-ral jut el oda. A 18-tól az image az adatot más elrendezésben is tartja — a tár adatkönyvtára /var/lib/postgresql-ként van csatolva, és a klaszter a 18/docker alkönyvtárában él.

A role megtagadja, hogy egy 18-as image-et a régi elrendezésű adatkönyvtáron indítson (PG_VERSION a gyökerében): ott a Postgres egy új, üres adatbázist inicializálna a régi fájlok mellé. Egyszer mérve (2026-10-11, egy labor-telepítésen, 16.15 → 18.6): friss mentés, a unit leállítva, a régi könyvtár félreátnevezve, egy üres a helyére, abba restore a dumpból az új image-dzsel, majd a role — a sor-számok egyeztek a mentés manifestjével. Egy új telepítés eleve a pinelt majoron indul, és ebből semmi nem kell neki.

Egy minor verziós image-csere a meglévő adatköteten várhatóan esemény nélküli — de ez hipotézis, nem mérés: ebben a telepítésben nem mértük. Előbb mentsd a kötetet, és olvasd el annak a minornak az upstream kiadási jegyzetét, amire lépsz.

Keycloak — a beépített adatbázis egy köteten áll

Az identity provider start-dev módban fut, a beépített adatbázisa a keycloak/data köteten. Az image cseréje tehát ennek a kötetnek a DB-migrációját jelenti, amit az új verzió az első induláskor végez el. Egyszer mérve (2026-10-11, egy labor-telepítésen): 26.3.5 → 26.8.0, öt minor verzió egy ugrással — a migráció az első induláskor lefutott, az identity provider nagyjából fél perc után válaszolt, és a realm, a kliens meg az LDAP-föderáció változatlanul megmaradt. Egy mérés, nem garancia minden ugrásra.

Tehát: előbb mentsd a kötetet, és csak utána írd át a pint. Ha a migráció elromlik, a mentés az út vissza az előtte lévő állapotba. A kötet fájljai a konténer felhasználójáéi, ami a hoszton egy alárendelt uid — a felhasználói névtéren belül olvasd és állítsd vissza őket, például:

podman unshare tar czf <archive> -C <keycloak-home> data

A 26.8-tól a Keycloak újra bekéri a bind-jelszót, valahányszor az LDAP-föderáció connection URL-je vagy bind DN-je változik; maszkolt jelszót nem fogad el. A role erre szolgáló útja (a retransport-kapcsoló) eleve a valódi jelszót küldi. Egy kézi módosításnál az admin-konzolon a jelszót újra be kell írni.

RustFS, Prometheus, Grafana, node_exporter és Mailpit

Ennél az ötnél az automatizálásban nincs külön lépés: írd át a pint, futtasd a role-t, és a unit az új image-dzsel indul újra. Hogy egy adott verzióugrás megváltoztatja-e a komponens adatainak lemezformátumát, az itt nem mért — ugrás előtt olvasd el az upstream kiadási jegyzetét.

Egyikükről érdemes kimondani: a Mailpit egy teszt SMTP-csapda. Azért van ott, hogy egy telepítés látni tudja az átjáró által küldött levelet anélkül, hogy ki is küldené; nem levélszerver semmi valódihoz, és semmi nem veszik el, amikor a konténere kicserélődik.

Amit a riport NEM mond meg

A riport nem kérdezi meg az upstreamtől, mi a legfrissebb verzió, és egyáltalán nem hív ki a hálózatra: az egyetlen verzió-parancs, ami alapból online ellenőrizne, a Mailpité, --no-release-check-kel fut. Egy mért verziót az upstream által közzétetthez hasonlítani külön lépés, egy erre választott gépen.

Havi upstream-ellenőrzés

Ez a külön lépés a playbooks/component-upstream.yml. Csak a vezérlőn fut, minden pinelt komponens registry-jétől megkérdezi a legmagasabb stabil tagot, és mindegyikre verdiktet mond: current, behind vagy not_measured. A behind nem hiba — egy döntés bemenete.

Mit futtat, mikor, és hova ír. A playbooks/upstream-schedule.yml egy systemd user timert telepít a vezérlőre (az isg_upstream_schedule role). A timer minden hónap első napján 07:20-kor indul, legfeljebb 30 perc véletlen késéssel, és a Persistent=true egy kimaradt futást a vezérlő indulása után behoz. Minden futás a riportot egy JSON- és egy Markdown-fájlba írja, a vezérlő-felhasználó home-jának isg-component-reports könyvtárába (isg_upstream_schedule_report_dir). A timernek nem kell se root, se token, se sudo-jelszó: az ellenőrzés minden playje localhoston, become nélkül fut, és a role ezt a futtató fán telepítés ELŐTT megméri.

cd ansible
ansible-playbook -i inventory/<környezet>.ini -e isg_env=<környezet> \
  playbooks/upstream-schedule.yml
journalctl --user -u isg-upstream-<környezet>.service    # a futások

Mikor megy levél, és kinek. Ha legalább egy komponens behind, a futás a Markdown-táblát elküldi az isg_cfg_upstream_notify_to címeire, a telepítés meglévő SMTP-útján (isg_cfg_smtp_host, isg_cfg_smtp_port, isg_cfg_smtp_from). Ha semmi nem behind, nincs levél, és a napló ezt egy sorban kimondja; ugyanígy üres címzett-listánál. Az SMTP-hiba a futást pirossá teszi, a hosztot és a portot megnevezve — egy csendben el nem ment levél pont az, ami ellen a havi ellenőrzés van. A küldő sima SMTP-t beszél, TLS és hitelesítés nélkül; egy valódi relét az üzemeltető ad.

Mi a teendő egy behind-dal. Ne frissíts egy komponenst azon a napon, amikor a levele megjön. Gyűjtsd a behind-sorokat egy kötegbe, és a köteget együtt frissítsd: minden pint írj át az új tag index-digestjére, futtass verzióriportot előtte és utána (fent), és az ezen az oldalon álló komponensenkénti árakból nézd meg, mi kér egy újraindításnál többet.

A tűzfal az SMTP-úton. A címtár-hoszton az SMTP-port alapból csak a brókereknek nyílik (isg_directory_firewall_client_sources); a levél most a vezérlőről is jön, ezért a címe az isg_directory_firewall_smtp_extra_sources-ba kerül. E nélkül a tűzfal a vezérlőt elutasítja (mérve: „No route to host"), és a futás pirosra vált, a hosztot és a portot megnevezve.