Поиск по сайту:

Как защитить свой сайт в Kubernetes с помощью cert-manager, Traefik и Let’s Encrypt


Автор выбрал программу Write for DOnations.

Введение

TLS для защиты своего трафика. Однако может быть сложно управлять всеми движущимися частями, необходимыми для размещения сайта на основе TLS, от приобретения сертификата TLS до своевременного обновления этих сертификатов и настройки сервера для их использования.

К счастью, есть сервисы, которые вы можете запустить в своем кластере Kubernetes, чтобы справиться с этой сложностью за вас. Вы можете использовать Let’s Encrypt, поставщика бесплатных и автоматизированных безопасных сертификатов, который снижает нагрузку на управление вашими сертификатами, как правило, до такой степени, что вам нужно только выполнить первоначальную настройку.

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

Предпосылки

  • Кластер Kubernetes, доступный с помощью kubectl. Если вам нужно создать кластер, у DigitalOcean есть руководство по быстрому запуску Kubernetes.
  • Последняя версия kubectl для взаимодействия с вашим кластером. См. документацию по продукту для установки kubectl в Linux, MacOS и Windows.
  • Учетная запись DigitalOcean с установленным и настроенным doctl. Чтобы настроить это, см. нашу документацию по продукту, как установить и настроить doctl.
  • установка Helm.
  • Узнайте, как взаимодействовать с кластером Kubernetes с помощью kubectl. Чтобы приступить к работе, следуйте нашему руководству Создайте и разверните свой первый образ в своем первом кластере.
  • Зарегистрированное доменное имя. В этом руководстве будет использоваться ваш_домен. Вы можете приобрести доменное имя у Freenom или воспользоваться услугами регистратора доменов по вашему выбору.
  • Настройка DNS для вашего доменного имени. В этом руководстве предполагается, что вы используете DNS DigitalOcean, но это не обязательно. Если вы используете DigitalOcean, ознакомьтесь с нашей статьей «Как указать на серверы имен DigitalOcean от общих регистраторов доменов», чтобы получить информацию об использовании DNS DigitalOcean с обычными регистраторами доменов.
  • Персональный токен доступа с доступом для чтения и записи для DNS DigitalOcean, если вы используете DigitalOcean для DNS. Другие поставщики будут иметь аналогичные токены доступа.

Шаг 1 — Настройка cert-manager в вашем кластере

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

Однако с созданием cert-manager — службы, предназначенной для работы в Kubernetes, которая автоматически управляет жизненным циклом ваших сертификатов.

В этом разделе вы настроите cert-manager для работы в вашем кластере в собственном пространстве имен cert-manager.

Сначала установите cert-manager с помощью kubectl с файлом выпуска cert-manager:

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

По умолчанию cert-manager устанавливается в собственное пространство имен с именем cert-manager. По мере применения файла в вашем кластере будет создан ряд ресурсов, которые появятся в вашем выводе (часть вывода удалена из-за длины):

Output
namespace/cert-manager created customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created # some output excluded deployment.apps/cert-manager-cainjector created deployment.apps/cert-manager created deployment.apps/cert-manager-webhook created mutatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created

В этом разделе вы установили cert-manager для управления вашими безопасными сертификатами. Теперь вам нужно настроить способ сообщить cert-manager, как вы хотите выдавать свои сертификаты. В следующем разделе вы настроите эмитента Let’s Encrypt в своем кластере.

Шаг 2 — Настройка эмитента сертификата Let’s Encrypt

Использование безопасного сертификата для вашего веб-сайта — это способ сообщить вашим пользователям, что они могут доверять сайту, который они просматривают, с ваших серверов. Для этого центр сертификации должен подтвердить, что вы являетесь владельцем домена, для которого предназначен сертификат. Let’s Encrypt делает это, используя стандартную задачу DNS-01 с DNS-провайдером DigitalOcean.

В этом разделе вы создадите ClusterIssuer для своего кластера, чтобы сообщить cert-manager, как выдавать сертификаты от Let’s Encrypt и какие учетные данные использовать для выполнения запросов DNS, требуемых Let’s Encrypt.

Примечание. В этом руководстве предполагается, что вы используете DigitalOcean в качестве поставщика DNS и настраиваете ClusterIssuer с учетом этого предположения. cert-manager поддерживает ряд различных облачных провайдеров для задач HTTP и DNS, поэтому к ним можно применять одни и те же концепции.

Для получения дополнительной информации о других поставщиках, поддерживаемых cert-manager, см. раздел ACME Introduction в документации cert-manager.

Прежде чем создавать ClusterIssuer для своего кластера, вам нужно создать каталог для конфигурации вашего кластера. Используйте команду mkdir, чтобы создать каталог, а затем cd, чтобы войти в этот каталог:

  1. mkdir tutorial-cluster-config
  2. cd tutorial-cluster-config

После того, как вы создали свой каталог, вам понадобится токен личного доступа для доступа к DNS, который вы создали в рамках предварительных условий этого руководства. Токен доступа DigitalOcean будет похож на dop_v1_4321... с длинной строкой цифр.

Чтобы сохранить токен доступа в качестве секрета в Kubernetes, вам необходимо закодировать его в base-64. Для этого вы можете использовать команду echo, чтобы передать свой токен команде base64, заменив выделенную часть вашим токеном доступа:

  1. echo -n 'dop_v1_4321...' | base64

Эта команда отправит ваш токен доступа из echo в команду base64 для его кодирования. Опция -n гарантирует, что новая строка не будет добавлена в конце. В зависимости от вашего токена доступа вы получите вывод, аналогичный следующему:

Output
ZG9wX3YxX3RoaXNpc25vdGFyZWFsdG9rZW5idXRpbXB1dHRpbmdhYnVuY2hvZnN0dWZmaW5oZXJlc29sZW5ndGhzbWF0Y2g=

Эти выходные данные являются вашим токеном доступа в кодировке base-64. Скопируйте это, потому что вы будете использовать его дальше.

Используя nano или ваш любимый редактор, создайте и откройте новый файл с именем lets-encrypt-do-dns.yaml:

  1. nano lets-encrypt-do-dns.yaml

Добавьте следующий код, чтобы создать Secret Kubernetes. Обязательно используйте токен доступа в кодировке base-64 в поле access-token:

apiVersion: v1
kind: Secret
metadata:
  namespace: cert-manager
  name: lets-encrypt-do-dns
data:
  access-token: ZG9wX3Y...

Этот секрет будет называться lets-encrypt-do-dns и храниться в пространстве имен cert-manager. В разделе data вы включаете созданный ранее токен доступа в кодировке base-64. Этот секрет надежно хранит токен доступа, на который вы будете ссылаться при создании эмитента Let’s Encrypt.

Затем сохраните файл и примените его к кластеру с помощью kubectl apply:

  1. kubectl apply -f lets-encrypt-do-dns.yaml

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

Output
secret/lets-encrypt-do-dns created

Теперь создайте новый файл с именем lets-encrypt-issuer.yaml, чтобы содержать ClusterIssuer диспетчера сертификатов, который вы будете использовать для выпуска сертификатов Let’s Encrypt:

  1. nano lets-encrypt-issuer.yaml

Добавьте следующие строки, введя свой адрес электронной почты в поле spec.acme.email (это адрес, который Let’s Encrypt будет ассоциировать с предоставляемыми им сертификатами):

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-issuer
spec:
  acme:
    email: your_email_address
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-issuer-account-key
    solvers:
      - selector: {}
        dns01:
          digitalocean:
            tokenSecretRef:
              name: lets-encrypt-do-dns
              key: access-token

В первых двух строках apiVersion и kind говорят, что этот ресурс Kubernetes является диспетчером сертификатов ClusterIssuer. Затем вы называете его letsencrypt-issuer. В этом случае вы не включили поле namespace, потому что ресурс является ресурсом Cluster, то есть он применяется ко всему кластеру, а не к одному пространству имен.

Затем в разделе spec вы определяете раздел вызова acme, чтобы сообщить менеджеру сертификатов, что ClusterIssuer должен использовать ACME для выпуска сертификатов с использованием letsencrypt-эмитент. email — это ваш адрес электронной почты, на который Let’s Encrypt будет отправлять любые сообщения, связанные с сертификатом, например, напоминания о продлении, если возникнет проблема, и cert-manager не продлит их вовремя. Поле server указывает URL-адрес для связи с запросом вызовов ACME и устанавливается на производственный URL-адрес Let’s Encrypt. После поля server вы включаете поле privateKeySecretRef с именем секрета, который cert-manager будет использовать для хранения своего сгенерированного закрытого ключа для вашего кластера.

Одним из наиболее важных разделов в разделе spec.acme является раздел solvers. В этом разделе вы настраиваете решатели задач ACME, которые хотите использовать для letsencrypt-issuer. В этом случае вы включаете один решатель, решатель dns01. Первая часть конфигурации решателя, selector, настроена как {}, что означает «что угодно». Если вы хотите использовать разные решатели для других сертификатов в вашем кластере, вы можете настроить дополнительные селекторы в том же эмитенте.Дополнительную информацию о том, как это сделать, можно найти в ACME Introduction cert-manager.

Внутри раздела dns01 вы добавляете раздел digitalocean, чтобы сказать, что этот эмитент должен использовать DigitalOcean в качестве решателя DNS-01. Если вы используете другого облачного провайдера, здесь вы должны настроить другого провайдера. Внутри этого раздела вы включаете tokenSecretRef для ссылки на поле lets-encrypt-do-dns access-token в Secret, который вы создали ранее. cert-manager будет использовать этот токен доступа при создании DNS-записей от вашего имени.

Сохранив файл эмитента, примените его к кластеру с помощью kubectl apply:

  1. kubectl apply -f lets-encrypt-issuer.yaml

Вывод подтвердит, что ClusterIssuer с именем letsencrypt-issuer создан:

Output
clusterissuer.cert-manager.io/letsencrypt-issuer created

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

Шаг 3 — Использование балансировщика нагрузки с Traefik

балансировщик нагрузки, чтобы принимать сетевые подключения и отправлять их в разные экземпляры Traefik, фактически балансируя нагрузку сетевого трафика.

В этом разделе вы установите Traefik в свой кластер и подготовите его для использования с сертификатами, управляемыми cert-manager, и веб-сайтом, который вы добавите на шаге 5. Вы также настроите балансировщик нагрузки, который будет отправлять входящие сетевой трафик к вашей службе Traefik из-за пределов вашего кластера, а также подготовить вас к работе с несколькими экземплярами Traefik, если вы решите их запустить.

Сначала создайте пространство имен с именем traefik, куда вы установите Traefik. Для этого откройте файл с именем traefik-ns.yaml:

  1. nano traefik-ns.yaml

Введите ресурс Kubernetes Namespace:

apiVersion: v1
kind: Namespace
metadata:
  name: traefik

После сохранения файла примените его к кластеру с помощью kubectl apply:

  1. kubectl apply -f traefik-ns.yaml

Как только ваша команда запустится, выходные данные кластера подтвердят, что пространство имен было создано:

Output
namespace/traefik created

После создания пространства имен traefik вы установите саму службу Traefik. Для этого вы будете использовать утилиту под названием chart.

Во-первых, вам нужно добавить репозиторий Helm traefik в доступные репозитории, что позволит Helm найти пакет traefik:

  1. helm repo add traefik https://helm.traefik.io/traefik

После выполнения команды вы получите подтверждение того, что репозиторий traefik добавлен в репозитории Helm на вашем компьютере:

Output
"traefik" has been added to your repositories

Затем обновите репозиторий диаграмм:

  1. helm repo update

Вывод подтвердит, что репозиторий диаграмм traefik был обновлен:

Output
Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "traefik" chart repository Update Complete. ⎈Happy Helming!⎈

Наконец, установите traefik в пространство имен traefik, которое вы создали в своем кластере:

  1. helm install --namespace=traefik traefik traefik/traefik

В этой команде много traefik, поэтому давайте рассмотрим, что делает каждый из них. Первый traefik в вашей команде с --namespace=traefik указывает Helm установить Traefik в пространство имен traefik, которое вы создали ранее. Затем выделенный traefik — это имя, которое вы хотите присвоить этой установке Traefik в вашем кластере. Таким образом, если у вас есть несколько установок Traefik в одном кластере, вы можете дать им разные имена, например traefik-website1 и traefik-website2. Поскольку сейчас в вашем кластере будет только одна установка Traefik, вы можете просто использовать имя traefik. Третий traefik/ — это репозиторий, который вы добавили ранее и из которого хотите выполнить установку. Наконец, последний traefik — это имя диаграммы, которую вы хотите установить.

Как только вы запустите команду, вывод, подобный следующему, будет напечатан на экране:

NAME: traefik
LAST DEPLOYED: Sun Oct  2 16:32:57 2022
NAMESPACE: traefik
STATUS: deployed
REVISION: 1
TEST SUITE: None

После установки диаграммы Helm Traefik начнет загрузку в ваш кластер. Чтобы узнать, запущен ли Traefik, запустите kubectl get all, чтобы просмотреть все ресурсы Traefik, созданные в пространстве имен traefik:

  1. kubectl get -n traefik all

Ваш вывод будет похож на вывод ниже:

Output
NAME READY STATUS RESTARTS AGE pod/traefik-858bb8459f-k4ztp 1/1 Running 0 94s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/traefik LoadBalancer 10.245.77.251 <pending> 80:31981/TCP,443:30188/TCP 94s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/traefik 1/1 1 1 94s NAME DESIRED CURRENT READY AGE replicaset.apps/traefik-858bb8459f 1 1 1 94s

В зависимости от вашего кластера и времени выполнения предыдущей команды некоторые имена и возрасты могут отличаться. Если вы видите в разделе EXTERNAL-IP для вашего service/traefik, продолжайте запускать kubectl get -n traefik all, пока IP-адрес не будет указан. EXTERNAL-IP — это IP-адрес, с которого балансировщик нагрузки доступен в Интернете. Как только IP-адрес будет указан, запишите этот IP-адрес как свой traefik_ip_address. Вы будете использовать этот адрес в следующем разделе для настройки своего домена.

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

Шаг 4 — Доступ к Traefik с вашим доменом

Теперь, когда Traefik настроен в вашем кластере и доступен в Интернете с помощью балансировщика нагрузки, вам необходимо обновить DNS вашего домена, чтобы он указывал на ваш балансировщик нагрузки Traefik. Прежде чем продолжить, убедитесь, что ваш домен добавлен в вашу учетную запись DigitalOcean. cert-manager должен иметь возможность обновлять настройки DNS для вашего домена, используя токен доступа, который вы установили ранее. Вы будете использовать doctl, чтобы настроить записи DNS вашего домена, чтобы они указывали на балансировщик нагрузки Traefik.

Примечание. В этом разделе предполагается, что вы используете DigitalOcean в качестве хоста DNS. Если вы используете хост DNS, отличный от DigitalOcean, вы все равно будете создавать те же типы записей DNS с теми же значениями, но вам нужно будет обратиться к документации вашего хоста DNS, чтобы узнать, как их добавить.

Сначала создайте DNS-запись A для своего домена с именем tutorial-proxy.your_domain, которая указывает на ваш traefik_ip_address:

  1. doctl compute domain records create your_domain --record-name tutorial-proxy --record-type A --record-data traefik_ip_address

Запись DNS A сообщает DNS, что данное имя хоста должно указывать на определенный IP-адрес. В этом случае tutorial-proxy.your_domain будет указывать на traefik_ip_address. Таким образом, если кто-то запрашивает веб-сайт по адресу tutorial-proxy.ваш_домен, DNS-серверы направят его на traefik_ip_address. .

После запуска команды вы получите подтверждение того, что ваша запись создана:

Output
ID Type Name Data Priority Port TTL Weight 12345678 A tutorial-proxy traefik_ip_address 0 0 1800 0

Теперь создайте DNS-запись типа CNAME с именем tutorial-service.your_domain и направьте ее на tutorial-proxy. ваш_домен. Поскольку у вас, вероятно, в какой-то момент будет запущено несколько служб в вашем кластере, использование записи A для указания каждого домена на ваш прокси-сервер Traefik может потребовать много работы, если вам когда-нибудь понадобится изменить IP-адрес вашего прокси. адрес. Использование CNAME указывает DNS использовать адрес домена, на который он указывает. В данном случае используется домен tutorial-proxy.your_domain, поэтому вам нужно обновить только одну запись A, чтобы она указывала на новый IP-адрес. адрес вместо нескольких записей A.

Чтобы создать запись CNAME, снова используйте команду doctl. Обязательно включите завершающую точку (.) в --record-data:

  1. doctl compute domain records create your_domain --record-name tutorial-service --record-type CNAME --record-data tutorial-proxy.your_domain.

Это создаст вашу DNS-запись tutorial-service.your_domain CNAME, указывающую на tutorial-proxy.your_domain. . Теперь, когда кто-то запрашивает tutorial-service.ваш_домен, DNS-сервер сообщит ему о подключении к IP-адресу tutorial-proxy.ваш_домен указывает на. Завершающий . в --record-data сообщает DNS-серверу, что это конец предоставленного домена, и он не должен добавлять какую-либо другую информацию в конце, подобно тому, как точка (.) используется для окончания предложения.

После запуска команды вы увидите вывод, подобный следующему:

Output
ID Type Name Data Priority Port TTL Weight 12345679 CNAME tutorial-service tutorial-proxy.your_domain 0 0 1800 0

Поскольку DigitalOcean является вашим основным DNS-сервером, вы можете напрямую запросить сервер, чтобы определить, правильно ли он настроен, вместо того, чтобы ждать обновления других DNS-серверов в Интернете. Чтобы убедиться, что ваши настройки проходят через DNS-серверы правильно, используйте команду dig, чтобы просмотреть, какими, по мнению ns1.linux-console.net, основного DNS-сервера DigitalOcean, должны быть записи:

Примечание. Если вы используете DNS-хост, отличный от DigitalOcean, замените ns1.linux-console.net в этой команде на один из DNS-серверов, которые ваш DNS-хост установил в своем домене.

  1. dig @ns1.linux-console.net +noall +answer +domain=your_domain tutorial-proxy tutorial-service

Получить информацию DNS с помощью Dig.

Затем с помощью +domain=ваш_домен указывает dig добавить .your_domain в список конец любых имен хостов, предоставленных команде. Наконец, tutorial-proxy и tutorial-service — это имена хостов для поиска. Поскольку вы используете параметр +domain, вам не нужно использовать полную фразу tutorial-proxy.your_domain, так как это автоматически добавляются в конце.

Вы должны получить вывод, подобный следующему, с вашими собственными значениями для your_domain и traefik_ip_address:

Output
tutorial-proxy.your_domain. 1662 IN A traefik_ip_address tutorial-service.your_domain. 1800 IN CNAME tutorial-proxy.your_domain. tutorial-proxy.your_domain. 1800 IN A traefik_ip_address

Первая строка вывода показывает, что tutorial-proxy.your_domain является записью A (IN A), которая указывает на traefik_ip_address. Второй подтверждает, что tutorial-service.your_domain является записью CNAME (IN CNAME), указывающей на tutorial-proxy.ваш_домен. Наконец, последняя строка — это запрос dig, который выполняется для поиска адреса, на который указывает ваша запись CNAME. Поскольку это tutorial-proxy.ваш_домен, он будет показывать тот же IP-адрес записи A, что и раньше.

В этом разделе вы добавили DNS-запись типа A и DNS-запись типа CNAME в свой домен, чтобы сетевые клиенты, такие как браузеры, знали, куда идти. подключиться к вашему сервису Traefik. В следующем разделе вы настроите временный веб-сервер в своем кластере, чтобы завершить настройку.

Шаг 5 — Создание вашего веб-сервиса

В предыдущих разделах вы настроили cert-manager и Traefik для обработки безопасных сертификатов вашего веб-сайта и направления веб-трафика на ваш веб-сервис. Однако на данный момент у вас нет веб-службы для отправки трафика. В этом разделе вы будете использовать веб-сервер Nginx для имитации веб-сайта, который вы бы разместили в своем кластере.

Чтобы имитировать веб-сайт, вы настроите Deployment, используя образ Docker nginx. Он покажет только Nginx «Добро пожаловать!» странице, но этого достаточно, чтобы убедиться, что все правильно подключено и работает как положено.

Сначала создайте файл с именем tutorial-service.yaml:

  1. nano tutorial-service.yaml

Добавьте следующий код, который создает Namespace с именем tutorial и Deployment с именем tutorial-service:

apiVersion: v1
kind: Namespace
metadata:
  name: tutorial
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: tutorial
  name: tutorial-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app.kubernetes.io/name: tutorial-service
      app.kubernetes.io/part-of: tutorial
  template:
    metadata:
      labels:
        app.kubernetes.io/name: tutorial-service
        app.kubernetes.io/part-of: tutorial
    spec:
      containers:
        - name: service
          image: nginx
          ports:
            - containerPort: 80

Подобно пространству имен traefik, которое вы создали ранее, первый ресурс в этом файле создаст новое пространство имен в вашем кластере с именем tutorial. Следующий ресурс, tutorial-service Deployment, указывает, что вам нужны три реплики веб-сайта, работающие в вашем кластере, поэтому, если одна из них выйдет из строя, у вас останутся две другие. пока третий не вернется.

Следующий раздел, селектор, сообщает Kubernetes, как найти любые модули, связанные с этим развертыванием. В этом случае он найдет любые модули с совпадающими метками. В разделе template вы определяете, как должен выглядеть каждый из ваших модулей. Раздел metadata предоставляет метки, которые будут сопоставляться в селекторе, а spec указывает, что вы хотите, чтобы в модуле был один контейнер с именем сервис, который использует образ nginx и прослушивает сетевые подключения через порт 80.

Сохранив изменения, примените их к кластеру:

  1. kubectl apply -f tutorial-service.yaml

Вывод подтвердит, что пространство имен tutorial и развертывание tutorial-service созданы:

Output
namespace/tutorial created deployment.apps/tutorial-service created

Чтобы проверить, запущено ли ваше развертывание, вы можете использовать команду kubectl get pods, чтобы вывести список модулей, работающих в пространстве имен tutorial:

  1. kubectl get -n tutorial pods

Будет напечатан вывод, аналогичный следующему:

Output
NAME READY STATUS RESTARTS AGE tutorial-service-568b4f8477-hpstl 1/1 Running 0 2m15s tutorial-service-568b4f8477-mcpqd 1/1 Running 0 2m15s tutorial-service-568b4f8477-mg8mb 1/1 Running 0 2m15s

Вы должны найти список из трех модулей с STATUS Running и случайными именами после tutorial-service-. AGE зависит от того, сколько времени прошло между запуском команд kubectl apply и kubectl get.

Теперь, когда ваш веб-сервис запущен и работает, вам нужен способ отправки трафика по всем трем модулям. В Kubernetes для этого используется Service. Любой трафик, отправляемый в Service, будет распределяться по нагрузке между различными модулями, на которые указывает Service.

Чтобы создать свой Service, снова откройте файл tutorial-service.yaml и добавьте Service в конец:

...
        - name: service
          image: nginx
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  namespace: tutorial
  name: tutorial-service
spec:
  selector:
    app.kubernetes.io/name: tutorial-service
    app.kubernetes.io/part-of: tutorial
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

Подобно Deployment, ваш Service имеет раздел selector, в котором перечислены метки для поиска модулей, на которые вы хотите отправлять трафик. Эти метки совпадают с метками, которые вы включили в раздел template модуля в Deployment. Service также имеет один порт, указанный в разделе ports, в котором указано, что любой трафик TCP отправляется на port: 80 из служба должна быть отправлена на targetPort: 80 в модуле, выбранном балансировщиком нагрузки.

После сохранения изменений примените Service к кластеру:

  1. kubectl apply -f tutorial-service.yaml

На этот раз в выходных данных пространство имен и развертывание указаны как неизмененные (поскольку вы не вносили в них никаких изменений), а tutorial-service был создано:

Output
namespace/tutorial unchanged deployment.apps/tutorial-service unchanged service/tutorial-service created

После создания tutorial-service вы можете проверить, можете ли вы получить доступ к службе, используя команду kubectl port-forward, чтобы сделать службу доступной на вашем локальном компьютере:

  1. kubectl port-forward -n tutorial service/tutorial-service 8888:80

Эта команда перенаправляет любой трафик, отправленный на порт 8888 на вашем локальном компьютере, на порт 80 tutorial-service в кластере. В кластере Kubernetes вы настроили tutorial-service Service для прослушивания подключений через порт 80, и вам нужен способ отправки трафика с вашего локального компьютера на эту службу в кластере. В команде вы указываете, что хотите port-forward на service/tutorial-service в пространстве имен tutorial, а затем предоставляете комбинацию порты 8888:80. Первый указанный порт — это порт, который будет прослушивать ваш локальный компьютер, а второй порт (после :) — это порт на service/tutorial-service, через который будет проходить трафик. быть отправлены. Когда вы отправляете трафик на порт 8888 на локальном компьютере, весь этот трафик будет отправляться на порт 80 в service/tutorial-service, и в конечном итоге на модули, на которые указывает service/tutorial-service.

Когда вы запустите команду, вы получите вывод, подобный следующему:

Output
Forwarding from 127.0.0.1:8888 -> 80 Forwarding from [::1]:8888 -> 80

Обратите внимание, что команда не вернется и продолжит работу для пересылки трафика.

Чтобы сделать запрос к вашей службе, откройте второй терминал на своем компьютере и используйте команду curl на своем компьютере через порт 8888:

  1. curl http://localhost:8888/

Эта команда отправляет HTTP-запрос через ваш перенаправленный порт (8888) в tutorial-service кластера и возвращает HTML-ответ, содержащий страницу приветствия Nginx:

Output
<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>

Теперь в исходном терминале вы можете нажать CONTROL+C, чтобы остановить команду port-forward. Вы также увидите некоторые дополнительные выходные данные, когда вы установили соединение curl:

Output
Forwarding from 127.0.0.1:8888 -> 80 Forwarding from [::1]:8888 -> 80 Handling connection for 8888

В этом разделе вы настроите веб-службу nginx в своем кластере, используя Deployment и Service. Затем вы использовали kubectl port-forward с командой curl, чтобы убедиться, что nginx работает правильно. Теперь, когда cert-manager, Traefik и ваша служба настроены, вы соберете их вместе в следующем разделе и сделаете свою службу доступной через HTTPS в Интернете с помощью cert-manager и Traefik.

Шаг 6 — Обеспечение доступности и безопасности вашего веб-сервиса

Несмотря на то, что в вашем кластере работают все отдельные службы, все они работают относительно независимо. cert-manager просто сидит там, Traefik не знает ни о каких сайтах, которые он должен обслуживать, а ваш веб-сайт Nginx доступен только в том случае, если вы переносите его в кластер. В этом разделе вы создадите ресурс Ingress для подключения всех ваших сервисов.

Сначала снова откройте tutorial-service.yaml:

  1. nano tutorial-service.yaml

Добавьте Ingress в конец файла после tutorial-service Service, добавленного ранее. Обязательно обновите конфигурацию, указав свое собственное доменное имя, и включите --- в начале, чтобы отделить ваш ресурс Ingress от ресурса Service. над ним:

...
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tutorial-service-ingress
  namespace: tutorial
  annotations:
    traefik.ingress.kubernetes.io/router.entrypoints: websecure
    traefik.ingress.kubernetes.io/router.tls: "true"
    cert-manager.io/cluster-issuer: letsencrypt-issuer
spec:
  rules:
    - host: tutorial-service.your_domain
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: tutorial-service
                port:
                  number: 80
  tls:
    - secretName: tutorial-service-cert
      hosts:
        - tutorial-service.your_domain

Эти строки включают в себя правила и аннотации, чтобы рассказать все, как сочетаться друг с другом. Ресурс Ingress включает ссылки на Traefik, cert-manager и ваш tutorial-service. Раздел annotations содержит несколько разных, но важных аннотаций.

Аннотация traefik.ingress.kubernetes.io/router.entrypoints сообщает Traefik, что трафик для этого Ingress должен быть доступен через точку входа websecure. Это точка входа, которую диаграмма Helm настраивает по умолчанию для обработки трафика HTTPS и прослушивания порта traefik_ip_address 443, используемого по умолчанию для HTTPS.

Следующая аннотация, traefik.ingress.kubernetes.io/router.tls, имеет значение true, чтобы Traefik отвечал только на HTTPS-трафик, а не на HTTP-трафик. Поскольку ваш веб-сайт должен быть безопасным для обработки любых конфиденциальных данных, вы не хотите, чтобы ваши пользователи случайно использовали небезопасную версию.

Последняя аннотация, cert-manager.io/cluster-issuer, имеет значение letsencrypt-issuer, чтобы сообщить cert-manager эмитента, которого вы хотели бы использовать при выпуске безопасных сертификатов. для этого Ingress. На данный момент letsencrypt-issuer — единственный настроенный вами эмитент, но позже вы можете добавить больше и использовать разные для разных сайтов.

В разделе Ingress spec.rules вы включаете одно правило для маршрутизации трафика, отправляемого на Ingress. В нем говорится, что для host с именем tutorial-service.your_domain используйте http для заданных путей. Единственный включенный path — это корневой путь / с pathType Prefix, что означает, что любой отправляемый трафик должен быть отправлено на указанный бэкенд. В разделе backend указано, что это service, и что служба, на которую он должен отправлять трафик, — это tutorial-service Service. вы создали ранее, и этот трафик должен быть отправлен на порт 80 Service.

Раздел spec.tls Ingress предоставляет информацию, необходимую диспетчеру сертификатов для запроса и выдачи ваших безопасных сертификатов, а также информацию, необходимую Traefik для использования этих сертификатов. secretName — это Secret Kubernetes, куда cert-manager поместит выданный безопасный сертификат, а Secret Traefik будет использовать для загрузки выданного сертификата. В разделе hosts перечислены имена хостов, для которых cert-manager будет запрашивать сертификаты. В этом случае это будет только имя хоста tutorial-service.your_domain, но вы также можете указать другие, которыми владеете, если хотите, чтобы сайт реагировал на несколько имен хостов. .

После сохранения созданного вами Ingress снова используйте kubectl apply, чтобы применить новый ресурс к вашему кластеру:

  1. kubectl apply -f tutorial-service.yaml

Ingress будет создан, а другие ресурсы останутся без изменений:

Output
namespace/tutorial unchanged deployment.apps/tutorial-service unchanged service/tutorial-service unchanged ingress.networking.k8s.io/tutorial-service-ingress created

Как только Ingress будет создан, Traefik начнет настраивать себя, а cert-manager начнет процесс запроса/ответа для выдачи сертификата. Это может занять несколько минут, поэтому вы можете проверить, был ли выдан сертификат, просмотрев сертификаты в вашем пространстве имен tutorial:

  1. kubectl get -n tutorial certificates

Вы получите вывод, аналогичный следующему:

Output
NAME READY SECRET AGE tutorial-service-cert False tutorial-service-cert 12m

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

Примечание. Если ваш сертификат не выдается через 10-15 минут, может быть полезно просмотреть сообщения журнала для cert-manager, чтобы узнать, не возникли ли у него проблемы с запросом сертификата. Чтобы просмотреть эти журналы, вы можете использовать следующую команду для просмотра журналов и нажать CONTRL+C, чтобы прекратить следить за ними:

  1. kubectl logs -n cert-manager deployment/cert-manager --tail=10 -f

Как только ваш сертификат будет готов, вы можете сделать HTTPS-запрос к вашему кластеру, используя curl:

  1. curl https://tutorial-service.your_domain

Примечание. В зависимости от того, как давно вы обновили свои записи DNS и сколько времени требуется для распространения записей DNS по DNS-серверам в Интернете, вы можете увидеть ошибку о том, что ваш домен не может быть найден или он попадает в неправильное место. Если это произойдет, вы можете использовать обходной путь curl, чтобы пропустить проверку DNS на данный момент, выполнив следующую команду:

  1. curl https://tutorial-service.your_domain --resolve 'tutorial-service.your_domain:443:traefik_ip_address'

Эта команда указывает команде curl использовать параметр --resolve для переопределения любого разрешения DNS для tutorial-service.your_domain на порт 443 вместо traefik_ip_address. Поскольку результат DNS, который получает curl, неверен, это все равно позволит вам подключиться к Traefik внутри вашего кластера, пока DNS не будет полностью обновлен.

На выходе вы получите тот же Nginx «Добро пожаловать!» страница из перенаправления портов ранее, но на этот раз она доступна через Интернет:

Output
<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>

Однако если вы попытаетесь запросить HTTP-версию своего сайта, вы не получите ответа:

  1. curl http://tutorial-service.your_domain

Вместо этого будет загружена ошибка 404:

Output
404 page not found

Поскольку вы настроили свой сайт в Ingress так, чтобы он не отвечал на HTTP-трафик, Traefik никогда не настраивал сайт по этому адресу и возвращает ошибку 404. Это может сбить с толку ваших пользователей, если они знают, что должны увидеть веб-сайт, поэтому многие администраторы настраивают свои серверы для автоматического перенаправления HTTP-трафика на сайт HTTPS. Traefik также позволяет сделать это, обновив Traefik, чтобы он перенаправлял весь веб-трафик на порт websecure:

  1. helm upgrade --namespace=traefik traefik traefik/traefik --set 'ports.web.redirectTo=websecure'

Параметр --set ports.web.redirectTo=websecure указывает Traefik перенастроить себя для автоматического перенаправления.

Вы должны увидеть сообщение, похожее на приведенное ниже, о том, что установка traefik была \обновлена:

Output
Release "traefik" has been upgraded. Happy Helming! NAME: traefik LAST DEPLOYED: Sun Oct 2 19:17:34 2022 NAMESPACE: traefik STATUS: deployed REVISION: 2 TEST SUITE: None

Теперь, если вы сделаете запрос к своему местоположению HTTP, вы получите вывод о том, что сайт был перемещен:

  1. curl http://tutorial-service.your_domain

Этот ответ ожидается:

Output
Moved Permanently

Поскольку вы хотите, чтобы весь ваш трафик направлялся на ваш HTTPS-сайт, Traefik теперь возвращает автоматическое перенаправление на HTTPS-сайт с HTTP-сайта от вашего имени. Веб-браузеры будут выполнять это перенаправление автоматически, но curl требует дополнительной опции, -L, чтобы указать ему следовать перенаправлениям. Обновите команду curl с параметром -L, чтобы следовать перенаправлениям:

  1. curl -L http://tutorial-service.your_domain

Вывод будет содержать страницу приветствия Nginx с вашего HTTPS-сайта:

Output
<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>

Эти выходные данные подтверждают, что перенаправление работает должным образом.

В этом разделе вы связали cert-manager, Traefik и ваш веб-сайт Nginx вместе с помощью ресурса Kubernetes Ingress. Вы также обновили конфигурацию Traefik для перенаправления трафика HTTP на веб-сайты HTTPS, чтобы пользователи могли найти ваш веб-сайт.

Заключение

В этом руководстве вы установили несколько различных служб в свой кластер Kubernetes, чтобы упростить запуск веб-сайта с безопасными сертификатами. Вы установили службу cert-manager для управления жизненным циклом сертификатов TLS, выпущенных Let’s Encrypt. Вы установили Traefik, чтобы сделать свои веб-сайты доступными за пределами вашего кластера и использовать сертификаты TLS, выданные Let’s Encrypt. Наконец, вы создали веб-сайт Nginx в своем кластере, чтобы протестировать свои конфигурации cert-manager и Traefik.

Теперь, когда в вашем кластере настроены cert-manager и Traefik, вы также можете настроить больше веб-сайтов с разными ресурсами Ingress для обслуживания множества веб-сайтов из одного кластера с помощью одной установки cert-manager и Traefik.

Вы можете прочитать, что cert-manager также имеет обширную документацию о том, как использовать его с другими типами вызовов Let’s Encrypt, а также источниками, отличными от Let’s Encrypt.

Чтобы продолжить настройку кластера Kubernetes, ознакомьтесь с другими нашими руководствами по Kubernetes.