Cert-manager – это сервис в Kubernetes, который автоматизирует выпуск и управление TLS-сертификатами.
Требования:
- Готовый Kubernetes-кластер (или K3S)
- Ingress NGINX
- Приватный репозиторий Harbor
- helm, nerdctl/docker
- Развёрнутый Vault + настроенные роли
- Запись в DNS: vault.k8s.domain.local (Ваш домен), например gitlab.k8s.domain.local
Данный гайд - это часть общей архитектуры по построению полноценной системы выпуска TLS сертификатов.
Cert-manager из этого мануала может быть настроен как отдельно, так и совместно с общей схемой.

План:
- Подготовить chart и образы cert-manager
- Установить cert-manager
- Создать Issuer через serviceAccountRef
- Выпустить тестовый Certificate
- Подключить сертификаты к Ingress приложений
Шаг 1. Онлайн установка
1
2
3
| helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack --version <CHART_VERSION> -n cert-manager --create-namespace --set crds.enabled=true
|
В <CHART_VERSION> ставьте версию своего чарта.
Установка завершена.
Шаг 2. Оффлайн установка
Подготовка cert-manager chart и образов
На компе/сервере с инетом:
1
2
3
4
| helm repo add jetstack https://charts.jetstack.io
helm repo update
helm pull jetstack/cert-manager --untar
cd cert-manager
|
Извлекаем имена образов:
1
2
| helm template cert-manager . > rendered.yaml
grep -oE 'image:\s*"?[^"]+' rendered.yaml | sed -E 's/^image:\s*"?//; s/"$//' | sort -u > cm-images.txt
|
Скачиваем:
1
2
3
| while read -r img; do
docker pull "$img"
done < cm-images.txt
|
Сохраняем:
1
| docker save -o cm-images.tar $(cat cm-images.txt)
|
Упаковываем образы:
1
2
| cd ..
tar -cvf cert-manager-src.tgz cert-manager
|
Загрузка в приватный репозиторий
Переносим архивы в закрытый контур:
1
2
| tar -xvf cert-manager-src.tgz
cd cert-manager
|
Загружаем образы:
1
| sudo docker load -i ./cm-images.tar
|
Указываем куда грузить образы Harbor репозиторий и имя проекта созданного в нём
У меня создан приватный репозиторий с именем platform

1
2
3
4
5
6
7
8
| export HARBOR="harbor.domain.local"
export PROJECT="platform"
while read -r img; do
new="${HARBOR}/${PROJECT}/${img}"
docker tag "${img}" "$new"
docker push "$new"
done < cm-images.txt
|
Удаляем лишний мусор:
1
| sudo rm cm-images.txt cm-images.tar rendered.yaml
|
Делаем из файлов Chart и пушим его в репозиторий Harbor:
1
2
| helm package . -d .
helm push cert-manager-*.tgz oci://harbor.domain.local/helm
|
Установка cert-manager
Для справки: Cert-manager использует ресурсы Issuer, ClusterIssuer и Certificate - это базовая модель работы сертификатов в Kubernetes.
Создаём файл:
1
| nano certman-values.yaml:
|
Наполняем:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| replicaCount: 2
podDisruptionBudget:
enabled: true
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
global:
imagePullSecrets:
- name: harbor-regcred
image:
repository: harbor.domain.local/platform/quay.io/jetstack/cert-manager-controller
webhook:
image:
repository: harbor.domain.local/platform/quay.io/jetstack/cert-manager-webhook
cainjector:
image:
repository: harbor.domain.local/platform/quay.io/jetstack/cert-manager-cainjector
startupapicheck:
image:
repository: harbor.domain.local/platform/quay.io/jetstack/cert-manager-startupapicheck
|
Если доступ в репозиторий Harbor без авторизации, то секцию:
1
2
| imagePullSecrets:
- name: harbor-regcred
|
Удалить. В противном случае создать сикрет для доступа с этим именем в кластере кубернетес.
Запуск оффлайн установки
Запускаем установку:
1
2
3
4
5
| helm install cert-manager oci://harbor.domain.local/helm/cert-manager \
--version <CHART_VERSION> \
-n cert-manager \
--create-namespace \
-f certman-values.yaml
|
Проверка:
1
2
| kubectl get pods -n cert-manager
kubectl get crds | grep cert-manager
|
Поды должны подняться, а custom resource deffinitions создаться.
Шаг 3. Подключение cert-manager к Vault
Рекомендуемый вариант ClusterIssuer
Создаём файл:
Добавляем содержимое запроса:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: vault-issuer
spec:
vault:
server: http://vault.vault.svc:8200
path: pki/sign/k8s-domain
auth:
kubernetes:
mountPath: /v1/auth/kubernetes
role: cert-manager
serviceAccountRef:
name: cert-manager
|
Для актуальных версий cert-manager используем serviceAccountRef.
Где ServiceAccountRef — это service account, от имени которого cert-manager запрашивает токен.
Применяем:
1
| kubectl apply -f issuer.yaml
|
Проверяем:
1
2
| kubectl get clusterissuers.cert-manager.io vault-issuer -o wide
kubectl describe clusterissuer vault-issuer
|
Выпуск тестового сертификата
Создаём файл:
С тестовым запросом сертификата. Домен указывайте ваш:
1
2
3
4
5
6
7
8
9
10
11
12
13
| apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: test-cert
namespace: default
spec:
secretName: test-cert-tls
issuerRef:
name: vault-issuer
kind: ClusterIssuer
commonName: test.k8s.domain.local
dnsNames:
- test.k8s.domain.local
|
Применяем:
1
| kubectl apply -f test-cert.yaml
|
Если всё хорошо, появится TLS secret с ключом и сертификатом.
1
2
| kubectl -n default describe certificate test-cert
kubectl -n default get secret test-cert-tls
|
Пример запроса сертификата для приложения Gitlab
Создаётся файл:
Внутри прописываем доменное имя сервиса и создаём имя секрета, который содержит внутри ключ и сертификат:
1
2
3
4
5
6
7
8
9
10
11
12
| apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: gitlab-cert
namespace: gitlab
spec:
secretName: gitlab-tls
issuerRef:
name: vault-issuer
kind: ClusterIssuer
dnsNames:
- gitlab.k8s.domain.local
|
У меня GitLab развёрнут через Helm чарт, поэтому в Helm чарте я изменяю Ingress на работу с https
1
2
3
4
5
| Ingress:
tls:
- hosts:
- gitlab.k8s.domain.local
secretName: gitlab-tls
|
Если вы используете манифесты для ingress, то логика такая же включить tls и указать созданный ранее сикрет.
Получаем защищенное TLS соединение, а когда срок сертификата будет подходить к концу cert-manager сам его обновит.

Типовые проверки
Команды для проверки и диагностики cert-manager:
1
2
3
4
5
| kubectl get pods -n cert-manager
kubectl get clusterissuer
kubectl describe clusterissuer vault-issuer
kubectl get certificaterequests -A
kubectl get certificates -A
|
Команды для проверки и диагностики Vault:
1
2
3
4
5
6
7
| kubectl -n vault exec -it vault-0 -- vault status
kubectl -n vault exec -it vault-0 -- vault secrets list
kubectl -n vault exec -it vault-0 -- vault list pki/issuers
kubectl -n vault exec -it vault-0 -- vault read pki/config/urls
kubectl -n vault exec -it vault-0 -- vault read pki/roles/k8s-domain
kubectl -n vault exec -it vault-0 -- vault read auth/kubernetes/config
kubectl -n vault exec -it vault-0 -- vault read auth/kubernetes/role/cert-manager
|