Kubernetes 网关 API

除了自己的流量管理API之外,Istio还支持Kubernetes Gateway API,并计划将其作为未来流量管理的默认API。本文档描述了Istio和Kubernetes API之间的差异,并提供了一个简单的示例,演示如何使用Gateway API配置Istio以在服务网格集群外部公开服务。请注意,这些API是Kubernetes 服务入口API的积极开发演变。

设置

  1. 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 -; }
    
  2. 使用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中,每种协议类型都有其自己的资源,例如HTTPRouteTCPRoute
  • 虽然Gateway API提供了丰富的路由功能,但它尚未涵盖Istio功能集的100%。目前正在努力扩展API以涵盖这些用例,以及利用API的可扩展性更好地公开Istio功能。

配置网关

有关API的信息,请参阅Gateway API文档。

在此示例中,我们将部署一个简单的应用程序并使用Gateway将其公开到外部。

  1. 首先,部署httpbin测试应用程序。

    压缩
    $ kubectl apply -f @samples/httpbin/httpbin.yaml@
    
  2. 部署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
    
  3. 设置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}')
    
  4. 使用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。

  5. 访问任何未明确公开的其他URL。您应该会看到HTTP 404错误。

    $ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST/headers"
    HTTP/1.1 404 Not Found
    ...
    
  6. 更新路由规则,以公开/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
    
  7. 再次访问/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配置自动配置网关DeploymentService。对于高级用例,仍然允许手动部署。

自动部署

默认情况下,每个Gateway都会自动配置一个同名的ServiceDeployment。如果Gateway发生更改(例如,添加了新端口),这些配置将自动更新。

可以通过几种方式自定义这些资源。

  • Gateway上的注释和标签将复制到ServiceDeployment。这允许配置诸如内部负载均衡器之类的东西,这些负载均衡器从这些字段读取。

  • 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
    ...
    

注意:只能指定一个地址。

资源附加和扩展

可以将资源附加Gateway以自定义它。但是,大多数Kubernetes资源目前不支持直接附加到Gateway,但可以将其附加到相应的生成的DeploymentService。这很容易做到,因为这两个资源都是使用名称<gateway name>-<gateway class name>生成的,并且具有标签gateway.networking.k8s.io/gateway-name: <gateway name>

例如,要部署具有HorizontalPodAutoscalerPodDisruptionBudgetGateway

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

手动部署

如果您不想进行自动部署,则可以手动配置DeploymentService

执行此操作时,您需要手动将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

更多详细信息和示例可以在其他流量管理任务中找到。

清理

  1. 删除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
    
  2. 卸载Istio。

    $ istioctl uninstall -y --purge
    $ kubectl delete ns istio-system
    
  3. 如果不再需要Gateway API CRD,请将其删除。

    $ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.0" | kubectl delete -f -
    
这些信息是否有用?
您对改进有什么建议?

感谢您的反馈!