Kubernetes Gateway API
Окрім власного API для управління трафіком, Istio підтримує Kubernetes Gateway API і має намір зробити його стандартним API для управління трафіком в майбутньому. Цей документ описує відмінності між API Istio та Kubernetes і надає простий приклад, який показує, як налаштувати Istio для експонування сервісу за межі кластера службової мережі, використовуючи Gateway API. Зверніть увагу, що ці API є активно еволюціями API Kubernetes Service та Ingress, що активно розвиваються.
Налаштування
API Gateway не встановлені стандартно ну більшості кластерів Kubernetes. Встановіть CRD для Gateway API, якщо вони відсутні:
$ kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \ { kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.0" | kubectl apply -f -; }
Встановіть Istio, використовуючи профіль
minimal
:$ istioctl install --set profile=minimal -y
Відмінності від API Istio
API Gateway мають багато спільного з API Istio, такими як Gateway та VirtualService. Основний ресурс має ту ж назву, Gateway
, і ресурси служать подібним цілям.
Нові API Gateway прагнуть використати досвід різних реалізацій Kubernetes ingress, включаючи Istio, щоб створити стандартизований нейтральний до постачальника API. Ці API зазвичай виконують ті ж функції, що й Istio Gateway та VirtualService, з кількома ключовими відмінностями:
- В API Istio,
Gateway
конфігурує наявний Deployment/Service шлюзу, який був розгорнутий. В API Gateway ресурсGateway
конфігурує і розгортає шлюз. Див. Методи розгортання для отримання додаткової інформації. - У
VirtualService
Istio всі протоколи конфігуруються в одному ресурсі. В API Gateway кожен тип протоколу має свій ресурс, наприклад,HTTPRoute
таTCPRoute
. - Хоча API Gateway пропонують багато розширених функцій маршрутизації, вони ще не охоплюють 100% функціональності Istio. Триває робота над розширенням API для покриття цих випадків використання, а також над використанням розширюваності API для кращого відображення функціональності Istio.
Налаштування Gateway
Див. документацію Gateway API для отримання інформації про API.
У цьому прикладі ми розгорнемо простий застосунок та експонуємо його назовні за допомогою Gateway
.
Спочатку розгорніть тестовий застосунок
httpbin
:$ kubectl apply -f @samples/httpbin/httpbin.yaml@
Розгорніть конфігурацію Gateway API, включаючи один експонований маршрут (тобто
/get
):$ kubectl create namespace istio-ingress $ kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway namespace: istio-ingress spec: gatewayClassName: istio listeners: - name: default hostname: "*.example.com" port: 80 protocol: HTTP allowedRoutes: namespaces: from: All --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http namespace: default spec: parentRefs: - name: gateway namespace: istio-ingress hostnames: ["httpbin.example.com"] rules: - matches: - path: type: PathPrefix value: /get backendRefs: - name: httpbin port: 8000 EOF
Встановіть змінну оточення Ingress Host:
$ kubectl wait -n istio-ingress --for=condition=programmed gateways.gateway.networking.k8s.io gateway $ export INGRESS_HOST=$(kubectl get gateways.gateway.networking.k8s.io gateway -n istio-ingress -ojsonpath='{.status.addresses[0].value}')
Зверніться до сервісу
httpbin
за допомогою curl:$ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST/get" ... HTTP/1.1 200 OK ... server: istio-envoy ...
Зверніть увагу на використання прапорця
-H
для встановлення HTTP-заголовка Host на “httpbin.example.com”. Це необхідно, оскількиHTTPRoute
налаштовано на обробку “httpbin.example.com”, але у вашому тестовому середовищі ви не маєте привʼязки DNS для цього хосту і просто надсилаєте запит на вхідну IP-адресу.Перейдіть за будь-якою іншою URL-адресою, яка не була відкрита явно. Ви побачите помилку HTTP 404:
$ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST/headers" HTTP/1.1 404 Not Found ...
Оновіть правило маршруту, щоб воно також враховувало
/headers
і додавало заголовок до запиту:$ kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http namespace: default spec: parentRefs: - name: gateway namespace: istio-ingress hostnames: ["httpbin.example.com"] rules: - matches: - path: type: PathPrefix value: /get - path: type: PathPrefix value: /headers filters: - type: RequestHeaderModifier requestHeaderModifier: add: - name: my-added-header value: added-value backendRefs: - name: httpbin port: 8000 EOF
Знову зверніться до
/headers
і помітьте, що до запиту було додано заголовокMy-Added-Header
:$ curl -s -HHost:httpbin.example.com "http://$INGRESS_HOST/headers" | jq '.headers["My-Added-Header"][0]' ... "added-value" ...
Методи розгортання
В наведеному вище прикладі не потрібно було встановлювати Deployment
для ingress gateway перед налаштуванням Gateway
. У стандартній конфігурації Deployment
та Service
для gateway автоматично створюються на основі конфігурації Gateway
.
Для складніших випадків використання також дозволено ручне розгортання.
Автоматизоване розгортання
Стандартно кожен Gateway
автоматично створює Service
та Deployment
з тим самим імʼям. Ці конфігурації автоматично оновлюватимуться, якщо Gateway
зміниться (наприклад, якщо буде додано новий порт).
Ці ресурси можна налаштувати кількома способами:
Анотації та мітки на
Gateway
будуть скопійовані доService
таDeployment
. Це дозволяє налаштовувати такі речі, як Внутрішні балансувальники навантаження, які читають з цих полів.Istio пропонує додаткову анотацію для налаштування створених ресурсів:
Анотація Призначення networking.istio.io/service-type
Контролює поле Service.spec.type
. Наприклад, встановітьClusterIP
, щоб не відкривати сервіс зовні. Стандартне значення —LoadBalancer
.Поле
Service.spec.loadBalancerIP
може бути явно задано шляхом конфігурації поляaddresses
:apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway spec: addresses: - value: 192.0.2.0 type: IPAddress ...
Примітка: можна вказати лише одну адресу.
- (Додатково) Згенеровану конфігурацію Pod можна налаштувати за допомогою власних шаблонів інʼєкцій.
Прикріплення ресурсів і масштабування
Ресурси можуть бути прикріплені до Gateway
для його налаштування. Однак більшість ресурсів Kubernetes наразі не підтримують пряме прикріплення до Gateway
, але їх можна прикріпити до відповідних згенерованих Deployment
і Service
замість цього. Це легко здійснити, оскільки обидва ці ресурси створюються з іменем <gateway name>-<gateway class name>
і з міткою gateway.networking.k8s.io/gateway-name: <gateway name>
.
Наприклад, щоб розгорнути Gateway
з HorizontalPodAutoscaler
і PodDisruptionBudget
:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: gateway
spec:
gatewayClassName: istio
listeners:
- name: default
hostname: "*.example.com"
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: All
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: gateway
spec:
# Match the generated Deployment by reference
# Note: Do not use `kind: Gateway`.
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: gateway-istio
minReplicas: 2
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: gateway
spec:
minAvailable: 1
selector:
# Match the generated Deployment by label
matchLabels:
gateway.networking.k8s.io/gateway-name: gateway
Ручне розгортання
Якщо ви не хочете автоматичного розгортання, Deployment
і Service
можна налаштувати вручну.
При цьому вам буде потрібно вручну зв’язати Gateway
з Service
, а також підтримувати їх конфігурацію портів в актуальному стані.
Щоб зв’язати Gateway
з Service
, налаштуйте поле addresses
, щоб воно вказувало на один Hostname
.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: gateway
spec:
addresses:
- value: ingress.istio-gateways.svc.cluster.local
type: Hostname
...
Трафік mesh-мережі
API Gateway також можна використовувати для налаштування трафіку мережі. Це робиться шляхом налаштування parentRef
, щоб вказувати на сервіс, а не на шлюз.
Наприклад, щоб додати заголовок до всіх запитів до сервісу всередині кластера з назвою example
:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: mesh
spec:
parentRefs:
- group: ""
kind: Service
name: example
rules:
- filters:
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: my-added-header
value: added-value
backendRefs:
- name: example
port: 80
Більш детальну інформацію та приклади можна знайти в інших завданнях з управління трафіком.
Очищення
Видаліть зразок
httpbin
і шлюз:$ kubectl delete -f @samples/httpbin/httpbin.yaml@ $ kubectl delete httproute http $ kubectl delete gateways.gateway.networking.k8s.io gateway -n istio-ingress $ kubectl delete ns istio-ingress
Видаліть Istio:
$ istioctl uninstall -y --purge $ kubectl delete ns istio-system
Видаліть CRD API шлюзу, якщо вони більше не потрібні:
$ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.0" | kubectl delete -f -