• Русский
  • Предоставление сервиса через Kubernetes Gateway API в ambient-режиме

    В ambient-режиме Istio Kubernetes Gateway API является рекомендуемым способом настройки маршрутизации входящего трафика. Вы можете создать ресурсы Gateway и HTTPRoute, чтобы развернуть шлюз, делающий сервисы внутри mesh доступными для внешнего трафика.

    Прокси Waypoint для маршрутизации уровня 7

    Чтобы применять политики маршрутизации уровня 7 (L7), включая маршрутизацию по пути и сопоставление заголовков, разверните waypoint-прокси в пространстве имен, содержащем целевой сервис. Waypoint-прокси обрабатывает L7-трафик и применяет правила маршрутизации, определенные с помощью ресурсов HTTPRoute и GRPCRoute.

    WARNING

    В ambient-режиме ресурсы VirtualService имеют ограниченную совместимость и не должны использоваться совместно с конфигурацией Gateway API. Используйте ресурсы Kubernetes Gateway API как стандартный подход к маршрутизации трафика в ambient-режиме.

    Предварительные требования

    • Установлен Alauda Service Mesh v2 Operator.
    • Ресурсы Istio и IstioCNI настроены с ambient-профилем.
    • Создан ресурс Ztunnel.
    • Подтверждена совместимость с ядром Linux.
    • Ваш Kubernetes-кластер поддерживает внешние балансировщики нагрузки (то есть Services типа LoadBalancer).

    Процедура

    1. Создайте пространство имен httpbin:

      kubectl create namespace httpbin
    2. Добавьте метку istio-discovery=enabled в пространство имен httpbin:

      kubectl label namespace httpbin istio-discovery=enabled
    3. Включите ambient-режим для пространства имен, применив метку режима dataplane:

      kubectl label namespace httpbin istio.io/dataplane-mode=ambient
    4. Разверните тестовый сервис httpbin:

      kubectl apply -n httpbin -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/httpbin/httpbin.yaml
    5. Создайте файл httpbin-waypoint.yaml для определения waypoint-прокси. Этот ресурс Gateway использует класс шлюза istio-waypoint для обработки L7-трафика сервисов в пространстве имен.

      apiVersion: gateway.networking.k8s.io/v1
      kind: Gateway
      metadata:
        name: httpbin-waypoint
        namespace: httpbin
        labels:
          istio.io/waypoint-for: service
      spec:
        gatewayClassName: istio-waypoint
        listeners:
          - name: mesh
            port: 15008
            protocol: HBONE
      1. Метка istio.io/waypoint-for: service указывает, что этот waypoint обрабатывает трафик сервисов. Значение метки определяет тип обрабатываемого трафика. Подробности см. в разделе Waypoint traffic types (документация Istio).
      2. Указывает класс шлюза istio-waypoint, который разворачивает waypoint-прокси вместо стандартного ingress gateway.
    6. Примените конфигурацию waypoint-прокси:

      kubectl apply -f httpbin-waypoint.yaml
    7. Добавьте метку к сервису httpbin, чтобы направлять входящий трафик через waypoint-прокси:

      kubectl label service httpbin -n httpbin istio.io/ingress-use-waypoint=true
      NOTE

      Метка istio.io/ingress-use-waypoint=true гарантирует, что трафик, поступающий из ingress gateway, проходит через waypoint-прокси, что позволяет применять L7-политики, настроенные на waypoint, до того, как трафик достигнет сервиса httpbin.

    8. Свяжите все сервисы в пространстве имен с waypoint-прокси, добавив метку к пространству имен:

      kubectl label ns httpbin istio.io/use-waypoint=httpbin-waypoint
    9. Создайте файл httpbin-gw.yaml, который определяет ресурс Kubernetes Gateway. Это настраивает прокси шлюза на прием HTTP-трафика на порту 80 для хоста httpbin.example.com.

      apiVersion: gateway.networking.k8s.io/v1
      kind: Gateway
      metadata:
        annotations:
          networking.istio.io/service-type: ClusterIP
        name: httpbin-gateway
        namespace: httpbin
      spec:
        gatewayClassName: istio
        listeners:
          - name: default
            hostname: "httpbin.example.com"
            port: 80
            protocol: HTTP
            allowedRoutes:
              namespaces:
                from: All
      1. Указывает тип Service для шлюза; по умолчанию используется LoadBalancer.
      2. Указывает виртуальное имя хоста, которое клиенты используют при доступе к сервису mesh на этом порту.
    10. Примените конфигурацию шлюза:

      kubectl apply -f httpbin-gw.yaml
    11. Создайте файл httpbin-ingress-hr.yaml, который определяет ресурс HTTPRoute для ingress gateway. Этот ресурс задает, как трафик маршрутизируется от proxy шлюза к сервису httpbin.

      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        name: httpbin-ingress
        namespace: httpbin
      spec:
        parentRefs:
          - name: httpbin-gateway
            namespace: httpbin
        hostnames:
          - "httpbin.example.com"
        rules:
          - backendRefs:
              - name: httpbin
                port: 8000
      1. Привязывает этот HTTPRoute к ресурсу Kubernetes Gateway, созданному на предыдущем шаге.
      2. Направляет совпадающий трафик к сервису httpbin на порт 8000.
    12. Примените ingress HTTPRoute:

      kubectl apply -f httpbin-ingress-hr.yaml
    13. Создайте файл httpbin-waypoint-hr.yaml, который определяет ресурс HTTPRoute для waypoint-прокси. Этот ресурс настраивает правила маршрутизации по пути, которые применяет waypoint.

      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        name: httpbin-waypoint-route
        namespace: httpbin
      spec:
        parentRefs:
          - group: ""
            kind: Service
            name: httpbin
            namespace: httpbin
        rules:
          - matches:
              - path:
                  type: PathPrefix
                  value: /status
              - path:
                  type: PathPrefix
                  value: /headers
            backendRefs:
              - name: httpbin
                port: 8000
      1. Привязывает этот HTTPRoute к сервису httpbin. В сочетании с меткой istio.io/ingress-use-waypoint=true это настраивает правила L7-маршрутизации, применяемые waypoint-прокси для трафика, направленного к сервису.
      2. Перенаправляет совпадающий трафик к сервису httpbin на порт 8000.
    14. Примените waypoint HTTPRoute:

      kubectl apply -f httpbin-waypoint-hr.yaml
      NOTE

      В этой конфигурации трафик из ingress gateway проходит через waypoint-прокси благодаря метке istio.io/ingress-use-waypoint=true на сервисе. Затем waypoint HTTPRoute применяет политики маршрутизации по пути до того, как трафик достигнет сервиса httpbin.

    15. Дождитесь, пока waypoint-прокси станет готов:

      kubectl wait --for=condition=programmed gtw httpbin-waypoint -n httpbin

    Проверка

    1. Создайте пространство имен для клиента curl:

      kubectl create namespace curl
    2. Разверните клиент curl:

      kubectl apply -n curl -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/curl/curl.yaml
    3. Добавьте метку istio-discovery=enabled к пространству имен curl:

      kubectl label namespace curl istio-discovery=enabled
    4. Включите ambient-режим для пространства имен curl:

      kubectl label namespace curl istio.io/dataplane-mode=ambient
    5. Сохраните имя pod curl в переменной:

      export CURL_POD=$(kubectl get pods -n curl -l app=curl -o jsonpath='{.items[*].metadata.name}')
      echo "CURL_POD=$CURL_POD"
    6. Из клиента curl отправьте запрос к endpoint /headers приложения httpbin через Service ingress gateway. Установите заголовок Host в httpbin.example.com, чтобы он соответствовал хосту, указанному в ресурсах Kubernetes Gateway и HTTPRoute:

      kubectl exec $CURL_POD -n curl -- \
        curl -sS -I \
          -H Host:httpbin.example.com \
          httpbin-gateway-istio.httpbin.svc.cluster.local/headers

      Ответ должен вернуть статус HTTP/1.1 200 OK, что означает успешную обработку запроса.

      Пример вывода

      HTTP/1.1 200 OK
      ...
      server: istio-envoy
      ...
    7. Отправьте запрос к endpoint, для которого в waypoint HTTPRoute нет совпадающего URI-префикса:

      kubectl exec $CURL_POD -n curl -- \
        curl -sS -I \
          -H Host:httpbin.example.com \
          httpbin-gateway-istio.httpbin.svc.cluster.local/get

      Ответ возвращает HTTP/1.1 404 Not Found, что ожидаемо, поскольку для пути /get не определено соответствующее совпадение по префиксу в waypoint HTTPRoute.

      Пример вывода

      HTTP/1.1 404 Not Found
      ...
      server: istio-envoy
      ...
    8. Сделайте proxy шлюза доступным для трафика вне кластера, изменив тип Service на значение LoadBalancer по умолчанию:

      kubectl -n httpbin annotate gtw httpbin-gateway networking.istio.io/service-type-
    9. Проверьте, что сервис httpbin доступен извне кластера с использованием внешнего hostname или IP-адреса Service шлюза. Установите переменную INGRESS_HOST в соответствии с окружением вашего кластера.

      a. Установите переменную INGRESS_HOST:

      export INGRESS_HOST=$(kubectl get gtw httpbin-gateway -n httpbin -o jsonpath='{.status.addresses[0].value}')
      echo "INGRESS_HOST=$INGRESS_HOST"

      b. Установите переменную INGRESS_PORT:

      export INGRESS_PORT=$(kubectl get gtw httpbin-gateway -n httpbin -o jsonpath='{.spec.listeners[?(@.name=="default")].port}')
      echo "INGRESS_PORT=$INGRESS_PORT"

      c. Отправьте запрос curl к сервису httpbin, используя host шлюза:

      INFO

      Если $INGRESS_HOST является IPv6-адресом, заключите его в квадратные скобки при формировании URL. Например:

      curl -sS -g -I -H Host:httpbin.example.com http://[$INGRESS_HOST]:$INGRESS_PORT/headers
      curl -sS -g -I -H Host:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/headers
    10. Убедитесь, что ответ содержит статус HTTP/1.1 200 OK, что указывает на успешное выполнение запроса.

      Пример вывода

      HTTP/1.1 200 OK
      ...
      server: istio-envoy
      ...

    Очистка

    Удалите ресурсы, созданные в ходе этой процедуры:

    # Remove the namespaces from the ambient data plane
    kubectl label namespace curl istio.io/dataplane-mode-
    kubectl label namespace httpbin istio.io/dataplane-mode-
    # Remove the namespaces
    kubectl delete namespace curl
    kubectl delete namespace httpbin