Envoy Proxy使用介绍教程(八):envoy动态配置-聚合发现ADS的使用方法

作者:李佶澳  更新时间:2019-05-07 18:51:21 +0800

  项目    envoy    刷新

目录

说明

这篇笔记比较老,不再更新维护,请移步最新的手册: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: {}

准备支持ADS的Management Server

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

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.ConfigSourcecore.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

使用ADS的EDS

下面的代码中,直接初始化了一个层次很深很深的结构体,故意这样做的,这样子才能一眼看清结构体都包含哪些内容。生产实践时还是更具实际情况进行,不然代码太长、缩进太多了。

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)
}

使用ADS的RDS

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的使用方法

参考

  1. Aggregated Discovery Service
  2. xDS REST and gRPC protocol: Aggregated Discovery Services (ADS)
  3. 一个简单的Management Server实现
  4. go-control-plane
  5. core.ConfigSource
  6. core.AggregatedConfigSource
  7. Envoy Proxy使用介绍教程(七):envoy动态配置xDS的使用方法

站长微信(朋友圈有精华,一般不闲聊)

推荐阅读

Copyright @2011-2019 All rights reserved. 转载请添加原文连接,合作请加微信lijiaocn或者发送邮件: [email protected],备注网站合作

友情链接:  李佶澳的博客  小鸟笔记  软件手册  编程手册  运营手册  爱马影视  网络课程  奇技淫巧  课程文档  精选文章  发现知识星球  百度搜索 谷歌搜索