Gateway API 是 Kubernetes 中的一个 API 资源集合, 包括 GatewayClass,Gateway,HTTPRoute,TCPRoute,Service 等, 这些资源共同为各种网络用例构建模型.
Gateway API(之前叫 Service API)是由 SIG-NETWORK 社区管理的开源项目, 项目地址: https://gateway-api.sigs.k8s.io/.
主要原因是 Ingress 资源对象不能很好的满足网络需求, 很多场景下 Ingress 控制器都需要通过定义 annotations 或者 crd 来进行功能扩展, 这对于使用标准和支持是非常不利的, 新推出的 Gateway API 旨在通过可扩展的面向角色的接口来增强服务网络.
Gateway API 是 Kubernetes 中的一个 API 资源集合, 包括 GatewayClass,Gateway,HTTPRoute,TCPRoute,Service 等, 这些资源共同为各种网络用例构建模型.
Gateway API 的价值与定位
提供跨 Namespace 的一种 Ingress 机制: 让多个跨 Namespace 的服务, 可以分享一个 L7 LoadBalancer
可实现多租户的一种 Ingress 机制: 提供 HttpRoute 与 Gateway 分离的抽象组件, 让设计路由 (HttpRoute) 的人, 可以共享一个 L7 LoadBalancer,
蓝绿部署金丝雀部署时为使用同一个命名空间下的部署, 可以简单的定义在 HttpRoute 中
基于 Hostname,Header, 或 Subpath 的服务, 使用 AB 测试等等.
Gateway API 介绍
网关 API 主要分为以下几个角色:
- GatewayClass(由 Cloud 或 K8s 提供者提供),
- Gateway(由网管平台公司自建 GatewayClass),
- HTTPRoute(由开发者团队服务部署者选择对应的网关对接)
目前 GKE 提供了四种网关类, 分别是:
gke-l7-rilb 建立在内部 HTTP(S) 负载均衡上的区域内部 HTTP(S) 负载均衡器(单丛集 Internal LoadBalancer)
gke-l7-gxlb 建立在外部 HTTP(S) 负载均衡之上的全球外部 HTTP(S) 负载均衡器(单丛集 External LoadBalancer)
gke-l7-rilb-mc 基于 Internal HTTP(S) Load Balancing 的多集群区域负载均衡器(多丛集 Internal LoadBalancer)
gke-l7-gxlb-mc 基于 External HTTP(S) Load Balancing 的多集群全局负载均衡器(多丛集 External LoadBalancer)
网关部署
目前 GKE 的 Gateway APIK8S 1.20 以上的版本, 如果使用 GKE 发布频道需要捧油, 现在需要使用 RAPID 区域, 同时仅在以下提供公开 Beta 测试:
- us-west1
- us-east1
- us-central1
- europe-west4
- europe-west3
- europe-west2
- europe-west1
- asia-southeast1
下面的测试, 我们选择先测试 Interal-LoadBalancer 并尝试下面的拓扑图:
部署私有 GKE
我们先开发一个私人 GKE 集群, 可以参照我提供的 Terraform 脚本, 请直接将 shawn.tfvars 改为符合你集群的参数, 另外, 由于我使用远端 GCS 也请设置保存 tfstate, 修改 config.tf 里面的 bucket 名称. 其他经常设置和私有 GKE 类似, 只需要使用内部 LB 而增加了一个 proxy-only 的子网给 Envoy 使用.
部署网关
根据上述的第三个阶段, 我们先部署 Gateway API 的 CRD 档案:
- kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.3.0" \
- | kubectl apply -f -
- # 部署成功後, 可使用下方命令檢視單叢集 internal/external GatewayClass
- private-gke-tf % kubectl get gatewayclass
- NAME CONTROLLER AGE
- gke-l7-gxlb networking.gke.io/gateway 23h
- gke-l7-rilb networking.gke.io/gateway 23h
下一步我们准备部署网关, 使用 kubectl apply -f 部署底下 YAML:
- kind: Gateway
- apiVersion: networking.x-k8s.io/v1alpha1
- metadata:
- name: internal-http
- spec:
- gatewayClassName: gke-l7-rilb
- listeners:
- - protocol: HTTP
- port: 80
- routes:
- kind: HTTPRoute
- selector:
- matchLabels:
- gateway: internal-http
- namespaces:
- from: "All"
因为 Gateway 可以接受三个关联模式, 基于 kind,selector, 以及 namespace.
kind: 以下可选任一种 Route: HTTPRoute, TCPRoute, or customRoute
- private-gke-tf % kubectl describe gateway internal-http
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
- Normal SYNC 4m59s (x396 over 23h) sc-gateway-controller SYNC on default/internal-http was a success
- kind: HTTPRoute
- apiVersion: networking.x-k8s.io/v1alpha1
- metadata:
- name: store
- labels:
- gateway: internal-http
- spec:
- hostnames:
- - "store.example.com"
- rules:
- - forwardTo:
- - serviceName: store-v1
- port: 8080
- weight: 50
- - serviceName: store-v2
- port: 8080
- weight: 50
- - matches:
- - headers:
- type: Exact
- values:
- env: canary
- forwardTo:
- - serviceName: store-v2
- port: 8080
- - matches:
- - path:
- type: Prefix
- value: /de
- forwardTo:
- - serviceName: store-german
- port: 8080
- kind: HTTPRoute
- apiVersion: networking.x-k8s.io/v1alpha1
- metadata:
- name: site
- namespace: site
- labels:
- gateway: internal-http
- spec:
- gateways:
- allow: FromList
- gatewayRefs:
- - name: internal-http
- namespace: default
- hostnames:
- - "site.example.com"
- rules:
- - forwardTo:
- - serviceName: site-v1
- port: 8080
- kubectl get gateway internal-http -o jsonpath='{.status.addresses[0].value}'
- 10.81.68.140
- shawnho@jumper2:~$ curl -H "host: site.example.com" 10.81.68.140
- {
- "cluster_name": "pgke-1",
- "host_header": "site.example.com",
- "metadata": "site-v1",
- "node_name": "gke-pgke-1-cluster-runtime-425beb23-vx9j.c.shawn-demo-2021.internal",
- "pod_name": "site-v1-86dc4b4fbc-4g6jr",
- "pod_name_emoji": "",
- "project_id": "shawn-demo-2021",
- "timestamp": "2021-07-18T15:26:15",
- "zone": "asia-southeast1-a"
- }
- # 测试 header match
- shawnho@jumper2:~$ curl -H "host: store.example.com" -H "env: canary" 10.81.68.140
- {
- "cluster_name": "pgke-1",
- "host_header": "store.example.com",
- "metadata": "store-v2",
- "node_name": "gke-pgke-1-cluster-runtime-425beb23-vx9j.c.shawn-demo-2021.internal",
- "pod_name": "store-v2-6856f59f7f-49fv8",
- "pod_name_emoji": "",
- "project_id": "shawn-demo-2021",
- "timestamp": "2021-07-18T15:33:04",
- "zone": "asia-southeast1-a"
- }
- # 测试 prefix match
- shawnho@jumper2:~$ curl -H "host: store.example.com" 10.81.68.140/de
- {
- "cluster_name": "pgke-1",
- "host_header": "store.example.com",
- "metadata": "Gutentag!",
- "node_name": "gke-pgke-1-cluster-runtime-425beb23-vx9j.c.shawn-demo-2021.internal",
- "pod_name": "store-german-66dcb75977-ttngz",
- "pod_name_emoji": "♀",
- "project_id": "shawn-demo-2021",
- "timestamp": "2021-07-18T15:32:15",
- "zone": "asia-southeast1-a"
- }
- # 测试 default route
- shawnho@jumper2:~$ curl -H "host: store.example.com" 10.81.68.140
- {
- "cluster_name": "pgke-1",
- "host_header": "store.example.com",
- "metadata": "store-v1",
- "node_name": "gke-pgke-1-cluster-runtime-425beb23-vx9j.c.shawn-demo-2021.internal",
- "pod_name": "store-v1-65b47557df-rv65j",
- "pod_name_emoji": "♂",
- "project_id": "shawn-demo-2021",
- "timestamp": "2021-07-18T15:32:09",
- "zone": "asia-southeast1-a"
- }
- shawnho@jumper2:~$ curl -H "host: store.example.com" 10.81.68.140
- {
- "cluster_name": "pgke-2",
- "host_header": "store.example.com",
- "metadata": "store -v2",
- "node_name": "gke-pgke-2-cluster-runtime-e7f1b4b7-wg5a.c.shawn-demo-2021.internal",
- "pod_name": "store-v2-6856f59f7f-gkkct",
- "pod_name_emoji": "",
- "project_id": "shawn-demo-2021",
- "timestamp": "2021-07-18T15:32:29",
- "zone": "asia-southeast1-a"
- }
来源: http://os.51cto.com/art/202201/698988.htm