Ansible บอกว่าเริ่มแล้ว แต่ WireGuard ยังใช้การตั้งค่าเดิมอยู่
state: started ปล่อย unit ที่ทำงานอยู่แล้วไว้ตามเดิม ดังนั้น wg0.conf ที่เขียนใหม่จึงไม่ถูกนำไปใช้เลย เพิ่ม handler สำหรับการเปลี่ยนแปลง แล้วเปรียบเทียบอุปกรณ์ที่ทำงานอยู่กับไฟล์
การรัน playbook จบลงด้วยสีเขียว unit ของ WireGuard ทำงานอยู่ handshake ทำงาน และ peer ใหม่ก็ยังเข้าถึงอะไรไม่ได้ การเห็น playbook รายงานความสำเร็จขณะที่เซิร์ฟเวอร์ใช้การตั้งค่าของเมื่อวานนั้นน่าหงุดหงิดเป็นพิเศษ เพราะไม่มีอะไรผิดในผลลัพธ์ Ansible ทำตามที่ขอทุกประการ คือตรวจสอบให้แน่ใจว่า unit เริ่มทำงานแล้ว และ unit ก็เริ่มทำงานอยู่แล้ว การนำไฟล์การตั้งค่าที่เขียนใหม่ไปใช้นั้นเป็นงานอีกอย่างหนึ่ง และจะเกิดขึ้นก็ต่อเมื่อมีสิ่งใดสั่งให้บริการอ่านไฟล์นั้นใหม่
ดูว่าการรันครั้งที่สองรายงานอะไรจริง ๆ
รัน playbook สองครั้งโดยคงการตั้งค่าที่เปลี่ยนแปลงไว้ แล้วเปรียบเทียบสรุป การรันครั้งที่สองควรแสดงงานของ unit เป็น ok ไม่ใช่ changed เพราะบริการที่ทำงานอยู่แล้วจะถูกปล่อยไว้ตามการออกแบบ นี่คือ idempotence ที่ทำงานถูกต้อง และเป็นเหตุผลที่ไฟล์ใหม่ไม่เคยไปถึง kernel
เพิ่มการรันตรวจสอบพร้อมผลลัพธ์ 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เวลาทั้งสามค่าบอกเรื่องราวก่อนที่คุณจะอ่านบันทึกแม้แต่บรรทัดเดียว ถ้าไฟล์การตั้งค่าใหม่กว่าช่วงเวลาที่ unit เริ่มทำงาน อินเทอร์เฟซที่ทำงานอยู่ก็สร้างจากไฟล์เก่ากว่า และอาการทั้งหมดที่ตามมาจึงเกิดจากตรงนั้น
นี่ไม่ใช่ข้อบกพร่องของ Ansible พฤติกรรมเดียวกันนี้ปรากฏในเครื่องมือจัดการการตั้งค่าใดก็ตามที่แยก «ตรวจสอบให้แน่ใจว่ามันทำงาน» ออกจาก «ตรวจสอบให้แน่ใจว่ามันทำงานสิ่งนี้» ความแตกต่างดูเหมือนจุกจิกจนกว่าจะทำให้คุณเสียเวลาครึ่งวัน
เริ่มทำงานเป็นสถานะ ไม่ใช่การโหลดใหม่
state: started ยืนยันเงื่อนไขเกี่ยวกับ unit มันไม่ได้สัญญาว่าบริการจะอ่านอินพุตใหม่ และไม่สามารถรู้ได้ว่าไฟล์ที่มันไม่เคยเปิดนั้นเปลี่ยนไปแล้ว ในการติดตั้งด้วย wg-quick อินพุตได้แก่ การตั้งค่าอินเทอร์เฟซ ที่อยู่ เส้นทาง รายการ DNS และ hook แบบ post-up ใด ๆ
ดังนั้นไฟล์ที่อัปเดตแล้วอาจมี peer ใหม่ ที่อยู่ต่างออกไป หรือคำสั่งเส้นทางที่เปลี่ยนไป ขณะที่อินเทอร์เฟซที่ทำงานอยู่ยังให้บริการชุดเดิม handshake ยังสำเร็จเพราะคีย์และปลายทางที่โหลดไว้ยังใช้ได้ นั่นคือสิ่งที่ทำให้ความล้มเหลวยากต่อการมองเห็น และเป็นเหตุผลที่ผู้คนไล่ตาม DNS เป็นชั่วโมงก่อนตรวจสอบเวลา
ตัวเลือกอื่นอีกสองอย่างของโมดูลมักถูกเข้าใจผิดว่าเป็นทางแก้ daemon_reload ทำให้ systemd อ่านไฟล์ unit ใหม่ ซึ่งไม่เกี่ยวข้องกับไฟล์การตั้งค่า WireGuard state: reloaded ขอให้ unit ทำงานโหลดใหม่ของมัน และการที่มันทำสิ่งที่คุณต้องการหรือไม่นั้นขึ้นอยู่กับ unit ทั้งหมด ไม่มีอันใดทดแทน การรู้ว่ากระบวนการที่ทำงานอยู่อ่านอินพุตใดจริง ๆ
ติดตั้งไฟล์ แล้วแจ้ง 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: restartedhandler ทำงานตอนท้ายของ play หลังจากงานที่แจ้งมัน ดังนั้นงานที่อยู่ถัดไปใน play เดียวกันอาจยังเห็นอินเทอร์เฟซเก่า หากลำดับสำคัญ ให้ล้าง handler อย่างชัดเจนด้วย meta: flush_handlers ก่อนงานที่ขึ้นกับการตั้งค่าใหม่
ใช้ restart แทน reload เว้นแต่คุณจะตรวจสอบการทำงานโหลดใหม่ของ unit แล้ว unit ของ wg-quick จาก upstream รองรับและซิงโครไนซ์การตั้งค่า WireGuard แต่ไม่รันการตั้งค่าที่อยู่ เส้นทาง DNS หรือ hook ซ้ำ ดังนั้น reload หลังเพิ่มคำสั่งเส้นทางจึงดูเหมือนสำเร็จและไม่เปลี่ยนอะไร
เปรียบเทียบอุปกรณ์ที่ทำงานอยู่กับไฟล์
การตรวจสอบที่ปิดช่องบกพร่องประเภทนี้คือการเปรียบเทียบสิ่งที่ kernel ถืออยู่กับสิ่งที่ไฟล์บอก สองคำสั่งให้ผลลัพธ์ที่เทียบกันได้ และความต่างคือการเบี่ยงเบน
sudo wg showconf wg0
sudo wg-quick strip wg0
sudo diff <(sudo wg showconf wg0) <(sudo wg-quick strip wg0)wg showconf พิมพ์อุปกรณ์ที่ทำงานอยู่รวมถึงคีย์ส่วนตัว ดังนั้นให้ถือว่าผลลัพธ์นั้นเป็นความลับและอย่าวางในตั๋ว wg-quick strip พิมพ์ไฟล์โดยนำคีย์เฉพาะของ wg-quick ออก ซึ่งเป็นเหตุให้ทั้งสองเปรียบเทียบกันได้
ความต่างในรายการ peer หมายความว่าไฟล์ไม่เคยถูกนำไปใช้ ความต่างเฉพาะคีย์หรือปลายทางที่คุณคาดว่าจะเปลี่ยนหมายความว่ามีบางอย่างนำไปใช้บางส่วน ไม่มีความต่างเลยหมายความว่าการตั้งค่าเป็นปัจจุบันและความผิดพลาดอยู่ที่อื่น ซึ่งเป็นผลลัพธ์ที่มีประโยชน์ในตัว
จ่ายค่าของการรีสตาร์ตอย่างตั้งใจ
การรีสตาร์ตอินเทอร์เฟซทำให้อุโมงค์ขาด และหากอุโมงค์นั้นพาเซสชันผู้ดูแลของคุณอยู่ การรีสตาร์ตจะจบเซสชันที่ขอไว้ วาง handler ไว้หลังหน้าต่างการเปลี่ยนแปลง หรือรัน playbook จากเส้นทางการจัดการที่ไม่ขึ้นกับการรีสตาร์ตอินเทอร์เฟซ
ค่าใช้จ่ายคือเหตุผลที่ผู้คนหันไปใช้ reload เป็นสัญชาตญาณที่สมเหตุสมผล และจะถูกต้องเมื่อคุณรู้ว่า reload นำการเปลี่ยนแปลงใดไปใช้จริง สำหรับการเปลี่ยน peer และคีย์บน unit ของ wg-quick จาก upstream นั้นเพียงพอ สำหรับการกำหนดที่อยู่ การกำหนดเส้นทาง และ hook นั้นไม่พอ การทำให้กระจ่างสักครั้งถูกกว่าการค้นพบระหว่างหน้าต่างการเปลี่ยนแปลง
เอกสารของโมดูล systemd_service อธิบายความแตกต่างระหว่าง started, restarted และ reloaded และควรอ่านสักครั้งแทนการเดาจากสรุปสีเขียว ทุกอย่างในคู่มือนี้มาจากความแตกต่างเพียงข้อเดียวนั้น