Автоматический TLS с cert-manager, Let's Encrypt и Traefik IngressRoutes
Published: 2026-04-15
Каждый поддомен на этом сервере получает действующий TLS-сертификат автоматически. Никаких ручных продлений, никаких cronjob с certbot, никаких wildcard-сертификатов. Вот полная картина — от ClusterIssuer до замочка в браузере.
Два issuer: staging и production
yamlapiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- http01:
ingress:
ingressClassName: traefik
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
ingressClassName: traefik
Staging-issuer не расходует лимиты Let's Encrypt (50 сертификатов/домен/неделю). Всегда использовать staging при настройке нового домена — если HTTP-01 challenge провалится (неправильный DNS, заблокирован порт 80), лимиты production не сгорят.
Механика HTTP-01 challenge
Solver http01 доказывает владение доменом, отдавая токен по адресу:
http://<domain>/.well-known/acme-challenge/<token>
cert-manager временно создаёт объект Ingress для этого пути. Traefik подхватывает его и маршрутизирует запрос ACME-сервера к поду cert-manager.
Обязательные условия:
- A-запись домена должна указывать на публичный IP сервера до запроса сертификата.
- Порт 80 должен быть открыт. Traefik слушает на 80 с
hostNetwork: trueи перенаправляет на 443 — но ACME challenge обслуживается на 80 до срабатывания редиректа.
Объект Certificate
yamlapiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: site-tls
namespace: default
spec:
secretName: site-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- example.com
- www.example.com
- blog.example.com
- cv.example.com
- proxy.example.com
renewBefore: 720h # за 30 дней до истечения
Все поддомены используют общий сертификат с несколькими SAN. cert-manager:
- Запрашивает единый сертификат для всех имён
- Сохраняет ключ и цепочку сертификатов в Secret
site-tls - Автоматически продлевает за ~30 дней до истечения
- Запускает ротацию при добавлении новых записей в
dnsNames
Привязка в IngressRoute
Traefik использует собственный CRD вместо стандартного Ingress. Секция TLS ссылается на тот же Secret:
yamlapiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: site-main
spec:
entryPoints:
- websecure
routes:
- match: Host(`example.com`)
kind: Rule
services:
- name: site-backend
port: 8000
- match: Host(`www.example.com`)
kind: Rule
middlewares:
- name: www-redirect
services:
- name: site-backend
port: 8000
tls:
secretName: site-tls
Middleware: поддомен → path prefix
FastAPI-приложение обслуживает всё через один роутер. Поддомены переписываются в path-префиксы через Traefik Middleware:
yamlapiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: blog-prefix
spec:
addPrefix:
prefix: /weblog
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: www-redirect
spec:
redirectRegex:
regex: "^https://www\\.(.+)"
replacement: "https://${1}"
permanent: true
blog.example.com/ → приложение видит /weblog/. Один под, один Service, один Deployment обрабатывает все поддомены.
Проверка статуса сертификата
bash# Список всех сертификатов
kubectl get certificate -A
# Детали конкретного сертификата
kubectl describe certificate site-tls
# ACME order (если сертификат ожидает выпуска)
kubectl get orders -A
kubectl describe order <order-name>
# Challenge (если order ожидает)
kubectl get challenges -A
kubectl describe challenge <challenge-name>
Условие Ready: True — сертификат выпущен и сохранён. Если статус застрял в False, отследить цепочку order → challenge.
Отладка HTTP-01 challenge вручную
bash# Проверить, что solver-под cert-manager запущен
kubectl get pods -n cert-manager
# Проверить, что Traefik подхватил временный Ingress
kubectl get ingress -A | grep acme
# Проверить доступность порта 80
curl -v http://example.com/.well-known/acme-challenge/test
Принудительное обновление сертификата
cert-manager продлевает автоматически. Для принудительного обновления:
bashkubectl delete secret site-tls
cert-manager обнаруживает отсутствие Secret, повторно запускает ACME-процесс и создаёт новый сертификат. Traefik короткое время отдаёт старый сертификат из памяти (обычно менее 60 секунд).
Лимиты Let's Encrypt
- 50 сертификатов на зарегистрированный домен в неделю
- 5 ошибок на аккаунт на hostname в час
- У staging лимитов нет (но браузеры таким сертификатам не доверяют)
При превышении лимитов проверить все выпущенные сертификаты: https://crt.sh/?q=example.com.