Envoy實現.NET架構的閘道器(二)基於控制平面的動態配置

chester·chen發表於2021-10-30

什麼是控制皮膚

這篇我們來看看如何通過控制平面(Control Panel)來配置Envoy。

控制平面就是一個提供Envoy配置資訊的單獨服務,Envoy可以通過呼叫這個服務的api來載入配置。

配置控制皮膚

官方為我們提供了兩種已經實現好的控制皮膚。

go控制皮膚:https://github.com/envoyproxy/go-control-plane

java控制皮膚:https://github.com/envoyproxy/java-control-plane

我們下載官方的go語言控制皮膚,先來看看go控制皮膚中提供的樣例結構。

其中有三個核心檔案,main.go,server.go,與resource.go

1.main.go:啟動go-controll-panel的入口

2.server.go:定義go-controll-panel的grpc服務

3.resource.go:定義了envoy相關的資源配置,包括cluster,listener,endpoint等

其中resource.go組成了一個結構化的配置資訊,並通過server.go中的grpc提供給envoy,而main.go則是啟動了grpc,因此我們需要修改的就是resource.go中的資源配置,需要將裡面的cluster,listener,endpoint等設定為我們自己的服務資訊。下面我們就來將resource.go中的配置資訊改成我們自己的測試專案配置。

首先修改upstream資訊,指定我們的上游服務的ip與兩個上游服務的埠

const (
    ClusterName   = "example_proxy_cluster"
    RouteName     = "local_route"
    ListenerName  = "listener_0"
    ListenerPort  = 10000
    UpstreamHost  = "192.168.43.94"
    UpstreamPort  = 5000
    UpstreamPort2 = 5001
)

然後我們修改dns型別,將其修改為靜態dns解析

func makeCluster(clusterName string) *cluster.Cluster {
    return &cluster.Cluster{
        Name:                 clusterName,
        ConnectTimeout:       ptypes.DurationProto(5 * time.Second),
        ClusterDiscoveryType: &cluster.Cluster_Type{Type: cluster.Cluster_STATIC},
        LbPolicy:             cluster.Cluster_ROUND_ROBIN,
        LoadAssignment:       makeEndpoint(clusterName),
        DnsLookupFamily:      cluster.Cluster_V4_ONLY,
    }
}

修改makeEndpoint方法,指定兩個測試server,server1與server2的地址為Endpoint

func makeEndpoint(clusterName string) *endpoint.ClusterLoadAssignment {
    return &endpoint.ClusterLoadAssignment{
        ClusterName: clusterName,
        Endpoints: []*endpoint.LocalityLbEndpoints{{
            LbEndpoints: []*endpoint.LbEndpoint{{
                HostIdentifier: &endpoint.LbEndpoint_Endpoint{
                    Endpoint: &endpoint.Endpoint{
                        Address: &core.Address{
                            Address: &core.Address_SocketAddress{
                                SocketAddress: &core.SocketAddress{
                                    Protocol: core.SocketAddress_TCP,
                                    Address:  UpstreamHost,
                                    PortSpecifier: &core.SocketAddress_PortValue{
                                        PortValue: UpstreamPort,
                                    },
                                },
                            },
                        },
                    },
                },
            },
                {
                    HostIdentifier: &endpoint.LbEndpoint_Endpoint{
                        Endpoint: &endpoint.Endpoint{
                            Address: &core.Address{
                                Address: &core.Address_SocketAddress{
                                    SocketAddress: &core.SocketAddress{
                                        Protocol: core.SocketAddress_TCP,
                                        Address:  UpstreamHost,
                                        PortSpecifier: &core.SocketAddress_PortValue{
                                            PortValue: UpstreamPort2,
                                        },
                                    },
                                },
                            },
                        },
                    },
                },
            },
        }},
    }
}

啟動控制平面

 

 控制平面監聽在18000埠

配置Envoy

我們需要配置Envoy.yaml讓Envoy從控制平面中獲取詳細的配置資訊。我們可以參考官網的推薦配置。

1.需要在dynamic_resources中配置ads_config,並讓cds_config與lds_config從中讀取

2.另外我們需要配置xds cluster,讓Envoy知道控制平面的地址。

具體配置資訊如下:

admin:
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9902
      
node:
  cluster: test-cluster
  id: test-id

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: {}

static_resources:
  clusters:
  - type: STRICT_DNS
    typed_extension_protocol_options:
      envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
        "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
        explicit_http_config:
          http2_protocol_options: {}
    name: xds_cluster
    load_assignment:
      cluster_name: xds_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 192.168.43.94
                port_value: 18000

執行Envoy

我們通過docker執行Envoy

docker run --rm -it -p 9902:9902 -p 10000:10000 -v D:/gateway/envoy/config/dynamic-plane/:/etc/envoy/ -v D:/gateway/envoy/logs:/logs envoyproxy/envoy-dev  -c /etc/envoy/envoy.yaml

然後啟動我們上一節的server1與server2

測試

 我們通過http://localhost:10000/Name來判斷我們的配置是不是配置成功

可以看到其中一次呼叫返回了server1,另一次呼叫返回了server2,控制皮膚驗證成功!

二次開發

目前的樣例程式碼中提供的配置都是硬編碼的方式,把配置寫死在程式碼中,如果生產環境中我們想使用這種方式來配置envoy,我們可以基於現在的程式碼二次開發。開發的步驟如下:

1.新增資料庫表結構組織Envoy中的資源,比如Listener表,Cluster表,Endpoint表,Route表

2.新增介面來對Listener,Cluster,Endpoint,Route等資源進行增刪改查

3.新增UI來呼叫增刪改查介面,對資源進行管理

4.定時重新整理Snapshot資訊

 這樣我們就可以實現一個視覺化的介面來動態的配置我們的Envoy。

相關文章