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 -