מארח אחד, שתי עומסי עבודה ודרישה שמפרידה ביניהם: לקוח הורדה שחייב לצאת דרך VPN מסחרי, וממשק ניהול שחייב להמשיך להשתמש בחיבור של המארח. התקנת לקוח ה-VPN על המארח מפרה את הדרישה מיד, כי אז שני העומסים חולקים יציאה אחת. הדפוס שבאמת עובד הוא להעביר את המנהרה לקונטיינר משלה ולתת רק לעומסים שזקוקים לה להצטרף למרחב השמות של הרשת של אותו קונטיינר. כל השאר שומר על המסלול הרגיל של Docker, והפרטים שבהמשך הם תוצאות של מי שמחזיק במרחב השמות.

למה מרחב שמות משותף משנה את הכללים

קונטיינר שמצטרף למרחב השמות של אחר לא מקבל מחסנית רשת משלו. הוא רואה את אותם ממשקים, את אותה טבלת ניתוב ואת אותו loopback כמו הקונטיינר שאליו הצטרף, ובדיוק בגלל זה הדפוס שימושי: העומס מפענח ומתחבר כרגיל, והמנהרה שמתחת לוכדת את התעבורה בלי שהאפליקציה יודעת. המחיר הוא שלכל הגדרת רשת יש כעת בעלים אחד, והקונטיינר שמצטרף אינו הוא.

כלל הבעלות הזה עונה על רוב שאלות התצורה לפני שהן נשאלות. אם הגדרה חיה במחסנית הרשת, היא שייכת לקונטיינר הצדדי. אם היא מתארת את התהליך, היא נשארת עם העומס.

loopback הוא החלק שמפתיע אנשים. בתוך הקונטיינר שמצטרף, localhost מפוענח ל-loopback של הקונטיינר הצדדי, ולא לכזה פרטי משלו, כך ששירות שנקשר ל-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

השורה הרביעית היא זו שאנשים מאבחנים בטעות כבאג באפליקציה. בדיקה שנכתבה נגד ה-loopback של העומס עצמו בודקת כעת את קונטיינר המנהרה, ולכן היא או נכשלת או מדווחת על שירות שגוי לחלוטין.

כששם מארח אחד זקוק למנהרה

לפעמים מנהרה מלאה היא יותר מדי: שם פנימי אחד חייב לעבור דרך VPN ארגוני בזמן ששקע מקומי או חיבור תצוגה ממשיך לעבוד. מנהרה מלאה בתוך הקונטיינר שוברת את המסלול הזה ואת כל מה שממוען למארח, לכן נתבו רק את הקידומת שזקוקה לכך. עטיפת ניתוב מפוצל סביב הלקוח עושה זאת, שולחת את שם המארח הנקוב דרך המנהרה ומשאירה את המסלול הקודם ללא שינוי לכל השאר.

בחרו בזה כשאתם צריכים להגיע רק לשירות אחד ואינכם מנסים להעביר את כל התעבורה של הקונטיינר. זה כלי אחר מהקונטיינר הצדדי והוא עונה על שאלה אחרת.

אמתו, ואז עשו שזה ישרוד הפעלה מחדש

שאלו כל קונטיינר מאיזו כתובת נראה שהוא מגיע. זה שבמנהרה אמור להדפיס את כתובת הספק וזה הישיר את היציאה של המארח. תשובות זהות פירושן שהשירות הישיר ירש את מרחב השמות הלא נכון או ש-VPN ברמת המארח עדיין לוכד הכול, ושתי התיקונים האלה שונים. הריצו את הבדיקה שוב אחרי כל עריכת compose, כי בלוק שירות אחד שהועתק מספיק כדי להחזיר את הבעיה.

שלושה דברים נוטים להישבר מאוחר יותר. DNS הולך אחרי בעל מרחב השמות, לכן הגדרות הפותר ואזור החיפוש שייכות לקונטיינר הצדדי ולא למארח. VPN עם העברת פורטים מחליף את פורט האזנה שלו בהתחברות מחדש, לכן הפורט המועבר של הספק ופורט האזנה בצד הקונטיינר חייבים להיכתב חזרה בתצורת הלקוח או במיפוי הפורטים, בדרך כלל על ידי מעדכן קטן שקורא את ה-API של הספק. וכל בדיקה שנכתבה נגד localhost שואלת כעת את קונטיינר המנהרה ולא את העומס.

כתבו את הדפוס, כולל איזה קונטיינר מחזיק במרחב השמות ואילו פורטים שייכים לו. האדם הבא יוסיף שירות, יעתיק את הבלוק הלא נכון וישחזר את הכשל הראשון במאמר הזה.

מאמרים קשורים