يعمل ping من العقدة ويفشل من الحاوية، ولا شيء يصل إلى الجهة المحلية. النفق والمسار سليمان؛ عنوان المصدر على السلك ليس كذلك. ما يفرّق بين الحالتين هو ما تدّعيه الحزمة أنها عليه عند مغادرتها العنقود، ولـ GKE رأي في ذلك. الآلية قائمة استثناءات masquerade، وقراءتها تتطلب أمرًا واحدًا.

اقرأ القائمة الفعلية قبل تغيير أي شيء

يوفّر GKE وكيلًا يقرّر، لكل نطاق وجهة، ما إذا كانت حركة الحاويات تُعاد كتابتها إلى عنوان العقدة عند الخروج. تسمّي تهيئته المرفقة كتل RFC1918 الثلاث، 10.0.0.0/8 و 172.16.0.0/12 و 192.168.0.0/16، وجهات مستثناة. لذلك فإن كل ما ترسله من حاوية إلى مضيف 10.x محلي يغادر العقدة وعنوان الحاوية نفسه ما زال ملتصقًا. لا تُعاد كتابة حركة العقدة نفسها، ولهذا بالضبط يعمل ping منها.

اقرأ التهيئة المقصودة والقواعد المثبّتة، لأنهما قد يختلفان. يُظهر kubectl -n kube-system get configmap ip-masq-agent -o yaml ما قيل للوكيل، ويُظهر kubectl -n kube-system get pods -l k8s-app=ip-masq-agent ما إذا كان شيء يعمل لتطبيقه. على العقدة يُظهر iptables-save | grep -i masq القواعد الموجودة فعلًا في النواة. عندما تقول ConfigMap شيئًا وتقول القواعد شيئًا آخر، فالمشتبه به هو الوكيل لا الشبكة.

أكّد عنوان المصدر بالتقاط

التقط قبل أن تغيّر أي قائمة. مرشّح على وجهة واحدة يُبقي المخرجات مقروءة: tcpdump -ni any host 10.20.30.40.

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

ضيّق الاستثناء إلى CIDR الحاويات

الإصلاح المدعوم يضيّق الاستثناء بدلًا من إزالته: أبقِ CIDR الحاويات مستثنى وأسقط بقية فضاء 10.x. تعيش تلك القائمة في ConfigMap الوكيل تحت nonMasqueradeCIDRs، وتغييرها تعديل يتبعه نشر. استبدل الإدخال الواسع بنطاق الحاويات الفعلي للعنقود، وأبقِ الكتل الخاصة الأخرى إن كانت حركة داخل العنقود ما زالت تحتاجها، واترك resyncInterval كما هو إلا إذا كان لديك سبب. طبّقه، وأكّد أن حاويات الوكيل أعيد تشغيلها، وأكّد أن قواعد النواة تغيّرت.

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

في عنقود بجماعات عقد متعددة، تحقّق من أن الوكيل مجدول على العقد التي تعمل عليها الحاويات المتأثرة فعلًا. الجماعة التي لا تحتوي DaemonSet تحتفظ بقواعدها القديمة، ولن يُظهر شيء في ConfigMap ذلك.

البديل وكلفته

الخيار الآخر يبقي عناوين الحاويات سليمة ويعلّم المسار بها. يدخل CIDR الحاويات في محدّدات حركة Cloud VPN، ويحتاج الجانب المحلي إلى مسار عودة له كي تعرف الردود أين تذهب. هذا يحافظ على هوية الحاوية التي تريدها بعض نماذج الأمان، ويوسّع نطاق التوجيه ونطاق جدار الحماية اللذين يجب أن تقبلهما الجهة الأخرى.

المقايضة هي الوضوح مقابل النطاق. الترجمة تجعل الجانب المحلي يرى عنوانًا واحدًا لكل عقدة، وهو ما يسهل إضافته إلى قائمة السماح ويخفي أي حاوية أرسلت ماذا. عدم الترجمة يحفظ عنوان الحاوية من طرف إلى طرف، وهو أفضل للإسناد وأسوأ لكل جهاز في المسار عليه أن يتعلم نطاقًا جديدًا. لا أحد الخيارين عيب في Docker أو CNI؛ كلاهما قرار توجيه له فاتورة تشغيلية. اختر ما تستطيع فريقك دفع فاتورته، واكتب السبب.

تحقّق وارجع

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

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

الرجوع هو ConfigMap السابق، مطبَّقًا بالطريقة نفسها، مع التأكيد نفسه بأن الوكيل أعيد تشغيله وبأن القواعد تغيّرت. احفظ عنوان المصدر قبل وبعد لطلب واحد معروف في سجل التغيير، لأن ذلك السطر الواحد هو ما يثبت أن التغيير فعل ما قلته. توثّق دليل GKE لوكيل IP masquerade القيم الافتراضية وحقول ConfigMap. إذا لم يتغيّر عنوان المصدر بعد النشر، فالوكيل لا يعمل على تلك العقدة، ولن يصلح أي تعديل YAML ذلك.

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