Установка Ingress-контроллера NGINX с сертификатом из Yandex Certificate Manager
- Перед началом работы
- Добавьте сертификат в Certificate Manager
- Установите External Secrets Operator
- Настройте кластер Managed Service for Kubernetes
- Создайте ExternalSecret
- Установите Ingress-контроллер NGINX
- Создайте веб-ресурс в вашем кластере Managed Service for Kubernetes
- Настройте DNS-запись для Ingress-контроллера
- Создайте ресурс Ingress
- Проверьте доступность ресурса
- Удалите созданные ресурсы
Управляйте TLS-сертификатом для Ingress-контроллера NGINX через Yandex Certificate Manager.
External Secrets Operator
Перед началом работы
-
Если у вас еще нет интерфейса командной строки Yandex Cloud (CLI), установите и инициализируйте его.
По умолчанию используется каталог, указанный при создании профиля CLI. Чтобы изменить каталог по умолчанию, используйте команду
yc config set folder-id <идентификатор_каталога>. Также для любой команды вы можете указать другой каталог с помощью параметров--folder-nameили--folder-id. -
Установите утилиту
jq:sudo apt update && sudo apt install jq -
eso-service-account— для взаимодействия External Secrets Operator с Certificate Manager.k8s-saс ролямиk8s.clusters.agent,vpc.publicAdmin,container-registry.images.pullerиload-balancer.adminна каталог — для создания ресурсов кластера Managed Service for Kubernetes и скачивания Docker-образов. Рольload-balancer.adminнужна для создания сетевого балансировщика нагрузки.
-
Создайте авторизованный ключ для сервисного аккаунта и сохраните его в файл
authorized-key.json:yc iam key create \ --service-account-name eso-service-account \ --output authorized-key.json -
Создайте группы безопасности для кластера Managed Service for Kubernetes и входящих в него групп узлов.
Важно
От настройки групп безопасности зависит работоспособность и доступность кластера, а также запущенных в нем сервисов и приложений.
-
Создайте кластер Managed Service for Kubernetes и группу узлов любой подходящей конфигурации. В настройках кластера Managed Service for Kubernetes укажите сервисный аккаунт
k8s-saи группы безопасности, подготовленные ранее. -
Установите kubectl
и настройте его на работу с созданным кластером.
Необходимые платные ресурсы
В стоимость поддержки инфраструктуры входит:
- Использование мастера Managed Service for Kubernetes и исходящий трафик (см. тарифы Managed Service for Kubernetes).
- Использование узлов кластера Managed Service for Kubernetes (см. тарифы Yandex Compute Cloud).
- Использование публичных IP-адресов (см. тарифы Yandex Virtual Private Cloud).
- Входящий трафик, обработанный балансировщиком, и использование сетевого балансировщика (см. тарифы Yandex Network Load Balancer).
Добавьте сертификат в Certificate Manager
-
Выпустите и добавьте в Certificate Manager сертификат Let's Encrypt® или загрузите собственный сертификат.
-
Для сертификата Let's Encrypt® пройдите проверку прав на домен, который указан в сертификате.
-
Назначьте роль
certificate-manager.certificates.downloaderсервисному аккаунтуeso-service-account, чтобы он мог читать содержимое сертификата:yc cm certificate add-access-binding \ --id <идентификатор_сертификата> \ --service-account-name eso-service-account \ --role certificate-manager.certificates.downloader -
Проверьте, что права назначены:
yc cm certificate list-access-bindings --id <идентификатор_сертификата>Результат:
+---------------------------------------------+----------------+-------------------------------------+ | ROLE ID | SUBJECT TYPE | SUBJECT ID | +---------------------------------------------+----------------+-------------------------------------+ | certificate-manager.certificates.downloader | serviceAccount | <идентификатор_сервисного_аккаунта> | +---------------------------------------------+----------------+-------------------------------------+
Установите External Secrets Operator
Установите приложение External Secrets Operator с поддержкой Yandex Lockbox из Cloud Marketplace по инструкции со следующими параметрами:
- Пространство имен — создайте новое пространство имен
external-secrets. - Ключ сервисной учетной записи — вставьте содержимое файла
authorized-key.json, созданного ранее.
-
Добавьте Helm-репозиторий
external-secrets:helm repo add external-secrets https://charts.external-secrets.io -
Установите External Secrets Operator в кластер Managed Service for Kubernetes:
helm install external-secrets \ external-secrets/external-secrets \ --namespace external-secrets \ --create-namespaceЭта команда создаст новое пространство имен
external-secrets, необходимое для работы External Secrets Operator.Результат:
NAME: external-secrets LAST DEPLOYED: Sun Sep 19 11:20:58 2021 NAMESPACE: external-secrets STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: external-secrets has been deployed successfully! ...
Настройте кластер Managed Service for Kubernetes
-
Создайте пространство имен
nsдля объектов External Secrets Operator:kubectl create namespace ns -
Создайте секрет
yc-auth, содержащий в себе ключ сервисного аккаунтаeso-service-account:kubectl --namespace ns create secret generic yc-auth \ --from-file=authorized-key=authorized-key.json -
Узнайте поддерживаемые
apiVersionдля хранилища секретов (SecretStore) :kubectl get crd secretstores.external-secrets.io \ -o json | jq -r '.spec.versions[].name' -
Создайте хранилище секретов с именем
yc-cert-manager, содержащее секретyc-auth, указав поддерживаемуюapiVersion:kubectl --namespace ns apply -f - <<< ' apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: yc-cert-manager spec: provider: yandexcertificatemanager: auth: authorizedKeySecretRef: name: yc-auth key: authorized-key.json namespace: ns'Совет
В примере хранилище секретов создается с типом
kind: SecretStore, оно будет доступно только в пространстве именns, в котором было создано. Чтобы хранилище секретов было доступно во всех пространствах имен, используйте типkind: ClusterSecretStore.
Создайте ExternalSecret
-
Узнайте поддерживаемые
apiVersionдля ExternalSecret :kubectl get crd externalsecrets.external-secrets.io \ -o json | jq -r '.spec.versions[].name' -
Создайте объект ExternalSecret с именем
external-secret, указывающий на сертификат из Certificate Manager, указав поддерживаемуюapiVersion:kubectl --namespace ns apply -f - <<< ' apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: external-secret spec: refreshInterval: 1h secretStoreRef: name: yc-cert-manager kind: SecretStore target: name: k8s-secret template: type: kubernetes.io/tls data: - secretKey: tls.crt remoteRef: key: <идентификатор_сертификата> property: chain - secretKey: tls.key remoteRef: key: <идентификатор_сертификата> property: privateKey'Примечание
Если вы создавали хранилище секретов с типом
kind: ClusterSecretStore, исправьте в примере манифеста значениеspec:secretStoreRef:kindнаClusterSecretStore.Где:
k8s-secret— имя секрета, в который External Secret Operator поместит сертификат из Certificate Manager.tls.crt— параметр секретаk8s-secret, который будет содержать сертификат.tls.key— параметр секретаk8s-secret, который будет содержать закрытый ключ сертификата.
Доступны следующие значения параметра
property:chain— получить цепочку сертификатов в формате PEM.privateKey— получить закрытый ключ в формате PEM.chainAndPrivateKeyили пустое значение — получить и цепочку сертификатов, и закрытый ключ.
External Secrets Operator получит сертификат из Certificate Manager и поместит его в секрет
k8s-secret. -
Проверьте, что сертификат попал в секрет
k8s-secret:kubectl -n ns get secret k8s-secret -ojson \ | jq '."data"."tls.crt"' -r \ | base64 --decodeПример результата:
-----BEGIN CERTIFICATE----- MIIFKTCCBBGgAwIBAgISBAlQtxTUnXa75N1TnPYRWbSLMA0GCSqGSIb3DQEBCwUA MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD EwJSMzAeFw0yMjA3MTMxNDMxNTVaFw0yMjEwMTExNDMxNTRaMB0xGzAZBgNVBAMT EmRkb3Mtd2ViLm5yay5tZS51azCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC…Чтобы просмотреть сертификат в удобном виде, выполните команды:
kubectl -n ns get secret k8s-secret -ojson | jq '."data"."tls.crt"' -r \ | base64 --decode > cert.pemopenssl x509 -in cert.pem -textПример результата:
Certificate: Data: Version: 3 (0x2) Serial Number: 04:09:50:b7:14:d4:9d:76:bb:e4:dd:53:9c:f6:11:59:b4:8b Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, O = Let's Encrypt, CN = R3 Validity Not Before: Jul 13 14:31:55 2022 GMT Not After : Oct 11 14:31:54 2022 GMT Subject: CN = example.com ...
Установите Ingress-контроллер NGINX
Установите приложение Ingress NGINX из Cloud Marketplace по инструкции.
SSL-сертификат будет доступен только в пространстве имен ns, где создан секрет с этим сертификатом. Чтобы Ingress мог использовать этот сертификат в любом пространстве имен, добавьте в конфигурацию контроллера параметр --default-ssl-certificate:
-
Выполните команду:
kubectl edit deployment ingress-nginx-controller -
В открывшемся окне добавьте параметр
--default-ssl-certificate:spec: template: spec: containers: - args: - /nginx-ingress-controller ... - --default-ssl-certificate=ns/k8s-secret
При изменении параметра --default-ssl-certificate перезапустите Ingress-контроллер NGINX.
-
Добавьте в Helm-репозиторий для NGINX:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginxРезультат:
"ingress-nginx" has been added to your repositories -
Обновите набор данных для создания экземпляра приложения в кластере Managed Service for Kubernetes:
helm repo updateРезультат:
Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "ingress-nginx" chart repository Update Complete. ⎈Happy Helming!⎈ -
Установите контроллер. Он будет установлен вместе с Network Load Balancer:
helm install ingress-nginx ingress-nginx/ingress-nginxSSL-сертификат будет доступен только в пространстве имен
ns, где создан секрет с этим сертификатом. Чтобы Ingress мог использовать этот сертификат в любом пространстве имен, установите контроллер с параметромdefault-ssl-certificate:helm install ingress-nginx ingress-nginx/ingress-nginx \ --set controller.extraArgs.default-ssl-certificate="ns/k8s-secret"Результат:
NAME: ingress-nginx LAST DEPLOYED: Sun Jul 18 22:35:37 2021 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: The ingress-nginx controller has been installed. It may take a few minutes for the LoadBalancer IP to be available. You can watch the status by running 'kubectl --namespace default get services -o wide -w ingress-nginx-controller' ...При изменении параметра
default-ssl-certificateперезапустите Ingress-контроллер NGINX.
Чтобы настроить конфигурацию контроллера самостоятельно, обратитесь к документации Helm
Чтобы пробросить определенные порты при установке Ingress-контроллера NGINX, следуйте инструкции.
Создайте веб-ресурс в вашем кластере Managed Service for Kubernetes
Создайте объект
kubectl --namespace ns apply -f - <<< '
apiVersion: v1
kind: Service
metadata:
name: app
spec:
selector:
app: app
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
labels:
app: app
spec:
replicas: 1
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
containers:
- name: app
image: nginx:latest
ports:
- containerPort: 80'
Настройте DNS-запись для Ingress-контроллера
-
Узнайте IP-адрес Ingress-контроллера (значение в колонке
EXTERNAL-IP):kubectl get svcРезультат:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ... ingress-nginx-controller LoadBalancer 10.96.164.252 84.201.153.122 80:31248/TCP,443:31151/TCP 2m19s ... -
Разместите у своего DNS-провайдера или на собственном DNS-сервере A-запись, указывающую на публичный IP-адрес Ingress-контроллера:
<имя_домена> IN A 84.201.153.122
Примечание
Регистрация сертификата Let's Encrypt® и A-записи может занять несколько минут.
Создайте ресурс Ingress
Создайте ресурс Ingressk8s-secret для HTTPS:
kubectl --namespace ns apply -f - <<< '
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-test
namespace: ns
spec:
tls:
- hosts:
- <имя_домена>
secretName: k8s-secret
ingressClassName: nginx
rules:
- host: <имя_домена>
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app
port:
number: 80'
Где <имя_домена> — доменное имя, для которого выпущен сертификат.
Проверьте доступность ресурса
Выполните GET-запрос к ресурсу по HTTPS, например, командой:
curl https://<ваш_домен> -vv
Пример результата:
* Trying 51.250.64.86:443...
* Connected to <имя_домена> (51.250.64.86) port 443 (#0)
...
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=<имя_домена>
* start date: Jul 13 14:31:55 2022 GMT
* expire date: Oct 11 14:31:54 2022 GMT
* subjectAltName: host "<имя_домена>" matched cert's "<имя_домена>"
...
* SSL certificate verify ok.
Примечание
Если ресурс недоступен по указанному URL, то убедитесь, что группы безопасности для кластера Managed Service for Kubernetes и его групп узлов настроены корректно. Если отсутствует какое-либо из правил — добавьте его.
Сертификат от Let's Encrypt® должен обновляться автоматически вслед за обновлением сертификата в Certificate Manager.
Вы можете задать таймаут синхронизации в параметре refreshInterval объекта ExternalSecret.
Удалите созданные ресурсы
Некоторые ресурсы платные. Чтобы за них не списывалась плата, удалите ресурсы, которые вы больше не будете использовать: