Ingress Gateways
Разом із підтримкою ресурсів Ingress Kubernetes, Istio також дозволяє налаштувати вхідний трафік, використовуючи ресурс Istio Gateway або Kubernetes Gateway. Gateway забезпечує ширші налаштування та гнучкість, ніж Ingress, і дозволяє застосовувати функції Istio, такі як моніторинг та правила маршрутизації, до трафіку, що входить у кластер.
Ця задача описує, як налаштувати Istio для експонування сервісу за межами сервісної мережі, використовуючи Gateway.
Перш ніж почати
Налаштуйте Istio, дотримуючись інструкцій з Посібника з встановлення.
Запустіть httpbin, який буде служити цільовим сервісом для вхідного трафіку:
$ 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.
Створіть Kubernetes Gateway:
$ kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: httpbin-gateway
spec:
gatewayClassName: istio
listeners:
- name: http
hostname: "httpbin.example.com"
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Same
EOFОскільки створення ресурсу Kubernetes Gateway також виконає розгортання асоційованого проксі-сервісу, виконайте наступну команду, щоб дочекатися готовності шлюзу:
$ kubectl wait --for=condition=programmed gtw httpbin-gatewayНалаштуйте маршрути для трафіку, що входить через Gateway:
$ kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
spec:
parentRefs:
- name: httpbin-gateway
hostnames: ["httpbin.example.com"]
rules:
- matches:
- path:
type: PathPrefix
value: /status
- path:
type: PathPrefix
value: /delay
backendRefs:
- name: httpbin
port: 8000
EOFВи створили конфігурацію HTTP Route для сервісу httpbin, що містить два правила маршрутизації, які дозволяють трафік для шляхів /status та /delay.
Визначення IP-адреси та портів для вхідного трафіку
Кожен Gateway підтримується сервісом типу LoadBalancer. Зовнішня IP-адреса та порти навантажувача для цього сервісу використовуються для доступу до шлюзу. Сервіси Kubernetes типу LoadBalancer стандартно підтримуються у кластерах, що працюють на більшості хмарних платформ, але в деяких середовищах (наприклад, тестових) вам може знадобитися виконати наступні дії:
minikube— запустіть зовнішній навантажувач, виконавши наступну команду в іншому терміналі:$ minikube tunnelkind— дотримуйтеся посібника, щоб забезпечити роботу сервісів типу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}')Отримайте адресу та порт шлюзу з ресурсу шлюзу httpbin:
$ export INGRESS_HOST=$(kubectl get gtw httpbin-gateway -o jsonpath='{.status.addresses[0].value}')
$ export INGRESS_PORT=$(kubectl get gtw httpbin-gateway -o jsonpath='{.spec.listeners[?(@.name=="http")].port}')Доступ до сервісів ingress
Доступ до сервісу 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.Доступ до будь-якої іншої 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Якщо ви видалите імена хостів з конфігурацій Gateway і HTTPRoute, вони будуть застосовуватися до будь-якого запиту. Наприклад, змініть конфігурацію вхідних даних на наступну:
$ kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: httpbin-gateway
spec:
gatewayClassName: istio
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
spec:
parentRefs:
- name: httpbin-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /headers
backendRefs:
- name: httpbin
port: 8000
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-адреси для вхідного трафіку залежить від постачальника кластера:
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"IBM Cloud Kubernetes Service:
$ ibmcloud ks workers --cluster cluster-name-or-id $ export INGRESS_HOST=public-IP-of-one-of-the-worker-nodesDocker For Desktop:
$ export INGRESS_HOST=127.0.0.1Інші середовища:
$ export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n "${INGRESS_NS}" -o jsonpath='{.items[0].status.hostIP}')
Розвʼязання проблем
Перевірте значення змінних середовища
INGRESS_HOSTтаINGRESS_PORT. Переконайтеся, що вони мають дійсні значення відповідно до результатів наступних команд:$ kubectl get svc -n istio-system $ echo "INGRESS_HOST=$INGRESS_HOST, INGRESS_PORT=$INGRESS_PORT"Перевірте, що у вас немає інших шлюзів Istio, які визначені на тому ж порту:
$ kubectl get gateway --all-namespacesПеревірте, що у вас немає ресурсів Kubernetes Ingress, які визначені на тій самій IP-адресі та порту:
$ kubectl get ingress --all-namespacesЯкщо у вас є зовнішній навантажувач, і він не працює, спробуйте отримати доступ до шлюзу, використовуючи його NodePort.
Очищення
Видаліть конфігурації Gateway та VirtualService та вимкніть службу httpbin:
$ kubectl delete gateway httpbin-gateway
$ kubectl delete virtualservice httpbin
$ kubectl delete --ignore-not-found=true -f @samples/httpbin/httpbin.yaml@Видаліть конфігурації Gateway і VirtualService та вимкніть службу httpbin:
$ kubectl delete httproute httpbin
$ kubectl delete gtw httpbin-gateway
$ kubectl delete --ignore-not-found=true -f @samples/httpbin/httpbin.yaml@