Kubernetes Gateway API 刚刚 GA,旨在改进将集群服务暴露给外部的过程。这其中包括一套更标准、更强大的 API资源,用于管理已暴露的服务。在这篇文章中,我将介绍 Gateway API 资源,并以 Istio 为例来展示这些资源是如何关联的。通过这个示例,你将了解 Gateway API 的各个组成部分如何配合以将流量传递到后端服务。
背 景
允许外部与 Kubernetes 集群内的服务通信是 administrator 需要执行的最基本任务之一。Service 在 IP 层面上提供的功能十分有限,且缺乏根据应用层数据(如 DNS 主机名或 HTTP 路径)路由流量的能力。因此 Kubernetes 提供了 Ingress API 来实现应用层路由。
然而,Ingress API 有一些限制。Ingress2gateway 的公告[1]清楚地列出了这些限制:
Ingress 侧重于 HTTP 流量,因此用户需要找到其他解决方案来处理 UDP、TCP 或其他协议。
Ingress 资源混合了基础架构和应用程序配置,让细粒度的基于角色的访问控制(RBAC)的实施变得较为困难。
第二点对于已经熟悉 Ingress 的用户来说是最明显的。在平台工程中提供强大的 RBAC 是集群管理的关键步骤。将基础设施组件(负载均衡器、配置等)的权限与流量路由规则的权限分开,能够让权限的边界更加清晰。
接下来我将介绍 Gateway API 如何划分这些资源,以及它们如何最终结合在一起来路由流量。
设置测试环境
本文使用运行 Istio 和一个示例工作负载的测试环境来检查和理解各种 Gateway API 资源。如果你也想上手尝试,可以复制这个环境。
我用的是 K3s,使用 Kubernetes 集群也是类似的操作。如果选择使用 K3s,则在安装时不要启用 Traefik:
$ curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --disable=traefik" sh -
首先,部署 Gateway API CRD(Custom Resource Definitions),并按照官方文档安装 Istio( https://istio.io/latest/docs/tasks/traffic-management/ingress/gateway-api/):
# Install the CRDs $ kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || { kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.8.0" | kubectl apply -f -; } customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created # Install Istio $ istioctl install --set profile=minimal -y Istio core installed Istiod installed Installation complete Made this installation the default for injection and validation.
接下来创建一个简单的工作负载,比如一个 Nginx deployment ,并通过 deservice 将其暴露:
# Deployment.yaml --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx:latest name: nginx # Service.yaml --- apiVersion: v1 kind: Service metadata: labels: app: nginx name: nginx namespace: default spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: nginx type: ClusterIP
$ kubectl apply -f Deployment.yaml deployment.apps/nginx created $ kubectl apply -f Service.yaml service/nginx created
以上就是你用来理解 Gateway API 所需的全部基础设施。
了解 Gateway API 资源
想要使用 Gateway API,有三种资源类型你需要明确了解:
GatewayClass
Gateway
路由资源,比如 HTTPRoute或GRPCRoute。GA 版本仅包含在 v1 通道中到 HTTPRoute。
这些资源在标准 Ingress API 或自定义提供商负载均衡器和路由工具提供的 CRD 中以各种方式组合在一起。通过将这些资源拆分为单独的组件,Gateway API 实现了关注点分离和强大的、细粒度的访问控制。
让我们逐个了解这些资源,以了解它们之间的关系。
了解 GatewayClass 资源
GatewayClass资源的作用与现有 Ingress API 中的 IngressClass相同,类似于 Storage API 中的 StorageClass。它定义了可以创建的 Gateway类别。通常,此资源由你的基础架构平台(如 EKS 或 GKE)提供。也可以由第三方的 Ingress Controller 提供,例如 Istio 或 Nginx。Istio 包含两个 GatewayClasses:
$ kubectl get gatewayclass NAME CONTROLLER ACCEPTED AGE istio-remote istio.io/unmanaged-gateway True 19h istio istio.io/gateway-controller True 19h
spec字段提供了有关实现 GatewayClass功能的 controller 的信息,它定义了整个集群使用的控制器,而 GatewayClasses 是集群范围的资源,适用于所有命名空间。
$ kubectl get gatewayclass istio -o yaml apiVersion: gateway.networking.k8s.io/v1beta1 kind: GatewayClass metadata: creationTimestamp: "2023-10-30T0211Z" generation: 1 name: istio resourceVersion: "636" uid: dea0bb44-5f1b-4d23-8f7f-c34f70b4603c spec: controllerName: istio.io/gateway-controller description: The default Istio GatewayClass status: conditions: - lastTransitionTime: "2023-10-30T0211Z" message: Handled by Istio controller observedGeneration: 1 reason: Accepted status: "True" type: Accepted
GatewayClass还可以指定传递给控制器的参数。这样上游项目能够进一步定制向集群管理员公开的配置。也就是说, GatewayClass允许集群管理员专注于将其流量暴露给外部,而不必担心例如在底层基础设施上如何创建负载均衡器等实现细节。
创建 Gateway
Gateway 代表在基础设施提供商中实例化的负载均衡器服务。它可以是一个实际的云负载均衡器,用于处理流量。也可以代表现有负载均衡器中的虚拟配置。然后通过 GatewayClass 进行抽象。Cluster operator 专注于定义必要的 Gateway 资源,无需担心由 GatewayClass 处理的实现细节。
Gateway 在其规范中引用了一个 GatewayClass。下面的示例使用 istio 类,并定义了一个响应端口 8080 上 *.example.com 的 HTTP 请求的单个侦听器:
# Gateway.yaml --- apiVersion: gateway.networking.k8s.io/v1beta1 kind: Gateway metadata: name: tutorial-gw namespace: default spec: gatewayClassName: istio listeners: - name: default hostname: "*.example.com" port: 8080 protocol: HTTP allowedRoutes: namespaces: from: All
使用 Istio 在创建 Gateway 时还会相应配置Deployment和 Service 来处理流量。GatewayClass 的控制器负责为 Gateway 处理所需的基础设施或配置的设置:
$ kubectl get pods NAME READY STATUS RESTARTS AGE tutorial-gw-istio-65bfccf7c-45c4w 1/1 Running 2 (6m31s ago) 18h $ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE tutorial-gw-istio LoadBalancer 10.43.126.90 192.168.122.10 15021:31348/TCP,8080:31728/TCP 18h
这里需要注意的是 Gateway 中没有定义路由规则。Gateways 代表基础设施的配置,这种分离对于实现 RBAC 至关重要。访问控制模型允许 cluster operator 配置可用的Gateways ,让用户在其路由资源中引用,而无需暴露对基础设施配置本身的访问。
创建路由
现有的 Ingress API 仅支持 HTTP 和 HTTPS 服务,这是一个比较大的限制。
而新的 Gateway API 为各种入站流量类型提供通用支持。 HTTPRoute、TCPRoute 、 TLSRoute 、 GRPCRoute 等资源在特定 Gateway 上指定了实际的流量路由。Gateway API 的 GA 版本只在标准的 v1 通道中包含了 HTTPRoute资源,在未来的版本中将会有更多的协议支持。
HTTPRoute资源指定与用于暴露服务的 Gateway 的连接,以及一系列规则来将流量路由到适当的后端。下面的示例将 HTTPRoute附加到 tutorial-gw Gateway,并指定规则将所有流量路由到 nginx Service:
--- apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: tutorial-route namespace: default spec: parentRefs: - group: gateway.networking.k8s.io kind: Gateway name: tutorial-gw rules: - backendRefs: - group: "" kind: Service name: nginx port: 80 weight: 1 matches: - path: type: PathPrefix value: /
$ kubectl apply -f HTTPRoute.yaml httproute.gateway.networking.k8s.io/tutorial-route created $ kubectl get httproute NAME HOSTNAMES AGE tutorial-route 6s
综合以上
Gateway API 将许多传统上包含在单个资源定义中的资源拆分开来。要跟踪所有这些资源之间的连接可能有点困难,这里我将资源之间的关系图展示如下:
Gateway API 资源之间的关系
快速回顾
GatewayClass 定义了可以部署的 Gateway 类型。通常由基础设施提供商提供。在本示例中,Istio 定义了GatewayClass 。
Gateway 是负载均衡基础设施的实例化。这可以是在云环境中部署的实际负载均衡器,也可以是针对现有负载均衡器执行的一些配置。无论哪种方式,通过简单地引用所需的GatewayClass ,就能从 cluster administrator 中抽象出来。
HTTPRoute(或任何其他支持的 Route 资源)定义了处理流量的实际规则。这些路由附加到特定的 Gateway,最终决定了流量的转发。
有了所有这些配置,就可以对服务进行测试请求。本示例Gateway 配置为侦听端口 8080 上 *.example.com 的 HTTP 请求,因此你的请求需要设置适当的 Host header 和端口:
$ curl -H "Host: www.example.com" 192.168.122.10:8080Welcome to nginx!
这样,你就使用新的网关 API 成功配置了第一组资源咯!
全部0条评论
快来发表一下你的评论吧 !