初识Gateway API
文章目录
[初识Gateway API](#初识Gateway API)
资源列表
操作系统
配置
主机名
IP
版本
Open Euler
2C4G
master
192.168.93.101
1.31
Open Euler
2C4G
node1
192.168.93.102
1.31
Open Euler
2C4G
node2
192.168.93.103
1.31
为什么要部署metallb?核心原因是Kubernetes本身不具备为LoadBalancer类型Service分配公网/集群内外可访问IP的能力,而MetalLb恰好填补了这一空白------尤其是在非云厂商托管的Kubernetes集群(如物理机、虚拟机搭建的自建集群)中,MetalLb是实现Gateway对外暴露流量的关键组件。
MetalLB 是Kubernetes的LoadBalancer 控制器实现,专门解决自建集群中LoadBalancer Service 的IP分配问题,具体能力:
管理员提前为MetalLB配置一段可用的IP网段(可以是集群内网段,也可以是公网网段),当Gateway对应的LoadBalancer Service创建后,MetalLB 会从该网段中分配一个固定IP给Service。
两种工作模式适配不同场景
Layer2模式:通过ARP/DNP协议将分配的IP绑定到集群节点的网卡上,集群内/外设备可通过该IP访问Gateway,部署简单,无需网络设备配合;
BGP模式:与集群的路由器建立BGP连接,将IP路由信息发布到整个网络,支持更高的流量吞吐和故障自动切换,适合生成环境。
保障Gateway的流量接入稳定性:分配的IP是固定的(而非随机的NodePort端口),且MetalLB 会监控节点状态,当绑定IP的节点故障时,自动将IP飘逸到健康节点,确保Gateway的接入点不中断。
1.2、修改kube-proxy的configMap
bash
复制代码
# 执行以后如果回显字段有strictARP: true表明执行成功
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl diff -f - -n kube-system
# 更改模式为ipvs
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
sed -e 's#mode: ""#mode: "ipvs"#' | \
kubectl apply -f - -n kube-system
bash
复制代码
wget https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml
kubectl apply -f metallb-native.yaml
bash
复制代码
# 查看metallb的状态
watch kubectl get all -o wide -n metallb-system
############################################################
# pod 状态是 runing 即可
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/controller-5589b69744-4wgpm 1/1 Running 0 5m9s 10.244.166.129 node1 <none> <none>
pod/speaker-2n4dg 1/1 Running 0 5m9s 192.168.93.146 node1 <none> <none>
pod/speaker-chdtn 1/1 Running 0 5m9s 192.168.93.145 master <none> <none>
pod/speaker-lvrxd 1/1 Running 0 5m9s 192.168.93.147 node2 <none> <none>
############################################################
bash
复制代码
# 可能会创建多个对外暴露的 service, 所以需要分配多个没有用到的IP地址给 Metallb
[root@master ~]# cat metallb-ip-pool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
# 注意改为你自己为 MetalLB 分配的 IP 地址
# 更改为自己网段内没有用到的 IP 地址
- 192.168.93.10-192.168.93.200
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
bash
复制代码
# 创建地址池资源
[root@master ~]# kubectl apply -f metallb-ip-pool.yaml
bash
复制代码
# 查看资源
[root@master ~]# kubectl get ipaddresspools.metallb.io -n metallb-system
NAME AUTO ASSIGN AVOID BUGGY IPS ADDRESSES
first-pool true false ["192.168.93.10-192.168.93.200"]
二、部署网关控制器
为什么要部署网关控制器?核心原因是:Gateway API仅定义了[声明式的流量规则配置(如Gateway、HTTPRoute),但本身不具备执行这些规则的能力------控制器是连接"配置声明"与"实际流量转发"的核心桥梁,负责将API资源的意图转化为具体的网络转发行为。]
Gateway支持的Controller:https://gateway-api.sigs.k8s.io/implementations/#gateway-controller-implementation-status
bash
复制代码
[root@master ~]# kubectl apply --server-side -f https://github.com/envoyproxy/gateway/releases/download/v1.6.1/install.yaml
三、安装Gateway API
bash
复制代码
[root@master ~]# kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.1/standard-install.yaml
四、部署一个简单的网关
如果你是Gateway API新手,这部分的内容将对你至关重要。它展示了最简单的部署方式:由同一资源所有者将Gateway与路由资源一并部署。这与Ingress所采用的部署模式十分相识。我们会部署一个Deployment、Service、GatewayClass、Gateway、HTTPRoute,然后将其流量转发到我们部署的foo-svc Service上。
4.1、部署Deployment和Svc
bash
复制代码
# 创建一个 namespace
[root@master ~]# kubectl create ns demo
bash
复制代码
[root@master ~]# cat demo_gateway_deploy.yaml
apiVersion: "apps/v1"
kind: Deployment
metadata:
name: nginx
namespace: demo
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: test-nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: "v1"
kind: Service
metadata:
name: foo-svc
namespace: demo
spec:
selector: # 标签选择器
app: nginx # 指定后端服务Pod,把流量路由到带有app=nginx的后端Pod上
type: ClusterIP # 因为我们会用 Gateway API 把服务暴露出去, 所有我们只需要创建一个 ClusterIP 类型的 Service 即可
ports:
- port: 80 # 对外暴露80端口
targetPort: 80 # 此处填写容器真实暴露出来的端口,流量将会被路由到这个端口上
bash
复制代码
[root@master ~]# kubectl apply -f demo_gateway_deploy.yaml
bash
复制代码
# 查看我们部署的资源
[root@master ~]# kubectl get pod,svc -n demo
NAME READY STATUS RESTARTS AGE
pod/nginx-745bb8f9f4-5pzpd 1/1 Running 0 21s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/foo-svc ClusterIP 10.104.229.68 <none> 80/TCP 21s
4.2、配置GatewayClass
GatewayClass其实就是对标Ingress的ingressclass。
bash
复制代码
# GatewayClass 的 namespace 可以自定义设置, 我这里直接就干脆创建在 default 下了
[root@master ~]# cat gateway_class.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: eg
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
bash
复制代码
# apply 一下
[root@master ~]# kubectl apply -f gateway_class.yaml
# ACCEPTED 字段为 True 即可
[root@master ~]# kubectl get gc
NAME CONTROLLER ACCEPTED AGE
eg gateway.envoyproxy.io/gatewayclass-controller True 77s
4.3、配置Gateway
bash
复制代码
[root@master ~]# cat gateway-demo.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: prod-web
namespace: demo
spec:
gatewayClassName: eg # 指定为刚刚创建的 GatewayClass
listeners:
- protocol: HTTP
port: 80 # Gateway 地址对外暴露的端口
name: prod-web-gw
bash
复制代码
# apply 一下
[root@master ~]# kubectl apply -f gateway-demo.yaml
# 通过下面的查看回显可以看到, 由于部署了 metallb 所以自动给我们分配了一个地址, 确保 PROGRAMMED 字段为 True 即可
[root@master ~]# kubectl get gateway -n demo
NAME CLASS ADDRESS PROGRAMMED AGE
prod-web eg 192.168.93.11 True 57s
4.4、配置HTTPRoute
bash
复制代码
[root@master ~]# cat httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: foo
namespace: demo
spec:
parentRefs:
- name: prod-web # 使用的 Gateway 名称, 如果 HTTPRoute 和 Gateway 不在同一个 namespace 下, 那就需要显式指定, 例如: namespace: gateway-ns
rules:
- backendRefs:
- name: foo-svc # 后端 Service 的名字和端口
port: 80
bash
复制代码
# apply 一下
[root@master ~]# kubectl apply -f httproute.yaml
4.5、测试访问
所需的资源都配置好之后,我们就访问测试一下看看是否把流量接管了,并且看到Nginx默认页面。
bash
复制代码
# 通过 Gateway 的 ADDRESS 地址进行访问(这个地址是 ping 不通的)
[root@master ~]# kubectl get gateway -n demo
NAME CLASS ADDRESS PROGRAMMED AGE
prod-web eg 192.168.93.11 True 7m26s
[root@master ~]# curl 192.168.93.11
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
4.6、Envoy控制器作用
其实我们所能看到的这些流量,是强大的Envoy代理帮我们实现的,每当我们部署了Gateway并且交给Envoy控制器之后(也就是创建Gateway指定的GatewayClass),会自动在部署envoy的命名空间下创建一个pod(控制器),
bash
复制代码
[root@master ~]# kubectl get pod -n envoy-gateway-system
NAME READY STATUS RESTARTS AGE
############################################################
envoy-demo-prod-web-0a42c290-5598548578-8hjwv 2/2 Running 0 9m32s
############################################################
envoy-gateway-68dc4cd4f9-7dhf6 1/1 Running 0 32m
命名格式为:envoy-<命名空间>-<Gateway名字>-<哈希值>-<Deployment 后缀>-<随机字符>
也就是这个pod在处理我们的请求
bash
复制代码
[root@master ~]# kubectl logs -n envoy-gateway-system envoy-demo-prod-web-0a42c290-5598548578-8hjwv
{":authority":"192.168.93.11","bytes_received":0,"bytes_sent":0,"connection_termination_details":null,"downstream_local_address":"10.244.166.134:10080","downstream_remote_address":"192.168.93.1:58371","duration":2,"method":"GET","protocol":"HTTP/1.1","requested_server_name":null,"response_code":304,"response_code_details":"via_upstream","response_flags":"-","route_name":"httproute/demo/foo/rule/0/match/0/*","start_time":"2025-12-13T07:23:58.816Z","upstream_cluster":"httproute/demo/foo/rule/0","upstream_host":"10.244.166.133:80","upstream_local_address":"10.244.166.134:50402","upstream_transport_failure_reason":null,"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0","x-envoy-origin-path":"/","x-envoy-upstream-service-time":null,"x-forwarded-for":"192.168.93.1","x-request-id":"06aabbd0-805e-4888-b21c-c52e58198e6e"}