Использование TLS с контроллером объекта ingress в Службе Azure Kubernetes (AKS)
Протокол TLS — это протокол для обеспечения безопасности при обмене данными, например с помощью шифрования, аутентификации и обеспечения целостности, путем использования сертификатов. Использование TLS с контроллером объекта ingress в AKS позволяет защитить обмен данными между приложениями, а также получить все преимущества контроллера объекта ingress.
Вы можете использовать собственные сертификаты и интегрировать их с драйвером CSI хранилища секретов. Кроме того, можно использовать cert-manager, который используется для автоматического создания и настройки сертификатов Let's Encrypt. Наконец, в кластере AKS запущено два приложения, каждое из которых доступно по одному IP-адресу.
Примечание
Существует два контроллера объекта ingress с открытым исходным кодом для Kubernetes на основе Nginx: один поддерживается сообществом Kubernetes (kubernetes/ingress-nginx), а второй — компанией Nginx, Inc. (nginxinc/kubernetes-ingress). В этой статье будет использоваться контроллер объекта ingress сообщества Kubernetes.
Подготовка к работе
В этой статье также предполагается, что у вас есть контроллер объекта ingress и настроенные приложения. Если вам нужен контроллер объекта ingress или примеры приложений, см. статью Создание контроллера входящего трафика в Службе Azure Kubernetes (AKS).
В данной статье используется Helm 3 для установки контроллера объекта ingress NGINX в поддерживаемую версию Kubernetes. Убедитесь, что используете последний выпуск Helm. Вам также понадобится доступ к репозиториям Helm ingress-nginx и jetstack. Порядок действий, описанный в этой статье, может не подходить для предыдущих версий диаграммы Helm, контроллера объекта ingress NGINX или Kubernetes.
Дополнительную информацию о настройке и использовании Helm см. в статье Использование Helm со службой Azure Kubernetes. Инструкции по обновлению см. в документации по установке Helm.
Кроме того, предполагается, что у вас уже есть кластер AKS с интегрированным Реестром контейнеров Azure (ACR). Дополнительные сведения о создании кластера AKS с интегрированным ACR см. в статье Проверка подлинности в Реестре контейнеров Azure из Службы Azure Kubernetes.
Для работы с этой статьей требуется Azure CLI 2.0.64 или более поздней версии. Чтобы узнать версию, выполните команду az --version. Если вам необходимо выполнить установку или обновление, см. статью Установка Azure CLI 2.0.
Использование TLS с собственными сертификатами с драйвером CSI хранилища секретов
Чтобы использовать TLS с собственными сертификатами с драйвером CSI хранилища секретов, вам потребуется кластер AKS с настроенным драйвером CSI хранилища секретов и экземпляром Azure Key Vault. Дополнительные сведения см. в статье Настройка драйвера CSI хранилища секретов для включения контроллера объекта ingress NGINX с протоколом TLS.
Использование протокола TLS с сертификатами Let's Encrypt
Чтобы использовать TLS с сертификатами Let's Encrypt, вы развернете cert-manager, который используется для автоматического создания и настройки сертификатов Let's Encrypt.
Импорт образов cert-manager, используемых чартом Helm, в ACR
Для импорта этих образов в ACR используйте команду az acr import.
REGISTRY_NAME=<REGISTRY_NAME>
CERT_MANAGER_REGISTRY=quay.io
CERT_MANAGER_TAG=v1.8.0
CERT_MANAGER_IMAGE_CONTROLLER=jetstack/cert-manager-controller
CERT_MANAGER_IMAGE_WEBHOOK=jetstack/cert-manager-webhook
CERT_MANAGER_IMAGE_CAINJECTOR=jetstack/cert-manager-cainjector
az acr import --name $REGISTRY_NAME --source $CERT_MANAGER_REGISTRY/$CERT_MANAGER_IMAGE_CONTROLLER:$CERT_MANAGER_TAG --image $CERT_MANAGER_IMAGE_CONTROLLER:$CERT_MANAGER_TAG
az acr import --name $REGISTRY_NAME --source $CERT_MANAGER_REGISTRY/$CERT_MANAGER_IMAGE_WEBHOOK:$CERT_MANAGER_TAG --image $CERT_MANAGER_IMAGE_WEBHOOK:$CERT_MANAGER_TAG
az acr import --name $REGISTRY_NAME --source $CERT_MANAGER_REGISTRY/$CERT_MANAGER_IMAGE_CAINJECTOR:$CERT_MANAGER_TAG --image $CERT_MANAGER_IMAGE_CAINJECTOR:$CERT_MANAGER_TAG
Примечание
Помимо импорта в ACR образов контейнеров, туда также можно импортировать чарты Helm. Дополнительные сведения см. в статье Отправка чартов Helm в Реестр контейнеров Azure и их извлечение оттуда.
Параметры конфигурации контроллера объекта ingress
По умолчанию контроллер входящего трафика NGINX создается с новым назначением общедоступного IP-адреса. Этот общедоступный IP-адрес является статическим только на время жизненного цикла контроллера входящего трафика и теряется, если контроллер удаляется и создается повторно.
Вы можете выбрать один из следующих способов:
- использование динамического общедоступного IP-адреса;
- использование статического общедоступного IP-адреса.
Использование статического общедоступного IP-адреса
Общее требование конфигурации — предоставить контроллеру входящего трафика NGINX имеющийся статический общедоступный IP-адрес. Статический общедоступный IP-адрес останется, если контроллер входящего трафика будет удален.
Приведенные ниже команды создают IP-адрес, который будет удален при удалении кластера AKS.
Сначала получите имя группы ресурсов для кластера ASK, выполнив команду az aks show:
az aks show --resource-group myResourceGroup --name myAKSCluster --query nodeResourceGroup -o tsv
Создайте общедоступный IP-адрес с помощью метода статического выделения, используя команду az network public-ip create. В следующем примере создается общедоступный IP-адрес myPublicIP в группе ресурсов AKS, о которой говорилось на предыдущих шагах.
az network public-ip create --resource-group MC_myResourceGroup_myAKSCluster_eastus --name myAKSPublicIP --sku Standard --allocation-method static --query publicIp.ipAddress -o tsv
Вы также можете создать IP-адрес в другой группе ресурсов, которой можно управлять отдельно от кластера AKS. Если вы создаете IP-адрес в другой группе ресурсов, проверьте следующие характеристики:
- Удостоверение кластера, используемое кластером AKS, имеет делегированные разрешения на доступ к группе ресурсов, например участник сетей.
- Добавьте параметр
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-resource-group"="<RESOURCE_GROUP>". Замените<RESOURCE_GROUP>именем группы ресурсов, в которой находится IP-адрес.
При обновлении контроллера объекта ingress необходимо передать параметр в выпуск Helm, чтобы контроллер объекта ingress был осведомлен о статичном IP-адресе подсистемы балансировки нагрузки, выделяемом службе контроллера объекта ingress. Чтобы обеспечить правильную работу сертификатов HTTPS, для настройки полного доменного имени для IP-адреса контроллера объекта ingress используется метка DNS-имени.
- Добавьте параметр
--set controller.service.loadBalancerIP="<EXTERNAL_IP>". Укажите собственный общедоступный IP-адрес, созданный на предыдущем шаге. - Добавьте параметр
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"="<DNS_LABEL>". Метку DNS можно задать либо при первом развертывании контроллера объекта ingress, либо настроить позже.
DNS_LABEL="demo-aks-ingress"
NAMESPACE="ingress-basic"
STATIC_IP=<STATIC_IP>
helm upgrade nginx-ingress ingress-nginx/ingress-nginx \
--namespace $NAMESPACE \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"=$DNS_LABEL \
--set controller.service.loadBalancerIP=$STATIC_IP
Дополнительные сведения см. в статье Использование статического общедоступного IP-адреса и DNS-метки с подсистемой балансировки нагрузки Службы Azure Kubernetes (AKS).
Использование динамического IP-адреса
При создании контроллера объекта ingress для него создается общедоступный IP-адрес Azure. Этот IP-адрес является статическим только на время жизненного цикла контроллера входящего трафика. При удалении контроллера входящего трафика этот общедоступный IP-адрес теряется. Если создать дополнительный контроллер объекта ingress, ему назначается новый общедоступный IP-адрес.
Чтобы получить общедоступный IP-адрес, используйте команду kubectl get service.
kubectl --namespace ingress-basic get services -o wide -w nginx-ingress-ingress-nginx-controller
В примере выходных данных показаны сведения о контроллере объекта ingress:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx-ingress-ingress-nginx-controller LoadBalancer 10.0.74.133 EXTERNAL_IP 80:32486/TCP,443:30953/TCP 44s app.kubernetes.io/component=controller,app.kubernetes.io/instance=nginx-ingress,app.kubernetes.io/name=ingress-nginx
Если вы используете личный домен, необходимо добавить запись A в зону DNS. В противном случае необходимо настроить общедоступный IP-адрес с полным доменным именем (FQDN).
Добавление записи A в зону DNS
Добавьте запись A в зону DNS с внешним IP-адресом службы NGINX с помощью команды az network dns record-set a add-record.
az network dns record-set a add-record \
--resource-group myResourceGroup \
--zone-name MY_CUSTOM_DOMAIN \
--record-set-name "*" \
--ipv4-address MY_EXTERNAL_IP
Настройка полного доменного имени контроллера объекта ingress
При необходимости можно настроить полное доменное имя для IP-адреса контроллера входящего трафика вместо личного домена. Полное доменное имя будет иметь вид <CUSTOM LABEL>.<AZURE REGION NAME>.cloudapp.azure.com.
Метод 1. Задание метки DNS с помощью Azure CLI
Этот пример предназначен для оболочки Bash.
# Public IP address of your ingress controller
IP="MY_EXTERNAL_IP"
# Name to associate with public IP address
DNSNAME="demo-aks-ingress"
# Get the resource-id of the public ip
PUBLICIPID=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$IP')].[id]" --output tsv)
# Update public ip address with DNS name
az network public-ip update --ids $PUBLICIPID --dns-name $DNSNAME
# Display the FQDN
az network public-ip show --ids $PUBLICIPID --query "[dnsSettings.fqdn]" --output tsv
Метод 2. Задание метки DNS с помощью параметров чарта Helm
Вы можете передать параметр заметки в конфигурацию чарта Helm с помощью параметра --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name". Этот параметр можно задать либо при первом развертывании контроллера объекта ingress, либо настроить позже.
В следующем примере показано, как обновить этот параметр после развертывания контроллера.
DNS_LABEL="demo-aks-ingress"
NAMESPACE="ingress-basic"
helm upgrade nginx-ingress ingress-nginx/ingress-nginx \
--namespace $NAMESPACE \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"=$DNS_LABEL
Установка cert-manager
Контроллер входящего трафика NGINX поддерживает обработку подключений TLS для последующей передачи. Получить и настроить сертификаты для HTTPS можно несколькими способами. В этой статье демонстрируется использование проекта cert-manager, который обеспечивает автоматические функции создания сертификатов Lets Encrypt и управления ими.
Установка контроллера cert-manager:
# Set variable for ACR location to use for pulling images
ACR_URL=<REGISTRY_URL>
# Label the ingress-basic namespace to disable resource validation
kubectl label namespace ingress-basic cert-manager.io/disable-validation=true
# Add the Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io
# Update your local Helm chart repository cache
helm repo update
# Install the cert-manager Helm chart
helm install cert-manager jetstack/cert-manager \
--namespace ingress-basic \
--version $CERT_MANAGER_TAG \
--set installCRDs=true \
--set nodeSelector."kubernetes\.io/os"=linux \
--set image.repository=$ACR_URL/$CERT_MANAGER_IMAGE_CONTROLLER \
--set image.tag=$CERT_MANAGER_TAG \
--set webhook.image.repository=$ACR_URL/$CERT_MANAGER_IMAGE_WEBHOOK \
--set webhook.image.tag=$CERT_MANAGER_TAG \
--set cainjector.image.repository=$ACR_URL/$CERT_MANAGER_IMAGE_CAINJECTOR \
--set cainjector.image.tag=$CERT_MANAGER_TAG
Дополнительные сведения о конфигурации cert-manager см. в описании проекта cert-manager.
Создание издателя кластера ЦС
Для выдачи сертификатов средству cert-manager нужен ресурс Issuer или ClusterIssuer. Эти ресурсы Kubernetes имеют аналогичную функциональность, однако Issuer работает в отдельном пространстве имен, а ClusterIssuer — во всех. Дополнительные сведения см. в документации по издателю cert-manager.
Создайте издатель кластера, например cluster-issuer.yaml, используя приведенный ниже пример манифеста. Измените адрес электронной почты на действительный адрес вашей организации:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: MY_EMAIL_ADDRESS
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: nginx
podTemplate:
spec:
nodeSelector:
"kubernetes.io/os": linux
Чтобы создать издатель, используйте команду kubectl apply.
kubectl apply -f cluster-issuer.yaml
Обновление маршрутов входящего трафика
Вам потребуется обновить маршруты входящего трафика для направления трафика на полное доменное имя или личный домен.
В следующем примере трафик к адресу hello-world-ingress.MY_CUSTOM_DOMAIN перенаправляется к службе aks-helloworld-one. Трафик к адресу hello-world-ingress.MY_CUSTOM_DOMAIN/hello-world-two перенаправляется к службе aks-helloworld-two. Трафик к hello-world-ingress.MY_CUSTOM_DOMAIN/static перенаправляется к службе aks-helloworld-one для статических ресурсов.
Примечание
Если вы настроили полное доменное имя для IP-адреса контроллера входящего трафика вместо личного домена, используйте полное доменное имя вместо hello-world-ingress.MY_CUSTOM_DOMAIN. Например, если полное доменное имя — demo-aks-ingress.eastus.cloudapp.azure.com, замените hello-world-ingress.MY_CUSTOM_DOMAIN на demo-aks-ingress.eastus.cloudapp.azure.com в hello-world-ingress.yaml.
Создайте или обновите файл hello-world-ingress.yaml с помощью приведенного ниже примера YAML. Обновите spec.tls.hosts и spec.rules.host, указав DNS-имя, которое вы создали на предыдущем шаге.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-world-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/use-regex: "true"
cert-manager.io/cluster-issuer: letsencrypt
spec:
ingressClassName: nginx
tls:
- hosts:
- hello-world-ingress.MY_CUSTOM_DOMAIN
secretName: tls-secret
rules:
- host: hello-world-ingress.MY_CUSTOM_DOMAIN
http:
paths:
- path: /hello-world-one(/|$)(.*)
pathType: Prefix
backend:
service:
name: aks-helloworld-one
port:
number: 80
- path: /hello-world-two(/|$)(.*)
pathType: Prefix
backend:
service:
name: aks-helloworld-two
port:
number: 80
- path: /(.*)
pathType: Prefix
backend:
service:
name: aks-helloworld-one
port:
number: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-world-ingress-static
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /static/$2
spec:
ingressClassName: nginx
tls:
- hosts:
- hello-world-ingress.MY_CUSTOM_DOMAIN
secretName: tls-secret
rules:
- host: hello-world-ingress.MY_CUSTOM_DOMAIN
http:
paths:
- path: /static(/|$)(.*)
pathType: Prefix
backend:
service:
name: aks-helloworld-one
port:
number: 80
Обновите ресурс входящего трафика с помощью команды kubectl apply.
kubectl apply -f hello-world-ingress.yaml --namespace ingress-basic
Проверка создания объекта сертификата
Далее нужно создать ресурс сертификата. Этот ресурс сертификата определяет необходимый сертификат X.509. Дополнительные сведения см. в описании сертификатов cert-manager. cert-manager автоматически создал объект сертификата с помощью ingress-shim — оболочки совместимости, которая автоматически развертывается с помощью cert-manager начиная с версии 0.2.2. Дополнительные сведения см. в документации по ingress-shim.
Чтобы убедиться, что сертификат успешно создан, используйте команду kubectl get certificate --namespace ingress-basic и убедитесь, что параметр READY имеет значение true. Это может занять несколько минут.
kubectl get certificate --namespace ingress-basic
В примере выходных данных ниже показано состояние сертификата:
NAME READY SECRET AGE
tls-secret True tls-secret 11m
Проверка конфигурации входящего трафика
Откройте браузер по адресу hello-world-ingress.MY_CUSTOM_DOMAIN или по полному доменному имени контроллера объекта ingress в Kubernetes. Обратите внимание, что вы перенаправлены на использование протокола HTTPS, сертификат является доверенным, а демонстрационное приложение отображается в веб-браузере. Добавьте путь /hello-world-two и обратите внимание на второе демонстрационное приложение с пользовательским заголовком.
Очистка ресурсов
В этой статье для установки компонентов обработки входящего трафика, сертификатов и примеров приложений используется Helm. При развертывании чарта Helm создается множество ресурсов Kubernetes. К ним относятся элементы pod, развертывания и службы. Чтобы очистить эти ресурсы, можно удалить весь пример пространства имен либо отдельные ресурсы.
Удаление примера пространства имен и всех ресурсов
Чтобы удалить весь пример пространства имен, используйте команду kubectl delete и укажите имя пространства имен. Все ресурсы в пространстве имен будут удалены.
kubectl delete namespace ingress-basic
Удаление ресурсов по отдельности
Можно использовать более скрупулезный подход — удалить отдельные созданные ресурсы. Сначала удалите ресурсы издателя кластера:
kubectl delete -f cluster-issuer.yaml --namespace ingress-basic
Получите список выпусков Helm с помощью команды helm list. Найдите диаграммы nginx и cert-manager, как показано в следующем примере выходных данных:
$ helm list --namespace ingress-basic
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
cert-manager ingress-basic 1 2020-01-15 10:23:36.515514 -0600 CST deployed cert-manager-v0.13.0 v0.13.0
nginx ingress-basic 1 2020-01-15 10:09:45.982693 -0600 CST deployed nginx-ingress-1.29.1 0.27.0
Удалите выпуски командой helm uninstall. В следующем примере производится удаление развертываний входящего трафика NGINX и cert-manager.
$ helm uninstall cert-manager nginx --namespace ingress-basic
release "cert-manager" uninstalled
release "nginx" uninstalled
Затем удалите два примера приложений:
kubectl delete -f aks-helloworld-one.yaml --namespace ingress-basic
kubectl delete -f aks-helloworld-two.yaml --namespace ingress-basic
Удалите маршрут входящего трафика, направлявший трафик в пример приложения.
kubectl delete -f hello-world-ingress.yaml --namespace ingress-basic
Наконец, можно удалить само пространство имен. Используйте команду kubectl delete и укажите имя пространства имен:
kubectl delete namespace ingress-basic
Дальнейшие действия
В данной статье упоминаются некоторые внешние компоненты для AKS. Чтобы узнать больше об этих компонентах, см. следующие страницы проекта:
Кроме того, вы можете сделать следующее: