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

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

    Содержание

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

    • Шлюз Istio установлен с использованием gateway injection.

    Процедура

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

      kubectl create namespace httpbin
    2. Включите внедрение sidecar для пространства имён. Если в вашей конфигурации используется стратегия обновления 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.26.3   47h
      2. Пометьте пространство имён с помощью имени ревизии, чтобы включить внедрение sidecar:

        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. Этот ресурс настраивает прокси шлюза на открытие порта 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. По умолчанию конфигурация Istio Gateway применяется к подходящим pod шлюза во всех пространствах имён.
      2. В поле hosts перечислите адреса, которые клиенты могут использовать для доступа к mesh-сервису на соответствующем порту.
    5. Примените YAML-файл командой:

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

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

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

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

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

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

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

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

      В некоторых средах балансировщик нагрузки может быть доступен по имени хоста, а не по 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}')

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

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