Το playbook τελειώνει πράσινο, η μονάδα WireGuard είναι ενεργή, η χειραψία λειτουργεί, και ο νέος peer δεν φτάνει πουθενά. Το να βλέπεις το playbook να αναφέρει επιτυχία ενώ ο διακομιστής τρέχει τη χθεσινή διαμόρφωση είναι ιδιαίτερα εκνευριστικό, γιατί τίποτα στην έξοδο δεν είναι λάθος. Το Ansible έκανε ακριβώς αυτό που του ζητήθηκε: φρόντισε η μονάδα να είναι ξεκινημένη, και ήταν ήδη. Η εφαρμογή ενός ξαναγραμμένου αρχείου διαμόρφωσης είναι άλλη εργασία και συμβαίνει μόνο αν κάτι πει στην υπηρεσία να το ξαναδιαβάσει.

Δείτε τι αναφέρει πραγματικά μια δεύτερη εκτέλεση

Εκτελέστε το playbook δύο φορές με την αλλαγμένη διαμόρφωση στη θέση της και συγκρίνετε τη σύνοψη. Η δεύτερη εκτέλεση πρέπει να δείξει την εργασία της μονάδας ως ok και όχι changed, γιατί μια υπηρεσία που ήδη τρέχει αφήνεται ήσυχη εξ ορισμού. Αυτή είναι η idempotence να δουλεύει σωστά, και γι' αυτό το νέο αρχείο δεν φτάνει ποτέ στον πυρήνα.

Προσθέστε μια δοκιμαστική εκτέλεση με έξοδο diff για να δείτε ποιες εργασίες θα άγγιζαν κάτι.

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

Οι τρεις χρονοσημάνσεις λένε την ιστορία πριν διαβάσετε μία γραμμή log. Αν το αρχείο διαμόρφωσης είναι νεότερο από τη στιγμή που η μονάδα έγινε ενεργή, η διεπαφή που τρέχει χτίστηκε από παλαιότερο αρχείο και κάθε επόμενο σύμπτωμα προκύπτει από αυτό.

Δεν είναι σφάλμα του Ansible. Η ίδια συμπεριφορά εμφανίζεται σε κάθε εργαλείο διαχείρισης διαμόρφωσης που χωρίζει το «σιγουρέψου ότι τρέχει» από το «σιγουρέψου ότι τρέχει αυτό». Η διάκριση φαίνεται σχολαστική μέχρι να σου κοστίσει ένα απόγευμα.

Το ξεκίνησε είναι κατάσταση, όχι επαναφόρτωση

Το state: started βεβαιώνει μια συνθήκη για τη μονάδα. Δεν υπόσχεται ότι η υπηρεσία ξαναδιαβάζει τις εισόδους της και δεν μπορεί να ξέρει ότι ένα αρχείο που δεν άνοιξε ποτέ άλλαξε. Σε ανάπτυξη wg-quick οι είσοδοι περιλαμβάνουν τη διαμόρφωση της διεπαφής, τις διευθύνσεις, τις διαδρομές, τις εγγραφές DNS και τυχόν hooks post-up.

Γι' αυτό ένα ενημερωμένο αρχείο μπορεί να περιέχει νέο peer, άλλη διεύθυνση ή αλλαγμένη οδηγία δρομολόγησης ενώ η ζωντανή διεπαφή συνεχίζει να σερβίρει το παλιό σύνολο. Η χειραψία πετυχαίνει ακόμη, γιατί τα κλειδιά και τα endpoints που φορτώθηκαν ισχύουν ακόμη. Αυτό ακριβώς κάνει τη βλάβη δύσκολη να φανεί, και γι' αυτό οι άνθρωποι κυνηγούν το DNS για μία ώρα πριν ελέγξουν μια χρονοσήμανση.

Δύο άλλες επιλογές του module θεωρούνται συχνά λύση. Το daemon_reload κάνει το systemd να ξαναδιαβάσει αρχεία μονάδων, που είναι άσχετο με αρχείο διαμόρφωσης WireGuard. Το state: reloaded ζητά από τη μονάδα να εκτελέσει την ενέργεια επαναφόρτωσης, και αν αυτό κάνει ό,τι χρειάζεσαι εξαρτάται απολύτως από τη μονάδα. Κανένα δεν αντικαθιστά το να ξέρεις ποιες εισόδους διάβασε πραγματικά η διεργασία που τρέχει.

Εγκαταστήστε το αρχείο και μετά ειδοποιήστε έναν handler

Το μοτίβο που κρατά την idempotence και εφαρμόζει αλλαγές είναι το συνηθισμένο: η εργασία που γράφει το αρχείο ειδοποιεί έναν handler, και ο handler τρέχει μόνο όταν το αρχείο άλλαξε πραγματικά. Μια δεύτερη εκτέλεση χωρίς αλλαγές δεν κάνει τίποτα, και αυτό θέλεις.

- 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

Οι handlers τρέχουν στο τέλος του play, μετά τις εργασίες που τους ειδοποίησαν, οπότε μια εργασία αργότερα στο ίδιο play μπορεί να βλέπει ακόμη την παλιά διεπαφή. Αν η σειρά μετρά, άδειασε τους handlers ρητά με meta: flush_handlers πριν από την εργασία που εξαρτάται από τη νέα διαμόρφωση.

Χρησιμοποιήστε restart και όχι reload, εκτός αν έχεις επαληθεύσει την ενέργεια επαναφόρτωσης της μονάδας. Η upstream μονάδα wg-quick υποστηρίζει μία και συγχρονίζει τη διαμόρφωση WireGuard, αλλά δεν ξανατρέχει ρύθμιση διευθύνσεων, διαδρομών, DNS ή hooks. Ένα reload μετά την προσθήκη οδηγίας διαδρομής φαίνεται λοιπόν επιτυχές και δεν αλλάζει τίποτα.

Συγκρίνετε τη ζωντανή συσκευή με το αρχείο

Ο έλεγχος που κλείνει αυτή την κατηγορία σφαλμάτων είναι σύγκριση ανάμεσα σε αυτό που κρατά ο πυρήνας και σε αυτό που λέει το αρχείο. Δύο εντολές δίνουν συγκρίσιμη έξοδο, και η διαφορά είναι η απόκλιση.

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

Το wg showconf εκτυπώνει τη ζωντανή συσκευή, μαζί με το ιδιωτικό κλειδί, οπότε αντιμετώπισε αυτή την έξοδο ως μυστικό και μην την επικολλάς σε ticket. Το wg-quick strip εκτυπώνει το αρχείο χωρίς τα κλειδιά που αφορούν μόνο το wg-quick, και γι' αυτό τα δύο είναι συγκρίσιμα.

Διαφορά στη λίστα peer σημαίνει ότι το αρχείο δεν εφαρμόστηκε ποτέ. Διαφορά μόνο σε κλειδιά ή endpoints που περίμενες να αλλάξουν σημαίνει ότι κάτι το εφάρμοσε μερικώς. Καμία διαφορά σημαίνει ότι η διαμόρφωση είναι τρέχουσα και η βλάβη είναι αλλού, που είναι από μόνο του χρήσιμο αποτέλεσμα.

Πλήρωσε το κόστος της επανεκκίνησης συνειδητά

Η επανεκκίνηση της διεπαφής ρίχνει το tunnel, και αν αυτό μεταφέρει τη διαχειριστική σου συνεδρία, η επανεκκίνηση τερματίζει τη συνεδρία που τη ζήτησε. Βάλε τον handler πίσω από παράθυρο αλλαγών, ή τρέξε το playbook από διαδρομή διαχείρισης που δεν εξαρτάται από την επανεκκίνηση της διεπαφής.

Το κόστος είναι ο λόγος που οι άνθρωποι καταφεύγουν στο reload. Είναι λογικό ένστικτο και γίνεται σωστό όταν ξέρεις ποιες αλλαγές εφαρμόζει πραγματικά. Για αλλαγές peer και κλειδιών στην upstream μονάδα wg-quick αρκεί· για διευθυνσιοδότηση, δρομολόγηση και hooks όχι. Το να το ξεκαθαρίσεις μία φορά είναι φθηνότερο από το να το ανακαλύψεις σε παράθυρο αλλαγών.

Η τεκμηρίωση του module systemd_service εξηγεί τη διαφορά ανάμεσα σε started, restarted και reloaded, και αξίζει ένα διάβασμα αντί να τη μαντέψεις από μια πράσινη σύνοψη. Όλα σε αυτή τη διαδρομή προκύπτουν από αυτή τη μία διάκριση.

Σχετικά άρθρα