L'execució del playbook acaba en verd, la unitat de WireGuard és activa, l'handshake funciona i el nou peer encara no arriba enlloc. Veure un playbook que informa d'èxit mentre el servidor funciona amb la configuració d'ahir és especialment frustrant, perquè res de la sortida no és incorrecte. Ansible va fer exactament el que se li va demanar: va assegurar que la unitat estigués iniciada, i ja ho estava. Aplicar un fitxer de configuració reescrit és una altra tasca, i només passa si alguna cosa diu al servei que el torni a llegir.

Mira què informa realment una segona execució

Executa el playbook dues vegades amb la configuració canviada al seu lloc i compara el resum. La segona execució hauria de mostrar la tasca de la unitat com a ok, no com a changed, perquè un servei que ja funciona es deixa tranquil per disseny. Això és la idempotència funcionant correctament, i també la raó per la qual el fitxer nou no arriba mai al nucli.

Afegeix una execució de comprovació amb sortida diff per veure quines tasques tocarien alguna cosa.

ansible-playbook -i inventory site.yml --check --diff
systemctl show wg-quick@wg0 -p ActiveEnterTimestamp -p NRestarts
stat -c '%y %n' /etc/wireguard/wg0.conf

Les tres marques de temps expliquen la història abans de llegir una sola línia de registre. Si el fitxer de configuració és més nou que el moment en què la unitat es va activar, la interfície en execució es va construir amb un fitxer més antic, i tots els símptomes posteriors en deriven.

No és un defecte d'Ansible. El mateix comportament apareix amb qualsevol eina de gestió de configuració que separa «assegura't que funciona» de «assegura't que funciona amb això». La distinció sembla pedant fins que et costa una tarda.

Iniciat és un estat, no una recàrrega

state: started afirma una condició sobre la unitat. No promet que el servei torni a llegir les seves entrades, i no pot saber que un fitxer que mai ha obert ha canviat. En un desplegament wg-quick les entrades inclouen la configuració de la interfície, les adreces, les rutes, les entrades DNS i qualsevol hook post-up.

Per això un fitxer actualitzat pot contenir un peer nou, una adreça diferent o una directiva d'encaminament canviada mentre la interfície viva continua servint el conjunt antic. L'handshake encara té èxit perquè les claus i els extrems carregats encara són vàlids. És exactament el que fa difícil de veure la fallada, i per què la gent persegueix el DNS durant una hora abans de comprovar una marca de temps.

Dues altres opcions del mòdul es confonen sovint amb una solució. daemon_reload fa que systemd torni a llegir els fitxers d'unitat, cosa irrellevant per a un fitxer de configuració de WireGuard. state: reloaded demana a la unitat que executi la seva acció de recàrrega, i si això fa el que necessites depèn totalment de la unitat. Cap de les dues no substitueix saber quines entrades ha llegit realment el procés en execució.

Instal·la el fitxer i després notifica un handler

El patró que manté la idempotència i aplica els canvis és l'habitual: la tasca que escriu el fitxer notifica un handler, i el handler només s'executa quan el fitxer ha canviat de debò. Una segona execució sense edicions no fa res, i és el que vols.

- name: write the interface configuration
  ansible.builtin.template:
    src: wg0.conf.j2
    dest: /etc/wireguard/wg0.conf
    owner: root
    mode: "0600"
  notify: apply wg0

- name: ensure the interface unit is enabled
  ansible.builtin.systemd_service:
    name: wg-quick@wg0
    enabled: true
    state: started

- name: apply wg0
  listen: apply wg0
  ansible.builtin.systemd_service:
    name: wg-quick@wg0
    state: restarted

Els handlers s'executen al final de l'obra, després de les tasques que els han notificat, així que una tasca posterior de la mateixa obra encara pot veure la interfície antiga. Si l'ordre importa, buida els handlers explícitament amb meta: flush_handlers abans de la tasca que depèn de la configuració nova.

Fes servir restart en lloc de reload tret que hagis verificat l'acció de recàrrega de la unitat. La unitat wg-quick d'origen sí que en suporta una, i sincronitza la configuració de WireGuard, però no torna a executar la configuració d'adreces, rutes, DNS ni hooks. Per això un reload després d'afegir una directiva de ruta sembla tenir èxit i no canvia res.

Compara el dispositiu viu amb el fitxer

La comprovació que tanca aquesta classe d'errors és una comparació entre el que té el nucli i el que diu el fitxer. Dues ordres produeixen una sortida comparable, i la diferència és la desviació.

sudo wg showconf wg0
sudo wg-quick strip wg0
sudo diff <(sudo wg showconf wg0) <(sudo wg-quick strip wg0)

wg showconf imprimeix el dispositiu viu, inclosa la clau privada, així que tracta aquesta sortida com un secret i no l'enganxis en un tiquet. wg-quick strip imprimeix el fitxer sense les claus exclusives de wg-quick, i per això les dues sortides són comparables.

Una diferència en la llista de peers vol dir que el fitxer no es va aplicar mai. Una diferència limitada a claus o extrems que esperaves canviar vol dir que alguna cosa el va aplicar parcialment. Cap diferència vol dir que la configuració és actual i la fallada és en un altre lloc, cosa que ja és un resultat útil.

Paga el cost del reinici deliberadament

Reiniciar la interfície fa caure el túnel, i si aquest túnel porta la teva sessió administrativa, el reinici acaba la sessió que l'ha demanat. Posa el handler darrere d'una finestra de canvi, o executa el playbook des d'un camí de gestió que no depengui del reinici de la interfície.

El cost és per què la gent opta pel reload. És un instint raonable, i esdevé correcte quan saps quins canvis aplica realment un reload. Per a canvis de peer i de claus a la unitat wg-quick d'origen n'hi ha prou; per a adreçament, encaminament i hooks no. Resoldre-ho un cop surt més barat que descobrir-ho durant una finestra de canvi.

La documentació del mòdul systemd_service explica la diferència entre started, restarted i reloaded, i val la pena llegir-la un cop en lloc d'inferir-la d'un resum verd. Tot en aquest recorregut surt d'aquesta única distinció.

Articles relacionats