یک میزبان، دو بار کاری و شرطی که آن‌ها را جدا می‌کند: یک کلاینت دانلود که باید از یک VPN تجاری بیرون بیاید و یک رابط مدیریت که باید از اتصال میزبان استفاده کند. نصب کلاینت VPN روی میزبان شرط را فوراً نقض می‌کند، زیرا آن‌گاه هر دو بار کاری یک خروجی را به اشتراک می‌گذارند. الگویی که واقعاً کار می‌کند این است که تونل را به کانتینر خودش منتقل کنید و فقط به بارهای کاری که به آن نیاز دارند اجازه دهید به فضای نام شبکهٔ آن کانتینر بپیوندند. هر چیز دیگری مسیر معمول Docker را نگه می‌دارد و جزئیاتی که در ادامه می‌آید پیامد این است که مالک فضای نام چه کسی است.

چرا یک فضای نام مشترک قواعد را تغییر می‌دهد

کانتینری که به فضای نام دیگری می‌پیوندد پشتهٔ شبکهٔ خودش را نمی‌گیرد. همان رابط‌ها، همان جدول مسیریابی و همان loopback را می‌بیند که کانتینری که به آن پیوسته است، و دقیقاً به همین دلیل الگو سودمند است: بار کاری به‌طور عادی نام را تجزیه می‌کند و متصل می‌شود و تونل زیر آن ترافیک را بدون اینکه برنامه بداند ضبط می‌کند. هزینه این است که هر تنظیم شبکه‌ای اکنون یک مالک دارد و کانتینری که می‌پیوندد آن مالک نیست.

این قاعدهٔ مالکیت به بیشتر پرسش‌های پیکربندی پیش از آنکه پرسیده شوند پاسخ می‌دهد. اگر تنظیمی در پشتهٔ شبکه زندگی می‌کند، متعلق به کانتینر کناری است. اگر فرایند را توصیف می‌کند، با بار کاری می‌ماند.

loopback همان بخشی است که مردم را شگفت‌زده می‌کند. درون کانتینری که می‌پیوندد، localhost به loopback کانتینر کناری تجزیه می‌شود، نه به یک 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 نوشته شده باشد اکنون از کانتینر تونل می‌پرسد نه از بار کاری.

الگو را بنویسید، از جمله اینکه کدام کانتینر مالک فضای نام است و کدام پورت‌ها به آن تعلق دارند. نفر بعدی یک سرویس اضافه می‌کند، بلوک اشتباه را کپی می‌کند و نخستین خرابی این مقاله را بازتولید می‌کند.

مقالات مرتبط