К содержанию
Pingera

Настройка cert-manager, nginx-ingress и Let's Encrypt

  • Опубликовано:
  • Обновлено
  • 5 мин чтения

Развертывание веб приложений в Kubernetes является одной из стандартных задач для бизнеса. В современной инфраструктуре использование сертификатов TLS и HTTPs протокола не является опциональным (например, с 2018 года браузер Chrome помечает все HTTP сайты как небезопасные). В этой статье мы рассмотрим как с помощью приложений с открытым исходным кодом абсолютно бесплатно получить сертификат для вашего приложения, автоматизировать весь процесс и обновление.

В нашем примере мы будем рассматривать следующие компоненты:

  1. Kubernetes кластер - подойдет любой кластер с доступом в Интернет и публичным IP-адресом
  2. ingress-nginx - их много вариантов, но мы возьмем тот, что активно поддерживается сообществом и Cloud Native Computing Foundation
  3. cert-manager - это оператор, который автоматизирует создание и управление сертификатами в k8s
  4. Let’s Encrypt - бесплатный, автоматизированный центр сертификации - выпускают TLS сертификаты

Установка компонентов

Веб сервис

Для начала задеплоим простейший Под с nginx и создадим для него Service объект:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app.kubernetes.io/name: my-test-app
spec:
  containers:
  - name: nginx
    image: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: my-test-app
  ports:
    - protocol: TCP
      port: 80

Это будет наше приложение, которое спрятано за сертификатами.

Ingress

Установим ingress-nginx. Проще всего делать это с helm:

helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace

Это установит ingress контроллер и выставит его во внешний мир через LoadBalancer сервис. Если у ваш кластер не поддерживает LoadBalancer, то есть другие варианты, которые вы можете посмотреть в документации.

cert-manager

Проще всего тоже взять команду из документации, так как версии могут отличаться. На момент написания статьи, стабильная версия 1.14.3:

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.3/cert-manager.yaml

HTTP

Все готово к первым шагам. Начнем с того, что наше приложение будет доступно по HTTP через ingress. Для этого, создадим Ingress объект:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.allow-http: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: mytest.pingera.ru
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

Из основных параметров:

  1. ingressClassName: nginx - указывает, что мы хотим использовать именно ingress-nginx контроллер. Это нужно, если у вас в кластере есть и другие контроллеры. Например, так часто бывает в публичных облаках.
    • host: mytest.pingera.ru - открывает секцию, которая указывает на Домен, который мы хотим выставить наружу.
  2. Секция backend: - говорит Ingress объекту, куда нужно отправлять запросы для этого сайта. Это наш сервис, который смотрит на Под nginx.

Посмотреть состояние Ingress можно следующим образом:

% kubectl get ingress
NAME           CLASS   HOSTS           ADDRESS          PORTS   AGE
test-ingress   nginx   mytest.pingera.ru   12.123.123.123   80      5m1s

Можно проверить, все ли работает и увидеть стандартное приглашение nginx:

% curl -H "Host: mytest.pingera.ru" http://12.123.123.123
…
<h1>Welcome to nginx!</h1>
…

Чтобы двигаться дальше, нужно добавить в DNS запись, которая направит нужный домен на IP-адрес ингресса. В моем случае, я добавлю A-запись:

mytest.pingera.ru A 12.123.123.123

Теперь сайт откроется и в браузере.

HTTPs

Staging

cert-manager будет заниматься тем, что запросит для нас сертификат у Let’s Encrypt и создаст секрет в кубернетес кластере, который ingress будет использовать. У Let’s Encrypt очень жесткие лимиты по количеству подключений в минуту, поэтому для начала обкатываем все на staging.

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-staging
  namespace: default
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: <YOUR_EMAIL> # поменять на ваш имейл
    privateKeySecretRef:
      name: letsencrypt-staging
    solvers:
    - http01:
        ingress:
          ingressClassName: nginx

Если попробовать открыть страницу, то сертификат будет невалидный, так как подписан staging CA Let’s Encrypt:

% curl -v --insecure https://mytest.pingera.ru
…
* Server certificate:
* subject: CN=mytest.pingera.ru
* start date: Feb 23 11:56:07 2024 GMT
* expire date: May 23 11:56:06 2024 GMT
* issuer: C=US; O=(STAGING) Let's Encrypt; CN=(STAGING) Artificial Apricot R3

Production

Если все работает, то можно пробовать Let’s Encrypt production. Для этого нужно создать production Issuer:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-production
  namespace: default
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: <YOUR_EMAIL>
    privateKeySecretRef:
      name: letsencrypt-production
    solvers:
    - http01:
        ingress:
          ingressClassName: nginx

Так же меняем Ingress, где указываем, что Issuer будет production:

% diff -u ingress-https-staging.yaml ingress-https-prod.yaml
--- ingress-https-staging.yaml	2024-02-23 15:53:22
+++ ingress-https-prod.yaml	2024-02-23 18:03:02
@@ -5,7 +5,7 @@
   namespace: default
   annotations:
     kubernetes.io/ingress.allow-http: "true"
-    cert-manager.io/issuer: letsencrypt-staging
+    cert-manager.io/issuer: letsencrypt-production
     acme.cert-manager.io/http01-edit-in-place: "true"
 spec:
   ingressClassName: nginx

Теперь у нас есть полностью валидный сертификат.

Wildcard

Wildcard дает возможность покрыть TLS сертификатами поддомены. Это удобно, если у вас приложение обслуживает несколько субдоменов сразу. Например:

  • abc.pingera.ru
  • def.pingera.ru

Для получения wildcard сертификата, небходима проверка DNS01. Можно почитать про это здесь. У cert-manager есть нативная интеграция со многими DNS провайдерами, например AWS Route 53 (список). К тому же есть поддержка вебхуков (webhooks). Вебхуки для всевозможных провайдеров можно найти в Гитхабе в поиске по cert-manager-webhook. Есть официальные проекты, например от Яндекса.

Свой вебхук тоже можно написать, используя пример отсюда. Мы используем name.com для домена pingera.ru, который тоже поддерживается только хуками. Берем вот этот проект: https://github.com/imgrant/cert-manager-webhook-namecom/tree/main

Деплоим все по инструкции. В итоге мы создаем следующие ресурсы

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-namecom
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: <YOUR_EMAIL>
    privateKeySecretRef:
      name: letsencrypt-account-key
    solvers:
    - dns01:
        webhook:
          groupName: acme.name.com
          solverName: namedotcom
          config:
            username: <YOUR_LOGIN>
            apitokensecret:
              name: namedotcom-credentials
              key: api-token
  • Certificate - сам сертификат wild card. Это создаст сертификат в wild-cert.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: pingera-test
spec:
  dnsNames:
    - '*.pingera.ru'
  issuerRef:
    name: letsencrypt-namecom
    kind: ClusterIssuer
  secretName: wild-cert

Теперь можно и поменять наш Ingress. Мы поменяем домен на *.pingera.ru и будем ссылаться на сертификат напрямую:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.allow-http: "true"
spec:
  ingressClassName: nginx
  tls:
    - secretName: wild-cert
      hosts:
        - '*.pingera.ru'
  rules:
  - host: '*.pingera.ru'
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

Теперь мы можем направить любой поддомен pingera.ru на этот ingress, приложение уже само будет распределять трафик по субдоменам.

Заключение

В заключение, использование сертификатов TLS и протокола HTTPS в Kubernetes является критически важным аспектом для обеспечения безопасности и надежности веб-приложений. В этом посте мы обсудили, как можно легко и бесплатно развернуть сертификаты для вашего приложения, используя открытые и доступные инструменты, такие как ingress-nginx, cert-manager, и Let’s Encrypt.

Следуя этим шагам, вы не только обеспечите безопасность своего веб-приложения, но и автоматизируете процесс обновления сертификатов, снизив тем самым ручные усилия и вероятность возникновения ошибок. Это демонстрирует мощь и гибкость Kubernetes как платформы для развертывания современных веб-приложений и подчеркивает важность внедрения лучших практик безопасности с самого начала разработки.

Читайте также

Изменение ресурсов контейнера в Поде без перезагрузки

Изменение ресурсов контейнеров без перезагрузки Подов важно для динамических сред. В этом посте рассмотрим новый Alpha функционал в Kubernetes -#nbsp;#nbsp;InPlacePodVerticalScaling.

  • Опубликовано:
  • Обновлено
  • 3 мин чтения

Новости · Статус Страницы

Переворачиваем календарь: истории инцидентов в Статус Страницах

Обновление Статус Страниц Pingera: запуск календарного вида для раздела истории инцидентов (доступен автоматически для всех страниц) и исправление отображения кастомных подписей в почтовых уведомлениях.

  • Опубликовано:
  • Обновлено
  • 1 мин чтения

Проверки · Новости · Статус Страницы

Большое обновление платформы - Август 2026

Узнайте о главных обновлениях платформы за август: улучшенное управление инцидентами, RSS-ленты, интеграция с мессенджером MAX и полная поддержка SSL-сертификатов Минцифры для ваших проверок.

  • Опубликовано:
  • Обновлено
  • 2 мин чтения