【云原生】初识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

  • 为什么要部署metallb?核心原因是Kubernetes本身不具备为LoadBalancer类型Service分配公网/集群内外可访问IP的能力,而MetalLb恰好填补了这一空白------尤其是在非云厂商托管的Kubernetes集群(如物理机、虚拟机搭建的自建集群)中,MetalLb是实现Gateway对外暴露流量的关键组件。

1.1、MetalLB 的核心作用

  • MetalLB KubernetesLoadBalancer 控制器实现,专门解决自建集群中LoadBalancer Service IP分配问题,具体能力:
    • 管理员提前为MetalLB配置一段可用的IP网段(可以是集群内网段,也可以是公网网段),当Gateway对应的LoadBalancer Service创建后,MetalLB 会从该网段中分配一个固定IPService
    • 两种工作模式适配不同场景
      • 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

1.3、安装metallb

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>
############################################################

1.4、创建Metallb地址池

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所采用的部署模式十分相识。我们会部署一个DeploymentServiceGatewayClassGatewayHTTPRoute,然后将其流量转发到我们部署的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其实就是对标Ingressingressclass
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"}
相关推荐
java干货9 小时前
<span class=“js_title_inner“>微服务:把一个简单的问题,拆成 100 个网络问题</span>
微服务·云原生·架构
Spring_java_gg15 小时前
<span class=“js_title_inner“>面向云原生时代的 LLM 推理|Kthena入局了!!!</span>
云原生
eso198319 小时前
如何确保程序化广告系统中微服务架构的高可用性和可扩展性?
微服务·云原生·架构
江畔何人初20 小时前
/etc/profile,.profile,.bashrc三者区分
linux·运维·云原生
努力搬砖的咸鱼21 小时前
部署你的第一个应用到 K8s
微服务·云原生·容器·kubernetes
舰长1151 天前
使用 kubeadm搭建生产环境的单 master 节点 K8S 集群(一)
云原生·容器·kubernetes
lynnlovemin1 天前
云原生提速秘籍:Spring Boot转Spring Native实战指南
spring boot·spring·云原生·spring native
hwj运维之路1 天前
Docker面试题汇总系列
运维·docker·云原生·容器