这篇笔记比较老,不再更新维护,请移步最新的手册:envoy相关笔记。
Aggregated Discovery Service中简单介绍了ADS,简单说就是:CDS/EDS/RDS等动态配置的Managerment Server可以是同一个ADS。xDS REST and gRPC protocol: Aggregated Discovery Services (ADS)给出了一个例子:
node:
id: <node identifier>
dynamic_resources:
cds_config: {ads: {}}
lds_config: {ads: {}}
ads_config:
api_type: GRPC
grpc_services:
envoy_grpc:
cluster_name: ads_cluster
static_resources:
clusters:
- name: ads_cluster
connect_timeout: { seconds: 5 }
type: STATIC
hosts:
- socket_address:
address: <ADS management server IP address>
port_value: <ADS management server port>
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
go-control-plane提供了ADS API,一个简单的Management Server实现中的Management Server用go-control-plane提供的API实现了ADS,如下:
func main() {
snapshotCache := cache.NewSnapshotCache(false, NodeConfig{}, nil)
server := xds.NewServer(snapshotCache, nil)
grpcServer := grpc.NewServer()
lis, _ := net.Listen("tcp", ":5678")
//ADS
discovery.RegisterAggregatedDiscoveryServiceServer(grpcServer, server)
...
完整代码这里不贴了,可以到一个简单的Management Server实现中查看。
ADS在dynamic_resources
中配置,可以指向static_resources
中的一个cluster,这也是推荐的做法。
static_resources中配置的cluster(Management Server地址):
static_resources:
clusters:
- name: ads_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
load_assignment:
cluster_name: ads_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 5678
dynamic_resources
中的配置的ads_config:
dynamic_resources:
ads_config:
api_type: GRPC
grpc_services:
envoy_grpc:
cluster_name: ads_cluster
然后将dynamic_resources中的cds_config和lds_config指向ads:
dynamic_resources:
cds_config: {ads: {}}
lds_config: {ads: {}}
注意,在1.8.0和1.9.0版本中(更早的版本没有查看),cds_config和lds_config中的ads都是一个空的结构体
,在core.ConfigSource和core.AggregatedConfigSource中可以看到:
{
"path": "...",
"api_config_source": "{...}",
"ads": "{...}"
}
Aggregated Discovery Service (ADS) options. This is currently empty, but when set in ConfigSource can be used to specify that ADS is to be used.
另外,Cluster中的EDS和LDS中的RDS,既可以使用其它的Mangement Server,也可以使用ADS(配置成{ads: {}}
)。将所有的动态配置都设置为ADS,似乎是一个好的做法。
最终相关配置如下:
dynamic_resources:
ads_config:
api_type: GRPC
grpc_services:
envoy_grpc:
cluster_name: ads_cluster
cds_config: {ads: {}}
lds_config: {ads: {}}
static_resources:
clusters:
- name: ads_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
load_assignment:
cluster_name: ads_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 5678
下面的代码中,直接初始化了一个层次很深很深的结构体,故意这样做的,这样子才能一眼看清结构体都包含哪些内容。生产实践时还是更具实际情况进行,不然代码太长、缩进太多了。
func ADD_Cluster_With_ADS_Endpoint(n *NodeConfig) {
endpoint := &api.ClusterLoadAssignment{
ClusterName: "ads_endpoint",
Endpoints: []endpoint.LocalityLbEndpoints{
endpoint.LocalityLbEndpoints{
LbEndpoints: []endpoint.LbEndpoint{
endpoint.LbEndpoint{
Endpoint: &endpoint.Endpoint{
Address: &core.Address{
Address: &core.Address_SocketAddress{
SocketAddress: &core.SocketAddress{
Protocol: core.TCP,
Address: "192.16.129.26",
PortSpecifier: &core.SocketAddress_PortValue{
PortValue: 80,
},
},
},
},
},
},
},
},
},
Policy: &api.ClusterLoadAssignment_Policy{
DropOverloads: []*api.ClusterLoadAssignment_Policy_DropOverload{
&api.ClusterLoadAssignment_Policy_DropOverload{
Category: "drop_policy1",
DropPercentage: &envoy_type.FractionalPercent{
Numerator: 3,
Denominator: envoy_type.FractionalPercent_HUNDRED,
},
},
},
OverprovisioningFactor: &proto_type.UInt32Value{
Value: 140,
},
},
}
cluster := &api.Cluster{
Name: "cluster_with_ads_endpoint",
ConnectTimeout: 1 * time.Second,
Type: api.Cluster_EDS,
LbPolicy: api.Cluster_ROUND_ROBIN,
EdsClusterConfig: &api.Cluster_EdsClusterConfig{
EdsConfig: &core.ConfigSource{
ConfigSourceSpecifier: &core.ConfigSource_Ads{
Ads: &core.AggregatedConfigSource{}, //使用ADS
},
},
ServiceName: "ads_endpoint", //与endpoint中的ClusterName对应。
},
}
n.endpoints = append(n.endpoints, endpoint)
n.clusters = append(n.clusters, cluster)
}
func ADD_Listener_With_ADS_Route(n *NodeConfig) {
route := &api.RouteConfiguration{
Name: "ads_route",
VirtualHosts: []route.VirtualHost{
route.VirtualHost{
Name: "local",
Domains: []string{
"ads.webshell.com",
},
Routes: []route.Route{
route.Route{
Match: route.RouteMatch{
PathSpecifier: &route.RouteMatch_Prefix{
Prefix: "/",
},
CaseSensitive: &proto_type.BoolValue{
Value: false,
},
},
Action: &route.Route_Route{
Route: &route.RouteAction{
ClusterSpecifier: &route.RouteAction_Cluster{
Cluster: "cluster_with_ads_endpoint",
},
HostRewriteSpecifier: &route.RouteAction_HostRewrite{
HostRewrite: "webshell.com",
},
},
},
},
},
},
},
}
http_filter_router_ := &http_router.Router{
DynamicStats: &proto_type.BoolValue{
Value: true,
},
}
http_filter_router, err := util.MessageToStruct(http_filter_router_)
if err != nil {
glog.Error(err)
return
}
listen_filter_http_conn_ := &http_conn_manager.HttpConnectionManager{
StatPrefix: "ingress_http",
RouteSpecifier: &http_conn_manager.HttpConnectionManager_Rds{
Rds: &http_conn_manager.Rds{
RouteConfigName: "ads_route",
ConfigSource: core.ConfigSource{
ConfigSourceSpecifier: &core.ConfigSource_Ads{
Ads: &core.AggregatedConfigSource{}, //使用ADS
},
},
},
},
HttpFilters: []*http_conn_manager.HttpFilter{
&http_conn_manager.HttpFilter{
Name: "envoy.router",
ConfigType: &http_conn_manager.HttpFilter_Config{
Config: http_filter_router,
},
},
},
}
listen_filter_http_conn, err := util.MessageToStruct(listen_filter_http_conn_)
if err != nil {
glog.Error(err)
return
}
listener := &api.Listener{
Name: "listener_with_dynamic_route_port_9002",
Address: core.Address{
Address: &core.Address_SocketAddress{
SocketAddress: &core.SocketAddress{
Protocol: core.TCP,
Address: "0.0.0.0",
PortSpecifier: &core.SocketAddress_PortValue{
PortValue: 9002,
},
},
},
},
FilterChains: []listener.FilterChain{
listener.FilterChain{
Filters: []listener.Filter{
listener.Filter{
Name: "envoy.http_connection_manager",
ConfigType: &listener.Filter_Config{
Config: listen_filter_http_conn,
},
},
},
},
},
}
n.listeners = append(n.listeners, listener)
n.routes = append(n.routes, route)
}
这里记录的比较简单,如果对Envoy动态配置不了解,建议参阅Envoy Proxy使用介绍教程(七):envoy动态配置xDS的使用方法。