对于envoy 使用服务器实现动态配置,需要开发相应的响应程序,文档里提到使用 go 语言开发的 control plane 作为服务器,对 xds API 请求动态配置进行响应。相关文章envoy 文档动态配置示例 Dynamic configuration (control plane) 解释
proxy:
build:
context: .
dockerfile: Dockerfile-proxy
depends_on:
- service1
- service2
ports:
- 10000:10000
- 19000:19000
暴露 10000 端口给客户端
暴露 19000 端口作为外界向管理接口发出请求
基础镜像使用 envoyproxy/envoy:v1.23.1
指定容器中初始配置文件位置 /etc/envoy.yaml
FROM envoyproxy/envoy:v1.23.1
COPY ./envoy.yaml /etc/envoy.yaml
RUN chmod go+r /etc/envoy.yaml
CMD ["/usr/local/bin/envoy", "-c /etc/envoy.yaml"]
监听 19000
admin:
address:
socket_address:
address: 0.0.0.0
port_value: 19000
使用动态配置,并指定xds API 获取动态配置请求的服务器 xds_cluster
dynamic_resources:
ads_config:
api_type: GRPC
transport_api_version: V3
grpc_services:
- envoy_grpc:
cluster_name: xds_cluster
cds_config:
resource_api_version: V3
ads: {}
lds_config:
resource_api_version: V3
ads: {}
动态配置服务器的位置地址为 go-control-plane
端口号为 18000
name: xds_cluster
load_assignment:
cluster_name: xds_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: go-control-plane
port_value: 18000
go-control-plane:
build:
context: .
dockerfile: Dockerfile-control-plane
command: bin/example
healthcheck:
test: nc -zv localhost 18000
使用 golang:1.14 作为基础镜像,使用动态配置响应程序https://github.com/envoyproxy/go-control-plane
,该程序监听 18000
。编译前通过修改 resource.go
修改envoy的动态配置
const (
ClusterName = "example_proxy_cluster"
RouteName = "local_route"
ListenerName = "listener_0"
ListenerPort = 10000
UpstreamHost = "service1"
UpstreamPort = 8080
)
该程序编译好后放入镜像中,并在容器创建时运行该程序,用来响应 xds API 对动态配置的请求
FROM golang:1.14
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get -qq update \
&& apt-get -qq install --no-install-recommends -y netcat \
&& apt-get -qq autoremove -y \
&& apt-get clean \
&& rm -rf /tmp/* /var/tmp/* /var/lib/apt/lists/*
RUN git clone https://github.com/envoyproxy/go-control-plane && cd go-control-plane && git checkout b4adc3bb5fe5288bff01cd452dad418ef98c676e
ADD ./resource.go /go/go-control-plane/internal/example/resource.go
RUN cd go-control-plane && make bin/example
WORKDIR /go/go-control-plane
service1:
build:
context: ../shared/echo
hostname: service1
service2:
build:
context: ../shared/echo
hostname: service2
../shared/echo/Dockerfile
里使用 jmalloc/echo-server:0.3.3
作为基础镜像
https://github.com/jmalloc/echo-server
使用 docker-compose up
可以拉取并编译镜像,创建容器。
通过暴露的端口 10000
请求 envoy 前端代理
$ curl http://localhost:10000
Request served by service1
HTTP/1.1 GET /
Host: localhost:10000
Accept: */*
User-Agent: curl/7.61.1
X-Envoy-Expected-Rq-Timeout-Ms: 15000
X-Forwarded-Proto: http
X-Request-Id: 386e43f0-0dee-4db5-b341-f25c3b0c51df
如果配置了多个 endpoints 的话,而且 cluster 使用的轮换的负载均衡策略 round_robin 可以尝试 while sleep 1; do curl -i http://localhost:10000; done
循环请求观察是否按策略切换 endpoint
通过暴露的端口 19000
请求 envoy 前端代理容器里的管理接口
$ curl -s http://localhost:19000/config_dump | jq '.configs[1].dynamic_active_clusters[0].cluster.load_assignment.endpoints[0].lb_endpoints[0].endpoint.address.socket_address'
{
"address": "service1",
"port_value": 8080
}
由于这里将配置固定在 control plane 程序里了。这里通过重新编译 resource.go
然后重新创建 go-control-plane
所在容器的方式实现配置的变化。不需要重启前端代理 envoy
resource.go
const (
ClusterName = "example_proxy_cluster"
RouteName = "local_route"
ListenerName = "listener_0"
ListenerPort = 10000
UpstreamHost = "service2"
UpstreamPort = 8080
)
$ curl -s http://localhost:19000/config_dump | jq '.configs[1].dynamic_active_clusters[0].cluster.load_assignment.endpoints[0].lb_endpoints[0].endpoint.address.socket_address'
{
"address": "service2",
"port_value": 8080
}
$ curl http://localhost:10000
Request served by service2
HTTP/1.1 GET /
Host: localhost:10000
Accept: */*
User-Agent: curl/7.61.1
X-Envoy-Expected-Rq-Timeout-Ms: 15000
X-Forwarded-Proto: http
X-Request-Id: 7f2d1344-be24-4301-ae7d-f8c376ad1e13
Dynamic configuration (control plane) Official DOC
dynamic-config-cp Github
go-control-plane on pkg.go.dev
example#dynamic Official DOC