Гид по технологиям

Установка Cert‑Manager и выпуск сертификатов Let's Encrypt в Kubernetes

• 6 min read • Kubernetes • Обновлено 21 Nov 2025
Установка Cert‑Manager и Let's Encrypt в Kubernetes
Установка Cert‑Manager и Let's Encrypt в Kubernetes

Обложка: архитектура Cert-Manager и выпуск сертификатов

Кратко о Cert‑Manager

Cert‑Manager — это контроллер Kubernetes для управления сертификатами TLS. Он автоматизирует выпуск, проверку и продление сертификатов от разных поставщиков (Let’s Encrypt, HashiCorp Vault, Venafi, собственная подпись и прочие). Cert‑Manager следит за сроками действия сертификатов и обновляет их до истечения срока.

Ключевые объекты Cert‑Manager (в одной строке):

  • Issuer / ClusterIssuer — параметризуют CA и способ получения сертификата.
  • Certificate — namespaced ресурс, который ссылается на Issuer/ClusterIssuer и автоматически обновляется.
  • CertificateRequest — запрос на выпуск сертификата.
  • ACME Order / Challenge — внутренняя модель для взаимодействия с ACME (Let’s Encrypt).
  • Webhook — валидация и конверсия CRD.
  • CA Injector — внедряет CA в манифесты webhook’ов.

Важно: этот материал фокусируется на установке через Helm и интеграции с Ingress (HTTP‑01 challenge). Предполагается базовое знание Kubernetes и Ingress.

Что мы сделаем

  1. Проверим Ingress Controller в кластере
  2. Установим Cert‑Manager через Helm
  3. Создадим манифесты для образца приложения (3 приложения nginx)
  4. Настроим ClusterIssuer для Let’s Encrypt (staging и production)
  5. Развернём приложение и Ingress с аннотацией cert‑manager
  6. Проверим сертификаты, секреты и доступ по HTTPS

Предпосылки

  • Аккаунт в облаке (например, AWS).
  • Рабочий Kubernetes‑кластер.
  • NGINX Ingress Controller в кластере.
  • Helm v3 (в примере использована v3.5.3).
  • S3 для бэкапов/хранилища (если используется).
  • Доменное имя и настройка DNS (A/ALIAS/Кластерный балансировщик).
  • IAM с правами администратора (для примера на AWS).

Примечание: проверки по установке Ingress Controller, Helm и созданию кластера приведены как ссылки в оригинале; здесь предполагается, что вы уже прошли эти шаги.

Проверка Ingress Controller в кластере

Убедитесь, что контроллер Ingress запущен:

kubectl get pods
kubectl get svc

Если в выводе виден nginx‑ingress (или иной ingress controller), можно продолжать.

Установка Cert‑Manager через Helm

Пример с Helm (в исходном блоге использовался локальный бинарь ./helm — у вас может быть глобальная команда helm):

kubectl create namespace cert-manager
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.2.0 --set installCRDs=true

Установка Cert Manager — вывод Helm

Проверьте созданные поды в namespace cert‑manager:

kubectl get pods -n cert-manager

Поды Cert Manager

Ожидаемые компоненты: cert‑manager, cert‑manager‑webhook, cert‑manager‑cainjector.

Создание манифестов для примера приложения и Issuer’ов

Ниже — mанифесты из оригинала. Сохраните их как файлы и примените командой kubectl apply -f <файл>.

Создаём 1‑nginx‑main‑app.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: nginx
  name: nginx-deploy-main
spec:
  replicas: 1
  selector:
    matchLabels:
      run: nginx-main
  template:
    metadata:
      labels:
        run: nginx-main
    spec:
      containers:
      - image: nginx
        name: nginx


---
apiVersion: v1
kind: Service
metadata:
  name: nginx-deploy-main
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    run: nginx-main

Создаём 2‑nginx‑green‑app.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: nginx
  name: nginx-deploy-green
spec:
  replicas: 1
  selector:
    matchLabels:
      run: nginx-green
  template:
    metadata:
      labels:
        run: nginx-green
    spec:
      volumes:
      - name: webdata
        emptyDir: {}
      initContainers:
      - name: web-content
        image: busybox
        volumeMounts:
        - name: webdata
          mountPath: "/webdata"
        command: ["/bin/sh", "-c", 'echo "

I am GREEN

" > /webdata/index.html'] containers: - image: nginx name: nginx volumeMounts: - name: webdata mountPath: "/usr/share/nginx/html" --- --- apiVersion: v1 kind: Service metadata: name: nginx-deploy-green spec: type: ClusterIP ports: - port: 80 targetPort: 80 selector: run: nginx-green

Создаём 3‑nginx‑blue‑app.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: nginx
  name: nginx-deploy-blue
spec:
  replicas: 1
  selector:
    matchLabels:
      run: nginx-blue
  template:
    metadata:
      labels:
        run: nginx-blue
    spec:
      volumes:
      - name: webdata
        emptyDir: {}
      initContainers:
      - name: web-content
        image: busybox
        volumeMounts:
        - name: webdata
          mountPath: "/webdata"
        command: ["/bin/sh", "-c", 'echo "

I am BLUE

" > /webdata/index.html'] containers: - image: nginx name: nginx volumeMounts: - name: webdata mountPath: "/usr/share/nginx/html" --- apiVersion: v1 kind: Service metadata: name: nginx-deploy-blue spec: type: ClusterIP ports: - port: 80 targetPort: 80 selector: run: nginx-blue

Создаём Ingress для staging (4‑tls‑ingress.yaml):

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: letsencrypt-staging
  name: ingress-resource-3
spec:
  tls:
  - hosts:
    - kops.devopslee.com
    secretName: sample-kubernetes-tls
  rules:
  - host: kops.devopslee.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx-deploy-main
          servicePort: 80
      - path: /blue
        backend:
          serviceName: nginx-deploy-blue
          servicePort: 80
      - path: /green
        backend:
          serviceName: nginx-deploy-green
          servicePort: 80

Ingress для production (5‑tls‑ingress‑prod‑issuer.yaml) отличается только аннотацией:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: letsencrypt-production
  name: ingress-resource-3
spec:
  tls:
  - hosts:
    - kops.devopslee.com
    secretName: sample-kubernetes-tls
  rules:
  - host: kops.devopslee.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx-deploy-main
          servicePort: 80
      - path: /blue
        backend:
          serviceName: nginx-deploy-blue
          servicePort: 80
      - path: /green
        backend:
          serviceName: nginx-deploy-green
          servicePort: 80

ClusterIssuer для Let’s Encrypt Staging (staging_issuer.yaml):

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # Email address used for ACME registration
    email: your-email-id-here
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # Name of a secret used to store the ACME account private key
      name: letsencrypt-staging-private-key
    # Add a single challenge solver, HTTP01 using nginx
    solvers:
    - http01:
        ingress:
          class: nginx

ClusterIssuer для Let’s Encrypt Production (production_issuer.yaml):

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-production
spec:
  acme:
    # Email address used for ACME registration
    email: your-email-id-here
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # Name of a secret used to store the ACME account private key
      name: letsencrypt-production-private-key
    # Add a single challenge solver, HTTP01 using nginx
    solvers:
    - http01:
        ingress:
          class: nginx

Все файлы можно хранить в Git и применять из репозитория.

Установка ClusterIssuer (staging и production)

Применяем staging Issuer:

kubectl apply -f cluster-issuer/staging_issuer.yaml

Логирование cert‑manager поможет наблюдать процесс:

kubectl logs -n cert-manager -f deploy/cert-manager

После успешного применения появится секрет с приватным ключом ACME‑аккаунта:

kubectl get secret letsencrypt-staging-private-key -n cert-manager -o json

Проверка секретов staging

Аналогично для production:

kubectl apply -f cluster-issuer/production_issuer.yaml
kubectl get secret letsencrypt-production-private-key -n cert-manager -o json

Проверка секретов production

Развёртывание образца приложения

Применяем три приложения:

kubectl apply -f sample-app/1-nginx-main-app.yaml
kubectl apply -f sample-app/2-nginx-green-app.yaml
kubectl apply -f sample-app/3-nginx-blue-app.yaml

Проверяем ресурсы:

kubectl get deployments
kubectl get pods
kubectl get svc

Развёртывание примера

Развёртывание Ingress и автоматический выпуск сертификата (staging)

Применяем Ingress со ссылкой на letsencrypt‑staging:

kubectl apply -f sample-app/4-tls-ingress.yaml

Проверяем Ingress и его состояние:

kubectl get ingress
kubectl describe ingress ingress-resource-3

Ingress с staging Issuer

Cert‑Manager создаст объекты Certificate, CertificateRequest, Order и Challenges:

kubectl get certificate -A
kubectl get certificaterequests.cert-manager.io -A
kubectl get orders.acme.cert-manager.io -A
kubectl get challenges.acme.cert-manager.io -A

И секрет с TLS материалами:

kubectl get secret sample-kubernetes-tls -o yaml

Проверка Certificate и секретов

Переход по HTTPS покажет предупреждение в браузере, если использован staging (невалидный CA для браузеров):

Проверка HTTPS c staging

Переход на production Issuer

Удаляем staging Ingress и создаём Ingress с production‑issuer:

kubectl delete -f sample-app/4-tls-ingress.yaml
kubectl apply -f sample-app/5-tls-ingress-prod-issuer.yaml

Проверяем, что cert‑manager обработал запрос и сертификат выдан от Let’s Encrypt production. При корректной конфигурации браузер не покажет предупреждений.

Ingress с production Issuer

Проверка HTTPS с production

Отладка и часто встречаемые проблемы

  • ACME challenge не проходит: проверьте, что Ingress доступен извне и DNS указывает на ваш балансировщик.
  • Неправильный класс Ingress: убедитесь, что в ClusterIssuer solver указан ingress.class: nginx, если у вас nginx controller.
  • Firewall / Security Group блокирует HTTP (80): HTTP‑01 требует доступ по 80 порту.
  • Секрет не создаётся: посмотрите логи cert‑manager и описания Certificate/CertificateRequest для ошибок.

Команды для диагностики:

kubectl describe certificaterequest  -n 
kubectl describe challenge  -n 
kubectl logs -n cert-manager deploy/cert-manager

Резервный план и ограничения

  • Если DNS‑провайдер не поддерживает быструю пропагацию, ACME‑challenge по HTTP может падать — используйте DNS‑01 (требует API доступа к DNS).
  • Для приватных кластеров без внешнего доступа используйте Vault/ACME DNS‑01 или внутренний CA.

Контрольные списки по ролям

Администратор кластера:

  • Создать namespace cert‑manager
  • Установить Helm chart с installCRDs=true
  • Обеспечить доступ к 80/443 извне
  • Настроить RBAC для cert‑manager

DevOps-инженер:

  • Подготовить ClusterIssuer и email для ACME
  • Настроить DNS и проверить A/ALIAS записи
  • Развернуть Ingress с аннотацией cert-manager.io/cluster-issuer

Разработчик приложения:

  • Убедиться, что сервисы работают на ожидаемых портах
  • Добавить readiness/liveness probes
  • Тестировать доступ через Ingress по HTTP и HTTPS

Мини‑методология выпуска TLS‑сертификата (шаги)

  1. Установить cert‑manager и CRD.
  2. Настроить ClusterIssuer (staging для тестов, production для реального трафика).
  3. Развернуть приложение и Service.
  4. Создать Ingress с аннотацией cert‑manager и TLS секцией.
  5. Проверить объекты Certificate / CertificateRequest / Order / Challenge.
  6. Подтвердить получение секрета и доступ по HTTPS.
  7. Настроить мониторинг и оповещения на ошибки продления.

Критерии приёмки

  • Certificate успешно создан и имеет статус Ready.
  • Секрет sample-kubernetes-tls содержит tls.crt и tls.key.
  • HTTPS на домене доступен без предупреждений (для production).
  • Cert‑Manager автоматически продлевает сертификат за N дней до истечения (N определяется в spec.Certificate).

Тесты и приёмочные сценарии

  • Применить staging ClusterIssuer и Ingress → ожидать создание Certificate и секретов.
  • Удалить Ingress → Certificate не должен автоматически удалять секрет (поведение зависит от spec).
  • Переключиться на production ClusterIssuer и убедиться, что сертификат меняется без аварийного простоя.

Примеры, когда этот подход не сработает

  • Отсутствует внешний доступ по HTTP (порт 80) — HTTP‑01 не пройдёт.
  • DNS‑провайдер не предоставляет API для автоматизации (для DNS‑01 потребуется ручная подстановка TXT).
  • Приватная сеть, где внешний ACME‑сервер не видит ваш Ingress — нужен внутренний CA.

Факт‑бокс — ключевые объекты и поведение

  • Issuer / ClusterIssuer — задаёт параметры CA и challenge solver.
  • Certificate — создает Secret, содержащий tls.crt/tls.key.
  • ACME workflow: CertificateRequest → Order → Challenge → Validation → Certificate.
  • Webhook и CA injector обеспечивают корректную работу CRD и автоматическую подстановку CA в webhook’ы.

Диаграмма принятия решения (Mermaid)

flowchart TD
  A[Нужен TLS для домена?] -->|Да| B{Есть внешний доступ по HTTP?
}
  B -- Да --> C[Использовать HTTP-01 через Ingress]
  B -- Нет --> D{Можно ли управлять DNS через API?}
  D -- Да --> E[Использовать DNS-01]
  D -- Нет --> F[Использовать внутренний CA или Vault]
  A -->|Нет| G[Оставить HTTP]

Безопасность и эксплуатация

  • Храните секреты TLS в Kubernetes в зашифрованном виде (например, использовать KMS или Sealed Secrets).
  • Контролируйте доступ к namespace cert‑manager и ClusterIssuer ресурсам.
  • Логи cert‑manager не должны содержать приватных ключей.

Краткий глоссарий (1‑строка)

  • ACME — протокол автоматического выпуска сертификатов (используется Let’s Encrypt).
  • HTTP‑01 — ACME challenge, где CA проверяет доступность ресурса по HTTP.
  • DNS‑01 — ACME challenge через TXT запись в DNS.

Локальные рекомендации и ошибки для региона

  • При использовании облачных провайдеров убедитесь, что DNS записи обновляются быстро; в некоторых регионах возможна задержка репликации DNS.
  • Для корпоративных сред с жёсткой сетевой политикой предпочтительнее DNS‑01 или внутренний CA.

Заключение

Мы прошли полный путь: установка Cert‑Manager через Helm, создание ClusterIssuer для Let’s Encrypt (staging и production), развёртывание трёх демонстрационных приложений и настройка Ingress с автоматическим выпуском TLS‑сертификатов. Cert‑Manager автоматизирует рутинную часть управления сертификатами, но требует корректной настройки сетевого доступа, DNS и ролей доступа.

Краткие рекомендации для эксплуатации: используйте staging для тестов, всегда проверяйте доступность HTTP/80 перед запуском HTTP‑01, поставьте мониторинг и оповещения о неудачных продлениях.

Дополнительно проверьте официальную документацию Cert‑Manager для сложных сценариев (DNS‑01, Vault, Venafi и т.д.).

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Несколько аккаунтов Skype: Multi Skype Launcher
Программное обеспечение

Несколько аккаунтов Skype: Multi Skype Launcher

Журнал для работы: повысить продуктивность
Productivity

Журнал для работы: повысить продуктивность

Персональные звуки уведомлений на Android
Android.

Персональные звуки уведомлений на Android

Скачивание шоу Hulu для офлайн‑просмотра
Стриминг

Скачивание шоу Hulu для офлайн‑просмотра

Microsoft Start: персонализированная новостная лента
Новости

Microsoft Start: персонализированная новостная лента

Как изменить имя в Epic Games быстро
Гайды

Как изменить имя в Epic Games быстро