دليل الحالة واستكشاف الأخطاء في Envoy Gateway: ماذا تعني Accepted و ResolvedRefs و Programmed فعلًا
أكثر سيناريو هندسي مرعب ليس ظهور رسالة خطأ، بل هذا:
لقد طبّقت الـ YAML، ونجح kubectl apply، لكن المرور ما زال لا يمر.
إذا اكتفيت عند هذه النقطة بالتحديق في spec، فستبدأ بالشعور وكأنك تقرأ أوراق الشاي.
أما معلومات التشخيص الحقيقية في Gateway API فتعيش داخل status.
هدف هذه المقالة واحد: أن تمنحك أقصر مسار ممكن لـ debugging. فعندما لا يأخذ Gateway أو HTTPRoute أو Listener مفعوله، ستعرف أين تنظر أولًا بدلًا من أن تبدأ مباشرة بالتساؤل إن كان الكون نفسه منطقيًا.
ابدأ من هنا: شخّص بقراءة status، لا بتغيير spec
أكثر الأوامر فائدة:
kubectl get gateway -A
kubectl get httproute -A
kubectl get grpcroute -A
kubectl describe gateway <name>
kubectl describe httproute <name>
kubectl get gateway <name> -o yaml
kubectl get httproute <name> -o yamlالفكرة ليست أن تعيد قراءة الـ YAML مئة مرة إضافية، بل أن تتحقق هل قبل الـ controller إعداداتك فعلًا.
فكّر في status على أنه ورقة علامات امتحان:
specهو الإجابة التي سلّمتهاstatusهو النتيجة التي قيّمها النظام
أن تنظر فقط إلى ما سلّمته، ولا تتحقق أبدًا من النتيجة، فهذا مجرد راحة نفسية وليس debugging.
أهم ثلاث Conditions: إذا فهمتها فقد غطيت الأساس
Accepted
يشير هذا عادةً إلى ما إذا كان المورد قد تم قبوله من parent الخاص به. وبالنسبة إلى route، فهذا يعني غالبًا:
- هل ارتبط بنجاح بالـ Gateway/listener المقصود
- وهل تحتوي القواعد على تعارضات أو إعدادات غير صالحة بشكل واضح
إذا كانت Accepted تساوي False، فابدأ بالاشتباه في:
- أن
parentRefsيشير إلى Gateway أو listener خاطئ - أن شروط الـ hostname/الـ listener لا تتطابق
- أن الـ listener يرفض هذا النوع من الـ route
- أن
allowedRoutesيمنعك
ResolvedRefs
تشير هذه إلى ما إذا كانت الكائنات المشار إليها داخل المورد قد تم resolved لها بنجاح. مثلًا:
- هل الـ
Serviceالمشار إليه داخلbackendRefsموجود؟ - هل يمكن الإشارة قانونيًا إلى الـ
Secretالموجود داخلcertificateRefs؟ - هل تم إعداد
ReferenceGrantبشكل صحيح للإشارات عبر namespaces؟
هذه الحالة مفيدة جدًا. فكثير من حالات فشل الإعدادات لا تكون بسبب خطأ في منطق التوجيه، بل لأن الأشياء المشار إليها غير موجودة أصلًا، أو لأنك لا تملك صلاحية الوصول إليها.
Programmed
تشير هذه عادةً إلى ما إذا كانت الإعدادات قد طُبقت فعليًا على مستوى الـ implementation. فكّر فيها هكذا:
- الـ controller قبل الإعدادات
- ثم دفعها إلى مستوى البيانات أو البنية التحتية
إذا كانت Accepted تساوي True بالفعل لكن المرور ما زال لا يمر، فحينها يصبح من المفيد التحقق من Programmed، ومن Gateway address، وحالة الـ listeners، وموارد Envoy الأساسية.
💡 قد تعرض الموارد المختلفة مجموعات مختلفة من الـ conditions، لكن
AcceptedوResolvedRefsوProgrammedهي أول ثلاث حالات يجب أن تبني الحدس تجاهها.
أقصر مسار Debugging: هذا الترتيب ينجح غالبًا
الخطوة 1: تحقق هل الـ Gateway يعمل فعلًا
kubectl get gateway -A
kubectl get gateway eg -o yamlتحقّق من:
- هل تحتوي
status.addressesعلى قيمة؟ - هل توجد أي حالات غير طبيعية في الـ listeners؟
- هل hostname/protocol/port الخاصة بالـ listener تطابق ما تتوقعه؟
إذا لم يكن لدى الـ Gateway أي عنوان، فحتى أجمل YAML للـ route ليس سوى كتابة إبداعية.
الخطوة 2: تحقق هل تم إرفاق الـ Route بنجاح
kubectl get httproute -A
kubectl get httproute app-route -o yamlركّز على:
status.parentsAcceptedResolvedRefsobservedGeneration
ومن المهم الانتباه إلى observedGeneration.
فإذا لم يلحق بـ metadata.generation، فقد لا يكون الـ controller قد عالج أحدث نسخة من الإعدادات بعد.
الخطوة 3: تحقق هل الموارد المشار إليها موجودة فعلًا
هذه الخطوة يتم تجاوزها أكثر من أي خطوة أخرى:
kubectl get svc -A
kubectl get secret -A
kubectl get referencegrant -Aالمشاكل الشائعة:
- اسم خدمة الـ backend خطأ
- المنفذ خطأ
- الـ Secret ليس في الـ namespace الذي تعتقده
- هناك إشارة عبر namespaces من دون
ReferenceGrant
إذا كانت ResolvedRefs تساوي False، فاتبع هذا المسار مباشرة.
الخطوة 4: تحقق من مستوى البيانات والـ Controller
إذا بدت حالات الـ Gateway والـ Route صحيحة تقريبًا لكن المرور ما زال لا يمر، فانظر أعمق:
kubectl get pods -n envoy-gateway-system
kubectl logs -n envoy-gateway-system deployment/envoy-gatewayعند هذه النقطة أنت لا تشخّص "هل تم قبول القاعدة"، بل تتحقق هل يعمل مستوى التحكم ومستوى البيانات بشكل طبيعي.
إذا كان لديك egctl مثبتًا، فقد يساعدك على فحص الحالة بسرعة.
لكن حتى من دونه، فإن kubectl get/describe -o yaml كافٍ لحل معظم المشاكل.
أربعة أنماط فشل هي الأكثر شيوعًا
1. الـ Route صحيح، لكنه لم يرتبط بالـ Listener المقصود
الأعراض:
- يبدو الـ YAML صحيحًا
- لكن المرور لا يصل إلى القاعدة
تحقّق من:
parentRefs.nameparentRefs.sectionName- هل يطابق اسم Gateway listener الاسم المطلوب حرفيًا
في البيئات متعددة الـ listeners، يكفي خطأ إملائي واحد في sectionName لتضييع جلسة debugging كاملة.
2. نجاح Accepted لكن فشل ResolvedRefs
هذا يعني عادة أن منطق الارتباط صحيح، لكن هناك مشكلة في شيء تمت الإشارة إليه. أكثر الأسباب شيوعًا:
- خدمة Backend غير موجودة
- اسم Secret خاطئ
- إشارة عبر namespaces من دون تصريح
أكثر ما يزعج في هذا النوع من الفشل هو أنك تشعر أنك على وشك الوصول، بينما أنت في الحقيقة عالق في طبقة references.
3. يوجد Listeners في Gateway لكن لا يوجد العنوان المتوقع
يظهر هذا كثيرًا في الـ clusters المحلية أو البيئات التي لا تملك implementation لـ LoadBalancer.
المشكلة ليست أن Gateway API معطوب، بل أن البنية التحتية أسفله لا توفر عنوانًا خارجيًا.
الخيارات:
- تحقق هل يملك الـ cluster قدرة
LoadBalancer - استخدم
port-forwardللتحقق من مسار التوجيه
4. أخذ الـ YAML مفعوله، لكن الطلبات تعيد 404 / 503
في هذه المرحلة، تكون المشكلة غالبًا ليست حقلًا واحدًا خاطئًا، بل سلسلة مكسورة في مكان ما:
- Host header خاطئ
- الـ path لا يطابق أي rule
- backend Pod غير صحي
- service selector لا يلتقط أي Pods
مشاكل ingress قد تبدو أحيانًا وكأنها فشل في البروكسي، بينما الـ backend نفسه لم يكن جاهزًا. فلا تلقِ اللوم كله على طبقة البروكسي، فهي لديها ما يكفي أصلًا.
الخلاصة في سطر واحد
أكثر طريقة فعّالة لـ debugging في Gateway API ليست الاستمرار في تغيير YAML، بل تعلّم قراءة status.
تخبرك Accepted هل تم التقاط الطلب. وتخبرك ResolvedRefs هل تم حل الإشارات. وتخبرك Programmed هل طُبقت الإعدادات فعلًا. افصل هذه الطبقات الثلاث أثناء الفحص، وسترتفع سرعة الاستكشاف بشكل كبير.
الخطوة التالية
بهذا تكتمل سلسلة Envoy Gateway المكوّنة من 10 مقالات. وإذا أردت الرجوع إلى خريطة السلسلة الكاملة: