Создание неуправляемого контроллера входящего трафика

Контроллер входящего трафика является программным компонентом, предоставляющим для служб Kubernetes обратный прокси-сервер, настраиваемую маршрутизацию трафика и обработку подключений TLS для последующей передачи. Ресурсы входящего трафика Kubernetes используются при настройке правил входящего трафика и маршрутов для отдельных служб Kubernetes. Когда вы используете контроллер объекта ingress и правила входящего трафика, для маршрутизации трафика в несколько служб в кластере Kubernetes можно использовать один IP-адрес.

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

Важно!

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

Примечание.

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

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

  • В данной статье описано использование Helm 3 для установки контроллера объекта ingress NGINX на поддерживаемую версию Kubernetes. Убедитесь, что вы используете последний выпуск Helm и имеете доступ к репозиторию Helm ingress-nginx. Порядок действий, описанный в этой статье, может не подходить для предыдущих версий диаграммы Helm, контроллера объекта ingress NGINX или Kubernetes.
  • В этой статье предполагается, что у вас есть существующий кластер AKS с интегрированным Реестр контейнеров Azure (ACR). Дополнительные сведения о создании кластера AKS с интегрированным ACR см. в статье Проверка подлинности в Реестре контейнеров Azure из Службы Azure Kubernetes.
  • Конечная точка healthz работоспособности API Kubernetes устарела в Kubernetes версии 1.16. Вместо этого можно заменить эту конечную точку livez на конечные точки и readyz конечные точки. Сведения о том, какую конечную точку следует использовать для сценария, см. в конечных точках API Kubernetes.
  • Если вы используете 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.

Базовая конфигурация

Для создания базового контроллера объекта ingress NGINX без настройки значений по умолчанию вы будете использовать Helm. Следующая конфигурация использует конфигурацию по умолчанию для простоты. Можно добавить параметры для настройки развертывания, например --set controller.replicaCount=3.

Примечание.

Если вы хотите включить сохранение исходного IP-адреса клиента для запросов к контейнерам в кластере, добавьте --set controller.service.externalTrafficPolicy=Local к команде установки Helm. Исходный IP-адрес клиента хранится в заголовке запроса в разделе X-Forwarded-For. При использовании контроллера объекта ingress с включенным сохранением исходного IP-адреса клиента сквозная передача данных по протоколу TLS не будет работать.

NAMESPACE=ingress-basic

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

helm install ingress-nginx ingress-nginx/ingress-nginx \
  --create-namespace \
  --namespace $NAMESPACE \
  --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
  --set controller.service.externalTrafficPolicy=Local

Примечание.

В этом руководстве service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path задано значение /healthz. Это означает, что если код ответа запросов /healthz не 200является, весь контроллер входящего трафика будет отключен. Значение можно изменить на другой универсальный код ресурса (URI) в собственном сценарии. Вы не можете удалить эту часть или не указать значение, или контроллер входящего трафика по-прежнему будет отключен. Пакетingress-nginx, используемый в этом руководстве, который предоставляется официальным сотрудником Kubernetes, всегда возвращает 200 код ответа при запросе/healthz, так как он разработан в качестве серверной части по умолчанию для пользователей, чтобы иметь быстрый запуск, если только он не перезаписывается правилами входящего трафика.

Настроенная конфигурация

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

Импорт в ACR изображений, используемых чартом Helm

Для управления версиями образа их необходимо импортировать в свой Реестр контейнеров Azure. В чарте Helm контроллера объекта ingress NGINX используется три образа контейнеров. Для импорта этих образов в ACR используйте команду az acr import.

REGISTRY_NAME=<REGISTRY_NAME>
SOURCE_REGISTRY=registry.k8s.io
CONTROLLER_IMAGE=ingress-nginx/controller
CONTROLLER_TAG=v1.8.1
PATCH_IMAGE=ingress-nginx/kube-webhook-certgen
PATCH_TAG=v20230407
DEFAULTBACKEND_IMAGE=defaultbackend-amd64
DEFAULTBACKEND_TAG=1.5

az acr import --name $REGISTRY_NAME --source $SOURCE_REGISTRY/$CONTROLLER_IMAGE:$CONTROLLER_TAG --image $CONTROLLER_IMAGE:$CONTROLLER_TAG
az acr import --name $REGISTRY_NAME --source $SOURCE_REGISTRY/$PATCH_IMAGE:$PATCH_TAG --image $PATCH_IMAGE:$PATCH_TAG
az acr import --name $REGISTRY_NAME --source $SOURCE_REGISTRY/$DEFAULTBACKEND_IMAGE:$DEFAULTBACKEND_TAG --image $DEFAULTBACKEND_IMAGE:$DEFAULTBACKEND_TAG

Примечание.

Помимо импорта в ACR образов контейнеров, туда также можно импортировать чарты Helm. Дополнительные сведения см. в статье Отправка чартов Helm в Реестр контейнеров Azure и их извлечение оттуда.

Создание контроллера входящего трафика

Чтобы создать контроллер входящего трафика, используйте Helm для установки ingress-nginx. Контроллер объекта Ingress необходимо запланировать на узле Linux. Узлы Windows Server не должны запускать контроллер Ingress. Селектор узла указывается с помощью параметра --set nodeSelector, чтобы сообщить планировщику Kubernetes о необходимости запуска контроллера NGINX Ingress на узле под управлением Linux.

Для дополнительной избыточности две реплики контроллеров NGINX Ingress развертываются с параметром --set controller.replicaCount. Чтобы максимально эффективно использовать реплики контроллера входящего трафика, убедитесь, что в кластере AKS используется несколько узлов.

В следующем примере для ресурсов Ingress создается пространство имен Kubernetes с именем ingress-basic, которое затем используется в этом примере. При необходимости укажите пространство имен для своего окружения. Если ваш кластер AKS не поддерживает управление доступом на основе ролей Kubernetes, добавьте строку --set rbac.create=false в команды Helm.

Примечание.

Если вы хотите включить сохранение исходного IP-адреса клиента для запросов к контейнерам в кластере, добавьте --set controller.service.externalTrafficPolicy=Local к команде установки Helm. Исходный IP-адрес клиента хранится в заголовке запроса в разделе X-Forwarded-For. При использовании контроллера объекта ingress с включенным сохранением исходного IP-адреса клиента сквозная передача данных по протоколу TLS не будет работать.

# Add the ingress-nginx repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# Set variable for ACR location to use for pulling images
ACR_LOGIN_SERVER=<REGISTRY_LOGIN_SERVER>

# Use Helm to deploy an NGINX ingress controller
helm install ingress-nginx ingress-nginx/ingress-nginx \
    --version 4.7.1 \
    --namespace ingress-basic \
    --create-namespace \
    --set controller.replicaCount=2 \
    --set controller.nodeSelector."kubernetes\.io/os"=linux \
    --set controller.image.registry=$ACR_LOGIN_SERVER \
    --set controller.image.image=$CONTROLLER_IMAGE \
    --set controller.image.tag=$CONTROLLER_TAG \
    --set controller.image.digest="" \
    --set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux \
    --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
    --set controller.service.externalTrafficPolicy=Local \
    --set controller.admissionWebhooks.patch.image.registry=$ACR_LOGIN_SERVER \
    --set controller.admissionWebhooks.patch.image.image=$PATCH_IMAGE \
    --set controller.admissionWebhooks.patch.image.tag=$PATCH_TAG \
    --set controller.admissionWebhooks.patch.image.digest="" \
    --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
    --set defaultBackend.image.registry=$ACR_LOGIN_SERVER \
    --set defaultBackend.image.image=$DEFAULTBACKEND_IMAGE \
    --set defaultBackend.image.tag=$DEFAULTBACKEND_TAG \
    --set defaultBackend.image.digest=""

Создание контроллера входящего трафика с помощью внутреннего IP-адреса

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

--set controller.service.loadBalancerIP Используйте параметры, --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-internal"=true чтобы назначить внутренний IP-адрес контроллеру входящего трафика. Укажите собственный внутренний IP-адрес для использования с контроллером входящего трафика. Убедитесь, что этот IP-адрес не используется в вашей виртуальной сети. Если вы используете существующую виртуальную сеть и подсеть, необходимо настроить кластер AKS с правильными разрешениями для управления виртуальной сетью и подсетью. Дополнительные сведения см. в статьях Использование сети kubenet с пользовательскими диапазонами IP-адресов в службе Azure Kubernetes (AKS) и Настройка сети Azure CNI в службе Azure Kubernetes (AKS).

# Add the ingress-nginx repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# Set variable for ACR location to use for pulling images
ACR_LOGIN_SERVER=<REGISTRY_LOGIN_SERVER>

# Use Helm to deploy an NGINX ingress controller
helm install ingress-nginx ingress-nginx/ingress-nginx \
    --version 4.7.1 \
    --namespace ingress-basic \
    --create-namespace \
    --set controller.replicaCount=2 \
    --set controller.nodeSelector."kubernetes\.io/os"=linux \
    --set controller.image.registry=$ACR_LOGIN_SERVER \
    --set controller.image.image=$CONTROLLER_IMAGE \
    --set controller.image.tag=$CONTROLLER_TAG \
    --set controller.image.digest="" \
    --set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux \
    --set controller.service.loadBalancerIP=10.224.0.42 \
    --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-internal"=true \
    --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
    --set controller.admissionWebhooks.patch.image.registry=$ACR_LOGIN_SERVER \
    --set controller.admissionWebhooks.patch.image.image=$PATCH_IMAGE \
    --set controller.admissionWebhooks.patch.image.tag=$PATCH_TAG \
    --set controller.admissionWebhooks.patch.image.digest="" \
    --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
    --set defaultBackend.image.registry=$ACR_LOGIN_SERVER \
    --set defaultBackend.image.image=$DEFAULTBACKEND_IMAGE \
    --set defaultBackend.image.tag=$DEFAULTBACKEND_TAG \
    --set defaultBackend.image.digest="" 

Проверка службы балансировки нагрузки

Проверьте службу подсистемы балансировки нагрузки с помощью kubectl get services.

kubectl get services --namespace ingress-basic -o wide -w ingress-nginx-controller

При создании службы балансировки нагрузки Kubernetes для контроллера объекта ingress NGINX назначается IP-адрес в разделе EXTERNAL-IP, как показано в следующем примере выходных данных.

NAME                       TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                      AGE   SELECTOR
ingress-nginx-controller   LoadBalancer   10.0.65.205   EXTERNAL-IP     80:30957/TCP,443:32414/TCP   1m   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx

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

Запуск демонстрационных версий приложений

Чтобы увидеть контроллер входящего трафика в действии, запустите два демонстрационных приложения в кластере AKS. В этом примере для развертывания двух экземпляров простого приложения Hello World применяется команда kubectl apply.

  1. Создайте файл aks-helloworld-one.yaml и скопируйте в него следующий пример кода YAML.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-one  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-one
      template:
        metadata:
          labels:
            app: aks-helloworld-one
        spec:
          containers:
          - name: aks-helloworld-one
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "Welcome to Azure Kubernetes Service (AKS)"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-one  
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-one
    
  2. Создайте файл aks-helloworld-two.yaml и скопируйте в него следующий пример кода YAML.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-two  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-two
      template:
        metadata:
          labels:
            app: aks-helloworld-two
        spec:
          containers:
          - name: aks-helloworld-two
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "AKS Ingress Demo"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-two  
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-two
    
  3. Запустите два демонстрационных приложения с помощью команды kubectl apply:

    kubectl apply -f aks-helloworld-one.yaml --namespace ingress-basic
    kubectl apply -f aks-helloworld-two.yaml --namespace ingress-basic
    

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

Оба приложения запущены в кластере Kubernetes. Для маршрутизации трафика для каждого приложения создайте ресурс входящего трафика Kubernetes. Ресурс входящего трафика настраивает правила, по которым осуществляется маршрутизация трафика к одному из двух приложений.

В следующем примере трафик, передаваемый на EXTERNAL_IP/hello-world-one, направляется в службу aks-helloworld-one. Трафик, передаваемый на адрес EXTERNAL_IP/hello-world-two, направляется в службу aks-helloworld-two. Трафик, передаваемый на адрес EXTERNAL_IP/static, направляется в службу с именем aks-helloworld-one для статических ресурсов.

  1. Создайте файл hello-world-ingress.yaml и скопируйте в него следующий пример кода YAML:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hello-world-ingress
      annotations:
        nginx.ingress.kubernetes.io/ssl-redirect: "false"
        nginx.ingress.kubernetes.io/use-regex: "true"
        nginx.ingress.kubernetes.io/rewrite-target: /$2
    spec:
      ingressClassName: nginx
      rules:
      - 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
      rules:
      - 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
    

Тестирование контроллера входящего трафика

Чтобы проверить маршруты для контроллера входящего трафика, перейдите в два приложения. Откройте браузер и введите IP-адрес своего контроллера объекта Ingress NGINX, например EXTERNAL_IP. Первое демонстрационное приложение отобразится в веб-браузере, как показано в следующем примере.

First app running behind the ingress controller

Теперь добавьте к IP-адресу путь /hello-world-two, например EXTERNAL_IP/hello-world-two. Отобразится второе демонстрационное приложение с пользовательским заголовком:

Second app running behind the ingress controller

Тестирование внутреннего IP-адреса

  1. Создайте тестовый модуль pod и подключите к нему сеанс терминала.

    kubectl run -it --rm aks-ingress-test --image=mcr.microsoft.com/dotnet/runtime-deps:6.0 --namespace ingress-basic
    
  2. Установите curl в модуле pod с помощью apt-get.

    apt-get update && apt-get install -y curl
    
  3. Доступ к адресу контроллера входящего трафика Kubernetes, curlнапример http://10.224.0.42. Укажите свой внутренний IP-адрес, указанный при развертывании контроллера объекта ingress.

    curl -L http://10.224.0.42
    

    Так как с этим адресом не был указан путь, для контроллера объекта ingress по умолчанию указан маршрут /. Первое демонстрационное приложение возвращается, как показано в следующем сокращенном примере выходных данных:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <link rel="stylesheet" type="text/css" href="/static/default.css">
        <title>Welcome to Azure Kubernetes Service (AKS)</title>
    [...]
    
  4. Добавьте путь /hello-world-two к адресу, напримерhttp://10.224.0.42/hello-world-two.

    curl -L -k http://10.224.0.42/hello-world-two
    

    Второе демонстрационное приложение с настраиваемым заголовком возвращается, как показано в следующем сокращенном примере выходных данных:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <link rel="stylesheet" type="text/css" href="/static/default.css">
        <title>AKS Ingress Demo</title>
    [...]
    

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

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

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

Чтобы удалить весь пример пространства имен, используйте команду kubectl delete и укажите имя пространства имен. Все ресурсы в пространстве имен будут удалены.

kubectl delete namespace ingress-basic

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

Можно использовать более скрупулезный подход — удалить отдельные созданные ресурсы.

  1. Получите список выпусков Helm с помощью команды helm list.

    helm list --namespace ingress-basic
    

    Найдите диаграммы с именем ingress-nginx и aks-helloworld, как показано в следующем примере выходных данных:

    NAME                    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
    ingress-nginx           ingress-basic   1               2020-01-06 19:55:46.358275 -0600 CST    deployed        nginx-ingress-1.27.1    0.26.1  
    
  2. Удалите выпуски командой helm uninstall.

    helm uninstall ingress-nginx --namespace ingress-basic
    
  3. Удалите два примера приложений.

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

    kubectl delete -f hello-world-ingress.yaml
    
  5. Удалите пространство имен с помощью kubectl delete команды и укажите имя пространства имен.

    kubectl delete namespace ingress-basic
    

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

Сведения о настройке TLS с существующими компонентами входящего трафика см. в статье Использование TLS с контроллером объекта ingress.

Сведения о настройке кластера AKS для использования маршрутизации приложений HTTP см. в статье Включение надстройки маршрутизации приложений HTTP.

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