• Русский
  • Предоставление доступа к сервису через ресурсы Istio Gateway и VirtualService

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

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

    • Gateway Istio установлен с использованием gateway injection.
    • Ваш Kubernetes cluster поддерживает внешние load balancer'ы (то есть Service типа LoadBalancer).

    Процедура

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

      kubectl create namespace httpbin
    2. Включите sidecar injection для namespace. Если в вашей конфигурации используется стратегия обновления 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.6   47h
      2. Пометьте namespace с использованием имени revision, чтобы включить 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 proxies на открытие порта 80 (HTTP) для host 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 так, чтобы он соответствовал уникальному label или labels, определенным в pod template Deployment gateway proxy. По умолчанию конфигурация Istio Gateway применяется к соответствующим gateway pods во всех namespace.
      2. В поле hosts перечислите адреса, которые клиенты могут использовать для доступа к сервису mesh на соответствующем порту.
    5. Примените YAML-файл с помощью этой команды:

      kubectl apply -f httpbin-gw.yaml
    6. Создайте еще один YAML-файл с именем httpbin-vs.yaml для VirtualService. Этот VirtualService определит правила маршрутизации трафика от gateway proxy к сервису 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 Service httpbin.
    7. Примените YAML-файл с помощью этой команды:

      kubectl apply -f httpbin-vs.yaml

    Проверка

    1. Создайте namespace для клиента 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 отправьте запрос к endpoint /headers приложения httpbin через ingress gateway Service. Установите заголовок Host в значение httpbin.example.com, чтобы оно соответствовало host, указанному в Istio Gateway и VirtualService. Выполните следующую команду curl:

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

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

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

      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. Это ожидаемый результат, поскольку для endpoint /get в VirtualService httpbin не определено совпадение URI prefix.

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

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

      kubectl patch service <gateway_name> -n <gateway_namespace> -p '{"spec": {"type": "LoadBalancer"}}'
    8. Убедитесь, что сервис httpbin доступен извне кластера с использованием внешнего hostname или IP address Service 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"

      В некоторых средах load balancer может быть доступен с использованием host name вместо IP address. В этом случае значение EXTERNAL-IP ingress gateway не будет IP address, а будет host name, и приведенная выше команда не сможет задать переменную окружения 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, используя host gateway, выполнив эту команду:

      INFO

      Если $INGRESS_HOST — это IPv6 address, заключите его в квадратные скобки при формировании 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, что подтверждает успешное выполнение запроса.