تخطَّ إلى المحتوى
نسخة تجريبية

أتِح خدمات HTTP للعالم

تستطيع كل مجموعة Kubernetes أن تخدم مواقعك وواجهاتك البرمجية عبر HTTPS من خلال بوابتها المُدارة. اربط بها مسارًا من نوع HTTPRoute أو قاعدة Ingress، وتتولّى المنصّة اسم المضيف والشهادة، دون موزّع حمل تُعدّه.

المواقع والواجهات البرمجية (HTTP وHTTPS) ← استخدم البوابة المُدارة، على اسم مضيف المجموعة أو على نطاقك الخاص عبر سجل CNAME. وكل ما عدا ذلك (قواعد البيانات وخدمات TCP أو UDP) ← خدمة من نوع LoadBalancer، على منفذ خاص بها.

لكل مجموعة بوابة مُدارة مفعّلة افتراضيًا. فإن لم يعرض قسم الخدمات والمسارات في المجموعة البوابة المُدارة، فقد أُوقفت لمساحة عملك: تواصل مع الدعم.

كيف تعمل

تُنشئ المنصّة بوابة (Gateway) اسمها sahabti في مساحة الأسماء sahabti-gateway داخل المجموعة وتحافظ عليها: أنت تربط مساراتك بها ولا تعدّلها. يتصل الزوّار عبر HTTPS بحافة المنصّة (edge) التي تحمل الشهادات، وتصل طلباتهم إلى البوابة بصيغة HTTP عادية، ثم ترسل البوابة كلًّا منها إلى الخدمة التي يحدّدها مسارك. ولا تستخدم البوابة أي موزّع حمل، ولا تستهلك شيئًا من حصة موزّعات الحمل في مساحة عملك.

البدء السريع

احفظ ما يلي باسم hello.yaml: خادم ويب صغير، وخدمته، ومسار إليه.

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      labels:
        app: hello
    spec:
      containers:
        - name: hello
          image: nginx:1.27-alpine
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: hello
spec:
  selector:
    app: hello
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: hello
spec:
  parentRefs:
    - name: sahabti
      namespace: sahabti-gateway
  rules:
    - backendRefs:
        - name: hello
          port: 80
bash
kubectl apply -f hello.yaml

لا يحدّد المسار أي hostnames، فيجيب على اسم المضيف الخاص بالمجموعة، <cluster>.sahabti.app، الذي يعرضه قسم الخدمات والمسارات في المجموعة ضمن البوابة المُدارة. وحين تظهر حالة اسم المضيف يعمل، افتحه:

bash
curl https://<cluster>.sahabti.app/

يمكن أن يقع المسار في أي مساحة أسماء، ما دام parentRefs فيه يحدّد البوابة مع مساحة أسمائها، كما هنا.

استخدم Ingress

تعمل قواعد Ingress أيضًا، وهذا يناسب مخططات Helm والملفات التي تستخدمها أصلًا. أعطها الفئة sahabti:

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: shop
spec:
  ingressClassName: sahabti
  rules:
    - host: shop.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: hello
                port:
                  number: 80
  • الفئة sahabti هي فئة Ingress الافتراضية في المجموعة، إلا إذا كانت فئة أخرى هي الافتراضية من قبل.
  • تحوّل المنصّة كل قاعدة Ingress من هذه الفئة إلى مسارات HTTPRoute، وتُبقيها متزامنة معها.
  • يُتجاهل قسم tls فيها لأن HTTPS يُعالَج عند الحافة، وتتلقّى قاعدة Ingress حدثًا يوضّح ذلك.
  • تعرض حالتها اسم المضيف الخاص بالمجموعة، ويسرده kubectl get ingress عنوانًا لها.

يجب أن يكون host اسم مضيف تابعًا للمجموعة: انظر أسماء المضيفين.

أسماء المضيفين

لا تخدم المجموعة إلا أسماء المضيفين التابعة لها:

اسم المضيف الخاص بالمجموعة

لكل مجموعة اسم مضيف خاص بها، <cluster>.sahabti.app، يظهر في قسم الخدمات والمسارات منها، ولا يحتاج إلى أي إعداد. والمسار الذي لا يحدّد hostnames يجيب عليه، وعلى أي اسم مضيف تابع للمجموعة لا يطالب به مسار آخر.

نطاقك الخاص

تقديم shop.example.com من المجموعة خطوتان.

  1. أضف اسم المضيف. في قسم الخدمات والمسارات من المجموعة، ضمن البوابة المُدارة ← استخدام نطاقك الخاص، أدخل shop.example.com واختر إضافة اسم المضيف.
  2. وجّه سجل CNAME إلى المجموعة. أنشئ هذا السجل لدى مزوّد DNS. تعرضه لوحة التحكم وفيه اسم مضيف مجموعتك جاهزًا للنسخ.
النوعالاسمالقيمة
CNAMEshop.example.com<cluster>.sahabti.app

ثم اذكر اسم المضيف في مسار، كأي اسم مضيف آخر:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: shop
spec:
  parentRefs:
    - name: sahabti
      namespace: sahabti-gateway
  hostnames:
    - shop.example.com
  rules:
    - backendRefs:
        - name: hello
          port: 80

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

من المفيد أن تعرف:

  • لا حاجة إلى سجل TXT ولا إلى نطاق في مساحة العمل: سجل CNAME هو ما يثبت أن اسم المضيف ملكك.
  • إن عرض عليك مزوّد DNS تمرير السجل عبر وسيطه (proxy)، فأبقِه سجل DNS فقط، كي يبقى سجل CNAME ظاهرًا.
  • أبقِ السجل في مكانه. تواصل المنصّة التحقق منه؛ فإن توقّف عن الإشارة إلى المجموعة ظهرت حالة اسم المضيف سجل CNAME مفقود، وبعد ساعة يتوقف تقديمه. أعِد السجل فيعود تقديمه. أما اسم المضيف الذي لم يعد يستخدمه أي مسار فيُزال حينها.
  • لا يخدم اسمَ المضيف الواحد على المنصّة كلها إلا تطبيق واحد أو نسخة واحدة أو مجموعة واحدة، ويكون لأول مساحة عمل تثبت ملكيته. واسم المضيف الذي أضافته مساحة عمل أخرى دون أن يشير سجله إليها لا يمنعك أبدًا.
  • لا تُدعم أسماء المضيفين الشاملة (wildcard) مثل *.example.com.

نطاق جذر

لا يمكن وضع سجل CNAME على نطاق جذر مثل example.com. لتقديمه من المجموعة:

  1. في صفحة النطاقات في مساحة عملك، أضف example.com ووثّقه بسجل TXT الذي تعرضه الصفحة.
  2. في قسم الخدمات والمسارات من المجموعة، ضمن البوابة المُدارة ← طرق أخرى لإضافة اسم مضيف، اربط example.com من ربط نطاق مُوثَّق.
  3. لدى مزوّد DNS، وجّه example.com إلى apps.sahabti.app بسجل ALIAS أو ANAME أو CNAME مسطّح (flattened)، إن كان مزوّدك يتيح أحدها.

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

الأسماء الإضافية

لخدمة مواقع أخرى تحت sahabti.app، أضف أسماء إضافية في قسم الخدمات والمسارات من المجموعة، ضمن البوابة المُدارة ← طرق أخرى لإضافة اسم مضيف. يُخدَم كل اسم منها بالصيغة <name>--<cluster>.sahabti.app، فيصبح الاسم shop مثلًا shop--<cluster>.sahabti.app.

يتكوّن الاسم من 3 إلى 40 رمزًا: أحرف لاتينية صغيرة وأرقام وشرطات غير متتالية. ويجب ألا يزيد طول كل ما يسبق .sahabti.app على 63 رمزًا، فالمجموعة ذات الاسم الطويل تترك له مساحة أقل.

ولتوجيه اسم إضافي إلى خدمة بعينها، ضع اسم المضيف كاملًا في hostnames في المسار، أو في host في قاعدة Ingress.

HTTPS وعنوان العميل

لا يحتاج HTTPS إلى أي شيء منك. ينتهي تشفير TLS عند حافة HTTPS في المنصّة، التي تُصدر الشهادات وتجدّدها، وتصل الطلبات إلى المجموعة بصيغة HTTP عادية على البوابة، فتستقبل خدماتك HTTP عاديًا ولا تحتاج إلى شهادات خاصة بها. ويصل عنوان العميل في الترويسة X-Forwarded-For.

تحقّق من الحالة

في قسم الخدمات والمسارات من المجموعة، تسرد البوابة المُدارة كل اسم مضيف مع حالته، وتذكر ما عليك فعله تاليًا:

الحالةمعناها
يعمليُخدَم عبر HTTPS
بلا مسار بعدجاهز، لكن لا يذكره أي HTTPRoute أو Ingress بعد
بانتظار DNSسجل CNAME الخاص به لا يشير إلى المجموعة بعد؛ ويظهر بجانبه السجل المطلوب إنشاؤه
يجري إصدار الشهادةالسجل موجود والشهادة في طريقها
سجل CNAME مفقودتوقّف سجله عن الإشارة إلى المجموعة؛ ويتوقف تقديمه بعد ساعة ما لم يُعَد السجل
قيد الانتظارلا يُخدَم بعد، مع ذكر السبب، كانتظار أن تبدأ البوابة
غير مسموحيستخدمه مسار، لكن المجموعة لا تستطيع امتلاكه، مع ذكر السبب
متوقّفالبوابة المُدارة متوقّفة
خطأفشل إعداده، مع ما عليك فعله

لا يُخدَم المسار الذي يستخدم اسم مضيف غير تابع للمجموعة، ويتلقّى حدث HostnameNotRouted:

bash
kubectl describe httproute shop

حل المشكلات

يبقى اسم المضيف على «بانتظار DNS»

تحقّق من السجل من جهازك:

bash
dig +short CNAME shop.example.com

يجب أن يكون الجواب اسم مضيف المجموعة، <cluster>.sahabti.app.، أو أحد أسمائها الإضافية.

  • السجل الذي يشير إلى apps.sahabti.app لا يحدّد أي مجموعة تقصد: وجّهه إلى اسم مضيف المجموعة نفسه.
  • السجل الذي يمرّره مزوّد DNS عبر وسيطه يجيب بعناوين بدل سجل CNAME: اجعله سجل DNS فقط.
  • قد يستغرق وصول سجل جديد أو معدَّل إلى كل المحلِّلات مدةً تصل إلى قيمة TTL الخاصة به.

يظهر اسم المضيف «غير مسموح»

تذكر الملاحظة بجانبه السبب:

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

يبقى اسم المضيف على «بلا مسار بعد»

تقدّمه المنصّة، لكن لا يذكره أي مسار، فلا تجد البوابة وجهة للطلب. أضفه إلى hostnames في HTTPRoute أو إلى host في Ingress.

لا تصل الشهادة

قد يكون في نطاقك سجل CAA لا يسمح لجهة إصدار الشهادة. اسمح فيه بـletsencrypt.org وpki.goog وssl.com، أو احذف سجل CAA، ثم أزل اسم المضيف وأضفه من جديد.

تعرض البوابة مشكلة

تسمّيها لوحة التحكم. وأكثرها شيوعًا خدمة لديك تستخدم منفذ العقدة 30080 الذي تحتاج إليه البوابة المُدارة على كل عقدة: امنح تلك الخدمة منفذ عقدة آخر.

الحدود

الخطة المجانيةالخطط المدفوعة
أسماء المضيفين لكل مجموعة: نطاقاتك الخاصة والنطاقات المربوطة والأسماء الإضافية معًا20100

لا تستخدم البوابة المُدارة نفسها أيًّا من موزّعات الحمل في مساحة عملك.

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

التحديثات

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

أوقِف البوابة المُدارة

في قسم الإعدادات من المجموعة، أوقِف البوابة المُدارة. يسحب الإيقاف كل أسماء المضيفين من الحافة، ويزيل كائنات البوابة من المجموعة. تبقى مسارات HTTPRoute وقواعد Ingress لديك، لكنها لا تعود تُخدَم. وأعِد تشغيلها لتعود.

شغّل بوابتك أو متحكّم Ingress الخاص بك

البوابة المُدارة خيار افتراضي، وليست إلزامية. لتقديم HTTP عبر متحكّم من اختيارك:

  1. في الإعدادات الخاصة بالمجموعة، أوقِف البوابة المُدارة حتى لا يجيب متحكّمان عن موارد Ingress نفسها. ويمكنك أيضًا إبقاؤها مفعّلة ومنح موارد Ingress لديك فئةً خاصة بك.
  2. ثبّت تطبيق Gateway API أو متحكّم Ingress الذي تفضّله، واعرضه عبر خدمة من نوع LoadBalancer. يُحتسب من حصة موزّعات الحمل في مساحة عملك، ويجيب على منفذ عام في عنوان IP المشترك لمساحة عملك؛ ولا يمكن بعد منح موزّعات حمل المجموعة عنوان IP مخصّصًا، لذا لا يتاح لها المنفذان 80 و443.
  3. لكي تستخدمه موارد Ingress التي لا تحدّد فئة، اجعل IngressClass الخاصة بك الافتراضية بالتعليق ingressclass.kubernetes.io/is-default-class: "true". لا تُجعل فئة البوابة المُدارة sahabti افتراضية إلا إذا لم تكن هناك فئة افتراضية أخرى.
  4. وجّه نطاقك إلى عنوان موزّع الحمل وأدِر شهاداته بنفسك: حافة المنصّة وشهاداتها تخدم البوابة المُدارة فقط.

متى تستخدم موزّع حمل بدلًا منها

استخدم خدمة من نوع LoadBalancer لكل ما ليس موقعًا أو واجهة برمجية، كقواعد البيانات وخوادم الألعاب وحركة TCP أو UDP الخام، أو حين تحتاج إلى إنهاء TLS بنفسك. وتُحتسب كل خدمة منها من حصة موزّعات الحمل في مساحة عملك: انظر موزّع حمل لخدمة. وعلى عنوان IP المشترك لمساحة عملك يستجيب موزّع الحمل على منفذ عام خاص به، فيتصل العملاء باسم مضيفه مع ذلك المنفذ، مثل prod-default-db-e5f6a7b8-q2w7ze.lb.sahabti.app:40002؛ أما HTTPS بلا رقم منفذ فمن شأن البوابة المُدارة.

ولا تزال فئة البوابة sahabti متاحة لتشغيل بوابة خاصة بك خلف موزّع حمل، كما في توجيه HTTP حسب اسم المضيف. وانتبه إلى الأسماء: المسارات المرتبطة بالبوابة sahabti في sahabti-gateway، وقواعد Ingress من الفئة sahabti، تستخدم البوابة المُدارة؛ أما البوابة التي تنشئها أنت بـgatewayClassName: sahabti فتعمل خلف موزّع حمل.