Docker: กำหนดเส้นทางคอนเทนเนอร์หนึ่งตัวผ่าน VPN และปล่อยอีกตัวให้ต่อตรง
ให้อุโมงค์มีคอนเทนเนอร์ของตัวเอง อนุญาตเฉพาะบริการที่ต้องการใช้เนมสเปซนั้นร่วมกัน แล้วคำนึงถึงสิ่งที่ตามเจ้าของมา: พอร์ต localhost และ DNS
โฮสต์เดียว ปริมาณงานสองตัว และข้อกำหนดที่แยกทั้งสองออกจากกัน: ไคลเอนต์ดาวน์โหลดที่ต้องออกผ่าน VPN เชิงพาณิชย์ และอินเทอร์เฟซการจัดการที่ต้องใช้การเชื่อมต่อของโฮสต์ต่อไป การติดตั้งไคลเอนต์ VPN บนโฮสต์ทำให้ข้อกำหนดล้มเหลวทันที เพราะปริมาณงานทั้งสองจะใช้ทางออกร่วมกันเพียงทางเดียว รูปแบบที่ได้ผลจริงคือย้ายอุโมงค์เข้าไปในคอนเทนเนอร์ของตัวเอง และอนุญาตเฉพาะปริมาณงานที่ต้องการให้ เข้าร่วมเนมสเปซเครือข่ายของคอนเทนเนอร์นั้น ส่วนอื่นทั้งหมดยังคงใช้เส้นทาง Docker ตามปกติ และรายละเอียดที่ตามมาคือผลสืบเนื่องของว่าใครเป็นเจ้าของเนมสเปซ
ทำไมเนมสเปซที่ใช้ร่วมกันจึงเปลี่ยนกฎ
คอนเทนเนอร์ที่เข้าร่วมเนมสเปซของอีกตัวจะไม่ได้สแตกเครือข่ายของตัวเอง มันเห็นอินเทอร์เฟซเดียวกัน ตารางเส้นทางเดียวกัน และลูปแบ็กเดียวกับคอนเทนเนอร์ที่เข้าร่วม และนั่นคือเหตุผลที่รูปแบบนี้มีประโยชน์: ปริมาณงานแปลงชื่อและเชื่อมต่อได้ตามปกติ และอุโมงค์ที่อยู่ข้างใต้ก็ดักจับทราฟฟิกโดยที่แอปพลิเคชันไม่รู้ ต้นทุนคือทุกการตั้งค่าเกี่ยวกับเครือข่ายมีเจ้าของเพียงรายเดียว และคอนเทนเนอร์ที่เข้าร่วมไม่ใช่เจ้าของนั้น
กฎความเป็นเจ้าของนี้ตอบคำถามเรื่องการกำหนดค่าเกือบทั้งหมดก่อนที่จะถูกถาม หากการตั้งค่าอยู่ในสแตกเครือข่าย มันเป็นของคอนเทนเนอร์ข้างเคียง หากมันอธิบายกระบวนการ มันก็อยู่กับปริมาณงาน
ลูปแบ็กคือส่วนที่ทำให้คนประหลาดใจ ภายในคอนเทนเนอร์ที่เข้าร่วม localhost จะถูกแปลงไปยังลูปแบ็กของคอนเทนเนอร์ข้างเคียง ไม่ใช่ของส่วนตัวของตัวเอง ดังนั้นบริการที่ผูกกับ 127.0.0.1 โดยคาดหวังการแยกตัวออกจากกันจึงใช้ที่อยู่เดียวกันกับคอนเทนเนอร์อุโมงค์แล้ว
เผยแพร่พอร์ตบนคอนเทนเนอร์ที่เป็นเจ้าของเนมสเปซ
การแมปพอร์ตเป็นของเจ้าของเนมสเปซ แม้กระบวนการที่รับฟังจะทำงานในอีกคอนเทนเนอร์หนึ่งก็ตาม ประกาศการแมปบนคอนเทนเนอร์ข้างเคียง และปล่อยให้ปริมาณงานคงการกำหนดค่ากระบวนการของตัวเองไว้โดยไม่ถูกแตะต้อง การแมปบนบริการที่เข้าร่วมไม่มีผลบังคับใช้ ไม่ว่าเอนจินจะปฏิเสธหรือเพิกเฉยอย่างเงียบ ๆ ขึ้นอยู่กับว่าคอนเทนเนอร์เริ่มทำงานอย่างไร และนั่นคือเหตุผลที่อินเทอร์เฟซซึ่งเข้าถึงได้เมื่อครู่หายไปทันทีที่นำรูปแบบไปใช้
services:
gluetun:
image: qmcgaw/gluetun
cap_add: [NET_ADMIN]
ports: ["8080:8080"]
client-vpn:
image: example/client
network_mode: "service:gluetun"
client-direct:
image: example/client
ports: ["8081:8080"]อ่านบล็อกนี้เป็นสามการตัดสินใจไม่ใช่สามบริการ คอนเทนเนอร์ข้างเคียงเป็นเจ้าของอุโมงค์และพอร์ตที่เผยแพร่ ไคลเอนต์ที่เข้าร่วมไม่ประกาศเครือข่ายใดเลย ไคลเอนต์ที่ต่อตรงยังคงการแมปของตัวเองบนเครือข่ายเริ่มต้น ความสามารถ NET_ADMIN คือสิ่งที่ทำให้คอนเทนเนอร์ข้างเคียงสร้างอินเทอร์เฟซและเปลี่ยนเส้นทางได้ และนั่นคือเหตุผลที่คอนเทนเนอร์นี้ต้องการสิทธิ์มากกว่าปริมาณงานที่มันให้บริการ
บริการที่ยังคงต่อตรงจะคงเครือข่ายของตัวเองไว้
ปริมาณงานที่ไม่ควรผ่านอุโมงค์จะคงบริดจ์เริ่มต้นหรือเครือข่ายที่ผู้ใช้กำหนดเอง พร้อมพอร์ตที่เผยแพร่และทางออกของตัวเอง การเชื่อมมันเข้ากับเครือข่ายของคอนเทนเนอร์ข้างเคียงเพื่อให้สองคอนเทนเนอร์คุยกันด้วยชื่อนั้นชวนทำ แต่ขั้นตอนเดียวนั้นก็ย้ายทราฟฟิกของมันเข้าไปในอุโมงค์อย่างเงียบ ๆ หากทั้งสองต้องเข้าถึงกัน ให้สร้างเครือข่ายที่ผู้ใช้กำหนดแยกต่างหาก เชื่อมทั้งสองเข้ากับมัน และปล่อยให้คอนเทนเนอร์ข้างเคียงเป็นทางออกเดียว
แยกคำถามสองข้อออกจากกัน: คอนเทนเนอร์ใดเข้าถึงกันได้ และตัวใดออกไปที่ใด การรวมทั้งสองเข้าด้วยกันคือวิธีที่พบบ่อยที่สุดที่การออกแบบนี้กลายเป็น VPN ทั่วทั้งโฮสต์อีกครั้ง
เมทริกซ์ความล้มเหลวสำหรับชั่วโมงแรก
ความพยายามครั้งแรกส่วนใหญ่ล้มเหลวในหนึ่งในสี่วิธี และแต่ละวิธีมีสาเหตุต่างกัน ตรวจสอบตามลำดับนี้ เพราะสองข้อแรกอธิบายรายงานเกือบทั้งหมด
| Symptom | Likely cause |
|---|---|
| Web UI unreachable after the change | Port mapping declared on the joining container instead of the sidecar |
| Both containers show the provider's exit address | The direct service was attached to the sidecar network |
| Internal names stop resolving | Resolver settings live on the host, not in the shared namespace |
| Health check fails but the app works | The check probes localhost, which now means the sidecar |
แถวที่สี่คือสิ่งที่ผู้คนวินิจฉัยผิดว่าเป็นบั๊กของแอปพลิเคชัน การตรวจที่เขียนขึ้นกับลูปแบ็กของปริมาณงานเองตอนนี้กำลังทดสอบคอนเทนเนอร์อุโมงค์ ดังนั้นมันจึงล้มเหลวหรือรายงานบริการที่ผิดทั้งหมด
เมื่อชื่อโฮสต์เดียวต้องการอุโมงค์
บางครั้งอุโมงค์เต็มรูปแบบก็มากเกินไป: ชื่อภายในหนึ่งชื่อต้องผ่าน VPN องค์กรในขณะที่ซ็อกเก็ตภายในหรือการเชื่อมต่อจอยังทำงานอยู่ อุโมงค์เต็มรูปแบบในคอนเทนเนอร์ทำลายเส้นทางนั้นและทุกสิ่งที่ส่งถึงโฮสต์ ดังนั้นกำหนดเส้นทางเฉพาะคำนำหน้าที่ต้องการเท่านั้น ตัวห่อการกำหนดเส้นทางแบบแบ่งรอบไคลเอนต์ทำสิ่งนี้ ส่งชื่อโฮสต์ที่ระบุผ่านอุโมงค์และปล่อยเส้นทางเดิมไว้ไม่แตะต้องสำหรับทุกอย่างอื่น
เลือกสิ่งนี้เมื่อคุณต้องการเข้าถึงบริการเดียวและไม่ได้พยายามย้ายทราฟฟิกทั้งหมดของคอนเทนเนอร์ มันเป็นเครื่องมือที่แตกต่างจากคอนเทนเนอร์ข้างเคียงและตอบคำถามที่แตกต่าง
ตรวจสอบ แล้วทำให้ทนต่อการรีสตาร์ท
ถามคอนเทนเนอร์แต่ละตัวว่าดูเหมือนมาจากที่อยู่ใด ตัวที่อยู่ในอุโมงค์ควรพิมพ์ที่อยู่ของผู้ให้บริการ และตัวที่ต่อตรงควรพิมพ์ทางออกของโฮสต์ คำตอบที่เหมือนกันหมายความว่าบริการที่ต่อตรงสืบทอดเนมสเปซผิด หรือ VPN ระดับโฮสต์ยังคงดักจับทุกอย่าง และการแก้ไขทั้งสองแบบนั้นต่างกัน รันการตรวจสอบอีกครั้งหลังการแก้ไขคอมโพสทุกครั้ง เพราะบล็อกบริการที่คัดลอกมาเพียงบล็อกเดียวก็เพียงพอที่จะทำให้ปัญหาเกิดขึ้นอีก
สามสิ่งมักพังในภายหลัง DNS เป็นไปตามเจ้าของเนมสเปซ ดังนั้นการตั้งค่าตัวแปลงชื่อและโดเมนค้นหาจึงเป็นของคอนเทนเนอร์ข้างเคียง ไม่ใช่ของโฮสต์ VPN ที่มีการส่งต่อพอร์ตจะเปลี่ยนพอร์ตที่รับฟังเมื่อเชื่อมต่อใหม่ ดังนั้นพอร์ตที่ผู้ให้บริการส่งต่อและพอร์ตที่รับฟังฝั่งคอนเทนเนอร์ต้องเขียนกลับลงในการกำหนดค่าไคลเอนต์หรือการแมปพอร์ต โดยปกติผ่านตัวอัปเดตเล็ก ๆ ที่อ่าน API ของผู้ให้บริการ และการตรวจใด ๆ ที่เขียนขึ้นกับ localhost ตอนนี้กำลังถามคอนเทนเนอร์อุโมงค์ไม่ใช่ปริมาณงาน
เขียนรูปแบบลงไป รวมถึงคอนเทนเนอร์ใดเป็นเจ้าของเนมสเปซและพอร์ตใดเป็นของมัน คนถัดไปจะเพิ่มบริการ คัดลอกบล็อกผิด และทำให้ความล้มเหลวแรกในบทความนี้เกิดขึ้นซ้ำ