cert-manager CSI Driver — это дополнение для Kubernetes, которое позволяет подключать TLS-сертификаты напрямую к подам. Оно работает вместе с cert-manager: параметры сертификата задаются в манифесте пода, а драйвер запрашивает сертификат и монтирует его вместе с приватным ключом в указанный каталог. Создавать отдельный ресурс Certificate и секрет для сертификата пода не требуется.
Такой способ подключения подходит для приложений, которые сами обрабатывают TLS-соединения и читают сертификаты из файлов. Например, драйвер может выдать и подключить сертификат к поду с Nginx или предоставить каждому поду собственный сертификат для взаимной аутентификации между сервисами. Сертификаты выпускаются через настроенный Issuer или ClusterIssuer, в том числе от Let's Encrypt.
Каждая реплика приложения получает собственный сертификат и ключ. Приватный ключ генерируется на ноде, где запущен под, хранится в оперативной памяти и не передается драйвером по сети. При удалении пода файлы удаляются, а при его пересоздании сертификат выпускается заново. Если сертификат нужно сохранять между пересозданиями подов или использовать для HTTPS на Ingress-контроллере, можно настроить его через cert-manager с ресурсом Certificate и секретом.
Установка
Для работы дополнения в кластере должен быть установлен cert-manager.
Откройте панель управления кластером, перейдите во вкладку «Дополнения» и выберите cert-manager CSI Driver. В открывшемся мастере нажмите кнопку «Установить» и дождитесь завершения установки.

Для проверки подключитесь к кластеру с помощью kubectl и выполните команду:
kubectl get csidriver csi.cert-manager.io
В выводе должен присутствовать драйвер csi.cert-manager.io с режимом Ephemeral. Он используется для временных томов, связанных с жизненным циклом пода. Создавать StorageClass, PersistentVolume и PersistentVolumeClaim для них не нужно.
Драйвер запускается на рабочих нодах как DaemonSet. Проверить его состояние можно командой:
kubectl get daemonsets -A
Найдите DaemonSet cert-manager CSI Driver. Значения в колонках DESIRED и READY должны совпадать и быть больше нуля.
Пример использования
В качестве примера развернем Nginx и подключим к нему сертификат с помощью cert-manager CSI Driver. Выпустим сертификат Let's Encrypt для домена site.example.com, подключим его к поду через CSI Driver и настроим доступ к сайту через балансировщик нагрузки. HTTPS-соединения будет обрабатывать Nginx внутри пода.
Помимо cert-manager и cert-manager CSI Driver, для примера потребуются:
-
дополнение cert-manager Webhook — для подтверждения владения доменом через
DNS-01; -
домен, расположенный на наших NS;
В манифестах и командах замените site.example.com на свой домен или поддомен.
Настройка ClusterIssuer
Для выпуска сертификатов потребуется ClusterIssuer с именем letsencrypt-dns. Создайте его по инструкции по настройке cert-manager Webhook, указав свою почту в параметре email и ID кластера в groupName. Если такой ClusterIssuer уже настроен, его можно использовать повторно.
Проверьте готовность созданного ресурса:
kubectl get clusterissuer letsencrypt-dns
В колонке READY должно быть значение True.
При запросе сертификата cert-manager Webhook автоматически создаст TXT-запись в DNS. Это позволяет подтвердить владение доменом до запуска Nginx и настройки A-записи сайта.
Выполнять шаги из раздел «Выпуск сертификата» из инструкции про Webhook не нужно. CSI Driver сам создаст CertificateRequest при запуске пода. Секрет, указанный в privateKeySecretRef у ClusterIssuer, будет хранить только ключ учетной записи ACME для взаимодействия с Let's Encrypt.
Создание ConfigMap
Для ресурсов сайта создадим отдельный неймспейс:
kubectl create namespace csi-tls-example
Конфигурацию Nginx и HTML-страницу сохраним в ConfigMap. Создайте файл nginx-config.yaml со следующим содержимым:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-site-config
namespace: csi-tls-example
data:
default.conf: |
server {
listen 8443 ssl;
server_name site.example.com;
ssl_certificate /tls/tls.crt;
ssl_certificate_key /tls/tls.key;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
index.html: |
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Nginx с сертификатом Let’s Encrypt</title>
</head>
<body>
<h1>Сайт работает по HTTPS</h1>
<p>Сертификат подключен через cert-manager CSI Driver.</p>
</body>
</html>
В этом манифесте:
-
default.conf— конфигурация Nginx. Сервер принимает HTTPS-соединения на порту8443для домена изserver_name. -
ssl_certificateиssl_certificate_key— пути к сертификату и приватному ключу, которые подключит CSI Driver. -
index.html— страница, которая будет отображаться при обращении к сайту.
Примените манифест:
kubectl apply -f nginx-config.yaml
Создание Deployment
Теперь создадим деплоймент с Nginx. Подключим к контейнеру конфигурацию и страницу из ConfigMap, а сертификат и ключ смонтируем в каталог /tls с помощью CSI Driver.
Создайте файл nginx-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-site
namespace: csi-tls-example
spec:
replicas: 1
selector:
matchLabels:
app: nginx-site
template:
metadata:
labels:
app: nginx-site
spec:
containers:
- name: nginx
image: nginx:1.28-alpine
ports:
- name: https
containerPort: 8443
readinessProbe:
httpGet:
path: /
port: https
scheme: HTTPS
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d
readOnly: true
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
- name: tls
mountPath: /tls
readOnly: true
volumes:
- name: nginx-config
configMap:
name: nginx-site-config
items:
- key: default.conf
path: default.conf
- name: html
configMap:
name: nginx-site-config
items:
- key: index.html
path: index.html
- name: tls
csi:
driver: csi.cert-manager.io
readOnly: true
volumeAttributes:
csi.cert-manager.io/issuer-name: letsencrypt-dns
csi.cert-manager.io/issuer-kind: ClusterIssuer
csi.cert-manager.io/dns-names: "site.example.com"
csi.cert-manager.io/key-usages: "digital signature,key encipherment,server auth"
Параметры сертификата задаются в секции volumeAttributes:
-
csi.cert-manager.io/issuer-name— имяIssuer, через который будет выпущен сертификат. В примере используетсяletsencrypt-dns. -
csi.cert-manager.io/issuer-kind— тип ресурса:IssuerилиClusterIssuer. При использованииIssuerон должен находиться в том же неймспейсе, что и под. -
csi.cert-manager.io/dns-names— домен сайта. Если нужно указать несколько имен, перечислите их через запятую. -
csi.cert-manager.io/key-usages— назначение ключа и сертификата. Значениеserver authиспользуется для аутентификации HTTPS-сервера.
В секциях volumes и volumeMounts том подключается в режиме только для чтения — readOnly: true. Сертификат и ключ будут храниться в оперативной памяти ноды, в файловой системе tmpfs.
В примере запускается одна реплика Nginx. При увеличении количества реплик каждый новый под получит отдельный сертификат для того же домена. При масштабировании и частом пересоздании подов учитывайте лимиты Let's Encrypt.
Примените манифест:
kubectl apply -f nginx-deployment.yaml
Проверьте состояние пода:
kubectl get pods -n csi-tls-example
При создании пода драйвер сформирует CertificateRequest в неймспейсе csi-tls-example. cert-manager обработает запрос через letsencrypt-dns, а драйвер запишет полученный сертификат в подключенный том.
Выпуск может занять несколько минут из-за распространения DNS-записей. В это время под может находиться в статусе ContainerCreating. После получения сертификата запустится Nginx.
Повторно выполните команду проверки. У пода nginx-site-... в колонке STATUS должно появиться Running, а в READY — 1/1.
Проверка сертификата
Проверить статус выпуска можно командой:
kubectl get certificaterequests,orders,challenges -n csi-tls-example
При успешном выпуске у CertificateRequest в колонке READY будет значение True, а у Order — состояние valid. Ресурс Challenge после завершения проверки может быть удален автоматически.
Проверьте, что файлы сертификата доступны в поде:
kubectl exec deployment/nginx-site -n csi-tls-example -- ls -l /tls
В каталоге должны быть файлы tls.crt и tls.key. Первый содержит сертификат сайта и промежуточные сертификаты цепочки, второй — приватный ключ.
Чтобы посмотреть центр сертификации, срок действия и доменное имя, передайте содержимое tls.crt в локальный openssl:
kubectl exec deployment/nginx-site -n csi-tls-example -- cat /tls/tls.crt \
| openssl x509 -noout -issuer -dates -ext subjectAltName
В поле issuer будет указан центр сертификации Let's Encrypt, а в Subject Alternative Name — ваш домен.
Создание балансировщика нагрузки
Для доступа к сайту из интернета создадим Service типа LoadBalancer. Он получит внешний IP-адрес и будет передавать TCP-трафик на HTTPS-порт Nginx.
Создайте файл nginx-loadbalancer.yaml:
apiVersion: v1
kind: Service
metadata:
name: nginx-site
namespace: csi-tls-example
spec:
type: LoadBalancer
selector:
app: nginx-site
ports:
- name: https
port: 443
targetPort: https
protocol: TCP
appProtocol: k8s.timeweb.cloud/proto-tcp
Балансировщик принимает соединения на порту 443 и передает их на порт 8443 в поде. Параметр appProtocol: k8s.timeweb.cloud/proto-tcp включает передачу TCP-трафика: TLS-соединение обрабатывает Nginx, где находятся сертификат и ключ. Настраивать сертификат на самом балансировщике не требуется.
Примените манифест:
kubectl apply -f nginx-loadbalancer.yaml
Дождитесь создания балансировщика и проверьте, что сервис получил внешний IP-адрес:
kubectl get service nginx-site -n csi-tls-example
IP-адрес будет отображаться в колонке EXTERNAL-IP. Создание балансировщика также можно отследить в разделе «Балансировщики» панели управления.
Настройка домена и проверка HTTPS
Создайте A-запись для домена site.example.com, указав IP-адрес балансировщика. После обновления DNS откройте https://site.example.com в браузере. Должна появиться страница «Сайт работает по HTTPS» без предупреждений о сертификате.
Если DNS еще не обновился, можно проверить сайт, явно указав IP-адрес балансировщика. Замените EXTERNAL_IP на полученный адрес и выполните:
curl --fail --show-error \ --resolve site.example.com:443:EXTERNAL_IP \ https://site.example.com/
Параметр --resolve направляет запрос на указанный IP-адрес, сохраняя проверку сертификата для домена site.example.com.
Удаление примера
Чтобы удалить ресурсы сайта, созданные в примере, выполните:
kubectl delete namespace csi-tls-example
Вместе с неймспейсом будут удалены поды, конфигурация сайта и сервис LoadBalancer. Связанный балансировщик также будет удален из панели управления. Если домен больше не используется, удалите его A-запись.
Дополнения, ClusterIssuer и ключ учетной записи ACME останутся в кластере — их можно использовать для других приложений.