Playbook-körningen slutar grönt, WireGuard-enheten är aktiv, handskakningen fungerar, och den nya peer-en når fortfarande ingenting. Att se en playbook rapportera framgång medan servern kör gårdagens konfiguration är särskilt frustrerande, eftersom ingenting i utdata är fel. Ansible gjorde precis det som efterfrågades: det säkerställde att enheten var startad, och enheten var redan startad. Att tillämpa en omskriven konfigurationsfil är en annan uppgift, och det sker bara om något säger åt tjänsten att läsa om den.

Se vad en andra körning faktiskt rapporterar

Kör playbooken två gånger med den ändrade konfigurationen och jämför sammanfattningen. Den andra körningen bör visa enhetsuppgiften som ok, inte changed, eftersom en tjänst som redan körs med avsikt lämnas i fred. Det är idempotens som fungerar korrekt, och det är också anledningen till att den nya filen aldrig når kärnan.

Lägg till en kontrollkörning med diff-utdata för att se vilka uppgifter som alls skulle röra något.

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

De tre tidsstämplarna berättar historien innan du läser en enda logglinje. Om konfigurationsfilen är nyare än ögonblicket då enheten blev aktiv byggdes det körande gränssnittet från en äldre fil, och varje efterföljande symtom följer av det.

Det här är inte en defekt i Ansible. Samma beteende visas med alla konfigurationshanteringsverktyg som skiljer «se till att det körs» från «se till att det kör det här». Skillnaden verkar pedantisk tills den kostar dig en eftermiddag.

Startad är ett tillstånd, inte en omladdning

state: started hävdar ett villkor om enheten. Det lovar inte att tjänsten läser om sina indata, och det kan inte veta att en fil som den aldrig öppnade har ändrats. Vid en wg-quick-distribution omfattar indata gränssnittskonfigurationen, adresserna, rutterna, DNS-posterna och eventuella post-up-krokar.

Därför kan en uppdaterad fil innehålla en ny peer, en annan adress eller ett ändrat routingdirektiv medan det levande gränssnittet fortsätter att betjäna den gamla uppsättningen. Handskakningen lyckas fortfarande eftersom nycklarna och slutpunkterna som lästes in fortfarande är giltiga. Just det gör felet svårt att se, och därför jagar folk DNS i en timme innan de kontrollerar en tidsstämpel.

Två andra modulalternativ uppfattas ofta som en lösning. daemon_reload får systemd att läsa om enhetsfiler, vilket är irrelevant för en WireGuard-konfigurationsfil. state: reloaded ber enheten köra sin omladdningsåtgärd, och om den gör det du behöver beror helt på enheten. Ingen av dem ersätter att veta vilka indata den körande processen faktiskt läste.

Installera filen och meddela sedan en hanterare

Mönstret som bevarar idempotensen och ändå tillämpar ändringar är det vanliga: uppgiften som skriver filen meddelar en hanterare, och hanteraren körs bara när filen faktiskt har ändrats. En andra körning utan redigeringar gör ingenting, och det är vad du vill.

- 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

Hanterare körs i slutet av playet, efter uppgifterna som meddelade dem, så en uppgift senare i samma play kan fortfarande se det gamla gränssnittet. Om ordningen är viktig, töm hanterarna uttryckligen med meta: flush_handlers innan uppgiften som beror på den nya konfigurationen.

Använd restart i stället för reload, om du inte har verifierat enhetens omladdningsåtgärd. Upstream wg-quick-enheten stöder en, och den synkroniserar WireGuard-konfigurationen, men den kör inte om inställningen av adresser, rutter, DNS eller krokar. En reload efter att ha lagt till ett ruttdirektiv verkar därför lyckas och ändrar ingenting.

Jämför den levande enheten med filen

Kontrollen som stänger den här felklassen är en jämförelse mellan vad kärnan håller och vad filen säger. Två kommandon ger jämförbar utdata, och skillnaden är avvikelsen.

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

wg showconf skriver ut den levande enheten, inklusive den privata nyckeln, så behandla utdata som en hemlighet och klistra inte in dem i ett ärende. wg-quick strip skriver ut filen utan de wg-quick-specifika nycklarna, och därför är de två alls jämförbara.

En skillnad i peer-listan betyder att filen aldrig tillämpades. En skillnad begränsad till nycklar eller slutpunkter som du förväntade dig skulle ändras betyder att något tillämpade den delvis. Ingen skillnad betyder att konfigurationen är aktuell och felet ligger någon annanstans, vilket i sig är ett användbart resultat.

Betala kostnaden för omstarten medvetet

En omstart av gränssnittet river tunneln, och om den tunneln bär din administrativa session avslutar omstarten den session som bad om den. Sätt hanteraren bakom ett ändringsfönster, eller kör playbooken från en hanteringsväg som inte beror på att gränssnittet startas om.

Kostnaden är anledningen till att folk griper efter reload. Det är en rimlig instinkt, och den blir korrekt när du vet vilka ändringar en reload faktiskt tillämpar. För peer- och nyckeländringar på upstream wg-quick-enheten räcker det; för adressering, routing och krokar inte. Att reda ut det en gång är billigare än att upptäcka det under ett ändringsfönster.

Dokumentationen för systemd_service-modulen förklarar skillnaden mellan started, restarted och reloaded, och den är värd att läsa en gång i stället för att gissa från en grön sammanfattning. Allt i den här genomgången följer av den enda skillnaden.

Relaterade artiklar