1、Gateway API介绍
1、简介
Gateway API(之前叫 Service API)是由 SIG-NETWORK 社区管理的开源项目,项目地址:https://gateway-api.sigs.k8s.io/ 主要原因是 Ingress 资源对象不能很好的满足网络需求,很多场景下 Ingress 控制器都需要通过定义 annotations 或者 crd 来进行功能扩展,这对于使用标准和支持是非常不利的,新推出的 Gateway API 旨在通过可扩展的面向角色的接口来增强服务网络。
Gateway APl是Kubernetes 中的一个 API资源集合,包括 GatewayClass、Gateway、HTTPRoute、CPRoute、Service等,这些资源共同为各种网络用例构建模型。
Gateway API的改进比当前的 Ingress 资源对象有很多更好的设计:
- 面向角色-Gateway 由各种 API资源组成,这些资源根据使用和配置Kubernetes 服务网络的角色进行建模。
- 通用性·和 Ingress 一样是一个具有众多实现的通用规范,Gateway API是一个被设计成由许多实现支持的规范标准。更具表现力-Gateway A阶资源支持基于 Header 头的匹配、流量权重等核心功能,这些功能在 Ingress 中只能通过白定义注解才能实现。
- 可扩展性-Gateway API允许自定义资源链接到 API的各个层,这就允许在 API结构的适当位置进行更精细的定制。还有一些其他值得关注的功能:
- GatewayClasses·GatewayClases 将负载均衡实现的类型形式化,这些类使用户可以很容易了解到通过 Kubernetes 资源可以获得什么样的能力。
- 共享网关和跨命名空间支持·它们允许共享负载均衡器和 VIP,允许独立的路由资源绑定到同一个网关,这使得团队可以安全地共享(包括跨命名空间)基础设施,而不需要直接协调。
- 规范化路由和后端-GatewyAPI支持类型化的路由资源和不同类型的后端,这使得 API可以灵活地支持各种协议(如 HTTP和gRPC)和各种后端服务(如 Kubernetes Service、存储桶或函数)。
2、面向角色设计
无论是道路、电力、数据中心还是 Kubernetes 集群,基础设施都是为了共享而建的,然而共享基础设施提供了一个共同的挑战,那就是如何为基础设施用户提供灵活性的同时还能被所有者控制。
Gatewav API通过对 Kubernetes 服务网络进行面向角色的设计来实现这一目标,平衡了灵活性和集中控制。它允许共享的网络基础设施(硬件负载均衡器、云网络、集群托管的代理等)被许多不同的团队使用,所有这些都受到集群运维设置的各种策略和约束。下面的例子显示了是如何在实践中运行的。
一个集群运维人员创建了一个基于 GatewayClass 的 Gateway 资源,这个 Gateway 部署或配置了它所代表的基础网络资源,集群运维和特定的团队必须沟通什么可以附加到这个 Gateway 上来暴露他们的应用。集中的策略,如 TLS,可以由集群运维在 Gateway 上强制执行,同时,Store 和 Site 应用在他们自己的命名空间中运行,但将他们的路由附加到相同的共享网关上,允许他们独立控制他们的路由逻辑。
这种关注点分离的设计可以使不同的团队能够管理他们自己的流量,同时将集中的策略和控制留给集群运维。
3、Gateway API概念
在整个 Gateway API 中涉及到3个角色:基础设施提供商、集群管理员、应用开发人员,在某些场景下可能还会涉及到应用管理员等角色。Gateway API 中定义了3种主要的资源模型:GatewayClass、Gateway、Route。
3.1、GatewayClass
GatewayClass 定义了一组共享相同配置和动作的网关。每个GatewayClass 由一个控制器处理,是一个集群范围的资源,必须至少有一个 GatewayClass 被定义。
这与 Ingress 的 IngressClass 类似,在 Ingress v1beta1 版本中,与 GatewayClass 类似的是 ingress-class 注解,而在Ingress V1 版本中,最接近的就是 IngressClass 资源对象。
3.2、Gateway
Gateway 网关描述了如何将流量转化为集群内的服务,也就是说,它定义了一个请求,要求将流量从不了解 Kubernetes 的地方转换到集群内的服务。例如,由云端负载均衡器、集群内代理或外部硬件负载均衡器发送到 Kubernetes 服务的流量。
它定义了对特定负载均衡器配置的请求,该配置实现了 GatewayClass 的配置和行为规范,该资源可以由管理员直接创建,也可以由处理 GatewayClass 的控制器创建。
Gateway 可以附加到一个或多个路由引用上,这些路由引用的作用是将流量的一个子集导向特定的服务。
3.3、Route 资源
路由资源定义了特定的规则,用于将请求从网关映射到 Kubernetes 服务。
从 v1alpha2 版本开始,API 中包含四种 Route 路由资源类型,对于其他未定义的协议,鼓励采用特定实现的自定义路由类型,当然未来也可能会添加新的路由类型。
3.3.1、HTTPRoute
HTTPRoute 适用于 HTTP 或 HTTPS 连接,适用于我们想要检查 HTTP 请求并使用 HTTP 请求进行路由或修改的场景,比如使用 HTTP Headers 头进行路由,或在请求过程中对它们进行修改。
3.3.2、TLSRoute
TLSRoute 用于 TLS 连接,通过 SNI 进行区分,它适用于希望使用 SNI 作为主要路由方法的地方,并且对 HTTP 等更高级别协议的属性不感兴趣,连接的字节流不经任何检查就被代理到后端。
3.3.3、TCPRoute 和 UDPRoute
TCPRoute(和UDPRoute)旨在用于将一个或多个端口映射到单个后端。在这种情况下,没有可以用来选择同一端口的不同后端的判别器,所以每个 TCPRoute 在监听器上需要一个不同的端口。你可以使用 TLS,在这种情况下,未加密的字节流会被传递到后端,当然也可以不使用 TLS,这样加密的字节流将传递到后端。
4、组合
GatewayClass、Gateway、xRoute 和 Service 的组合定义了一个可实施的负载均衡器。下图说明了不同资源之间的关系:
使用反向代理实现的网关的典型客户端/网关 API 请求流程如下所示:
1.客户端向 http://foo.example.com 发出请求
2.DNS 将域名解析为 Gateway 网关地址
3.反向代理在监听器上接收请求,并使用 Host Header 来匹配HTTPRoute
4.(可选)反向代理可以根据 HTTPRoute 的匹配规则进行路由
5.(可选)反向代理可以根据 HTTPRoute 的过滤规则修改请求,即添加或删除 headers
6.最后,反向代理根据 HTTPRoute 的 forwardTo 规则,将请求转发给集群中的一个或多个对象,即服务。
2.1、Kubernetes gateway CRD安装
要在 Traefik 中使用 GatewayAP!,首先我们需要先手动安装 GatewaVAP的 CRDS,使用如下命令即可安装,这将安装包括 GatewavClass、Gateway、HTTPRoute、TCPRoute等CRDS:
[root@k8s-master01 ~]# kubectl apply -k "github.com/kubernetes-sigs/service-apis/config/crd?ref=v0.3.0"
customresourcedefinition.apiextensions.k8s.io/backendpolicies.networking.x-k8s.io created
customresourcedefinition.apiextensions.k8s.io/gatewayclasses.networking.x-k8s.io created
customresourcedefinition.apiextensions.k8s.io/gateways.networking.x-k8s.io created
customresourcedefinition.apiextensions.k8s.io/httproutes.networking.x-k8s.io created
customresourcedefinition.apiextensions.k8s.io/tcproutes.networking.x-k8s.io created
customresourcedefinition.apiextensions.k8s.io/tlsroutes.networking.x-k8s.io created
customresourcedefinition.apiextensions.k8s.io/udproutes.networking.x-k8s.io created
2.2、为traefik授权(RBAC)
[root@k8s-master01 traefik]# vim traefik-gatewayapi-rbac.yaml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: gateway-role
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- networking.x-k8s.io
resources:
- gatewayclasses
- gateways
- httproutes
- tcproutes
- tlsroutes
verbs:
- get
- list
- watch
- apiGroups:
- networking.x-k8s.io
resources:
- gatewayclasses/status
- gateways/status
- httproutes/status
- tcproutes/status
- tlsroutes/status
verbs:
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: gateway-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: gateway-role
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: kube-system
[root@k8s-master01 traefik]# kubectl apply -f traefik-gatewayapi-rbac.yaml
clusterrole.rbac.authorization.k8s.io/gateway-role created
clusterrolebinding.rbac.authorization.k8s.io/gateway-controller created
2.3、Traefik开启gateway api的支持
在前面部署Traefik的时候已经开启了,检查你的是否开启
[root@k8s-master01 traefik]# cat traefik-configmap.yaml
……
providers:
kubernetesCRD: "" ## 启用 Kubernetes CRD 方式来配置路由规则
kubernetesingress: "" ## 启用 Kubernetes Ingress 方式来配置路由规则
kubernetesGateway: "" ## 启用 Kubernetes Gateway API ----> 检查是否存在此行
experimental: #----> 检查是否存在此行
kubernetesGateway: true ## 允许使用 Kubernetes Gateway API ----> 检查是否存在此行
……
# 重新生效
[root@k8s-master01 traefik]# kubectl delete -f traefik-configmap.yaml
[root@k8s-master01 traefik]# kubectl apply -f traefik-configmap.yaml
2.4、创建Gateway API的GatewayClass
[root@k8s-master01 traefik]# vim gatewayclass.yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: GatewayClass
metadata:
name: traefik
spec:
controller: traefik.io/gateway-controller
[root@k8s-master01 traefik]# kubectl apply -f gatewayclass.yaml
gatewayclass.networking.x-k8s.io/traefik created
[root@k8s-master01 traefik]# kubectl get gatewayclasses.networking.x-k8s.io
NAME CONTROLLER AGE
traefik traefik.io/gateway-controller 9s
[root@k8s-master01 traefik]#
3.1、GatewayAPI高级应用-暴露Traefik dashboard
1、创建Gateway
[root@k8s-master01 traefik]# cat trafik-dashboard-gateway.yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: Gateway
metadata:
name: http-traefik
namespace: kube-system
spec:
gatewayClassName: traefik
listeners:
- protocol: HTTP
port: 80
routes:
kind: HTTPRoute
namespaces:
from: All
selector:
matchLabels:
app: traefik
[root@k8s-master01 traefik]# kubectl apply -f trafik-dashboard-gateway.yaml
gateway.networking.x-k8s.io/http-traefik created
[root@k8s-master01 traefik]# kubectl get gateway -n kube-system
NAME CLASS AGE
http-traefik traefik 18s
2、创建HTTPRoute
[root@k8s-master01 traefik]# cat trafik-dashboard-httproute.yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
name: traefik-dashboard-gateway-api-route
namespace: kube-system
labels:
app: traefik
spec:
hostnames:
- "traefik.tkdashboard.com"
rules:
- matches:
- path:
type: Prefix
value: /
forwardTo:
- serviceName: traefik
port: 8080
weight: 1
[root@k8s-master01 traefik]# kubectl apply -f trafik-dashboard-httproute.yaml
httproute.networking.x-k8s.io/traefik-dashboard-gateway-api-route created
[root@k8s-master01 traefik]# kubectl get httproute -n kube-system
NAME HOSTNAMES AGE
traefik-dashboard-gateway-api-route ["traefik.tkdashboard.com"] 49s
3、集群外主机添加解析后,测试访问,本次在worker04上测试
[root@k8s-worker04 ~]# echo "192.168.122.11 traefik.tkdashboard.com" >> /etc/hosts
3.2、通过Gateway API方式暴露WEB应用
1、创建WEB应用
[root@k8s-master01 traefik]# cat nginx-web-gatewayapi.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-web-gatewayapi
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx-web-gatewayapi
template:
metadata:
labels:
app: nginx-web-gatewayapi
spec:
containers:
- name: nginx-web-gatewayapi
image: nginx:1.24.0
lifecycle:
postStart:
exec:
command: ["/bin/bash", "-c", "echo nginx-web-gatewayapi > /usr/share/nginx/html/index.html"]
ports:
- containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: nginx-web-gatewayapi
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-web-gatewayapi
[root@k8s-master01 traefik]# kubectl apply -f nginx-web-gatewayapi.yaml
deployment.apps/nginx-web-gatewayapi created
service/nginx-web-gatewayapi created
[root@k8s-master01 traefik]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/nfs-client-provisioner-856696f4c-cmlgq 1/1 Running 1 8d
pod/nginx-web-gatewayapi-5bfb495f6d-4njp8 1/1 Running 0 22s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 30d
service/nginx-web-gatewayapi ClusterIP 10.104.77.1 <none> 80/TCP 22s
2、通过Gateway API方式暴露nginx
2.1、创建Gateway
[root@k8s-master01 traefik]# cat nginx-web-gateway.yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: Gateway
metadata:
name: nginx-web-gatewayapi
namespace: default
spec:
gatewayClassName: traefik
listeners:
- protocol: HTTP
port: 80
routes:
kind: HTTPRoute
namespaces:
from: All
selector:
matchLabels:
app: nginx-web-gatewayapi
[root@k8s-master01 traefik]# kubectl apply -f nginx-web-gateway.yaml
gateway.networking.x-k8s.io/nginx-web-gatewayapi created
[root@k8s-master01 traefik]# kubectl get gateway
NAME CLASS AGE
nginx-web-gatewayapi traefik 6s
[root@k8s-master01 traefik]#
2.3、创建HTTPRoute
[root@k8s-master01 traefik]# cat nginx-web-gateway-httproute.yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
name: nginx-web-gatewayapi
namespace: default
labels:
app: nginx-web-gatewayapi
spec:
hostnames:
- "nginx.tkdashboard.com"
rules:
- matches:
- path:
type: Prefix
value: /
forwardTo:
- serviceName: nginx-web-gatewayapi
port: 80
weight: 1
root@k8s-master01 traefik]# kubectl get httproutes.networking.x-k8s.io
NAME HOSTNAMES AGE
nginx-web-gatewayapi ["nginx.tkdashboard.com"] 14s
2.4、测试
集群外主机添加解析,并测试,本次在worker04上测试
[root@k8s-worker04 ~]# echo "192.168.122.11 nginx.tkdashboard.com" >> /etc/hosts
3.3、通过GatewayAPI部署金丝雀发布
Gateway APIs 规范可以支持的另一个功能是金丝雀发布,假设你想在一个端点上运行两个不同的服务(或同一服务的两个版本),并将部分请求路由到每个端点,则可以通过修改你的 HTTPRoute 来实现
1、部署应用
[root@k8s-master01 traefik]# cat nginx-web01_or_web02.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-web-01
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx-web-01
template:
metadata:
labels:
app: nginx-web-01
spec:
containers:
- name: nginx-web-01
image: nginx:1.24.0
lifecycle:
postStart:
exec:
command: ["/bin/bash", "-c", "echo nginx-web-01 > /usr/share/nginx/html/index.html"]
ports:
- containerPort: 80
protocol: TCP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-web-02
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx-web-02
template:
metadata:
labels:
app: nginx-web-02
spec:
containers:
- name: nginx-web-02
image: nginx:1.24.0
lifecycle:
postStart:
exec:
command: ["/bin/bash", "-c", "echo nginx-web-02 > /usr/share/nginx/html/index.html"]
ports:
- containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: nginx-web-01
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-web-01
---
apiVersion: v1
kind: Service
metadata:
name: nginx-web-02
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-web-02
[root@k8s-master01 traefik]# kubectl apply -f nginx-web01_or_web02.yaml
deployment.apps/nginx-web-01 created
deployment.apps/nginx-web-02 created
service/nginx-web-01 created
service/nginx-web-02 created
[root@k8s-master01 traefik]#
[root@k8s-master01 traefik]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/nfs-client-provisioner-856696f4c-cmlgq 1/1 Running 1 8d
pod/nginx-web-01-95ddcb499-xfpbk 1/1 Running 0 19s
pod/nginx-web-02-6d95896b8-899bm 1/1 Running 0 19s
pod/nginx-web-gatewayapi-5bfb495f6d-4njp8 1/1 Running 0 16m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 30d
service/nginx-web-01 ClusterIP 10.98.196.223 <none> 80/TCP 19s
service/nginx-web-02 ClusterIP 10.98.81.62 <none> 80/TCP 19s
service/nginx-web-gatewayapi ClusterIP 10.104.77.1 <none> 80/TCP 16m
2、部署Gateway
使用发布Traefik时候的Gateway,也可以在创建一个Gateway,这里使用前面的Gateway,相关配置信息如下,我们不动,只打开看看
[root@k8s-master01 traefik]# vim nginx-web01_or_web02-gateway.yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: Gateway
metadata:
name: nginx-web01-or-web02
namespace: default
spec:
gatewayClassName: traefik
listeners:
- protocol: HTTP
port: 80
routes:
kind: HTTPRoute
namespaces:
from: All
selector:
matchLabels:
app: nginx-web01-or-web02
[root@k8s-master01 traefik]# kubectl apply -f nginx-web01_or_web02-gateway.yaml
gateway.networking.x-k8s.io/nginx-web01-or-web02 created
[root@k8s-master01 traefik]# kubectl get gateway
NAME CLASS AGE
nginx-web-gatewayapi traefik 35m
nginx-web01-or-web02 traefik 22s
3、创建HTTPRoute
[root@k8s-master01 traefik]# cat nginx-web01_or_web02-httproute.yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
name: nginx-web01-or-web02
namespace: default
labels:
app: nginx-web01-or-web02
spec:
hostnames:
- "nginx01.tkdashboard.com"
rules:
- forwardTo:
- serviceName: nginx-web-01
port: 80
weight: 3 # 3/4的请求转发到nginx-web-01
- serviceName: nginx-web-02
port: 80
weight: 1 # 1/4的请求转发到nginx-web-02
[root@k8s-master01 traefik]# kubectl apply -f nginx-web01_or_web02-httproute.yaml
httproute.networking.x-k8s.io/nginx-web01-or-web02 created
[root@k8s-master01 traefik]# kubectl get httproutes.networking.x-k8s.io
NAME HOSTNAMES AGE
nginx-web-gatewayapi ["nginx.tkdashboard.com"] 34m
nginx-web01-or-web02 ["nginx01.tkdashboard.com"] 6s
4、验证
dashboard查看,在worker04上添加解析并查看
[root@k8s-worker04 ~]# echo "192.168.122.11 nginx01.tkdashboard.com" >> /etc/hosts
[root@k8s-worker04 ~]# curl http://nginx01.tkdashboard.com
nginx-web-02
[root@k8s-worker04 ~]# curl http://nginx01.tkdashboard.com
nginx-web-01
[root@k8s-worker04 ~]# curl http://nginx01.tkdashboard.com
nginx-web-01
[root@k8s-worker04 ~]# curl http://nginx01.tkdashboard.com
nginx-web-01
[root@k8s-worker04 ~]# curl http://nginx01.tkdashboard.com
nginx-web-02
[root@k8s-worker04 ~]# curl http://nginx01.tkdashboard.com
nginx-web-01
[root@k8s-worker04 ~]# curl http://nginx01.tkdashboard.com
nginx-web-01
[root@k8s-worker04 ~]# curl http://nginx01.tkdashboard.com
nginx-web-01
[root@k8s-worker04 ~]# curl http://nginx01.tkdashboard.com
nginx-web-02
评论区