ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

ACME в Kubernetes: cert-manager против external-dns и ingress-shim (DNS-01 и HTTP-01)

Разбираем два подхода к автоматизации TLS в Kubernetes через ACME: cert-manager как единый контроллер и схему external-dns + ingress-shim. Покажу, как выбирать DNS-01/HTTP-01, настроить Issuer/ClusterIssuer, выпускать wildcard и безопасно хранить secret tls.
ACME в Kubernetes: cert-manager против external-dns и ingress-shim (DNS-01 и HTTP-01)

Зачем сравнивать cert-manager и связку external-dns + ingress-shim

Когда настраиваете ACME в Kubernetes (Let’s Encrypt или любой ACME-совместимый УЦ), быстро становится ясно: выписать один сертификат — не проблема. Проблема начинается с операционки: десятки Ingress, разные namespace, wildcard на поддомены, ротации, rate limits, и главный вопрос — кто и как управляет приватными ключами и обновляет Secret типа kubernetes.io/tls.

На практике обычно встречаются два подхода:

  • cert-manager как центральный контроллер: сам проходит ACME-челленджи (HTTP-01/DNS-01), создаёт/обновляет сертификаты и пишет их в Secrets.
  • external-dns + ingress-shim как «склейка» автоматики вокруг Ingress: external-dns управляет DNS-записями, а shim переводит аннотации Ingress в заявки на сертификаты (часто всё равно через cert-manager).

Важный нюанс: ingress-shim исторически — часть cert-manager. То есть речь обычно не о двух конкурирующих решениях, а о выборе стиля управления: «явные CRD Certificate» против «магия аннотаций на Ingress».

Карта компонентов: кто за что отвечает

cert-manager

cert-manager добавляет в кластер CRD и контроллеры, которые описывают и исполняют жизненный цикл сертификатов:

  • Issuer / ClusterIssuer — где и как выпускать (ACME endpoint, email, solvers, ссылки на секреты с токенами DNS-провайдера).
  • Certificate — декларация «выпусти SAN/wildcard и положи в secretName».
  • Order и Challenge — внутренняя механика ACME (очень полезно для дебага).

Формально вы описываете желаемое состояние (YAML), а cert-manager доводит его до факта: генерирует ключи, проходит проверку домена, обновляет секрет и следит за продлением.

external-dns

external-dns читает источники в Kubernetes (Ingress, Service, Gateway API и т.д.) и создаёт/обновляет DNS-записи у провайдера. Он решает задачу «куда должен указывать домен», но не выпускает TLS-сертификаты сам по себе.

В контексте ACME external-dns полезен для автоматизации A/AAAA/CNAME, чтобы HTTP-01-челленджи и трафик на Ingress вообще доходили до кластера без ручной возни с DNS.

ingress-shim

ingress-shim превращает TLS-описание и аннотации на Ingress в ресурсы Certificate. Дальше уже cert-manager выпускает сертификат и пишет его в secretName, указанный в Ingress.

ingress-shim не заменяет cert-manager. Он только создаёт Certificate по Ingress, а ACME-протокол выполняет cert-manager.

Если вы строите более «платформенный» подход (контроль доменов, лимиты, изоляция), обычно проще жить с явными Certificate и минимальной «магией» в Ingress.

Администратор проверяет ресурсы Certificate, Order и Challenge в Kubernetes для диагностики выпуска

ACME HTTP-01 vs DNS-01 в Kubernetes

HTTP-01: быстро, но зависит от маршрутизации

HTTP-01 подтверждает владение доменом запросом по пути /.well-known/acme-challenge/.... В Kubernetes это обычно означает, что cert-manager создаёт временные ресурсы для отдачи challenge и ожидает, что внешний мир дойдёт до ingress-controller.

Что нужно, чтобы HTTP-01 стабильно работал:

  • внешний DNS указывает на ваш ingress/LB;
  • входящие 80/tcp доступны;
  • маршрутизация не ломает challenge (редиректы, кастомные правила, несколько ingress-контроллеров).

Плюсы: минимум прав в DNS и простая модель для отдельных FQDN. Минусы: wildcard не поддерживается, а ошибки часто связаны не с ACME, а с сетевыми/ingress нюансами.

DNS-01: универсально и подходит для wildcard

DNS-01 подтверждает владение доменом через TXT-запись _acme-challenge. В Kubernetes это почти всегда лучший выбор для:

  • wildcard-сертификатов (*.example.com);
  • закрытых контуров без входящего HTTP;
  • сложных схем с несколькими ingress-контроллерами.

Цена — доступ к DNS API. В идеале TXT для ACME создаёт только cert-manager (через встроенные интеграции или webhook solver), а external-dns параллельно занимается «прикладными» A/AAAA/CNAME. Подробно про автоматизацию wildcard через DNS-01 — в отдельном разборе: wildcard TLS и DNS-01 в автоматизации.

FastFox VDS
Регистрация доменов от 99 руб.
Каждый проект заслуживает идеального доменного имени, выберите один из сотни, чтобы начать работу!

Issuer и ClusterIssuer: как не запутаться

Одна из самых частых ошибок: сделать Issuer в одном namespace, а потом ждать, что сертификаты выпустятся в другом.

  • Issuer действует только в пределах namespace.
  • ClusterIssuer действует на весь кластер.

Практический подход для платформенной команды: используйте ClusterIssuer для типовых сценариев (HTTP-01, DNS-01) и выдавайте командам право создавать Certificate в их namespace. Если у команд разные DNS-зоны/аккаунты/провайдеры и строгая изоляция, тогда Issuer действительно может быть логичнее.

RBAC и безопасность: где чаще всего “протекает”

Почти все «почините cert-manager» в итоге упираются в доступы к Secrets и в соблазн выдать кому-то cluster-admin. Так делать не стоит: это ухудшает безопасность и затрудняет аудит.

Критичные зоны ответственности:

  • Секреты с DNS API-токенами. Храните их в контролируемом namespace (часто cert-manager) и давайте cert-manager ровно те права, которые нужны для чтения этого секрета.
  • TLS Secrets с приватными ключами. Они живут в namespace приложения. Любой, у кого есть read на этот Secret, фактически получает приватный ключ — это нормально, но должно быть осознанно.
  • external-dns. Ему не нужен доступ к TLS secrets. Его зона ответственности — чтение источников и обновление DNS у провайдера.

Цель по безопасности простая: external-dns не видит приватные ключи и ACME/DNS-токены, а cert-manager не получает лишних прав на ресурсы приложения.

Что проще в эксплуатации: реальные сценарии

Сценарий A: отдельные домены без wildcard

Если у вас публичный Ingress и стабильный доступ по 80/tcp, то cert-manager + HTTP-01 закрывает задачу быстро. external-dns в этой схеме опционален: он полезен, когда DNS настраивать вручную уже тяжело, но сам выпуск сертификатов не заменит.

Где помогает ingress-shim: добавили TLS-секцию и аннотацию на Ingress — shim создал Certificate, cert-manager выпустил, секрет появился.

Сценарий B: wildcard на окружение/подзону

Для wildcard почти всегда выбирают DNS-01. В эксплуатации это выглядит просто: один Certificate на *.apps.example.com, один secretName, много Ingress, которые на него ссылаются.

Учитывайте “blast radius”: компрометация одного wildcard-секрета затрагивает все поддомены этой зоны. Если риск не устраивает — разделяйте зоны (например, по namespace/командам) или уходите от wildcard там, где это оправдано.

Сценарий C: мультикластер и/или несколько DNS-провайдеров

Здесь возникает соблазн разнести всё: external-dns делает DNS, команды где-то отдельно выпускают сертификаты и приносят их в виде Secrets. Это работает, но вы теряете единый жизненный цикл, ротации и наблюдаемость. На проде это часто заканчивается «сертификат истёк, никто не заметил».

Если по организационным причинам сертификаты должны выпускаться «снаружи», фиксируйте процесс: кто обновляет секреты, где мониторинг истечения, как делать rollback. Иначе платформа получится хрупкой.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

cert-manager vs external-dns + ingress-shim: сравнение по критериям

Источник истины (source of truth)

  • cert-manager-first: источником истины становится Certificate (или Ingress, если вы сознательно используете shim). Состояние прозрачно в API Kubernetes.
  • аннотации как “контракт”: источником истины становится Ingress. Удобно на старте, но сложнее стандартизировать в большой платформе.

Контроль над DNS и ACME

  • Для DNS-01 TXT должен создавать один компонент (обычно cert-manager). Это снижает гонки и упрощает дебаг.
  • external-dns отлично подходит для A/AAAA/CNAME, но попытки «заставить его помогать» с _acme-challenge часто приводят к конфликтам владения записями.

Наблюдаемость и дебаг

С cert-manager удобнее: вы смотрите события и статусы Certificate, Order, Challenge и быстро понимаете, где сломалось: нет прав, DNS не обновился, HTTP недоступен, упёрлись в rate limit.

В размазанной схеме «external-dns + shim + ещё что-то» проблема часто выглядит одинаково (секрета нет), а причин может быть много. Если вы регулярно упираетесь в лимиты при массовых изменениях, пригодится отдельный разбор: лимиты Let’s Encrypt и массовая автоматизация.

Риски по безопасности

  • Чем меньше компонентов имеют доступ к секретам и API-токенам, тем лучше.
  • С cert-manager проще выстроить строгую модель: где лежат токены, где создаются TLS Secrets, кто может заказывать сертификаты и на какие домены.

Иллюстрация DNS-01: TXT-запись _acme-challenge и подтверждение домена для wildcard-сертификата

Практические YAML-скелеты для ориентира

Ниже — минимальные «контуры» объектов, чтобы быстро сопоставить термины: ClusterIssuer/Issuer, Certificate, secretName. Обратите внимание: это примеры структуры, их нужно адаптировать под ваш ingress-класс и DNS-провайдера.

ClusterIssuer для ACME HTTP-01 (пример)

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-http01
spec:
  acme:
    email: admin@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-http01-account-key
    solvers:
    - http01:
        ingress:
          class: nginx

ClusterIssuer для ACME DNS-01 (пример-скелет)

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-dns01
spec:
  acme:
    email: admin@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-dns01-account-key
    solvers:
    - dns01:
        webhook:
          groupName: acme.example.com
          solverName: dns-provider
          config:
            apiTokenSecretRef:
              name: dns-api-token
              key: token

Certificate для wildcard

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: wildcard-apps
  namespace: apps
spec:
  secretName: wildcard-apps-tls
  issuerRef:
    kind: ClusterIssuer
    name: letsencrypt-dns01
  dnsNames:
  - "*.apps.example.com"
  - "apps.example.com"

Ingress, который использует готовый TLS secret

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app
  namespace: apps
spec:
  tls:
  - hosts:
    - app1.apps.example.com
    secretName: wildcard-apps-tls
  rules:
  - host: app1.apps.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app
            port:
              number: 80

Типовые грабли и как их распознать

Грабля 1: конфликт TXT-записей при DNS-01

Если два контроллера пытаются управлять _acme-challenge, появляются флаппинг TXT, validation failed и гонки. Правило простое: TXT для ACME создаёт только один выбранный компонент (обычно cert-manager).

Грабля 2: Ingress ссылается на secret, который не создался

Если shim создал Certificate, но issuerRef неверный (например, ожидался ClusterIssuer, а указан Issuer), TLS secret не появится, а ingress-controller будет ругаться на отсутствие секрета. Диагностика начинается со статуса Certificate и событий Order/Challenge, а не с самого Ingress.

Грабля 3: RBAC “починили” cluster-admin’ом и забыли

Такое «лечится» до первого инцидента. Если видите, что cert-manager или external-dns требуют слишком широких ролей, остановитесь и разберите: какие ресурсы читаются, какие создаются, в каких namespace и почему.

Грабля 4: rate limits и массовые перевыпуски

При миграциях и массовом пересоздании Ingress легко устроить лавину заявок в ACME и упереться в лимиты. Рабочие практики:

  • используйте staging endpoint для прогонов и тестов;
  • делайте wildcard там, где это действительно уменьшает количество выпусков;
  • стабилизируйте secretName и не пересоздавайте Certificate без необходимости.

Рекомендации по выбору

Берите cert-manager как основу, если

  • нужны декларативные объекты и предсказуемая ротация;
  • планируются wildcard и DNS-01;
  • важны наблюдаемость и единый стандарт для команд.

Подключайте external-dns дополнительно, если

  • хотите автоматически создавать A/AAAA/CNAME по Ingress/Service;
  • у вас много доменов/окружений и ручной DNS стал узким местом.

Осторожнее со ставкой на ingress-shim как на единственный интерфейс, если

  • несколько ingress-контроллеров и разные классы Ingress;
  • нужно строго контролировать, кто может выпускать сертификаты и для каких доменов;
  • вы хотите разнести ответственность: платформа задаёт Certificate, команды только подключают готовый TLS secret.

Итог

Самый устойчивый базовый вариант в Kubernetes — cert-manager как единый контроллер жизненного цикла сертификатов, а external-dns как отдельный слой для управления DNS-записями приложений. ingress-shim воспринимайте как удобный ускоритель на старте, но в зрелой платформе часто выгоднее явно описывать Certificate и контролировать, где и как создаются TLS Secrets.

Если важны wildcard, предсказуемость ротаций и понятный дебаг — выбирайте DNS-01 в cert-manager и аккуратно выстраивайте RBAC. Если нужна простота для небольшого набора доменов и стабильный публичный Ingress — HTTP-01 будет работать отлично, пока сеть и маршрутизация не мешают challenge.

Для инфраструктуры под Kubernetes, где приложения удобно разводить по окружениям и доменам, обычно также заранее решают вопрос с доменами и зоной: регистрация доменов и управление DNS лучше держать в предсказуемой системе, чтобы автоматизация ACME не упиралась в ручные правки.

Поделиться статьей

Вам будет интересно

CrowdSec vs Fail2ban в 2026: защита SSH и Nginx, репутация IP и bouncer’ы OpenAI Статья написана AI (GPT 5)

CrowdSec vs Fail2ban в 2026: защита SSH и Nginx, репутация IP и bouncer’ы

Практическое сравнение CrowdSec и Fail2ban в 2026 для админов: чем отличаются модели банов, как работает IP reputation, какие boun ...
GitOps и управление конфигурациями в 2026: Ansible vs SaltStack vs Puppet vs Chef OpenAI Статья написана AI (GPT 5)

GitOps и управление конфигурациями в 2026: Ansible vs SaltStack vs Puppet vs Chef

Разбираем Ansible, SaltStack, Puppet и Chef в 2026 году с позиции GitOps: push/pull, agentless vs agent, идемпотентность, работа с ...
CrowdSec vs Fail2ban в 2026: защита SSH и Nginx/HTTP на Linux OpenAI Статья написана AI (GPT 5)

CrowdSec vs Fail2ban в 2026: защита SSH и Nginx/HTTP на Linux

Разбираем CrowdSec и Fail2ban в 2026: чем IPS-подход отличается от «бана по шаблону», как работают решения и bouncer под nftables, ...