在上一篇文章中,我们探讨了如何利用Envoy实现负载均衡,并着重解决了获取真实后端Pod IP地址的问题,其方案是借助K8s的Headless Service,既利用了其服务发现能力,又规避了其自带的负载均衡。
然而,在一些特殊场景下,例如混合云部署中要求两端云拥有相同服务但禁止跨云访问,我们可能需要完全脱离K8s Service。此时,如何为Envoy赋予服务发现的能力呢?本文将介绍两种基础方法:静态配置与基于DNS的动态发现。
静态配置服务发现
这种方式最为直接,即将后端服务的地址明文写入Envoy的配置文件中。
static_resources:
clusters:
- name: backend_cluster
connect_timeout: 0.25s
type: STATIC
load_assignment:
cluster_name: backend_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 192.168.1.100
port_value: 8080
- endpoint:
address:
socket_address:
address: 192.168.1.101
port_value: 8080
其中,type: STATIC 是标识此为静态集群的关键配置。
基于DNS的服务发现
我们之前利用的K8s服务发现,本质上也是通过K8s DNS实现的。这里我们以常用的第三方注册中心Consul为例,演示如何构建基于DNS的服务发现体系,这是在复杂云原生/IaaS架构中整合异构系统的一种常见方式。
1. 安装Consul
使用Docker快速启动一个Consul服务节点:
docker run -d --name consul \
-p 8300-8302:8300-8302 \
-p 8500:8500 \
-p 8301-8302 \
-p 8600:8600/udp \
hashicorp/consul:1.22
注意,映射UDP端口8600至关重要,因为Consul的DNS服务默认通过此端口提供查询。
2. 配置CoreDNS转发
为了让K8s集群内的Pod能够解析Consul中注册的服务,需要修改CoreDNS的配置,将特定的域名查询转发到Consul的DNS服务。
kubectl -n kube-system edit cm coredns
在CoreDNS的Corefile配置中添加转发规则:
...
forward consul 10.22.12.178:8600 {
prefer_udp
}
...
此配置表示,所有对 .consul 后缀域名的解析请求,都将被转发到IP为10.22.12.178、端口为8600的Consul DNS服务。采用*.consul这种泛域名转发规则简单有效,因为Consul官方定义的服务发现域名格式就是 服务名.service.consul。
3. 向Consul注册服务
通过Consul的HTTP API注册一个服务实例:
curl -X PUT http://10.22.12.178:8500/v1/agent/service/register \
-H "Content-Type: application/json" \
-d '{
"Name": "backend-service-consul",
"ID": "service-1",
"Address": "10.244.0.82",
"Port": 10000
}'
这里注册了一个名为backend-service-consul,地址为10.244.0.82:10000的服务。
4. 配置Envoy使用Consul DNS
修改Envoy的集群配置,使其通过DNS解析来发现后端服务:
clusters:
- name: app_service
connect_timeout: 1s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: app_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: "backend-service-consul.service.consul"
port_value: 10000
配置完成后重启Envoy以生效。关键点在于address: "backend-service-consul.service.consul":
backend-service-consul 是我们在Consul中注册的服务名称。
.service.consul 是Consul规定的服务发现域名固定后缀。
5. 验证效果
通过访问Envoy的监听端口进行测试,观察日志输出:
[2025-12-18T09:42:47.296Z] "GET /test HTTP/1.0" 200 40 1 fd326a0e-ec4f-4cf3-a244-b29f4c0c0173 "curl/7.81.0" "-" 10.244.0.82:10000 app_service -
日志中显示请求被正确代理到了 10.244.0.82:10000,证明基于Consul DNS的服务发现已成功生效。
Consul方案小结
无论是使用K8s Headless Service还是Consul,其核心都是基于DNS的服务发现模式。在Consul的示例中,我们通过配置运维/DevOps层面的CoreDNS,将特定域名的解析指向Consul,从而实现了服务地址的动态获取。
总结与思考
本文介绍了为Envoy配置静态服务发现和基于DNS(Consul)动态服务发现两种方法。然而,这两种方式都存在一个共同缺点:当后端服务地址(如域名或端口)发生变化时,必须修改Envoy配置并重启进程才能生效。这无疑增加了系统的复杂性和运维风险。
那么,是否存在一种能够实现配置自动热加载的更优雅方案呢?答案是肯定的,这将是下一篇关于云原生/IaaS服务网格或xDS动态配置协议文章将要探讨的主题。