Автоматическая генерация сертификатов — на первый взгляд, нечто прямиком из мира крупных корпораций, и потому вне досягаемости обычного разработчика, который размещает контент в кластере Kubernetes, запущенном на Raspberry Pi. К счастью, автоматическая генерация сертификатов стала на редкость доступной благодаря Let’s Encrypt. И что лучше всего — любой владелец доменного имени может получить сертификат совершенно бесплатно.
В этом руководстве мы воспользуемся Let’s Encrypt для автоматического предоставления сертификатов ресурсам Ingress так, чтобы приложения были доступны по сети через HTTPS.
Предварительные требования
1. Кластер Raspberry Pi.
2. К3, запущенный в кластере Raspberry Pi.
3. Traefik в качестве провайдера для Kubernetes Ingress.
4. Доменное имя. Вы можете создать домен, к примеру, на godaddy.com.
Как работает Let’s Encrypt
Let’s Encrypt — это источник сертификатов (certificate authority, CA), который внедряет протокол ACME и позволяет конфигурировать HTTPS-сервер без вмешательства человека. Здесь мы настроим HTTPS-сервер для домена https://cloud-tack.com, а вы замените его на свой домен. Говоря точнее, HTTPS-сервер в этом руководстве — это Traefik Ingress Controller, который запущен как контейнер внутри K3 на Raspberry Pi.
Выдача сертификата проводится в два этапа. На первом этапе агент, который намерен запросить сертификат, должен доказать источнику сертификатов, что владеет доменом, для которого он выдается. Этот процесс называется валидация домена. Только после того, как агент предоставит доказательства, можно запрашивать, обновлять и отзывать сертификат. Агент в контексте этого руководства — приложение-менеджер сертификатов (cert-manager
), развернутое внутри пространства имен менеджера сертификатов (подробнее об этом далее в статье).
Агент инициирует процесс, запрашивая у источника сертификатов, как именно ему доказать владение доменом. Источник сертификатов отвечает набором вызовов, и агент должен исполнить один из вызовов в качестве доказательства. В этом гайде агент исполнит вызов HTTP01.
- Предоставьте HTTP-ресурс под хорошо известным URI на http://cloud-tack.com/ (например, http://cloud-tack.com/8303).
Агент разместит HTTP-файл по указанному URI. Далее источник сертификатов проверит, доступен ли этот файл, содержит ли необходимый контент и правильную сигнатуру. Для этого он скачает файл по указанному URI (например, http://cloud-tack.com/8303). Если мы не владеем доменом, то не можем разместить файл в нужном месте, с правильным контентом и сигнатурой. Следовательно, это — доказательство владения.
Менеджер сертификатов отвечает за создание этого файла и, вместе с ним, временного Ingress таким образом, чтобы http://cloud-tack.com/8303 перенаправлял трафик к файлу, и источник сертификатов мог скачать его. Только после того, как владение доменом доказано, агент может подавать запросы на выдачу, обновление и отзыв сертификата.
Сертификат, выданный Let’s Encrypt, хранится в качестве секрета Kubernetes. Когда этот секрет применяется к ресурсу Ingress для домена cloud-tack.com, ресурс cloud-tack.com становится доступен через HTTPS.
Сконфигурируйте сеть
Локальный маршрутизатор должен перенаправить порты HTTP (80) и HTTPS (443) по умолчанию на порты узлов Traefik для HTTP и HTTPS соответственно.
Создайте порты узлов Traefik
HTTP-трафик доступен через порт 30179
, а HTTPS-трафик — через 30180
, как сконфигурировано в следующем манифесте:
kubectl create -f traefik-svc-http-https.yaml
Содержимое traefik-svc-http-https.yaml
:
apiVersion: v1
kind: Service
metadata:
name: traefik
namespace: kube-system
labels:
app: traefik
spec:
type: NodePort
ports:
- name: traefik-https
port: 443
nodePort: 30180
targetPort: 443
- name: traefik-http
port: 80
nodePort: 30179
targetPort: 80
selector:
app: traefik
Пробросьте порты HTTP и HTTPS по умолчанию на ваш маршрутизатор
Следующие скриншоты получены с маршрутизатора Verizon Fios. Интерфейс каждого маршрутизатора немного различается, но все они позволяют конфигурировать проброс портов.
После входа в маршрутизатор по адресу 192.168.1.1 перейдите на страницу переброса портов (как указано в инструкции вашего маршрутизатора). На рисунке 1 в красной рамке указан IP-адрес главного узла Kubernetes. В синей рамке выбран HTTP-порт по умолчанию (80). Наконец, зеленая рамка указывает, на какой порт должен по умолчанию направляться трафик HTTP. Это значение соответствует порту узла traefik-http
из файла traefik-svc-http-https.yaml
. Чтобы указать целевой порт для HTTP и HTTPS по умолчанию, вам, возможно, придется открыть дополнительные параметры. Нажмите кнопку “Add”, чтобы добавить конфигурацию HTTP.
Выполните ту же последовательность операций, что и для HTTP, но измените значения для порта HTTPS по умолчанию, как показано на рисунке 2.
Проброс HTTP-порта позволяет cert-manager
и Let’s Encrypt завершить задачи проверки домена и выдачи. Трафик для HTTPS-доменов будет проходить через проброшенный порт HTTPS.
Настройка DNS
Домен, для которого вы собираетесь создать сертификат, должен указывать на общедоступный IP-адрес вашего маршрутизатора. Например, cloud-tack.com
-> 71.105.198.177. Мы создадим DNS-запись A, которая свяжет наш домен с этим IP. Запись A — это простой DNS-ресурс, который работает как псевдоним. Все запросы на cloud-tack.com
“под капотом” будут разрешаться на IP-адрес 71.105.198.177.
Определите общедоступный IP-адрес вашего маршрутизатора, перейдя на whatsmyip.org
. С помощью этого IP-адреса мы создадим запись A. Я создал домен cloud-tack.com
через GoDaddy, поэтому интерфейс для создания записи A будет отличаться от вашего, если у вас другой поставщик. В синей рамке на рисунке 3 видно, что запись типа A указывает на общедоступный IP-адрес моего маршрутизатора 71.105.198.177. Убедитесь, что это единственная запись A в списке и что в вашем домене нет никакой пользовательской переадресации.
Убедитесь, что DNS настроен правильно, запустив поиск по домену. Ответом должен быть общедоступный IP-адрес вашего маршрутизатора:
$ dig +short cloud-tack.com
71.105.198.177
Теперь, когда запись A создана, HTTP-трафик в вашем домене будет перенаправляться на порт 80 маршрутизатора. Аналогично, трафик HTTPS будет перенаправляться на порт 443. Затем ваш маршрутизатор перенаправит трафик с этих портов в Traefik Ingress Controller на порты 30179 и 30180 соответственно.
Развертывание диспетчера сертификатов
Для шифрования требуется агент, который запускает программное обеспечение, способное выполнять задачи проверки домена, а также выдачу, продление и отзыв сертификатов. С небольшими корректировками для работы на Raspberry Pi мы будем следовать руководству Kubernetes по развертыванию агента cert-manager
.
Подготовка манифеста
Загрузите манифест, предоставленный Jet stack для cert-manager
, и замените каждый образ cert-manager
тем, что совместим с ARM. Имейте в виду, что загружаемый вами манифест зависит от версии Kubernetes.
# Kubernetes 1.16+
$ curl -sL https://github.com/jetstack/cert-manager/releases/download/v1.1.0/cert-manager.yaml | \
sed -r 's/(image:.*quay.io\/jetstack\/cert-manager-.*):(.*)$/\1-arm:/g' > cert-manager.yaml
# Kubernetes <1.16
$ curl -sL https://github.com/jetstack/cert-manager/releases/download/v1.1.0/cert-manager-legacy.yaml | \
sed -r 's/(image:.*quay.io\/jetstack\/cert-manager-.*):(.*)$/\1-arm:/g' > cert-manager.yaml
Настройка менеджера сертификатов
Создайте пространство имен cert-manager
:
$ kubectl create namespace cert-manager
Примените cert-manager
на кластере:
$ kubectl apply -f cert-manager.yaml
Верифицируйте установку cert-manager
:
$ kubectl get pods --namespace cert-manager
NAME READY STATUS RESTARTS AGE
cert-manager-84f968b6f9-jm9rd 1/1 Running 0 52s
cert-manager-cainjector-64cdd465 1/1 Running 0 52s
cert-manager-webhook-57b8c5f965 1/1 Running 0 52s
Создайте ClusterIssuer ACME
Издатель ACME представляет собой учетную запись, зарегистрированную на сервере центра сертификации среды автоматического управления сертификатами. Эта учетная запись однозначно идентифицируется парой из открытого и закрытого ключей и необходима для выдачи сертификатов. Как упоминалось выше, для верификации домена агенту необходимо решать задачи. Здесь будет приведен пример манифеста ClusterIssuer, который решает задачу с HTTP01.
Примените ClusterIssuer к своему кластеру:
$ kubectl apply -f staging-issuer.yaml
Обязательно измените адрес электронной почты в строке 7:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: acme-staging
spec:
acme:
email: [email protected] # Замените на свой email
server: https://acme-staging-v02.api.letsencrypt.org/directory # staging
privateKeySecretRef:
name: acme-staging
solvers:
- http01:
ingress:
class: traefik
Проверьте, что ClusterIssuer настроен правильно:
$ kubectl get clusterissuers
NAME READY AGE
acme-staging True 10s
Создайте тестовый сертификат
Кластеризатор, который мы применили, будет ориентирован на непродуктовую среду Let’s Encrypt. Эта среда более скоростная, так что во время отладки вы можете выдавать много сертификатов и не получить блокировку. Как только мы убедимся, что можем создать сертификат в этой среде, то нацелимся на продакшн.
Примените сертификат к своему кластеру:
$ kubectl apply -f test-acme-certificate.yaml
Содержимое test-acme-certificate.yaml
:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: cloud-tack-com # Замените на свой домен
namespace: default
spec:
secretName: cloud-tack-com-tls # Замените на tls своего домена
issuerRef:
name: acme-staging
kind: ClusterIssuer
commonName: cloud-tack.com # Замените на свой домен
dnsNames:
- cloud-tack.com # Замените на свой домен
Убедитесь, что сертификат создан правильно:
$ kubectl get certificate
NAME READY SECRET AGE
cloud-tack-com True cloud-tack-com-tls 13s
Если статус остается False
, вам придется выполнить отладку. Например, убедитесь, что ваш домен может успешно перенаправлять интернет-трафик HTTP-запросов приложению, запущенному в вашем кластере. Самый быстрый способ — перенаправить трафик в Traefik по неизвестному пути (к примеру, http://your-domain.com/test-http-traffic). При правильном пробросе портов ответ должен быть “404 — страница не найдена”. Если вы получаете такой ответ и все еще не можете предоставить тестовый сертификат, потребуется дальнейшая отладка.
Удалите промежуточные ресурсы
Тестовые ресурсы были нужны только для проверки настроек. Уже сейчас можно их удалить.
Удалите сертификат:
$ kubectl delete certificate cloud-tack-com
certificate.cert-manager.io "cloud-tack-com" deleted
Удалите секрет:
$ kubectl delete secret cloud-tack-com-tls
secret "cloud-tack-com-tls" deleted
Удалите ClusterIssuer:
$ kubectl delete -f staging-issuer.yaml
Примените ClusterIssuer для продакшена
Теперь, когда мы знаем, что Let’s Encrypt может выдавать сертификаты, а cert-manager
способен решать задачи, можно переходить к настройке Let’s Encrypt на продакшене.
$ kubectl apply -f prod-issuer.yaml
Обязательно измените адрес электронной почты в строке 7:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: acme-prod
spec:
acme:
email: [email protected] # Замените на свой email
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: acme-prod
solvers:
- http01:
ingress:
class: traefik
Убедитесь, что издатель готов к обслуживанию:
$ kubectl get clusterissuers
NAME READY AGE
acme-prod True 20s
Отлично! Ваш кластер готов автоматически предоставлять сертификаты ресурсам Ingress.
Настройте Ingress Resource для HTTPS
Следующий манифест запускает Ingress для приложения fma-ui
, которое работает в кластере-примере. Вам нужно будет развернуть свое собственное приложение и настроить для него Ingress.
$ kubectl apply -f ingress-https.yaml
Ресурс Ingress предоставляет дополнительный раздел конфигурации для шифрования. Следующий манифест — пример ресурса Ingress, который настраивает сертификат для домена cloud-tack.com
. Если задействован Ingress, а секрет сертификата не существует, то для домена, указанного в строке 19, будет автоматически создан сертификат, а секрет получит имя из строки 20. Измените значения в строках 4, 12–16 и 19–20 этого манифеста, чтобы они соответствовали вашим потребностям. Другие строки менять не нужно!
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: fma-ui
annotations:
kubernetes.io/ingress.class: traefik
cert-manager.io/cluster-issuer: acme-prod
spec:
rules:
- http:
paths:
- path: /fma-ui
pathType: Prefix
backend:
serviceName: fma-ui
servicePort: 9090
tls:
- hosts:
- cloud-tack.com
secretName: cloud-tack-com-tls
Убедитесь, что сертификат создан:
$ kubectl get certificates
NAME READY SECRET AGE
cloud-tack-com-tls True cloud-tack-com-tls 20s
Вот и все! Теперь вы можете пользоваться URL-адресом https://cloud-tack.com/fma-ui. Этот сертификат действителен в течение 90 дней, после чего менеджер сертификатов автоматически продлит его действие.
Заключение
Настройка HTTPS значительно улучшит кластер Raspberry Pi. С помощью HTTPS вы сможете безопасно и профессионально разместить сайт в интернете.
Мы автоматизировали HTTPS для ресурсов Kubernetes Ingress, развернув менеджер сертификатов и кластеризатор, которые могут взаимодействовать с Let’s Encrypt и Traefik. Эти сертификаты предоставляются бесплатно и автоматически продляются по истечении срока действия.
Читайте также:
- Kubernetes: преимущества простых кластеров
- Kubernetes избавляется от Docker
- Airflow и Kubernetes - лучшее решение для конвейеров данных Geoblink
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи: Jonathan Scott: Use Let’s Encrypt to Automate HTTPS for Your Kubernetes Cluster on Raspberry Pi