تخطَّ إلى المحتوى
NerdLevelTech
السحابة و DevOps

شهادة cert-manager عالقة في حالة الانتظار؟ استكشاف الأخطاء وإصلاحها (٢٠٢٦)

شهادة cert-manager واقفة في حالة pending؟ افحص سلسلة الموارد من Certificate لـ Challenge وحل مشاكل الـ HTTP-01 والـ DNS-01 وأسباب الـ rate-limit في Let's Encrypt.

Nerd Level Techنُشر في ١٢ دقيقة للقراءةEnglish
صورة غلاف: شهادة cert-manager عالقة في حالة الانتظار؟ استكشاف الأخطاء وإصلاحها (2026)

يظل مورد Certificate الخاص بـ cert-manager معلقاً (pending) لأن مورداً تابعاً له — سواء كان CertificateRequest، أو ACME Order، أو Challenge — لم يتم التحقق منه بعد. قم بتشغيل kubectl describe عبر تلك السلسلة للعثور على المورد المحظور بالضبط، ثم قم بإصلاح التكوين الخاطئ لـ HTTP-01/DNS-01 أو حد معدل Let's Encrypt الذي يذكره.١

ملخص

يقوم cert-manager بإصدار شهادة من خلال أربعة موارد مرتبطة: Certificate ينشئ CertificateRequest، والذي — بالنسبة لمصدري ACME مثل Let's Encrypt — ينشئ Order، والذي بدوره ينشئ Challenge واحداً لكل اسم نطاق.١ "عالق في حالة الانتظار" تعني دائماً تقريباً أن أحد موارد Challenge تلك لم يجتز الفحص الذاتي بعد، وسوف يخبرك kubectl describe challenge <name> بالسبب تحديداً: جدار حماية يحظر أداة حل HTTP-01، أو سجل DNS-01 لم ينتشر بعد، أو خطأ في حساب ACME/حد المعدل ظهر في أعلى السلسلة. يستعرض هذا المنشور سلسلة تصحيح الأخطاء الكاملة مع مخرجات cert-manager 1.20 الحقيقية في كل خطوة، ويغطي الحل البديل cert-manager.io/issue-temporary-certificate لأخطاء tls: handshake failure، ويوضح متى يكون حد معدل Let's Encrypt — وليس خطأ في التكوين — هو السبب الحقيقي.٢٣

ما ستتعلمه

  • كيفية تتبع سلسلة Certificate → CertificateRequest → Order → Challenge باستخدام kubectl describe
  • ما تعنيه رسائل خطأ "الانتظار" والفحص الذاتي بالضبط في كل خطوة
  • الفرق بين فشل تحدي HTTP-01 و DNS-01، وكيفية تصحيح أخطاء كل منهما
  • متى تستخدم تعليق cert-manager.io/issue-temporary-certificate
  • لماذا يعالج cert-manager 60 تحدياً فقط في المرة الواحدة، وماذا يعني ذلك لعمليات طرح الشهادات بالجملة
  • ما إذا كان حد معدل Let's Encrypt — وليس ملف YAML الخاص بك — هو ما يمنع الإصدار فعلياً
  • لماذا يجب عليك توجيه cert-manager إلى بيئة staging الخاصة بـ Let's Encrypt قبل تصحيح الأخطاء في بيئة الإنتاج

لماذا شهادة cert-manager الخاصة بي عالقة في حالة الانتظار؟

شهادة Certificate الخاصة بك عالقة لأن المورد الذي تعتمد عليه لم يصل إلى حالة نهائية. توضح وثائق cert-manager نفسها ذلك بوضوح: "عند تصحيح أخطاء cert-manager، فإن أفضل صديق لك هو kubectl describe... لا ينصح باستخدام السجلات (logs) لأنها مطولة للغاية."١ ابدأ من الأعلى:

console
$ kubectl get certificate

NAME                READY   AGE
example-com-tls     False   1h

READY=False تعني فقط أن عملية الإصدار لم تنتهِ بعد — وهي ليست خطأً في حد ذاتها. قم بوصفها لرؤية الحالة الحالية وسجل الأحداث:

console
$ kubectl describe certificate example-com-tls

Status:
  Conditions:
    Last Transition Time:        2026-07-08T09:12:03Z
    Message:                     Issuing certificate as Secret does not exist
    Reason:                      DoesNotExist
    Status:                      False
    Type:                        Ready
  Next Private Key Secret Name:  example-com-tls-wtlww
Events:
  Type    Reason     Age   From          Message
  ----    ------     ----  ----          -------
  Normal  Issuing    105s  cert-manager  Issuing certificate as Secret does not exist
  Normal  Generated  105s  cert-manager  Stored new private key in temporary Secret resource "example-com-tls-wtlww"
  Normal  Requested  104s  cert-manager  Created new CertificateRequest resource "example-com-tls-bw5t9"

يسمي الحدث الأخير مورد CertificateRequest الذي أنشأه cert-manager. هذه هي محطتك التالية.

كيف يمكنني تصحيح أخطاء سلسلة CertificateRequest و Order و Challenge؟

اتبع السلسلة مورداً تلو الآخر — مخرجات describe لكل مورد تسمي المورد التالي في السلسلة.١ السلسلة الكاملة، مباشرة من مخطط بنية cert-manager، هي:

Ingress (optional) --> Certificate --> CertificateRequest --> Order --> Challenge
                                                          (ACME issuers only)

موردا Order و Challenge موجودان فقط لمصدري ACME (مثل Let's Encrypt و ZeroSSL وما شابه)؛ أما مصدرو CA الداخليون أو Vault فيتوقفون عند CertificateRequest.١ قم بوصف CertificateRequest:

console
$ kubectl describe certificaterequest example-com-tls-bw5t9

Spec:
  Issuer Ref:
    Group:  cert-manager.io
    Kind:   ClusterIssuer
    Name:   letsencrypt-production
Status:
  Conditions:
    Message:  Waiting on certificate issuance from order example-com-tls-fqtfg-1: "pending"
    Reason:   Pending
    Status:   False
    Type:     Ready
Events:
  Type    Reason        Age    From          Message
  ----    ------        ----   ----          -------
  Normal  OrderCreated  8m20s  cert-manager  Created Order resource example-com-tls-fqtfg-1

رسالة Waiting on certificate issuance from order ...: "pending" هي صياغة cert-manager الحرفية والدقيقة — إنها مؤشر وليست السبب الجذري.١ قم بوصف Order المسمى بعد ذلك:

console
$ kubectl describe order example-com-tls-fqtfg-1

State:  pending
URL:    https://acme-v02.API.letsencrypt.org/acme/order/41123272/265506123
Events:
  Type    Reason   Age   From          Message
  ----    ------   ----  ----          -------
  Normal  Created  1m    cert-manager  Created Challenge resource "example-com-tls-fqtfg-1-0" for domain "example.com"

أخيراً، يوضح kubectl get challenges السبب الفعلي لمنع الإصدار:

console
$ kubectl get challenges

NAME                         STATE     DOMAIN        REASON                                     AGE
example-com-tls-fqtfg-1-0    pending   example.com   Waiting for dns-01 challenge propagation   22s

عمود REASON هو المكان الذي يبدأ فيه تصحيح الأخطاء الحقيقي — وينقسم إلى وضعين مختلفين تماماً للفشل اعتماداً على ما إذا كنت تستخدم HTTP-01 أو DNS-01.٢

ماذا يعني "Waiting on certificate issuance from order ...: pending" فعلياً؟

يعني أن CertificateRequest ينتظر مورد Order التابع له، والذي ينتظر بدوره واحداً أو أكثر من موارد Challenge لإنهاء التحقق من ملكية النطاق — وهذا ليس خطأً في حد ذاته.١ تمر تحديات HTTP01 و DNS01 بعملية من مرحلتين: يقوم cert-manager أولاً بإجراء "فحص ذاتي" داخلي قبل إخبار خادم ACME بأن التحدي جاهز، وذلك تحديداً حتى لا يستهلك حدود معدل ACME في تحديات ستفشل بوضوح بسبب تأخر انتشار DNS أو موازن التحميل.٢ فقط بعد اجتياز الفحص الذاتي، يخبر cert-manager خادم Let's Encrypt بالتحقق، وعند هذه النقطة يتم تحديث حالة Challenge إلى valid وتعود السلسلة إلى الخلف وصولاً إلى Certificate.

HTTP-01 مقابل DNS-01: أي نوع من التحدي يفشل، وكيف يمكنني تصحيح أخطاء كل منهما؟

انظر إلى نطاق Challenge وسلسلة السبب — يوضح kubectl describe challenge آلية الحل المستخدمة وما الذي يفشل بالضبط.٢ يفشل الحلان لأسباب مختلفة تماماً تقريباً:

يثبت HTTP-01 الملكية من خلال تقديم رمز مميز (token) على الرابط http://<domain>/.well-known/acme-challenge/<token>. إذا فشل الفحص الذاتي، فسترى Reason مثل:

Waiting for http-01 challenge propagation: failed to perform self check GET request
'http://example.com/.well-known/acme-challenge/_fgdLz0i3TFiZW4LBjuhjgd5nTOkaMBhxYmTY':
Get "http://example.com/...": remote error: tls: handshake failure

اتبع قائمة التحقق هذه بالترتيب: تأكد من إمكانية الوصول إلى رابط التحدي (challenge URL) من الإنترنت العام، ثم تأكد من إمكانية الوصول إليه من داخل بود (Pod) في الكلاستر الخاص بك (وليس فقط من جهازك الشخصي) — تشير وثائق cert-manager تحديداً إلى ضرورة الاختبار من داخل Pod، لأن مسارات الشبكة الداخلية للكلاستر قد تختلف عن الإنترنت العام.٢ ظهور خطأ ٤٠٤ على هذا الرابط يعني أن بود حل ACME (solver pod) لا يعمل أو أن Ingress الذي أنشأه الحل غير متصل — تحقق باستخدام kubectl describe ingress على Ingress الخاص بحل HTTP-01.٢ أما خطأ tls: handshake failure فيعني أن متحكم ingress الخاص بك ليس لديه ما يقدمه على المنفذ ٤٤٣ بعد لهذا المضيف — راجع حل الشهادة المؤقتة أدناه.

تحدي DNS-01 يثبت الملكية عن طريق نشر سجل TXT باسم _acme-challenge.<domain>. إذا كان هذا السجل موجوداً (تحقق باستخدام dig أو لوحة تحكم مزود DNS الخاص بك) ولكن cert-manager لا يزال يبلغ عن التحدي كـ "قيد الانتظار" (pending)، فإن السبب الأكثر شيوعاً هو أن محلل DNS الداخلي لـ cert-manager لا يمكنه رؤية السجل بعد — حتى لو كان الإنترنت العام يراه.٢ هناك نمط فشل ثانٍ وأكثر دهاءً لـ DNS-01: يستخدم cert-manager سجلات SOA (Start of Authority) لتحديد منطقة DNS التي يجب كتابة سجل TXT فيها، وبعض المحللات (خاصة dnsmasq مع علم --filterwin2k، الذي يعرضه OpenWRT/LuCI كخيار "Filter useless") تقوم بإزالة سجلات SOA تماماً، مما يتسبب في تعريف cert-manager للمنطقة بشكل خاطئ.٢ الحل في كلتا الحالتين هو توجيه الفحص الذاتي لـ DNS-01 الخاص بـ cert-manager إلى مجموعة مختلفة من خوادم الأسماء بدلاً من المحلل الافتراضي للكلاستر.

ما هو التعليق التوضيحي cert-manager.io/issue-temporary-certificate، ومتى أحتاجه؟

استخدمه عندما يفشل الفحص الذاتي لـ HTTP-01 بخطأ tls: handshake failure — فهو يخبر cert-manager بإصدار شهادة مؤقتة موقعة ذاتياً على الفور حتى يكون لدى متحكم ingress الخاص بك شيء ما صالح لتقديمه على المنفذ ٤٤٣ بينما لا تزال شهادة ACME الحقيقية قيد الإصدار.٢ قم بتعيينه مباشرة على مورد Ingress أو Certificate:

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-com
  annotations:
    cert-manager.io/issue-temporary-certificate: "true"
    cert-manager.io/cluster-issuer: letsencrypt-production
spec:
  # ... rules, tls, etc.

إذا كنت تستخدم Google Cloud Load Balancer (GKE)، فإن وثائق cert-manager نفسها توصي بدمجه مع تعليق توضيحي ثانٍ، وهو acme.cert-manager.io/http01-edit-in-place: "true"، والذي يمنع GCLB من تخصيص عنوان IP ثانٍ لنقطة نهاية حل HTTP-01:٢

yaml
    cert-manager.io/issue-temporary-certificate: "true"
    acme.cert-manager.io/http01-edit-in-place: "true"

لماذا يعالج cert-manager 60 تحدياً فقط في المرة الواحدة، وهل يهم ذلك بالنسبة لي؟

هل يمنع حد معدل Let's Encrypt شهادتي، وليس خطأ في الإعدادات؟

أحياناً — ويستحق الأمر استبعاد ذلك قبل قضاء ساعة في تصحيح أخطاء DNS. تفرض Let's Encrypt عدة حدود إنتاج منفصلة، والوصول إلى أي منها سيترك Order أو Challenge عالقاً دون أن يصبح invalid أبداً:٣

الحدقيمة الإنتاجمعدل التعبئة
الطلبات الجديدة لكل حساب٣٠٠ / ٣ ساعات١ كل ٣٦ ثانية
الشهادات الجديدة لكل نطاق مسجل٥٠ / ٧ أيام (عالمياً، لجميع الحسابات)١ كل ٢٠٢ دقيقة
الشهادات الجديدة لكل مجموعة محددة من المعرفات٥ / ٧ أيام١ كل ٣٤ ساعة
فشل التفويض لكل معرف/حساب٥ / ساعة١ كل ١٢ دقيقة
فشل التفويض المتتالي لكل معرف/حساب١٬١٥٢ إجمالاً، ثم يتم الإيقاف المؤقتتعبئة واحدة/يوم

النطاق المسجل هنا يعني الجزء الذي اشتريته من مسجل النطاقات الخاص بك — example.com، وليس app.example.com.٣ هناك سلوكان يقع فيهما الناس مراراً وتكراراً: إلغاء الشهادة لا يعيد تعيين أي حد للمعدل، لأن الموارد التي استُهلكت لإصدارها قد استُنفدت بالفعل، وإعادة تثبيت عميل ACME الخاص بك أو مسح حالته المحلية بين المحاولات هو أحد أكثر الطرق شيوعاً لاستهلاك حد "مجموعة المعرفات المحددة" البالغ ٥ أسبوعياً عن طريق الخطأ، حيث تبدو كل محاولة جديدة كطلب جديد تماماً بدلاً من تجديد.٣ إذا كان عميلك يدعم ACME Renewal Info (ARI)، فإن التجديدات التي تشير صراحةً إلى الشهادة التي تستبدلها تُعفى من كل حدود المعدل؛ أما العملاء الأقدم الذين لا يدعمون ARI فيحصلون فقط على إعفاء جزئي (من حدود الحساب والنطاق، ولكن ليس من حدود مجموعة المعرفات أو حدود الفشل) طالما أن مجموعة النطاقات المطلوبة تطابق تماماً الشهادة التي يتم تجديدها، مع تجاهل حالة الأحرف وترتيب الأسماء.٣

هل يجب أن أختبر مقابل بيئة staging الخاصة بـ Let's Encrypt أولاً؟

نعم، لأي إعداد مصدر (issuer) جديد، أو DNS-01 webhook، أو نشر جماعي — تستخدم بيئة staging نفس بروتوكول ACME ولكن بحدود أعلى بكثير حتى تتمكن من التكرار دون استهلاك سعة الإنتاج.٤ وجه ClusterIssuer الخاص بك إلى دليل ACME الخاص ببيئة staging:

yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    server: https://acme-staging-v02.API.letsencrypt.org/directory
    email: you@example.com
    privateKeySecretRef:
      name: letsencrypt-staging-key
    solvers:
      - http01:
          ingress:
            ingressClassName: nginx

حد "الشهادات الجديدة لكل نطاق مسجل" في بيئة staging هو ٣٠٬٠٠٠ في الثانية (مقابل ٥٠ في الأسبوع في بيئة الإنتاج)، وحد "فشل التفويض لكل معرف لكل حساب" هو 200/ساعة (مقابل 5/ساعة).٤ هناك عقبة واحدة: شهادات staging تتصل بجذور (roots) بأسماء صريحة مثل "(STAGING) Pretend Pear X1" وهي غير موثوقة من قبل أي متصفح أو عميل حقيقي — لا تضف جذر staging إلى أي مخزن ثقة تستخدمه لأي شيء بخلاف الاختبار.٤ إذا كان سير عملك هو CI بدلاً من التكرار اليدوي، فإن Let's Encrypt توصي صراحةً بـ Pebble — خادم اختبار ACME المحلي المصمم لهذا الغرض — بدلاً من staging، لأن staging لا تزال تجري مكالمات شبكة حقيقية ولا توفر طريقة لتزييف DNS أو نجاح التحدي لعمليات اختبار قابلة للتكرار.٤

الخلاصة

لما تلاقي Certificate في cert-manager معلقة، دي مشكلة في "سلسلة الإجراءات" مش لغز: استخدام kubectl describe بالتدرج من CertificateRequest، لـ Order، وبعدين Challenge هيعرفك المورد المتعطل بالظبط ورسالة الخطأ بتاعته في كل مرة تقريبًا، والخطأ ده دايمًا بيقع تحت واحد من تلات احتمالات — غلط في إعدادات الشبكة أو الـ ingress لـ HTTP-01، أو مشكلة في انتشار الـ DNS أو اكتشاف الـ zone لـ DNS-01، أو إنك وصلت لحدود استخدام Let's Encrypt وإنت مش عارف. اختبر إعدادات الـ issuer الجديدة على بيئة staging الخاصة بـ Let's Encrypt الأول، واستخدم الـ annotation بتاع issue-temporary-certificate بس كحل مؤقت لحالة tls: handshake failure المحددة، مش كحل عام. لمسارات عمل تصحيح أخطاء الكلاستر ذات الصلة، شوف أدلتنا عن تصحيح أخطاء الـ pods باستخدام الحاويات المؤقتة (ephemeral containers) لما kubectl exec ميكونش فيها shell، و تحديثات Helm الآمنة والمتكررة (idempotent)، و أتمتة شهادات HTTPS بره Kubernetes باستخدام Caddy.

الأسئلة الشائعة

ليه شهادة cert-manager بتاعتي معلقة في حالة pending؟

لأن فيه مورد (resource) في سلسلة الإصدار — عادةً بيكون Challenge — لسه مخلصش التحقق من ملكية النطاق (domain ownership). شغل أمر kubectl describe بالتسلسل ده: Certificate ← CertificateRequest ← Order ← Challenge عشان تلاقي المورد المحدد اللي متعطل ورسالة الخطأ بتاعته.

إيه الفرق بين Order و Challenge في cert-manager؟

الـ Order بيمثل طلب شهادة ACME واحد ككل؛ وهو اللي بيعمل وبيتابع مورد Challenge واحد لكل اسم DNS بيتم التحقق منه جوه الطلب ده. إنت مش بتعمل أي واحد من الموارد دي يدويًا أبدًا — cert-manager بيدير الاتنين تلقائيًا.

كم عدد الـ challenges اللي cert-manager بيشغلها في نفس الوقت؟

لحد ٦٠ بشكل افتراضي على مستوى الكلاستر كله، وبيتم التحكم في ده عن طريق --max-concurrent-challenges (أو maxConcurrentChallenges في Helm)؛ والـ challenges اللي بتزيد عن الحد ده بتتحط في طابور (queue) بدل ما تفشل.

هل سحب (revoking) شهادة Let's Encrypt بيصفر حدود الاستخدام (rate limit) بتاعتي؟

لأ. Let's Encrypt واضحة في إن سحب الشهادة مش بيصفر أي حدود استخدام، لأن الموارد اللي استُخدمت لإصدارها استُهلكت بالفعل.

إيه الـ annotation اللي بيصلح خطأ tls: handshake failure أثناء التحقق من نوع HTTP-01؟

استخدم cert-manager.io/issue-temporary-certificate: "true" على الـ Ingress أو الـ Certificate — ده بيصدر شهادة مؤقتة موقعة ذاتيًا (self-signed) عشان الـ ingress controller يقدر يقدم أي حاجة عبر TLS والشهادة الحقيقية لسه معلقة؛ وفي حالة GKE/GCLB، استخدم معاها acme.cert-manager.io/http01-edit-in-place: "true".

هل المفروض أعمل debug مقابل بيئة الإنتاج ولا بيئة staging في Let's Encrypt؟

بيئة staging لأي حاجة تجريبية — حدود الاستخدام فيها أعلى بآلاف المرات (٣٠٬٠٠٠ في الثانية مقابل ٥٠ في الأسبوع لكل نطاق)، لكن الشهادات بتاعتها مش موثوقة في المتصفحات ومينفعش تستخدمها أبدًا لحركة المرور الحقيقية.

المراجع

  1. cert-manager, "Troubleshooting," https://cert-manager.io/docs/troubleshooting/ — official resource chain diagram, kubectl describe guidance, and exact status/event message formats. Fetched 2026-07-08. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8

  2. cert-manager, "Troubleshooting Problems with ACME / Let's Encrypt Certificates," https://cert-manager.io/docs/troubleshooting/acme/ — Order/Challenge debugging steps, HTTP-01/DNS-01 failure modes, issue-temporary-certificate and http01-edit-in-place annotations. Fetched 2026-07-08. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11

  3. Let's Encrypt، "Rate Limits،" https://letsencrypt.org/docs/rate-limits/ (آخر تحديث في ١٢ يونيو ٢٠٢٥) — قيم حدود المعدل للإنتاج، استثناءات تجديد ARI، سياسة عدم إعادة تعيين الحدود عند الإلغاء. تم الجلب في 08-07-2026. ↩ ↩٢ ↩٣ ↩٤ ↩٥ ↩٦

  4. Let's Encrypt، "Staging Environment،" https://letsencrypt.org/docs/staging-environment/ (آخر تحديث في ١٠ أبريل ٢٠٢٦) — رابط ACME لبيئة الاختبار، قيم حدود المعدل للاختبار، أسماء الجذور غير الموثوقة للاختبار، توصية Pebble لـ CI. تم الجلب في 08-07-2026. ↩ ↩٢ ↩٣ ↩٤ ↩٥

  5. cert-manager، "ACME Orders and Challenges،" https://cert-manager.io/docs/concepts/acme-orders-challenges/ — جدولة التحديات، التزامن الافتراضي لـ ٦٠ تحديًا، فاصل إعادة محاولة الفحص الذاتي لمدة ١٠ ثوانٍ، قواعد اكتشاف التعارض. تم الجلب في 08-07-2026. ↩ ↩٢

ابقَ على مسار النيرد

رسالتان كلّ أسبوع: شرح معمّق لموضوع واحد يوم الاثنين، وملخّص يوم الخميس للدورات والأدلّة والمقالات والبودكاست والوظائف.

بدون إزعاج. إلغاء الاشتراك في أي وقت.