Kubernetes Gateway API

本任务描述如何配置 Istio,以使用 Kubernetes Gateway API 在 Service Mesh 集群外部暴露服务。 这些 API 是 Kubernetes ServiceIngress API 的积极发展演进。

该特性目前被认为是 alpha 版本。 API (由 Kubernetes SIG-NETWORK 拥有)和 Istio 的实现方式都有可能在进一步升级之前发生改变。

设置

  1. 在大多数 Kubernetes 集群中,默认情况下不会安装 Gateway API。如果 Gateway API CRD 不存在,请安装:

    1. $ kubectl get crd gateways.gateway.networking.k8s.io || { kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.4.0" | kubectl apply -f -; }

与 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 中,每种协议类型都有自己的资源,例如 HTTPRouteTCPRoute
  • 虽然 Gateway API 提供了大量丰富的路由功能,但它还没有涵盖 Istio 的全部特性。 因此,正在进行的工作是扩展 API 以覆盖这些用例,以及利用 API 的可拓展性 来更好地暴露 Istio 的功能。

配置网关

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

在本例中,我们将部署一个简单的应用程序,并使用 Gateway 将其暴露到外部。

  1. 首先部署一个测试应用:

    Zip

    1. $ kubectl apply -f @samples/httpbin/httpbin.yaml@
  2. 部署 Gateway API 配置:

    1. $ kubectl create namespace istio-ingress
    2. $ kubectl apply -f - <<EOF
    3. apiVersion: gateway.networking.k8s.io/v1alpha2
    4. kind: Gateway
    5. metadata:
    6. name: gateway
    7. namespace: istio-ingress
    8. spec:
    9. gatewayClassName: istio
    10. listeners:
    11. - name: default
    12. hostname: "*.example.com"
    13. port: 80
    14. protocol: HTTP
    15. allowedRoutes:
    16. namespaces:
    17. from: All
    18. ---
    19. apiVersion: gateway.networking.k8s.io/v1alpha2
    20. kind: HTTPRoute
    21. metadata:
    22. name: http
    23. namespace: default
    24. spec:
    25. parentRefs:
    26. - name: gateway
    27. namespace: istio-ingress
    28. hostnames: ["httpbin.example.com"]
    29. rules:
    30. - matches:
    31. - path:
    32. type: PathPrefix
    33. value: /get
    34. filters:
    35. - type: RequestHeaderModifier
    36. requestHeaderModifier:
    37. add:
    38. - name: my-added-header
    39. value: added-value
    40. backendRefs:
    41. - name: httpbin
    42. port: 8000
    43. EOF
  3. 设置主机 Ingress

    1. $ kubectl wait -n istio-ingress --for=condition=ready gateways.gateway.networking.k8s.io gateway
    2. $ export INGRESS_HOST=$(kubectl get gateways.gateway.networking.k8s.io gateway -n istio-ingress -ojsonpath='{.status.addresses[*].value}')
  4. 使用 curl 访问 httpbin 服务:

    1. $ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST/get"
    2. HTTP/1.1 200 OK
    3. server: istio-envoy
    4. ...

    请注意,使用 -H 标志可以将 Host HTTP 标头设置为 “httpbin.example.com”。这一步是必需的,因为 HTTPRoute 已配置为处理”httpbin.example.com”的请求, 但是在测试环境中,该主机没有 DNS 绑定,只是将请求发送到入口 IP。

  5. 访问其他没有被显式暴露的 URL 时,将看到 HTTP 404 错误:

    1. $ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST/headers"
    2. HTTP/1.1 404 Not Found
    3. ...

部署方法

在上面的示例中,在配置网关之前,您不需要安装 ingress 网关 Deployment。 因为在默认配置中会根据 Gateway 配置自动分发网关DeploymentService。 但是对于高级别的用例,仍然允许手动部署。

自动部署

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

这些资源可以通过以下几种方式进行定义:

  • Gateway 上的注释和标签复制到 ServiceDeployment。 这就允许配置从上述字段中读取到的内容,如配置内部负载均衡器等。
  • Istio 提供了一个额外的注释来配置生成的资源:

    Annotation用途
    networking.istio.io/service-type控制 Service.spec.type 字段。 例如,设置 ClusterIP 为不对外暴露服务 , 将会默认为LoadBalancer
  • 通过配置 addresses 字段可以显式设置 Service.spec.loadBalancerIP 字段:

    1. apiVersion: gateway.networking.k8s.io/v1alpha2
    2. kind: Gateway
    3. metadata:
    4. name: gateway
    5. spec:
    6. addresses:
    7. - value: 192.0.2.0
    8. type: IPAddress
    9. ...

请注意:仅能指定一个地址。

手动部署

如果您不希望使用自动部署,可以进行手动配置 DeploymentService

完成此选项后,您将需要手动将 Gateway 链接到 Service,并保持它们的端口配置同步。

要将 Gateway 链接到 Service,需要将 addresses 字段配置为指向单个主机名。

  1. apiVersion: gateway.networking.k8s.io/v1alpha2
  2. kind: Gateway
  3. metadata:
  4. name: gateway
  5. spec:
  6. addresses:
  7. - value: ingress.istio-gateways.svc.cluster.local
  8. type: Hostname
  9. ...

网格流量

Gateway API 也可以用来配置网格流量。 具体做法是先配置 parentRef ,然后指向istio Mesh来实现的。 这个资源实际上并不存在于集群中,只是用来标识要使用的 Istio 网格参数。

例如,要将对 example.com 的调用重定向到另外一个名为 example 的集群内的 Service

  1. apiVersion: gateway.networking.k8s.io/v1alpha2
  2. kind: HTTPRoute
  3. metadata:
  4. name: mesh
  5. spec:
  6. parentRefs:
  7. - kind: Mesh
  8. name: istio
  9. hostnames: ["example.com"]
  10. rules:
  11. - backendRefs:
  12. - name: example
  13. port: 80