无服务注册中心时,Spring Cloud Gateway在K8s中路由至指定服务
在Kubernetes环境中用Spring Cloud Gateway实现无注册中心的服务路由
针对你升级Spring Cloud Gateway后遇到的服务路由问题,结合你的技术栈版本(Spring Boot 3.3.2、Spring Cloud 2023.0.3、Spring Cloud Kubernetes 1.1.10.RELEASE),可以通过以下步骤解决:
一、调整依赖配置
需确保引入Kubernetes服务发现与负载均衡的适配依赖,这是实现lb://serviceId路由的核心:
Maven依赖(pom.xml)
<dependencies> <!-- Spring Cloud Gateway核心 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- Spring Cloud LoadBalancer核心 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> <!-- Kubernetes服务发现 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-discovery</artifactId> </dependency> <!-- LoadBalancer与Kubernetes发现的适配 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-loadbalancer</artifactId> </dependency> </dependencies>
Gradle依赖(build.gradle)
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-gateway' implementation 'org.springframework.cloud:spring-cloud-starter-loadbalancer' implementation 'org.springframework.cloud:spring-cloud-starter-kubernetes-discovery' implementation 'org.springframework.cloud:spring-cloud-starter-kubernetes-loadbalancer' }
二、修正配置文件
调整application.yaml,启用Kubernetes服务发现与负载均衡适配,解决discovery-server-url报错及服务实例找不到的问题:
spring: cloud: # Gateway路由配置 gateway: routes: - id: your-service-route # 使用lb://+K8s Service名称作为路由目标 uri: lb://your-service-id predicates: - Path=/your-service/** # Kubernetes服务发现配置 kubernetes: discovery: enabled: true # 仅发现带有指定标签的K8s Service(和原Zuul配置一致) service-labels: discovery: enabled # 集群内部运行时无需手动指定discovery-server-url,会自动调用K8s内部API # 若在外部环境测试,可添加:discovery-server-url: https://kubernetes.default.svc:443 # 启用Kubernetes适配的LoadBalancer loadbalancer: enabled: true kubernetes: enabled: true # 禁用自动注册到外部服务注册中心(和原Zuul配置一致) service-registry: auto-registration: enabled: false
关键说明:
- 之前启动报错
需指定discovery-server-url,是因为缺少spring-cloud-starter-kubernetes-loadbalancer依赖,导致Kubernetes发现组件无法自动适配集群内部API地址; - 启用
spring.cloud.kubernetes.loadbalancer.enabled后,LoadBalancer会通过Kubernetes API获取Service的Endpoints,实现客户端侧负载均衡。
三、验证ServiceAccount权限
确保网关Pod绑定的ServiceAccount具备访问Kubernetes服务、端点的权限,创建RBAC规则:
# 定义ClusterRole,授予服务发现所需权限 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: gateway-discovery-role rules: - apiGroups: [""] resources: ["services", "endpoints", "pods"] verbs: ["get", "list", "watch"] --- # 绑定ClusterRole到网关的ServiceAccount apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-discovery-binding subjects: - kind: ServiceAccount name: gateway-sa namespace: your-namespace # 替换为网关所在命名空间 roleRef: kind: ClusterRole name: gateway-discovery-role apiGroup: rbac.authorization.k8s.io
在网关的Deployment中指定ServiceAccount:
spec: serviceAccountName: gateway-sa
四、测试路由
启动网关Pod后,可通过以下方式验证:
- 查看网关日志,确认是否成功获取到目标Service的Endpoints;
- 发送测试请求:
curl http://<gateway-ip>/your-service/<api-path>,检查是否能正确转发到目标服务。
补充:服务自动注册配置
若需实现服务自动注册到Kubernetes(替代外部注册中心),可添加以下配置:
spring: cloud: kubernetes: registration: enabled: true # 自定义注册的Service名称(可选,默认用spring.application.name) service-name: your-gateway-service # 暴露的端口 ports: - name: http port: 8080 target-port: 8080
内容的提问来源于stack exchange,提问作者Istvan Kiss




