Skip to content

创建Kubernetes Gateway ​

本文介绍如何通过Kubernetes Gateway API创建矩尺Gateway、Route和对外访问Service,并在矩尺Web界面中核验配置结果。集群接入尚未完成时,请先参见接入Kubernetes集群。

配置方式 ​

当前版本通过kubectl apply创建或更新Gateway API资源。矩尺Web界面用于查看Gateway、Route、Service及其拓扑和事件,不在Web界面中直接创建这些资源。

配置关系如下:

对象作用关键关联
GatewayClass指定矩尺Gateway控制器controllerName: normae.io/gateway
Gateway定义协议、监听器和端口gatewayClassName引用GatewayClass
Service将Gateway监听端口暴露到集群外targetPort与Gateway监听端口一致
HTTPRoute定义匹配、过滤和后端转发规则parentRefs引用Gateway,backendRefs引用后端Service

第一步:准备镜像 ​

必须先将控制器镜像和业务后端镜像放入集群节点可访问的镜像仓库,或导入各节点的容器运行时,再创建Gateway实例。离线环境中应以交付包内的实际镜像文件和标签为准。

K3s环境可执行以下命令检查和导入镜像:

bash
sudo k3s ctr images list
sudo k3s ctr images import /path/to/n6-k8sagent.tar
sudo k3s ctr images import /path/to/backend-image.tar

控制器Deployment使用的镜像名称必须与已导入镜像完全一致。推荐在离线环境中设置imagePullPolicy: IfNotPresent,并在继续配置前确认控制器Pod和业务后端Pod均为Running:

bash
kubectl get pods -A
kubectl get deployment -A -o wide

如果出现ImagePullBackOff或ErrImagePull,应先修正镜像名称、标签或仓库访问问题,不要继续创建Gateway。

第二步:确认后端Service ​

HTTPRoute引用的是Kubernetes Service,而不是直接引用Pod。创建Route前,确认后端Service已存在、端口正确且拥有可用Endpoint:

bash
kubectl get service -n <业务命名空间>
kubectl get endpoints -n <业务命名空间> <后端Service名称>

后续示例使用命名空间n6-k8s-controller-system和后端Servicebackend-a:80。请替换为实际业务命名空间、Service名称和端口。

第三步:创建GatewayClass、Gateway和Service ​

创建gateway.yaml:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: n6-gateway-class
  labels:
    network.normae.io/managed-by: n6-controller
spec:
  controllerName: normae.io/gateway
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: example-gateway
  namespace: n6-k8s-controller-system
  labels:
    network.normae.io/managed-by: n6-controller
spec:
  gatewayClassName: n6-gateway-class
  listeners:
    - name: http
      protocol: HTTP
      port: 9442
      allowedRoutes:
        namespaces:
          from: All
---
apiVersion: v1
kind: Service
metadata:
  name: example-gateway
  namespace: n6-k8s-controller-system
spec:
  type: NodePort
  selector:
    control-plane: controller-manager
  ports:
    - name: http
      port: 9442
      targetPort: 9442
      nodePort: 30221

应用配置并等待Gateway完成编程:

bash
kubectl apply -f gateway.yaml
kubectl wait -n n6-k8s-controller-system --for=condition=Programmed gateway/example-gateway --timeout=120s
kubectl get gateway -n n6-k8s-controller-system example-gateway
kubectl get service -n n6-k8s-controller-system example-gateway

nodePort必须在集群允许的NodePort范围内且未被占用。Service的selector必须能够选中矩尺Gateway控制器Pod,targetPort必须与Gateway监听端口一致。

第四步:创建HTTPRoute ​

创建route.yaml:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: example-route
  namespace: n6-k8s-controller-system
spec:
  parentRefs:
    - name: example-gateway
      namespace: n6-k8s-controller-system
  rules:
    - matches:
        - path:
            type: Exact
            value: /example
          method: GET
      backendRefs:
        - name: backend-a
          port: 80

应用配置:

bash
kubectl apply -f route.yaml
kubectl get httproute -n n6-k8s-controller-system example-route
kubectl describe httproute -n n6-k8s-controller-system example-route

Route状态中应同时出现Accepted=True和ResolvedRefs=True。如果ResolvedRefs=False,优先检查后端Service名称、命名空间和端口。

第五步:验证转发 ​

使用任一集群Node IP和Service的NodePort发起请求:

bash
curl -i http://<Node-IP>:30221/example

请求应到达backend-a对应的业务Pod。若请求失败,依次检查Gateway状态、Route状态、Service Endpoint、NodePort防火墙和控制器日志。

第六步:在Web界面核验 ​

  1. 进入【Kubernetes-环境配置】,确认目标集群已设为当前环境;
  2. 进入【Kubernetes-Gateway虚拟服务】,点击“查询”,确认example-gateway及其监听器存在;
  3. 进入【Kubernetes-Route分发规则】,点击“查询”,确认example-route绑定到example-gateway且服务器池为backend-a;
  4. 进入【Kubernetes-Service服务器池】,按名称查询example-gateway,确认类型为NodePort且端口映射正确。

通过命令行创建、更新或删除资源后,列表不会自动刷新,应再次点击“查询”。

Gateway列表

更新和删除 ​

修改YAML后再次执行kubectl apply即可更新配置。删除时应先删除Route,再删除Gateway对应的Service和Gateway:

bash
kubectl delete -f route.yaml
kubectl delete service -n n6-k8s-controller-system example-gateway
kubectl delete gateway -n n6-k8s-controller-system example-gateway

GatewayClass通常由多个Gateway共享。只有确认没有其他Gateway引用时,才能删除GatewayClass。建议将共享GatewayClass与业务Gateway分别保存为独立YAML文件,避免删除业务配置时误删共享对象。

常见问题 ​

Gateway没有达到Programmed状态 ​

执行以下命令检查Gateway事件和控制器Pod:

bash
kubectl describe gateway -n n6-k8s-controller-system example-gateway
kubectl get pods -n n6-k8s-controller-system
kubectl logs -n n6-k8s-controller-system <控制器Pod名称> --tail=200

重点检查GatewayClass的controllerName、监听端口、控制器镜像和Pod状态。

控制器出现OOMKilled ​

大量Gateway和Route同时创建时,如果控制器内存上限过低,可能在配置计算期间被OOMKilled。可通过kubectl describe pod确认上次终止原因。应根据资源规模提高控制器Deployment的内存限制,并在Pod重新就绪后重新检查Gateway、Route状态和实际流量。

ClusterIP或NodePort不可达 ​

先检查Service、Endpoint、路由、防火墙和NAT规则:

bash
kubectl get service,endpoints -A
sudo iptables -t nat -L -n
sudo nft -a list table ip raw

在K3s节点上,如果raw表存在针对cni0或lo的异常notrack规则,可能绕过连接跟踪并破坏Service NAT,表现为Kubernetes API ClusterIP超时或NodePort拒绝连接。不要直接照搬规则句柄执行删除;应先备份规则并由网络管理员确认规则来源和影响范围,再移除冲突规则。