Kubernetes Gateway API
除了自身的流量管理 API 之外,Istio 也支援 Kubernetes 的 Gateway API,並計劃將其作為未來流量管理的預設 API。本文將說明 Istio 和 Kubernetes API 之間的差異,並提供一個簡單的範例,展示如何設定 Istio,使用 Gateway API 將服務暴露在服務網格叢集之外。請注意,這些 API 是 Kubernetes Service 和 Ingress API 的積極開發演進。
設定
大多數 Kubernetes 叢集預設並未安裝 Gateway API。如果它們不存在,請安裝 Gateway API CRD。
$ 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 -; }
使用
minimal
設定檔安裝 Istio。$ istioctl install --set profile=minimal -y
與 Istio API 的差異
Gateway API 與 Istio API 有許多相似之處,例如 Gateway 和 VirtualService。主要資源共享相同的名稱 Gateway
,並且這些資源具有相似的目標。
新的 Gateway API 旨在吸收各種 Kubernetes Ingress 實作(包括 Istio)的經驗,以建立標準化的、供應商中立的 API。這些 API 的目的通常與 Istio Gateway 和 VirtualService 相同,但有一些關鍵差異。
- 在 Istio API 中,
Gateway
設定一個已部署的現有閘道 Deployment/Service。在 Gateway API 中,Gateway
資源既設定也部署閘道。有關更多資訊,請參閱部署方法。 - 在 Istio
VirtualService
中,所有協定都在單一資源內設定。在 Gateway API 中,每種協定類型都有自己的資源,例如HTTPRoute
和TCPRoute
。 - 雖然 Gateway API 提供了豐富的路由功能,但它尚未涵蓋 Istio 100% 的功能集。目前正在努力擴展 API 以涵蓋這些使用案例,並利用 API 的可擴展性,以便更好地公開 Istio 的功能。
設定閘道
有關 API 的資訊,請參閱Gateway 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}')
使用 curl 存取
httpbin
服務。$ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST/get" ... HTTP/1.1 200 OK ... server: istio-envoy ...
請注意,使用
-H
標誌是為了將 Host HTTP 標頭設定為 “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" ...
部署方法
在上面的範例中,您無需在設定 Gateway 之前安裝入口閘道 Deployment
。在預設設定中,會根據 Gateway
設定自動佈建閘道 Deployment
和 Service
。對於進階使用案例,仍然允許手動部署。
自動化部署
預設情況下,每個 Gateway
都會自動佈建一個同名的 Service
和 Deployment
。如果 Gateway
發生變更(例如,新增了新連接埠),這些設定將會自動更新。
可以使用幾種方式自訂這些資源。
Gateway
上的註解和標籤將會複製到Service
和Deployment
。這允許設定諸如從這些欄位讀取的內部負載平衡器之類的功能。Istio 提供額外的註解來設定產生的資源。
註解 目的 networking.istio.io/service-type
控制 Service.spec.type
欄位。例如,設定為ClusterIP
以不對外公開服務。預設值為LoadBalancer
。可以透過設定
addresses
欄位來明確設定Service.spec.loadBalancerIP
欄位。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>
產生。
例如,要部署具有 HorizontalPodAutoscaler
和 PodDisruptionBudget
的 Gateway
。
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
,並保持它們的連接埠設定同步。
為了支援原則附加,例如當您在 AuthorizationPolicy 上使用 targetRef
欄位時,您還需要透過將以下標籤新增至您的閘道 Pod 來參照您的 Gateway
名稱:gateway.networking.k8s.io/gateway-name: <gateway name>
。
若要將 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
...
網格流量
Gateway API 也可用於設定網格流量。這是透過將 parentRef
設定為指向服務而不是閘道來完成的。
例如,要將標頭新增至對叢集中名為 example
的 Service
的所有呼叫。
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
如果不再需要,請移除 Gateway API CRD。
$ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.0" | kubectl delete -f -