envoy control-plane を調べていた。control-plane から data-plane に接続するのかと思い込んでいたがそうではなかった。
今の解釈はこんな感じ
- envoy(data-plane)は Endpoint Discovery Service(EDS) 等のxDSの利用する側。クライアント
- control-plane は xDS を提供する側。サーバー
- envoy は control-plane から配信された情報から、自分の設定を更新していく
- envoy が参照すべき xDS のエンドポイントを envoy.yaml に設定しておく
という解釈ができるようになってから envoy.yaml を眺めると前より理解しやすくなった。
今回のコードはここに置きました。 envoyprac/prac1 at master · tjtjtj/envoyprac · GitHub
実験の流れ
ここを参考(ほとんどコピーですが)にさせていただきました。 感謝感謝
- helloを起動
- envoy 起動
- このときenvoyはhelloを知らない。 EDSのエンドポイントは知っている
- curl しても失敗するはず
- control-plane 起動
- envoy が control-plane(EDS) に接続
- control-plane がエンドポイントを配信
- curl するとhelloを参照するはず
実験
helloを起動
docker run --rm -d -p 8080:80 dockercloud/hello-world
直接 curl
# curl http://localhost:8080
<h3>My hostname is 9c2075e4f35a</h3> </body>
/tmp/envoy/envoy.yaml
node:
id: node0
cluster: cluster.local
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 80 }
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
stat_prefix: ingress_http
route_config:
name: route
virtual_hosts:
- name: hello_service
domains: ["hello.local"]
routes:
- match: { prefix: "/" }
route: { cluster: hello_cluster }
http_filters:
- name: envoy.router
clusters:
- name: hello_cluster
connect_timeout: 0.25s
lb_policy: ROUND_ROBIN
type: EDS
eds_cluster_config:
eds_config:
api_config_source:
api_type: GRPC
grpc_services:
envoy_grpc:
cluster_name: xds_cluster
- name: xds_cluster
connect_timeout: 0.25s
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
load_assignment:
cluster_name: xds_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: {address: 127.0.0.1, port_value: 20000 }
envoy 起動
# docker run \
--name envoy --rm --publish 80:80 \
--net=host \
-v /tmp/envoy:/etc/envoy \
envoyproxy/envoy:v1.10.0
最初の curl は失敗
# curl -H 'Host: hello.local' 127.0.0.1 no healthy upstream
prac1.go
package main
import (
"flag"
"fmt"
"log"
"net"
"os"
api "github.com/envoyproxy/go-control-plane/envoy/api/v2"
core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
"github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint"
"github.com/envoyproxy/go-control-plane/pkg/cache"
xds "github.com/envoyproxy/go-control-plane/pkg/server"
"google.golang.org/grpc"
)
// NodeHash interfaceの実装。Envoyの識別子から文字列をかえすハッシュ関数を実装する。
type hash struct{}
func (hash) ID(node *core.Node) string {
if node == nil {
return "unknown"
}
return node.Cluster + "/" + node.Id
}
var upstreams = map[string][]struct {
Address string
Port uint32
}{
// ここはコンテナのアドレス
"hello_cluster": {{"127.0.0.1", 8080}},
}
// スナップショットを返す。構造体の形はProtocol Bufferの定義と同じ。
func defaultSnapshot() cache.Snapshot {
var resources []cache.Resource
for cluster, ups := range upstreams {
eps := make([]endpoint.LocalityLbEndpoints, len(ups))
for i, up := range ups {
eps[i] = endpoint.LocalityLbEndpoints{
LbEndpoints: []endpoint.LbEndpoint{{
HostIdentifier: &endpoint.LbEndpoint_Endpoint {
Endpoint: &endpoint.Endpoint{
Address: &core.Address{
Address: &core.Address_SocketAddress{
SocketAddress: &core.SocketAddress{
Address: up.Address,
PortSpecifier: &core.SocketAddress_PortValue{PortValue: up.Port},
},
},
},
},
},
}},
}
}
assignment := &api.ClusterLoadAssignment{
ClusterName: cluster,
Endpoints: eps,
}
resources = append(resources, assignment)
}
return cache.NewSnapshot("0.0", resources, nil, nil, nil)
}
func run(listen string) error {
// xDSの結果をキャッシュとして設定すると、いい感じにxDS APIとして返してくれる。
snapshotCache := cache.NewSnapshotCache(false, hash{}, nil)
server := xds.NewServer(snapshotCache, nil)
// NodeHashで返ってくるハッシュ値とその設定のスナップショットをキャッシュとして覚える
err := snapshotCache.SetSnapshot("cluster.local/node0", defaultSnapshot())
if err != nil {
return err
}
// gRCPサーバーを起動してAPIを提供
grpcServer := grpc.NewServer()
api.RegisterEndpointDiscoveryServiceServer(grpcServer, server)
lsn, err := net.Listen("tcp", listen)
if err != nil {
return err
}
return grpcServer.Serve(lsn)
}
func main() {
var listen string
flag.StringVar(&listen, "listen", ":20000", "listen port")
flag.Parse()
log.Printf("Starting server with -listen=%s", listen)
err := run(listen)
if err != nil {
fmt.Println(os.Stderr, err)
os.Exit(1)
}
}
prac1.go(controle-plane) 起動後の curl は成功した。
# curl -H 'Host: hello.local' 127.0.0.1
<h3>My hostname is 9c2075e4f35a</h3> </body>
あーenvoy の stats の変化も確認するんだった。次回やる。