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

    В этом руководстве показано, как использовать ресурсы Istio Gateway и VirtualService для настройки gateway, развернутого с помощью gateway injection. Эти ресурсы настраивают gateway для открытия сервиса внутри mesh для трафика извне. Затем вы открываете gateway для трафика, поступающего извне кластера, изменяя тип Service gateway на LoadBalancer.

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

    • Gateway Istio установлен с использованием gateway injection.
    • Ваш Kubernetes кластер поддерживает внешние балансировщики нагрузки (то есть Services типа LoadBalancer).

    Процедура

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

      kubectl create namespace httpbin
    2. Включите sidecar injection для пространства имён. Если в вашей конфигурации используется стратегия обновления InPlace, выполните команду:

      kubectl label namespace httpbin istio-injection=enabled
      NOTE

      Если вы используете стратегию обновления RevisionBased, выполните следующие команды:

      1. Чтобы узнать ваш <revision-name>, выполните:

        kubectl get istiorevisions.sailoperator.io

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

        NAME      NAMESPACE      PROFILE   READY   STATUS    IN USE   VERSION   AGE
        default   istio-system             True    Healthy   True     v1.28.3   47h
      2. Пометьте пространство имён с помощью имени ревизии для включения sidecar injection:

        kubectl label namespace httpbin istio.io/rev=default
    3. Разверните пример сервиса httpbin, выполнив команду:

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

      apiVersion: networking.istio.io/v1
      kind: Gateway
      metadata:
        name: httpbin-gateway
        namespace: httpbin
      spec:
        selector:
          istio: <gateway_name>
        servers:
          - port:
              number: 80
              name: http
              protocol: HTTP
            hosts:
              - httpbin.example.com
      1. Установите selector так, чтобы он соответствовал уникальной метке или меткам, определённым в шаблоне pod для Deployment прокси gateway. По умолчанию конфигурация Istio Gateway применяется к подходящим pod gateway во всех пространствах имён.
      2. В поле hosts перечислите адреса, которые клиенты могут использовать для доступа к mesh-сервису на соответствующем порту.
    5. Примените YAML-файл командой:

      kubectl apply -f httpbin-gw.yaml
    6. Создайте ещё один YAML-файл с именем httpbin-vs.yaml для ресурса VirtualService. Этот VirtualService определит правила маршрутизации трафика от прокси gateway к сервису httpbin.

      apiVersion: networking.istio.io/v1
      kind: VirtualService
      metadata:
        name: httpbin
        namespace: httpbin
      spec:
        hosts:
          - httpbin.example.com
        gateways:
          - httpbin-gateway
        http:
          - match:
              - uri:
                  prefix: /status
              - uri:
                  prefix: /headers
            route:
              - destination:
                  port:
                    number: 8000
                  host: httpbin
      1. Определите hosts, к которым будут применяться правила маршрутизации VirtualService. Указанные hosts должны быть открыты ресурсом Istio Gateway, к которому прикреплён этот VirtualService.
      2. Прикрепите VirtualService к ресурсу Istio Gateway из предыдущего шага, добавив имя Gateway в список gateways.
      3. Направьте совпадающий трафик к ранее развернутому сервису httpbin, определив destination с указанием host и port сервиса httpbin.
    7. Примените YAML-файл командой:

      kubectl apply -f httpbin-vs.yaml

    Проверка

    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. Сохраните имя pod клиента curl в переменную CURL_POD, выполнив команду:

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

      kubectl exec $CURL_POD -n curl -- \
        curl -sS -I \
          -H Host:httpbin.example.com \
          <gateway_name>.<gateway_namespace>.svc.cluster.local/headers
    5. В ответе должен быть статус HTTP 200 OK, подтверждающий успешность запроса.

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

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

      kubectl exec $CURL_POD -n curl -- \
        curl -sS -I \
          -H Host:httpbin.example.com \
          <gateway_name>.<gateway_namespace>.svc.cluster.local/get

      В ответе должен быть статус 404 Not Found. Это ожидаемый результат, так как для эндпоинта /get не определено совпадение по префиксу URI в VirtualService httpbin.

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

      HTTP/1.1 404 Not Found
      server: istio-envoy
      ...
    7. Откройте прокси gateway для трафика извне кластера, изменив тип его Service на LoadBalancer:

      kubectl patch service <gateway_name> -n <gateway_namespace> -p '{"spec": {"type": "LoadBalancer"}}'
    8. Убедитесь, что сервис httpbin доступен извне кластера через внешний hostname или IP-адрес сервиса gateway. Убедитесь, что переменная INGRESS_HOST корректно установлена для вашей среды кластера.

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

      INGRESS_HOST=$(kubectl get service <gateway_name> -n <gateway_namespace> -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
      echo "INGRESS_HOST=$INGRESS_HOST"

      В некоторых средах балансировщик нагрузки может быть доступен по имени хоста, а не по IP-адресу. В этом случае значение EXTERNAL-IP ingress gateway не будет IP-адресом, а именем хоста, и приведённая выше команда не сможет установить переменную окружения INGRESS_HOST. Используйте следующую команду для корректировки значения INGRESS_HOST:

      INGRESS_HOST=$(kubectl get service <gateway_name> -n <gateway_namespace> -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
      echo "INGRESS_HOST=$INGRESS_HOST"

      b. Отправьте запрос curl к сервису httpbin, используя хост gateway, выполнив команду:

      INFO

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

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