Ingress Gateways

Разом із підтримкою ресурсів Ingress Kubernetes, Istio також дозволяє налаштувати вхідний трафік, використовуючи ресурс Istio Gateway або Kubernetes Gateway. Gateway забезпечує ширші налаштування та гнучкість, ніж Ingress, і дозволяє застосовувати функції Istio, такі як моніторинг та правила маршрутизації, до трафіку, що входить у кластер.

Ця задача описує, як налаштувати Istio для експонування сервісу за межами сервісної мережі, використовуючи Gateway.

Перш ніж почати

  • Налаштуйте Istio, дотримуючись інструкцій з Посібника з встановлення.

  • Запустіть httpbin, який буде служити цільовим сервісом для вхідного трафіку:

    Zip
    $ kubectl apply -f @samples/httpbin/httpbin.yaml@

    Зверніть увагу, що для цілей цього документа, який показує, як використовувати шлюз для контролю вхідного трафіку у вашому “Kubernetes кластері”, ви можете запустити сервіс httpbin з увімкненою чи вимкненою ін’єкцією sidecar (тобто, цільовий сервіс може бути як всередині, так і поза мережею Istio).

Налаштування вхідного трафіку за допомогою шлюзу

Вхідний Gateway описує балансувальник навантаження, який працює на периметрі мережі та приймає вхідні HTTP/TCP зʼєднання. Він налаштовує відкриті порти, протоколи тощо, але, на відміну від ресурсів Ingress Kubernetes, не включає жодної конфігурації маршрутизації трафіку. Маршрутизація трафіку для вхідного трафіку налаштовується за допомогою правил маршрутизації, точно так само, як і для внутрішніх запитів до сервісів.

Подивімось, як можна налаштувати Gateway на порту 80 для HTTP трафіку.

Створимо Istio Gateway:

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  # Селектор збігається з мітками podʼів ingress gateway.
  # Якщо ви встановили Istio за допомогою Helm, слідуючи стандартній документації, це буде "istio=ingress"
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "httpbin.example.com"
EOF

Налаштуйте маршрути для трафіку, що надходить через Gateway:

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - "httpbin.example.com"
  gateways:
  - httpbin-gateway
  http:
  - match:
    - uri:
        prefix: /status
    - uri:
        prefix: /delay
    route:
    - destination:
        port:
          number: 8000
        host: httpbin
EOF

Тепер ви створили конфігурацію віртуального сервісу для сервісу httpbin, що містить два правила маршрутизації, які дозволяють трафік для шляхів /status та /delay.

Список шлюзів вказує, що дозволені лише запити через ваш httpbin-gateway. Усі інші зовнішні запити будуть відхилені з відповіддю 404.

Визначення IP-адреси та портів для вхідного трафіку

Кожен Gateway підтримується сервісом типу LoadBalancer. Зовнішня IP-адреса та порти навантажувача для цього сервісу використовуються для доступу до шлюзу. Сервіси Kubernetes типу LoadBalancer стандартно підтримуються у кластерах, що працюють на більшості хмарних платформ, але в деяких середовищах (наприклад, тестових) вам може знадобитися виконати наступні дії:

  • minikube — запустіть зовнішній навантажувач, виконавши наступну команду в іншому терміналі:

    $ minikube tunnel
  • kind — дотримуйтеся посібника, щоб забезпечити роботу сервісів типу LoadBalancer.

  • інші платформи — ви можете використовувати MetalLB для отримання EXTERNAL-IP для сервісів типу LoadBalancer.

Для зручності ми збережемо IP-адресу та порти для вхідного трафіку у змінних середовища, які будуть використовуватися в подальших інструкціях. Налаштуйте змінні середовища INGRESS_HOST та INGRESS_PORT відповідно до наступних інструкцій:

Встановіть наступні змінні оточення на назву та простір імен, де знаходиться вхідний шлюз Istio у вашому кластері:

$ export INGRESS_NAME=istio-ingressgateway
$ export INGRESS_NS=istio-system

Запустіть наступну команду, щоб визначити, чи знаходиться ваш кластер Kubernetes в середовищі, яке підтримує зовнішні балансувальники навантаження:

$ kubectl get svc "$INGRESS_NAME" -n "$INGRESS_NS"
NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)   AGE
istio-ingressgateway   LoadBalancer   172.21.109.129   130.211.10.121   ...       17h

Якщо встановлено значення EXTERNAL-IP, ваше середовище має зовнішнього балансувальника навантаження, який ви можете використовувати для вхідного шлюзу. Якщо значення EXTERNAL-IP дорівнює <none> (або постійно <pending>), у вашому середовищі не передбачено зовнішнього балансувальника навантаження для вхідного шлюзу.

Якщо ваше середовище не підтримує зовнішні балансувальники навантаження, ви можете спробувати доступ до вхідного шлюзу за допомогою портів вузла. В іншому випадку, встановіть IP-адресу і порти вхідного шлюзу за допомогою наступних команд:

$ export INGRESS_HOST=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ export INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
$ export SECURE_INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="https")].port}')
$ export TCP_INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="tcp")].port}')

Доступ до сервісів ingress

  1. Доступ до сервісу httpbin за допомогою curl:

    $ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST:$INGRESS_PORT/status/200"
    ...
    HTTP/1.1 200 OK
    ...
    server: istio-envoy
    ...

    Зверніть увагу, що ви використовуєте прапорець -H, щоб встановити HTTP-заголовок Host на “httpbin.example.com”. Це необхідно, оскільки ваш вхідний Gateway налаштовано на обробку “httpbin.example.com”, але у вашому тестовому середовищі ви не маєте привʼязки DNS для цього хосту і просто надсилаєте запит на вхідний IP.

  2. Доступ до будь-якої іншої URL-адреси, яка не була відкрита явно. Ви побачите помилку HTTP 404:

    $ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST:$INGRESS_PORT/headers"
    HTTP/1.1 404 Not Found
    ...

Доступ до сервісів ingress за допомогою оглядача

Введення URL сервісу httpbin у оглядачі не працюватиме, оскільки ви не можете передати заголовок Host оглядачу так, як це зробили з curl. У реальній ситуації це не є проблемою, тому що ви налаштовуєте запитуваний хост правильно, і він доступний через DNS. Таким чином, ви використовуєте доменне ім’я хосту в URL, наприклад, https://httpbin.example.com/status/200.

Ви можете обійти цю проблему для простих тестів і демонстрацій наступним чином:

Використовуйте значення універсального символу * для хосту в конфігураціях Gateway та VirtualService. Наприклад, змініть вашу конфігурацію для вхідного трафіку на наступну:

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  # Селектор збігається з мітками podʼів ingress gateway.
  # Якщо ви встановили Istio за допомогою Helm, слідуючи стандартній документації, це буде "istio=ingress"
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - "*"
  gateways:
  - httpbin-gateway
  http:
  - match:
    - uri:
        prefix: /headers
    route:
    - destination:
        port:
          number: 8000
        host: httpbin
EOF

Потім ви можете використовувати $INGRESS_HOST:$INGRESS_PORT в URL-адресі оглядача. Наприклад, http://$INGRESS_HOST:$INGRESS_PORT/headers покаже всі заголовки, які надсилає ваш оглядач.

Розуміння того, що сталося

Ресурси конфігурації Gateway дозволяють зовнішньому трафіку потрапляти до сервісної мережі Istio і надають можливість використовувати функції керування трафіком та політики Istio для граничних сервісів.

У попередніх кроках ви створили сервіс всередині сервісної мережі та експонували HTTP-точку доступу цього сервісу для зовнішнього трафіку.

Використання NodePort сервісу ingress gateway

Якщо ваше середовище не підтримує зовнішні навантажувачі, ви все ще можете експериментувати з деякими функціями Istio, використовуючи NodePort сервісу istio-ingressgateway.

Налаштуйте порти для вхідного трафіку:

$ export INGRESS_PORT=$(kubectl -n "${INGRESS_NS}" get service "${INGRESS_NAME}" -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
$ export SECURE_INGRESS_PORT=$(kubectl -n "${INGRESS_NS}" get service "${INGRESS_NAME}" -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
$ export TCP_INGRESS_PORT=$(kubectl -n "${INGRESS_NS}" get service "${INGRESS_NAME}" -o jsonpath='{.spec.ports[?(@.name=="tcp")].nodePort}')

Налаштування IP-адреси для вхідного трафіку залежить від постачальника кластера:

  1. GKE:

    $ export INGRESS_HOST=worker-node-address

    Вам потрібно створити правила брандмауера для дозволу TCP-трафіку на порти сервісу ingressgateway. Виконайте наступні команди, щоб дозволити трафік для порту HTTP, захищеного порту (HTTPS) або обох:

    $ gcloud compute firewall-rules create allow-gateway-http --allow "tcp:$INGRESS_PORT"
    $ gcloud compute firewall-rules create allow-gateway-https --allow "tcp:$SECURE_INGRESS_PORT"
  2. IBM Cloud Kubernetes Service:

    $ ibmcloud ks workers --cluster cluster-name-or-id
    $ export INGRESS_HOST=public-IP-of-one-of-the-worker-nodes
  3. Docker For Desktop:

    $ export INGRESS_HOST=127.0.0.1
  4. Інші середовища:

    $ export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n "${INGRESS_NS}" -o jsonpath='{.items[0].status.hostIP}')

Розвʼязання проблем

  1. Перевірте значення змінних середовища INGRESS_HOST та INGRESS_PORT. Переконайтеся, що вони мають дійсні значення відповідно до результатів наступних команд:

    $ kubectl get svc -n istio-system
    $ echo "INGRESS_HOST=$INGRESS_HOST, INGRESS_PORT=$INGRESS_PORT"
  2. Перевірте, що у вас немає інших шлюзів Istio, які визначені на тому ж порту:

    $ kubectl get gateway --all-namespaces
  3. Перевірте, що у вас немає ресурсів Kubernetes Ingress, які визначені на тій самій IP-адресі та порту:

    $ kubectl get ingress --all-namespaces
  4. Якщо у вас є зовнішній навантажувач, і він не працює, спробуйте отримати доступ до шлюзу, використовуючи його NodePort.

Очищення

Видаліть конфігурації Gateway та VirtualService та вимкніть службу httpbin:

Zip
$ kubectl delete gateway httpbin-gateway
$ kubectl delete virtualservice httpbin
$ kubectl delete --ignore-not-found=true -f @samples/httpbin/httpbin.yaml@
Чи була ця інформація корисною?
Чи є у вас пропозиції щодо покращення?

Дякуємо за ваш відгук!