ما زالت حاويتك تُجيب عبر جسر التحكم الخاص بها، ومع ذلك تغادر كل حزمة صادرة عبر شبكة macvlan المكتبية. لم يفشل شيء. كل وصول يوفّر بوابة خاصة به، والمسير الافتراضي الوحيد ذهب إلى الشبكة التي لم تقصدها، فيستمر العمل بينما تسلك حزم البيانات مسارًا أطول. وحين يلاحظ أحد ذلك يكون الدليل جدول توجيه لا رسالة خطأ.

التفسير المعتاد أن Docker اختار الشبكة بالخطأ. عمليًا كان القرار القديم يتبع الترتيب الأبجدي لأسماء الشبكات الموصولة، فتحوّل التوجيه إلى نتيجة جانبية لتسمية. يستبدل gw_priority ذلك برقم تختاره عن قصد، وتبنّيه يستغرق نحو دقيقة بعد كتابة التخطيط.

لماذا يستقر المسير الافتراضي على الشبكة الخاطئة

كل شبكة ينضم إليها أي خدمة يمكنها تقديم بوابتها الخاصة، ومع ذلك تنتهي الحاوية بمسير افتراضي واحد فقط. قبل Compose 2.33.1 كان التعادل يُحسم بترتيب أسماء الشبكات، فاسم مثل control يأتي قبل office فيقرر إلى أين يذهب الترافيك. لا شيء داخل الحاوية يسجّل أن القرار كان اعتباطيًا، ولهذا ينجو من مراجعة الشيفرة ويظهر لاحقًا كمسار غريب. ووضع سياسة في ملف compose هو الطريقة الوحيدة لجعل الاختيار قابلًا للفحص.

هناك أمران يغيّران فعليًا أي شبكة تفوز: قيم gw_priority التي تعيّنها، وأي الشبكات موصولة أصلًا. أضف شبكة ثالثة فيكبر مرشحو الاختيار؛ وأزل macvlan فلا يبقى ما ينافس الجسر. لا يظهر أي من التغييرين في سجلات التطبيق، لأن المسير الافتراضي الخاطئ نادرًا ما يقطع الاتصال كليًا. إنه فقط يجعل الردود تأتي من عنوان قد لا يتوقعه الطرف الآخر.

ثبّت البوابة عبر gw_priority

يفصح Compose عن gw_priority في كل وصول من خدمة إلى شبكة بدءًا من الإصدار 2.33.1، والرقم الأعلى يفوز. لا يوجد مفتاح بوابة لكل خدمة، لذا تنتمي القيمة إلى كتلة networks الخاصة بالخدمة. يمنح المثال التالي المسير الافتراضي إلى control مع إبقاء office قابلًا للوصول عبر شبكته المحلية الموصولة مباشرة.

services:
  vpn:
    networks:
      control:
        gw_priority: 1
      office:
        gw_priority: 0

networks:
  control:
    driver: bridge
    ipam:
      config:
        - subnet: 172.30.50.0/24
  office:
    driver: macvlan
    driver_opts:
      parent: eno1.120
      macvlan_mode: bridge
    ipam:
      config:
        - subnet: 192.168.120.0/24
          ip_range: 192.168.120.192/27
          gateway: 192.168.120.1

اقرأ الكتلة كضابطين منفصلين: يحدد gw_priority المسير الافتراضي، وتحدد كتلة ipam العنونة. تغيير الشبكة الفرعية وحدها يترك اختيار المخرج على حاله، وهي الطريقة الأكثر شيوعًا لتطبيق هذا الإصلاح تطبيقًا ناقصًا. أبقِ الأولويات بجانب الشبكة التي تحكمها كي لا يحتاج القارئ التالي إلى التنقيب عن القرار.

لا تخلط بين gw_priority وخاصية priority المجردة التي تجاورها. تلك ترتب إنشاء الاتصالات ولا تقول شيئًا عن التوجيه، لذا لا يمكنها اختيار بوابة افتراضية ولا إصلاح تسمية الواجهات. وإذا أوصى أحد برفع priority لتوجيه الترافيك فالوصية خاطئة حتى لو بدا الترتيب الناتج صحيحًا بالمصادفة.

تحقق من الشبكة التي تحمل المسير الافتراضي فعلًا

افحص داخل الحاوية العاملة، لأن جدول توجيه المضيف يصف المضيف لا نطاق الأسماء الذي تستخدمه الخدمة. شغّل فحص الإعداد أولًا كي يفشل أي خطأ إملائي قبل إعادة التشغيل، ثم اقرأ المسير الذي ثبّته الحاوية فعلًا.

docker compose config --quiet
docker exec vpn ip -4 route show default
docker exec vpn cat /proc/net/route

النتيجة الصحيحة تذكر جهاز الجسر و172.30.50.1؛ والخاطئة تذكر 192.168.120.1 وجهاز macvlan. إذا لم تتضمن الصورة حزمة iproute2 فإن ملف /proc يظل يبلّغ عن المسير الافتراضي، بوجهة 00000000 وبايتات البوابة معكوسة. قارن عمود الواجهة مع docker inspect عندما تكون أسماء الأجهزة غير واضحة.

macvlan منفذ فيزيائي وليس نسخة من الجسر

يمنح macvlan الحاوية هوية ثانية على الشبكة، وهذا بالضبط ما يجعل الوصول إلى الأجهزة المحلية ممكنًا. ويعني أيضًا أن منفذ المحوّل والهايبرفايزور عليهما قبول عنوان MAC إضافي، وكثير من شبكات السحابة يرفض ذلك بهدوء. اختبر حاوية واحدة قبل التخطيط لأسطول، لأن عنوان MAC المرفوض يظهر عادة كوصلة قائمة لا تمرر شيئًا.

إعداد macvlan_mode: bridge هو نمط من أنماط مشغّل macvlan لا جسر Docker البرمجي، وpassthru نمط متخصص منفصل وليس وضعًا افتراضيًا. يمنع Linux أيضًا حاوية macvlan من الوصول إلى مضيفها نفسه عبر نفس الأب، ولهذا السبب يُبقى جسر التحكم بدل توقع أن يقوم وصول واحد بالمهمتين.

سمِّ أب VLAN قبل أن يراه Compose

يتعامل Docker مع أب منقوط مثل eno1.120 كواجهة فرعية 802.1Q وينشئ جهاز VLAN بنفسه. لهذه السهولة حدود: فالاسم المشتق يعتمد على اسم الواجهة الفيزيائية، وقد تدفع الأسماء الطويلة النتيجة إلى ما هو أبعد مما تتوقعه الأدوات المحيطة. إنشاء واجهة VLAN مسمّاة في إعداد شبكة المضيف وتوجيه parent إليها يجعل الطرفين متوقعين.

تذكّر أن المفتاح تحت networks اسم Compose لا جهاز Linux. البحث في المضيف عن واجهة باسم office سيفشل، لأن النواة لا ترى إلا واجهة الأب وزوج veth خلف الحاوية.

أفسح مجالًا لـ VPN فوق ذلك

يتصل عميل VPN بعد وجود هذه الشبكات، فيستطيع إضافة مسارات أكثر تحديدًا وقواعد سياسة ومرشحات بصرف النظر عن gw_priority. خطط بادئات الطرف البعيد مقابل الشبكتين المحليتين، بما في ذلك الردود التي يحتاجها مسار التحكم. وعندما تتداخل بادئة بعيدة مع شبكة office المحلية، أصلح مخطط العنونة بدل تجريد نطاق خاص كامل من النفق.

أعد فحص العناوين والمسارات ومسار الخدمة بعد بدء VPN ومرة أخرى بعد إعادة اتصاله، لأن إعادة الاتصال هي حيث يختفي مسار أُضيف يدويًا. دوّن الجدول المتوقع قبل الاختبار الأول كي يكون المقارنة بعده فرقًا لا تمرينًا على الذاكرة. أبقِ ملكية الشبكة الدائمة في Compose ودع إعداد VPN يملك سياسته وحدها.

مقالات ذات صلة