cert-manager: wildcard-сертификаты через DNS-01 challenge
Published: 2026-04-01
cert-manager автоматизирует выпуск и обновление TLS-сертификатов. Для wildcard-сертификатов (*.dev.test.antonnovikov.com) HTTP-01 challenge не подходит — нужен DNS-01, который подтверждает владение доменом через DNS TXT-запись.
Установка
cert-manager работает на infra-кластере и выпускает сертификаты для всех окружений. Spoke-кластеры получают их через SealedSecrets.
yamlapiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: cert-manager
namespace: cert-manager
spec:
chart:
spec:
chart: cert-manager
version: "v1.14.*"
sourceRef:
kind: HelmRepository
name: jetstack
namespace: flux-system
values:
installCRDs: true
podDnsPolicy: None
podDnsConfig:
nameservers:
- 8.8.8.8
- 1.1.1.1
Кастомный DNS важен — поды cert-manager должны опрашивать авторитативный DNS-сервер домена, а не кластерный DNS.
ClusterIssuer с ACME DNS-01
Для доменов на Yandex Cloud DNS:
yamlapiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@antonnovikov.com
privateKeySecretRef:
name: letsencrypt-prod-account-key
solvers:
- dns01:
webhook:
groupName: acme.yandex.cloud
solverName: yandex-cloud-dns
config:
folder: "${YC_FOLDER_ID}"
serviceAccountSecretRef:
name: yc-dns-sa-key
key: sa-key.json
Для AWS Route53:
yamlsolvers:
- dns01:
route53:
region: us-east-1
accessKeyIDSecretRef:
name: route53-credentials
key: access-key-id
secretAccessKeySecretRef:
name: route53-credentials
key: secret-access-key
Для Cloudflare:
yamlsolvers:
- dns01:
cloudflare:
email: admin@example.com
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token
Certificate
yamlapiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: dev-wildcard
namespace: ingress-apisix
spec:
secretName: dev-test-antonnovikov-com-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
commonName: "*.dev.test.antonnovikov.com"
dnsNames:
- "*.dev.test.antonnovikov.com"
- "dev.test.antonnovikov.com"
duration: 2160h # 90 дней (максимум Let's Encrypt)
renewBefore: 360h # обновить за 15 дней до истечения
cert-manager создаёт Secret с tls.crt и tls.key. APISIX или Ingress ссылается на этот Secret.
Распространение на spoke-кластеры
cert-manager работает только на infra. Spoke-кластеры получают сертификаты через SealedSecrets:
- cert-manager выпускает сертификат → Secret в
ingress-apisixна infra - Запечатать:
kubeseal --context=dev-k8s -o yaml < secret.yaml > sealed.yaml - Закоммитить в
fluxcd/projects/dev/kustomization/spoke/secrets/dev-wildcard-tls.yaml - Flux применяет на spoke при следующей реконсиляции
При обновлении (cert-manager обновляет за 15 дней до истечения) — перезапечатать и закоммитить.
Диагностика
bash# Статус сертификата
kubectl describe certificate dev-wildcard -n ingress-apisix
# Статус CertificateRequest
kubectl describe certificaterequest -n ingress-apisix
# Статус ACME challenge
kubectl describe challenge -n ingress-apisix
# Логи webhook
kubectl logs -n cert-manager -l app=cert-manager-webhook-yandex
# Проверить TXT-запись
dig TXT _acme-challenge.dev.test.antonnovikov.com @8.8.8.8
Самая частая проблема: TXT-запись не успела разойтись по DNS до проверки валидаторами Let's Encrypt. Убедитесь, что запись _acme-challenge.dev.test.antonnovikov.com появляется до истечения таймаута challenge (по умолчанию 60 секунд).
Жизненный цикл сертификата
Certificate → CertificateRequest → Order → Challenge
Если у Certificate условие Ready в состоянии False:
kubectl get challenge— challenge в pending дольше 2 минут означает медленное распространение DNS-записейkubectl get order— статус ACME order- Логи контроллера:
kubectl logs -n cert-manager deploy/cert-manager
Лимиты Let's Encrypt: 50 сертификатов на зарегистрированный домен в неделю. При тестировании используйте letsencrypt-staging.