โฮสต์เดียว ปริมาณงานสองตัว และข้อกำหนดที่แยกทั้งสองออกจากกัน: ไคลเอนต์ดาวน์โหลดที่ต้องออกผ่าน 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 ทั่วทั้งโฮสต์อีกครั้ง

เมทริกซ์ความล้มเหลวสำหรับชั่วโมงแรก

ความพยายามครั้งแรกส่วนใหญ่ล้มเหลวในหนึ่งในสี่วิธี และแต่ละวิธีมีสาเหตุต่างกัน ตรวจสอบตามลำดับนี้ เพราะสองข้อแรกอธิบายรายงานเกือบทั้งหมด

SymptomLikely cause
Web UI unreachable after the changePort mapping declared on the joining container instead of the sidecar
Both containers show the provider's exit addressThe direct service was attached to the sidecar network
Internal names stop resolvingResolver settings live on the host, not in the shared namespace
Health check fails but the app worksThe check probes localhost, which now means the sidecar

แถวที่สี่คือสิ่งที่ผู้คนวินิจฉัยผิดว่าเป็นบั๊กของแอปพลิเคชัน การตรวจที่เขียนขึ้นกับลูปแบ็กของปริมาณงานเองตอนนี้กำลังทดสอบคอนเทนเนอร์อุโมงค์ ดังนั้นมันจึงล้มเหลวหรือรายงานบริการที่ผิดทั้งหมด

เมื่อชื่อโฮสต์เดียวต้องการอุโมงค์

บางครั้งอุโมงค์เต็มรูปแบบก็มากเกินไป: ชื่อภายในหนึ่งชื่อต้องผ่าน VPN องค์กรในขณะที่ซ็อกเก็ตภายในหรือการเชื่อมต่อจอยังทำงานอยู่ อุโมงค์เต็มรูปแบบในคอนเทนเนอร์ทำลายเส้นทางนั้นและทุกสิ่งที่ส่งถึงโฮสต์ ดังนั้นกำหนดเส้นทางเฉพาะคำนำหน้าที่ต้องการเท่านั้น ตัวห่อการกำหนดเส้นทางแบบแบ่งรอบไคลเอนต์ทำสิ่งนี้ ส่งชื่อโฮสต์ที่ระบุผ่านอุโมงค์และปล่อยเส้นทางเดิมไว้ไม่แตะต้องสำหรับทุกอย่างอื่น

เลือกสิ่งนี้เมื่อคุณต้องการเข้าถึงบริการเดียวและไม่ได้พยายามย้ายทราฟฟิกทั้งหมดของคอนเทนเนอร์ มันเป็นเครื่องมือที่แตกต่างจากคอนเทนเนอร์ข้างเคียงและตอบคำถามที่แตกต่าง

ตรวจสอบ แล้วทำให้ทนต่อการรีสตาร์ท

ถามคอนเทนเนอร์แต่ละตัวว่าดูเหมือนมาจากที่อยู่ใด ตัวที่อยู่ในอุโมงค์ควรพิมพ์ที่อยู่ของผู้ให้บริการ และตัวที่ต่อตรงควรพิมพ์ทางออกของโฮสต์ คำตอบที่เหมือนกันหมายความว่าบริการที่ต่อตรงสืบทอดเนมสเปซผิด หรือ VPN ระดับโฮสต์ยังคงดักจับทุกอย่าง และการแก้ไขทั้งสองแบบนั้นต่างกัน รันการตรวจสอบอีกครั้งหลังการแก้ไขคอมโพสทุกครั้ง เพราะบล็อกบริการที่คัดลอกมาเพียงบล็อกเดียวก็เพียงพอที่จะทำให้ปัญหาเกิดขึ้นอีก

สามสิ่งมักพังในภายหลัง DNS เป็นไปตามเจ้าของเนมสเปซ ดังนั้นการตั้งค่าตัวแปลงชื่อและโดเมนค้นหาจึงเป็นของคอนเทนเนอร์ข้างเคียง ไม่ใช่ของโฮสต์ VPN ที่มีการส่งต่อพอร์ตจะเปลี่ยนพอร์ตที่รับฟังเมื่อเชื่อมต่อใหม่ ดังนั้นพอร์ตที่ผู้ให้บริการส่งต่อและพอร์ตที่รับฟังฝั่งคอนเทนเนอร์ต้องเขียนกลับลงในการกำหนดค่าไคลเอนต์หรือการแมปพอร์ต โดยปกติผ่านตัวอัปเดตเล็ก ๆ ที่อ่าน API ของผู้ให้บริการ และการตรวจใด ๆ ที่เขียนขึ้นกับ localhost ตอนนี้กำลังถามคอนเทนเนอร์อุโมงค์ไม่ใช่ปริมาณงาน

เขียนรูปแบบลงไป รวมถึงคอนเทนเนอร์ใดเป็นเจ้าของเนมสเปซและพอร์ตใดเป็นของมัน คนถัดไปจะเพิ่มบริการ คัดลอกบล็อกผิด และทำให้ความล้มเหลวแรกในบทความนี้เกิดขึ้นซ้ำ

บทความที่เกี่ยวข้อง