Kubernetes 网关 API
除了自己的流量管理API之外,Istio还支持Kubernetes Gateway API,并计划将其作为未来流量管理的默认API。本文档描述了Istio和Kubernetes API之间的差异,并提供了一个简单的示例,演示如何使用Gateway API配置Istio以在服务网格集群外部公开服务。请注意,这些API是Kubernetes 服务和 入口API的积极开发演变。
设置
Gateway API在大多数Kubernetes集群上默认未安装。如果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旨在吸取包括Istio在内的各种Kubernetes入口实现的经验教训,以构建标准化的供应商中立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 -