Использование TLS с контроллером объекта ingress в Службе Azure Kubernetes (AKS)

Протокол TLS использует сертификаты для обеспечения безопасности связи, шифрования, проверки подлинности и целостности. Использование TLS с контроллером входящего трафика в AKS позволяет защитить связь между приложениями и воспользоваться преимуществами контроллера входящего трафика.

Вы можете использовать собственные сертификаты и интегрировать их с драйвером CSI хранилища секретов. Кроме того, можно использовать cert-manager, который автоматически создает и настраивает сертификаты Let's Encrypt . Два приложения выполняются в кластере AKS, каждый из которых доступен по одному IP-адресу.

Внимание

Надстройка маршрутизации приложений рекомендуется для входящего трафика в AKS. Дополнительные сведения см. в статье Managed nginx Ingress с надстройкой маршрутизации приложений.

Внимание

Корпорация Майкрософт не управляет или не поддерживает диспетчер сертификатов и любые проблемы, связанные с его использованием. Сведения о проблемах с cert-manager см . в документации по устранению неполадок с cert-manager.

Существует два контроллера объекта ingress с открытым исходным кодом для Kubernetes на основе Nginx: один поддерживается сообществом Kubernetes (kubernetes/ingress-nginx), а второй — компанией Nginx, Inc. (nginxinc/kubernetes-ingress). В этой статье используется контроллер входящего трафика сообщества Kubernetes.

Подготовка к работе

  • В этой статье предполагается, что у вас есть контроллер входящего трафика и приложения. Если вам нужен контроллер объекта ingress или примеры приложений, см. статью Создание контроллера входящего трафика в Службе Azure Kubernetes (AKS).

  • В данной статье описано использование Helm 3 для установки контроллера объекта ingress NGINX на поддерживаемую версию Kubernetes. Убедитесь, что вы используете последний выпуск Helm и имеете доступ к ingress-nginxjetstack репозиториям Helm. Порядок действий, описанный в этой статье, может не подходить для предыдущих версий диаграммы Helm, контроллера объекта ingress NGINX или Kubernetes.

  • В этой статье предполагается, что у вас есть существующий кластер AKS с интегрированным Реестр контейнеров Azure (ACR). Дополнительные сведения о создании кластера AKS с интегрированным ACR см. в статье Аутентификация с помощью ACR из AKS.

  • Если вы используете Azure CLI, эта статья требует, чтобы вы использовали Azure CLI версии 2.0.64 или более поздней. Чтобы узнать версию, выполните команду az --version. Если вам необходимо выполнить установку или обновление, см. статью Установка Azure CLI 2.0.

  • Если вы используете Azure PowerShell, в этой статье требуется, чтобы вы работали с Azure PowerShell версии 5.9.0 или более поздней. Чтобы узнать версию, выполните команду Get-InstalledModule -Name Az. Если вам необходимо выполнить установку или обновление, см. статью об установке Azure PowerShell.

Использование TLS с собственными сертификатами с драйвером CSI хранилища секретов

Чтобы использовать TLS с собственными сертификатами с драйвером CSI хранилища секретов, вам потребуется кластер AKS с настроенным драйвером CSI хранилища секретов и экземпляром Azure Key Vault.

Дополнительные сведения см. в статье Настройка драйвера CSI хранилища секретов для включения контроллера объекта ingress NGINX с протоколом TLS.

Использование протокола TLS с сертификатами Let's Encrypt

Чтобы использовать TLS с сертификатами Let's Encrypt , вы развернете диспетчер сертификатов, который автоматически создает и настраивает сертификаты Let's Encrypt.

Импорт образов cert-manager, используемых чартом Helm, в ACR

  • Используйте az acr import для импорта следующих изображений в ACR.

    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
    

Примечание.

Вы также можете импортировать диаграммы Helm в ACR. Дополнительные сведения см. в статье "Отправка и извлечение диаграмм Helm" в ACR.

Параметры конфигурации контроллера объекта ingress

Контроллер входящего трафика NGINX можно настроить с помощью статического общедоступного IP-адреса или динамического общедоступного IP-адреса. Если вы используете личный домен, необходимо добавить запись A в зону DNS. Если вы не используете личный домен, можно настроить полное доменное имя (FQDN) для IP-адреса контроллера входящего трафика.

Создание статического или динамического общедоступного IP-адреса

Использование статического общедоступного IP-адреса

Контроллер входящего трафика можно настроить со статическим общедоступным IP-адресом. Статический общедоступный IP-адрес остается при удалении контроллера входящего трафика. IP-адрес не остается, если удалить кластер AKS.

При обновлении контроллера входящего трафика необходимо передать параметр в выпуск Helm, чтобы служба контроллера входящего трафика была осведомлена о подсистеме балансировки нагрузки, которая будет выделена для него. Чтобы сертификаты HTTPS работали правильно, используйте метку DNS для настройки полного доменного имени для IP-адреса контроллера входящего трафика.

  1. Получите имя группы ресурсов кластера AKS с az aks show помощью команды.

    az aks show --resource-group myResourceGroup --name myAKSCluster --query nodeResourceGroup -o tsv
    
  2. Создайте общедоступный IP-адрес со статическим методом выделения с помощью az network public-ip create команды. В следующем примере создается общедоступный IP-адрес с именем myAKSPublicIP в группе ресурсов кластера 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-адрес.
  1. Добавьте параметр --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"="<DNS_LABEL>". Метку DNS можно задать либо при первом развертывании контроллера объекта ingress, либо настроить позже.

  2. Добавьте параметр --set controller.service.loadBalancerIP="<STATIC_IP>". Укажите собственный общедоступный IP-адрес, созданный на предыдущем шаге.

    DNS_LABEL="<DNS_LABEL>"
    NAMESPACE="ingress-basic"
    STATIC_IP=<STATIC_IP>
    
    helm upgrade ingress-nginx 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 \
      --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz
    

Дополнительные сведения см. в статье Использование статического общедоступного IP-адреса и DNS-метки с подсистемой балансировки нагрузки Службы Azure Kubernetes (AKS).

Использование динамического общедоступного IP-адреса

Общедоступный IP-адрес Azure создается для контроллера входящего трафика при создании. Общедоступный IP-адрес является статическим в течение срока существования контроллера входящего трафика. Общедоступный IP-адрес не остается, если удалить контроллер входящего трафика. При создании нового контроллера входящего трафика он будет назначен новый общедоступный IP-адрес. Выходные данные должны выглядеть примерно так, как в следующем примере выходных данных.

  • kubectl get service Используйте команду, чтобы получить общедоступный IP-адрес для контроллера входящего трафика.

    # Get the public IP address for your ingress controller
    
    kubectl --namespace ingress-basic get services -o wide -w nginx-ingress-ingress-nginx-controller
    
    # Sample output
    
    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

Если вы используете личный домен, необходимо добавить запись A в зону DNS. Если вы не используете личный домен, можно настроить общедоступный IP-адрес с полным доменным именем.

  • Добавьте запись 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
    

Настройка полного доменного имени для контроллера входящего трафика

При необходимости можно настроить полное доменное имя для IP-адреса контроллера входящего трафика вместо личного домена, задав метку DNS. Полное доменное имя должно соответствовать следующей форме: <CUSTOM DNS LABEL>.<AZURE REGION NAME>.cloudapp.azure.com

Внимание

Ваша метка DNS должна быть уникальной в своем расположении Azure.

Полное доменное имя можно настроить с помощью одного из следующих методов:

  • Задайте метку DNS с помощью Azure CLI или Azure PowerShell.
  • Задайте метку DNS с помощью параметров диаграммы Helm.

Дополнительные сведения см. в метках DNS-имени общедоступного IP-адреса.

Настройка метки DNS с помощью Azure CLI или Azure PowerShell

Обязательно замените <DNS_LABEL> уникальной меткой DNS.

# Public IP address of your ingress controller
IP="MY_EXTERNAL_IP"

# Name to associate with public IP address
DNSLABEL="<DNS_LABEL>"

# 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 $DNSLABEL

# Display the FQDN
az network public-ip show --ids $PUBLICIPID --query "[dnsSettings.fqdn]" --output tsv

Задание метки DNS с помощью параметров диаграммы Helm

Вы можете передать параметр заметки в конфигурацию диаграммы Helm с помощью --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name" параметра. Этот параметр можно задать при первом развертывании контроллера входящего трафика или его можно настроить позже.

В следующем примере показано, как обновить этот параметр после развертывания контроллера. Обязательно замените <DNS_LABEL> уникальной меткой DNS.

DNSLABEL="<DNS_LABEL>"
NAMESPACE="ingress-basic"

helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
  --namespace $NAMESPACE \
  --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"=$DNSLABEL \
  --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz

Установка cert-manager

Контроллер NGINX Ingress поддерживает завершение TLS. Существует несколько способов извлечения и настройки сертификатов для протокола HTTPS. В этой статье используется диспетчер сертификатов, который предоставляет автоматическиефункции создания сертификатов и управления ими.

Чтобы установить контроллер 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.

Создание издателя кластера ЦС

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

  • Издатель, который работает в одном пространстве имен.
  • Ресурс ClusterIssuer, который работает во всех пространствах имен.

Дополнительные сведения см. в документации по издателю cert-manager.

  1. Создайте издатель кластера, например cluster-issuer.yaml, используя приведенный ниже пример манифеста. Замените MY_EMAIL_ADDRESS допустимым адресом из вашей организации.

    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
    
  2. Примените издателя с помощью kubectl apply команды.

    kubectl apply -f cluster-issuer.yaml --namespace ingress-basic
    

Обновление маршрутов входящего трафика

Необходимо обновить маршруты входящего трафика для обработки трафика в полное доменное имя или личный домен.

В следующем примере трафик направляется следующим образом:

  • Трафик к 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.

  1. Создайте или обновите файл с помощью следующего hello-world-ingress.yaml примера YAML-файла. spec.tls.hosts Обновите dns-имя, spec.rules.host созданное на предыдущем шаге.

    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
    
  2. Обновите ресурс входящего трафика с помощью команды kubectl apply.

    kubectl apply -f hello-world-ingress.yaml --namespace ingress-basic
    

Проверка создания объекта сертификата

Далее нужно создать ресурс сертификата. Этот ресурс сертификата определяет необходимый сертификат X.509. Дополнительные сведения см. в описании сертификатов cert-manager.

Cert-manager автоматически создает объект сертификата для вас с помощью ingress-shim, который автоматически развертывается с помощью диспетчера сертификатов с версии 0.2.2. Дополнительные сведения см. в документации по ingress-shim.

Чтобы убедиться, что сертификат был создан успешно, используйте kubectl get certificate --namespace ingress-basic команду и убедитесь , что готово к работе с значением 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. Убедитесь, что следующие значения имеют значение true:

  • Вы перенаправляетесь для использования HTTPS.
  • Сертификат является доверенным.
  • Демонстрационное приложение отображается в веб-браузере.
  • Добавьте /hello-world-two в конец домена и убедитесь, что второе демонстрационное приложение с пользовательским заголовком отображается.

Очистка ресурсов

В этой статье для установки компонентов обработки входящего трафика, сертификатов и примеров приложений используется Helm. При развертывании чарта Helm создается множество ресурсов Kubernetes. К ним относятся элементы pod, развертывания и службы. Чтобы очистить эти ресурсы, можно удалить все образец пространства имен или отдельные ресурсы.

Удаление примера пространства имен и всех ресурсов

При удалении примера пространства имен также удаляются все ресурсы в пространстве имен.

  • Удалите весь образец пространства имен с помощью kubectl delete команды и укажите имя пространства имен.

    kubectl delete namespace ingress-basic
    

Удаление ресурсов по отдельности

Кроме того, можно удалить ресурс по отдельности.

  1. Удалите ресурсы издателя кластера.

    kubectl delete -f cluster-issuer.yaml --namespace ingress-basic
    
  2. Получите список выпусков 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
    
  3. Удалите выпуски helm uninstall с помощью команды. В следующем примере производится удаление развертываний входящего трафика NGINX и cert-manager.

    $ helm uninstall cert-manager nginx --namespace ingress-basic
    
    release "cert-manager" uninstalled
    release "nginx" uninstalled
    
  4. Удалите два примера приложений.

    kubectl delete -f aks-helloworld-one.yaml --namespace ingress-basic
    kubectl delete -f aks-helloworld-two.yaml --namespace ingress-basic
    
  5. Удалите маршрут входящего трафика, направленный на примеры приложений.

    kubectl delete -f hello-world-ingress.yaml --namespace ingress-basic
    
  6. Удалите само пространство имен. kubectl delete Используйте команду и укажите имя пространства имен.

    kubectl delete namespace ingress-basic
    

Следующие шаги

В данной статье упоминаются некоторые внешние компоненты для AKS. Чтобы узнать больше об этих компонентах, см. следующие страницы проекта:

Кроме того, вы можете сделать следующее: