Cert-Manager на Kubernetes: Повний посібник з налаштування автоматизованого управління TLS-сертифікатами
Cert-Manager — це контролер Kubernetes з відкритим вихідним кодом, який повністю автоматизує життєвий цикл TLS-сертифікатів — від початкового видачі через перевірку та поновлення — шляхом прямої інтеграції з центрами сертифікації, такими як Let's Encrypt, HashiCorp Vault та приватними PKI-системами. Він усуває ручні процеси роботи із сертифікатами, розглядаючи їх як нативні ресурси Kubernetes, якими керують декларативно через Custom Resource Definitions (CRDs).
Для будь-якого виробничого кластера Kubernetes прострочені або неправильно налаштовані TLS-сертифікати є однією з найпоширеніших причин незапланованих простоїв. Cert-Manager вирішує цю проблему, постійно узгоджуючи стан сертифікатів, автоматично поновлюючи облікові дані до закінчення терміну дії та зберігаючи отриманий ключовий матеріал у Kubernetes Secrets, які контролери Ingress та робочі навантаження можуть використовувати негайно.
Чому Cert-Manager є стандартом для автоматизації TLS у Kubernetes
До того як Cert-Manager став де-факто рішенням, команди або писали скрипти для поновлення certbot на окремих вузлах, вручну ротували сертифікати між просторами імен, або покладалися на інтеграції, специфічні для хмарних провайдерів, що створювало прив’язку до постачальника. Cert-Manager об’єднує всі ці підходи під єдиною, нативною для Kubernetes площиною управління.
Ключові переваги порівняно з нестандартними підходами:
- Декларативне управління: Намір щодо сертифіката виражається як YAML-маніфест, що версіонується разом із кодом застосунку.
- Автоматичне узгодження: Цикл контролера виявляє розбіжності між бажаним і фактичним станом сертифіката та виправляє їх без участі людини.
- Підтримка кількох видавців: Один кластер може одночасно використовувати Let's Encrypt для публічних сервісів, внутрішній CA для service-mesh mTLS та HashiCorp Vault для робочих навантажень, чутливих до секретів.
- Журнал аудиту: Кожен об’єкт
CertificateRequestзберігається в Kubernetes API, надаючи вам повну історію видачі.
Запуск Kubernetes на платформі VPS Хостинг зі сховищем на основі NVMe та повним root-доступом дає вам контроль, необхідний для налаштування власних DNS-резолверів, управління правилами брандмауера для ACME HTTP-01 завдань та встановлення CRDs на рівні кластера без обмежень — усе це є передумовами для розгортання Cert-Manager виробничого рівня.
Основна архітектура: як Cert-Manager працює зсередини
Розуміння внутрішньої архітектури Cert-Manager запобігає неправильним конфігураціям і допомагає швидко налагоджувати збої видачі.
Машина станів життєвого циклу сертифіката
Cert-Manager керує сертифікатами через детерміновану машину станів. Кожен ресурс Certificate переходить через такі стани:
- Pending — Об’єкт
Certificateіснує, але жоден дійснийCertificateRequestне був виконаний. - Issuing —
CertificateRequestбуло створено та подано до налаштованого видавця. - Ready — Дійсний, непрострочений сертифікат зберігається у вказаному Kubernetes
Secret. - Renewal Pending — Сертифікат знаходиться у вікні
renewBefore(за замовчуванням: 30 днів до закінчення терміну дії) і новийCertificateRequestобробляється.
Контролер відстежує всі об’єкти Certificate у всьому кластері та постійно узгоджує їх стан. Якщо Secret видалено вручну, Cert-Manager виявляє відсутній ресурс і негайно ініціює повторну видачу — критична поведінка самовідновлення, що запобігає випадковим збоям.
Основні компоненти CRD
| Ресурс | Область | Призначення |
|---|---|---|
| — | — | — |
| `Issuer` | Простір імен | Визначає конфігурацію CA для одного простору імен |
| `ClusterIssuer` | Весь кластер | Визначає конфігурацію CA, доступну для всіх просторів імен |
| `Certificate` | Простір імен | Оголошує бажаний TLS-сертифікат та його властивості |
| `CertificateRequest` | Простір імен | Відстежує одиничний, одноразовий запит на підписання сертифіката |
| `Order` | Простір імен | Представляє замовлення ACME до CA (наприклад, Let's Encrypt) |
| `Challenge` | Простір імен | Відстежує одиничне завдання ACME (HTTP-01 або DNS-01) |
Ресурси Order та Challenge створюються автоматично видавцем ACME — ви рідко взаємодієте з ними безпосередньо, але їх перевірка є основним шляхом налагодження, коли видача зупиняється.
Зберігання сертифікатів та формат Secret
Після видачі Cert-Manager записує три ключі даних у цільовий Kubernetes Secret:
tls.crt— Повний ланцюжок сертифікатів (кінцевий + проміжні), закодований у PEM.tls.key— Приватний ключ, закодований у PEM.ca.crt— Сертифікат видавця CA (заповнюється для внутрішніх CA; може бути порожнім для видавців ACME).
Контролери Ingress, service mesh та поди застосунків монтують цей Secret безпосередньо. Формат сумісний з NGINX, Traefik, Istio, Linkerd та більшістю інших нативних для Kubernetes споживачів TLS.
Підтримувані видавці та коли використовувати кожен
ACME (Let's Encrypt та альтернативи)
Протокол ACME є найпоширенішим шляхом видачі. Cert-Manager реалізує повний ACME-клієнт RFC 8555, підтримуючи як тестові, так і виробничі кінцеві точки.
Завдання HTTP-01: Cert-Manager тимчасово обслуговує токен за адресою http://<domain>/.well-known/acme-challenge/<token>. Для цього потрібно, щоб домен розпізнавався до публічно доступної IP-адреси на порту 80. Це працює для сертифікатів з одним доменом та SAN, але не може видавати wildcard-сертифікати.
Завдання DNS-01: Cert-Manager створює TXT-запис _acme-challenge.<domain> через API DNS-провайдера. Це працює за брандмауерами, підтримує wildcard-сертифікати (*.example.com) і є обов’язковим для будь-якого кластера, не підключеного безпосередньо до інтернету. Підтримувані DNS-провайдери включають Cloudflare, Route53, Google Cloud DNS, Azure DNS та багато інших через webhook-розв’язувачі.
HashiCorp Vault
Видавець Vault інтегрується з рушієм секретів PKI у Vault. Це кращий вибір для:
- Внутрішнього mTLS мікросервісів, де сертифікати мають бути короткоживучими (години, а не місяці).
- Середовищ із суворими вимогами до зберігання ключів, де приватні ключі ніколи не повинні покидати Vault.
- Автоматичної ротації сертифікатів, пов’язаної з системою поновлення оренди Vault.
Самопідписані та CA-видавці
Видавець SelfSigned генерує сертифікати, підписані власним приватним ключем сертифіката — корисно для початкового завантаження кореневого CA в кластері. Видавець CA використовує Kubernetes Secret, що містить пару ключів CA, для підписання сертифікатів, що робить його придатним для внутрішніх середовищ розробки та PKI service mesh.
Venafi
Інтеграція з Venafi орієнтована на корпоративні середовища з централізованим застосуванням політики сертифікатів, аудитом відповідності та інтеграцією з апаратними модулями безпеки (HSM).
Cert-Manager порівняно з альтернативними підходами до автоматизації TLS
| Підхід | Підтримка Wildcard | Нативний для Kubernetes | Multi-CA | Автоматичне поновлення | Складність |
|---|---|---|---|---|---|
| — | — | — | — | — | — |
| Cert-Manager | Так (DNS-01) | Так (CRDs) | Так | Так | Середня |
| Ручний Certbot | Ні (лише HTTP-01) | Ні | Обмежено | За скриптом | Низька–Середня |
| Завершення TLS на хмарному балансувальнику навантаження | Залежить | Ні | Ні | Так | Низька |
| Istio / Service Mesh CA | Лише внутрішній | Так | Ні | Так | Висока |
| HashiCorp Vault (окремо) | Так | Ні | Так | Вручну | Висока |
Для команд, що запускають Kubernetes на Виділеному сервері або VPS, Cert-Manager є єдиним підходом, який одночасно є нативним для Kubernetes, підтримує всі основні CA та не потребує жодного постійного ручного втручання.
Встановлення Cert-Manager: налаштування виробничого рівня
Передумови
- Kubernetes 1.22+ (рекомендується 1.26+ для повної стабільності CRD)
kubectlналаштований з привілеями cluster-admin- Встановлений Helm 3.x
- Зареєстрований домен з доступом до управління DNS (для DNS-01) або публічно доступна IP-адреса ingress (для HTTP-01)
Якщо ви керуєте власним доменом, настійно рекомендується Реєстрація домену через провайдера, який надає API — це дозволяє повністю автоматизувати вирішення завдань DNS-01 без ручного втручання.
Крок 1: Встановлення CRDs та контролера Cert-Manager
Рекомендований метод виробничого встановлення використовує Helm з CRDs, що керуються окремо, щоб уникнути конфліктів при оновленні Helm:
# Add the Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io
helm repo update
# Install Cert-Manager with CRDs included
helm install cert-manager jetstack/cert-manager
--namespace cert-manager
--create-namespace
--version v1.14.5
--set installCRDs=true
--set global.leaderElection.namespace=cert-managerПеревірте, що всі три основні поди запущені, перш ніж продовжувати:
kubectl get pods --namespace cert-managerОчікуваний результат:
NAME READY STATUS RESTARTS AGE
cert-manager-xxxxxxxxx-xxxxx 1/1 Running 0 60s
cert-manager-cainjector-xxxxxxxxx-xxxxx 1/1 Running 0 60s
cert-manager-webhook-xxxxxxxxx-xxxxx 1/1 Running 0 60scainjector вставляє дані пакета CA у конфігурації webhook. webhook перевіряє та змінює об’єкти CRD Cert-Manager — якщо він не запущений, всі операції kubectl apply з ресурсами Cert-Manager завершаться невдачею.
Крок 2: Налаштування ClusterIssuer для Let's Encrypt
Завжди починайте з тестового середовища Let's Encrypt, щоб уникнути досягнення виробничих обмежень частоти (50 сертифікатів на зареєстрований домен на тиждень):
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: ops@example.com
privateKeySecretRef:
name: letsencrypt-staging-account-key
solvers:
- http01:
ingress:
class: nginxПісля успішної видачі тестових сертифікатів створіть виробничий видавець:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ops@example.com
privateKeySecretRef:
name: letsencrypt-prod-account-key
solvers:
- http01:
ingress:
class: nginxЗастосуйте обидва маніфести:
kubectl apply -f clusterissuer-staging.yaml
kubectl apply -f clusterissuer-prod.yamlПеревірте готовність видавця:
kubectl describe clusterissuer letsencrypt-prodПоле Status.Conditions повинно показувати Ready: True. Якщо воно показує False, реєстрація облікового запису ACME не вдалася — перевірте адресу електронної пошти та мережеве підключення з поду cert-manager.
Крок 3: Явний запит сертифіката
Ви можете запитувати сертифікати або шляхом безпосереднього створення ресурсу Certificate, або шляхом анотування ресурсу Ingress. Явний підхід Certificate дає вам більше контролю:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com-tls
namespace: production
spec:
secretName: example-com-tls-secret
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
commonName: example.com
dnsNames:
- example.com
- www.example.com
duration: 2160h # 90 days (Let's Encrypt default)
renewBefore: 720h # Renew 30 days before expiryЗастосуйте та відстежуйте видачу:
kubectl apply -f certificate.yaml
kubectl describe certificate example-com-tls -n productionСпостерігайте за об’єктами CertificateRequest та Order для отримання детального статусу:
kubectl get certificaterequest -n production
kubectl describe order -n productionКрок 4: Метод анотації Ingress (спрощений)
Для команд, що використовують NGINX Ingress Controller, Cert-Manager може бути запущений автоматично через анотацію — окремий маніфест Certificate не потрібен:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: production
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- example.com
- www.example.com
secretName: example-com-tls-secret
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80Cert-Manager виявляє анотацію та автоматично створює відповідний ресурс Certificate. Це найпоширеніший шаблон у GitOps-робочих процесах.
Розширені шаблони конфігурації
Wildcard-сертифікати з DNS-01 (приклад Cloudflare)
Wildcard-сертифікати вимагають перевірки DNS-01. Спочатку створіть Secret, що містить ваш API-токен Cloudflare:
kubectl create secret generic cloudflare-api-token
--from-literal=api-token=<YOUR_CLOUDFLARE_API_TOKEN>
--namespace cert-managerНалаштуйте ClusterIssuer з розв’язувачем DNS-01:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod-dns
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ops@example.com
privateKeySecretRef:
name: letsencrypt-prod-dns-account-key
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: api-tokenЗапитайте wildcard-сертифікат:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-example-com
namespace: production
spec:
secretName: wildcard-example-com-tls
issuerRef:
name: letsencrypt-prod-dns
kind: ClusterIssuer
dnsNames:
- "*.example.com"
- example.comКритична пастка: Secret, що містить облікові дані DNS-провайдера, повинен знаходитися в просторі імен cert-manager при посиланні з ClusterIssuer. Якщо ви розмістите його в іншому просторі імен, контролер не зможе його прочитати, і видача мовчки завершиться невдачею. Перевірте журнали контролера cert-manager за допомогою kubectl logs -n cert-manager deploy/cert-manager, якщо завдання зупиняються.
Внутрішня PKI з видавцем CA
Для mTLS між сервісами всередині кластера видавець CA, підкріплений самопідписаним кореневим сертифікатом, є більш відповідним, ніж ACME:
# Step 1: Create a self-signed root CA certificate
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-root
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: internal-root-ca
namespace: cert-manager
spec:
isCA: true
commonName: internal-root-ca
secretName: internal-root-ca-secret
issuerRef:
name: selfsigned-root
kind: ClusterIssuer
---
# Step 2: Create a CA issuer backed by the root certificate
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: internal-ca-issuer
spec:
ca:
secretName: internal-root-ca-secretСервіси тепер можуть запитувати короткоживучі сертифікати від internal-ca-issuer для mTLS без будь-якої залежності від зовнішнього CA.
Налаштування renewBefore для середовищ з підвищеною безпекою
Стандартне значення renewBefore у 30 днів підходить для 90-денних сертифікатів Let's Encrypt. Для короткоживучих внутрішніх сертифікатів (наприклад, з терміном дії 24 години) встановіть renewBefore як частку від загальної тривалості:
spec:
duration: 24h
renewBefore: 8hCert-Manager почне поновлення за 8 годин до закінчення терміну дії, надаючи контролеру три вікна поновлення протягом 24-годинного терміну дії сертифіката — критичний запас безпеки, якщо кластер відчуває тимчасову недоступність API-сервера.
Налагодження поширених збоїв Cert-Manager
Сертифікат застряг у стані “Issuing”
# Check the Certificate status
kubectl describe certificate <name> -n <namespace>
# Check the associated CertificateRequest
kubectl describe certificaterequest -n <namespace>
# Check the ACME Order
kubectl describe order -n <namespace>
# Check the Challenge
kubectl describe challenge -n <namespace>
# Check controller logs
kubectl logs -n cert-manager deploy/cert-manager --tail=100Поширені першопричини:
- Збій HTTP-01: Контролер Ingress неправильно маршрутизує трафік
/.well-known/acme-challenge/. Перевірте, що об’єктIngressзавдання був створений і що порт 80 доступний з інтернету. Брандмауери на хості повинні дозволяти вхідний TCP/80. - Збій DNS-01: API-токен DNS-провайдера має недостатні дозволи, або поширення DNS ще не завершено. Сервери перевірки Let's Encrypt можуть запитувати інші резолвери, ніж ваш локальний DNS — затримки поширення від 60 до 120 секунд є нормальними.
- Перевищено обмеження частоти: Let's Encrypt застосовує 5 невдалих спроб перевірки на домен на годину. Після досягнення цього обмеження необхідно зачекати перед повторною спробою. Завжди спочатку тестуйте з тестовою кінцевою точкою.
- Webhook не готовий: Якщо под webhook cert-manager не запущений, всі операції з CRD завершаться помилкою відмови в з’єднанні. Переконайтеся, що сервіс webhook має дійсну кінцеву точку.
Перевірка розгорнутого сертифіката
# Check the Secret contents
kubectl get secret example-com-tls-secret -n production -o jsonpath='{.data.tls.crt}' | base64 -d | openssl x509 -noout -text
# Check expiry date specifically
kubectl get secret example-com-tls-secret -n production -o jsonpath='{.data.tls.crt}' | base64 -d | openssl x509 -noout -enddateКонтрольний список для захисту виробничого середовища
Розгортання Cert-Manager у виробничому середовищі вимагає більшого, ніж стандартне встановлення Helm. Застосуйте ці заходи захисту перед запуском у виробництво:
- Обмеження ресурсів: Встановіть
requestsтаlimitsCPU і пам’яті для всіх трьох подів Cert-Manager, щоб запобігти конкуренції за ресурси на спільних вузлах. - Аудит RBAC: Cert-Manager вимагає широких дозволів RBAC. Перегляньте встановлені об’єкти
ClusterRoleта обмежте їх до мінімально необхідного для ваших типів видавців. - Окремий простір імен: Завжди розгортайте Cert-Manager у власному просторі імен
cert-manager, ізольованому від робочих навантажень застосунків. - Моніторинг: Відкрийте кінцеву точку метрик Prometheus Cert-Manager (
--metrics-listen-address) та налаштуйте сповіщення наcertmanager_certificate_expiration_timestamp_seconds, щоб виявляти збої поновлення до того, як вони вплинуть на сервіси. - Резервне копіювання стану CRD: Включіть об’єкти
Certificate,ClusterIssuerтаIssuerу вашу стратегію резервного копіювання кластера. Втрата цих маніфестів після події відновлення після аварії означає ручне відтворення всіх конфігурацій сертифікатів. - Тестова перевірка: Ніколи не видавайте перший сертифікат через виробничу кінцеву точку ACME. Порушення обмежень частоти можуть заблокувати ваш домен на строк до тижня.
Якщо ви запускаєте кілька кластерів Kubernetes — наприклад, розділяючи тестові та виробничі навантаження — Панелі керування VPS можуть спростити управління життєвим циклом кластера та надати вам єдиний інтерфейс для надання базової інфраструктури, на якій працює кожен кластер.
Для робочих навантажень, що потребують GPU-прискореного інференсу або обслуговування ML за TLS-завершеними кінцевими точками, ті самі шаблони Cert-Manager застосовуються на інфраструктурі GPU Хостинг, де автоматизоване управління сертифікатами є однаково критичним для захисту кінцевих точок API моделей.
Практична матриця рішень: вибір правильного видавця
| Сценарій | Рекомендований видавець | Тип завдання | Wildcard |
|---|---|---|---|
| — | — | — | — |
| Публічний веб-застосунок, один домен | `letsencrypt-prod` | HTTP-01 | Ні |
| Публічний веб-застосунок, кілька піддоменів | `letsencrypt-prod` | DNS-01 | Так |
| Ізольований / приватний кластер | `CA` або `Vault` | Н/Д (внутрішній) | Так |
| Корпоративне середовище з вимогами відповідності | `Venafi` | Н/Д | Так |
| Service mesh mTLS (короткоживучі сертифікати) | `Vault` або `CA` | Н/Д (внутрішній) | Так |
| Розробка / локальний кластер | `SelfSigned` або `CA` | Н/Д | Так |
Ключові висновки
- Встановлюйте Cert-Manager за допомогою Helm з
installCRDs=trueта завжди перевіряйте на тестовій кінцевій точці ACME перед переходом до виробництва. - Використовуйте
ClusterIssuerдля кластерів з кількома просторами імен; використовуйтеIssuerз областю простору імен лише тоді, коли вам потрібна ізоляція CA на рівні команди. - DNS-01 є суворо обов’язковим для wildcard-сертифікатів та для кластерів, не доступних безпосередньо з інтернету на порту 80.
- Поле
renewBeforeне є необов’язковим у виробництві — встановіть його принаймні на одну третину від загальногоdurationсертифіката. - Коли видача зупиняється, шлях налагодження завжди такий:
Certificate→CertificateRequest→Order→Challenge→ журнали контролера. - Облікові дані API DNS-провайдера, на які посилається
ClusterIssuer, повинні знаходитися в просторі іменcert-manager, а не в просторах імен застосунків. - Відстежуйте
certmanager_certificate_expiration_timestamp_secondsу Prometheus та налаштуйте сповіщення — мовчазні збої поновлення є найнебезпечнішим режимом відмови. - Включіть маніфести
CertificateтаClusterIssuerдо вашого плану відновлення після аварії.
Часті запитання
У чому різниця між Issuer та ClusterIssuer у Cert-Manager?
Issuer має область простору імен і може видавати сертифікати лише в межах простору імен, де він визначений. ClusterIssuer має область всього кластера і може бути використаний ресурсами Certificate в будь-якому просторі імен. Для більшості виробничих кластерів ClusterIssuer є правильним вибором, якщо тільки вам не потрібна суворо ізоляція CA на рівні простору імен.
Чому мій сертифікат Cert-Manager застряг у стані “Issuing”?
Перевірте об’єкти Order та Challenge в тому самому просторі імен за допомогою kubectl describe. Найпоширеніші причини: порт 80 заблокований брандмауером (HTTP-01), неправильні облікові дані API DNS або затримка поширення (DNS-01), перевищені обмеження частоти Let's Encrypt або под webhook cert-manager не запущений. Завжди перевіряйте журнали контролера за допомогою kubectl logs -n cert-manager deploy/cert-manager.
Чи може Cert-Manager видавати wildcard-сертифікати від Let's Encrypt?
Так, але лише з використанням типу завдання DNS-01. HTTP-01 не може перевіряти wildcard-домени. Ви повинні налаштувати інтеграцію з DNS-провайдером (Cloudflare, Route53 тощо) у конфігурації розв’язувача ClusterIssuer та переконатися, що облікові дані API мають дозвіл на створення TXT-записів для цільового домену.
Як Cert-Manager автоматично обробляє поновлення сертифікатів?
Контролер Cert-Manager постійно порівнює термін дії кожного об’єкта Certificate з поточним часом. Коли залишковий термін дії опускається нижче порогу renewBefore (за замовчуванням: 30 днів), контролер створює новий CertificateRequest, виконує завдання ACME та атомарно замінює вміст цільового Secret — все це без перезапуску подів, що використовують сертифікат. Поди, які монтують Secret як том, побачать оновлений сертифікат під час наступного циклу синхронізації kubelet.
Чи підходить Cert-Manager для захисту внутрішнього зв’язку між сервісами, а не лише публічного HTTPS?
Так. Використовуючи видавець CA або видавець HashiCorp Vault, Cert-Manager може видавати короткоживучі сертифікати для внутрішнього mTLS між мікросервісами. Це поширений шаблон у розгортаннях service mesh, де кожне робоче навантаження потребує унікального сертифіката ідентичності. Поля duration та renewBefore дозволяють сертифікатам бути настільки короткоживучими, як кілька хвилин, з повністю автоматизованою ротацією.
