• Русский
  • Открытие сервиса через Kubernetes Gateway API

    Вы можете использовать Kubernetes Gateway API для создания ресурсов Gateway и HTTPRoute для развертывания шлюза. Эти ресурсы настраивают шлюз так, чтобы сделать сервис внутри mesh доступным для трафика извне. Затем вы можете изменить Service шлюза на LoadBalancer, чтобы открыть его для трафика вне кластера.

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

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

    Процедура

    1. Создайте новое пространство имён с именем httpbin с помощью следующей команды:

      kubectl create namespace httpbin
    2. Разверните пример сервиса httpbin с помощью этой команды:

      kubectl apply -n httpbin -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/httpbin/httpbin.yaml
    3. Создайте файл с именем httpbin-k8s-gw.yaml, который определяет ресурс Kubernetes Gateway. Это настроит прокси шлюза для открытия порта 80 (HTTP) для хоста httpbin.example.com.

      Автоматическое развертывание

      По умолчанию каждый Gateway автоматически создаёт Service и Deployment. Они будут называться <Gateway name>-<GatewayClass name> (за исключением GatewayClass с именем istio-waypoint, который не добавляет суффикс). Эти конфигурации будут автоматически обновляться при изменении Gateway (например, при добавлении нового порта).

      Пример файла ресурса gateway

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

      kubectl apply -f httpbin-k8s-gw.yaml
    5. Создайте YAML-файл с именем httpbin-hr.yaml, который определяет ресурс HTTPRoute. Этот ресурс задаёт правила маршрутизации трафика от прокси шлюза к сервису httpbin.

      Пример файла HTTPRoute

      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        name: httpbin
        namespace: httpbin
      spec:
        parentRefs:
        - name: httpbin-gateway
          namespace: httpbin
        rules:
        - matches:
          - path:
              type: PathPrefix
              value: /status
          - path:
              type: PathPrefix
              value: /headers
          backendRefs:
          - name: httpbin
            port: 8000
      1. Связывает ресурс HTTPRoute с ранее созданным Kubernetes Gateway, добавляя имя шлюза в список.
      2. Направляет совпадающий трафик к сервису httpbin, определяя запись backendRefs с именем и портом сервиса httpbin.
    6. Примените YAML-файл, выполнив команду:

      kubectl apply -f httpbin-hr.yaml
    7. Убедитесь, что сервис Gateway API готов и имеет назначенный адрес, выполнив команду:

      kubectl wait --for=condition=programmed gtw httpbin-gateway -n httpbin
    8. Необязательно: Разверните шлюз на Infra Nodes:

      Нажмите, чтобы развернуть
      Предварительные требования

      Alauda Container Platform версии 4.2.0 или выше, либо обновите CRD Gateway API до последней версии.

      a. Создайте ConfigMap с именем asm-kube-gateway-options в том же пространстве имён, где планируете развернуть Gateway:

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: asm-kube-gateway-options
        namespace: httpbin
      data:
        deployment: |
          spec:
            template:
              spec:
                nodeSelector:
                  node-role.kubernetes.io/infra: ""
                tolerations:
                  - effect: NoSchedule
                    key: node-role.kubernetes.io/infra
                    value: reserved
                    operator: Equal
      1. Указывает имя ConfigMap.
      2. Указывает пространство имён ConfigMap, совпадающее с пространством имён шлюза.
      3. Задаёт nodeSelector и tolerations для планирования подов шлюза на Infra Nodes.

      b. Ссылайтесь на ConfigMap в вашем ресурсе Gateway, добавив поле infrastructure.parametersRef:

      apiVersion: gateway.networking.k8s.io/v1
      kind: Gateway
      metadata:
        name: httpbin-gateway
        namespace: httpbin
      spec:
        # Добавьте следующую инфраструктурную конфигурацию в ваш CR Gateway
        infrastructure:
          parametersRef:
            group: ""
            kind: ConfigMap
            name: asm-kube-gateway-options
        # ... остальная конфигурация Gateway
      1. Указывает имя шлюза.
      2. Указывает пространство имён шлюза.

    Проверка

    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. Установите переменную CURL_POD с именем пода curl командой:

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

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

      В ответе должен быть статус HTTP 200 OK, что указывает на успешный запрос.

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

      HTTP/1.1 200 OK
      server: istio-envoy
      ...
    5. Отправьте запрос curl к эндпоинту без совпадающего префикса URI в httpbin HTTPROUTE, выполнив команду:

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

      В ответе будет статус 404 Not Found. Это ожидаемо, так как эндпоинт /get не имеет совпадающего префикса URI, определённого в ресурсе httpbin HTTPROUTE.

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

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

      kubectl -n httpbin annotate gtw httpbin-gateway networking.istio.io/service-type-
    7. Проверьте, что сервис httpbin доступен извне кластера, используя внешний хост или IP-адрес сервиса шлюза. Убедитесь, что переменная 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=="http")].port}')
      echo "INGRESS_PORT=$INGRESS_PORT"

      c. Используя хост шлюза, отправьте запрос curl к сервису httpbin следующей командой:

      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
    8. Убедитесь, что в ответе отображается статус HTTP/1.1 200 OK, что подтверждает успешный запрос.