pkg/ambex/README.md
Ambassador prior to v0.50.0 worked by writing out Envoy v1 JSON configuration files, then triggering a hot restart of Envoy. This works, but it has some unpleasant limitations:
To get around these limitations, and generally go for a better
experience all 'round, we want to switch to the so-called xDS model,
in which Envoy's configuration is supplied by its various "Discovery
Services": e.g. the CDS is the Cluster Discovery Service; the
EDS is the Endpoint Discovery Service. For Ambassador, the
Aggregated Discovery Service or ADS is the one we want to use --
basically, it brings the other services together under one aegis and
lets you just tell Envoy "get everything dynamically."
However, the whole ADS thing is a bit of a pain:
ADS server.ADS then makes gRPC calls to the Envoy to feed the Envoy
configuration elements, but:ADS has to carefully order things such that the configuration
elements match what Envoy expects for consistency.Rather than do all that logic by hand, we'll use the Envoy
go-control-plane1 for the heavy lifting. This is also something of a
pain, given that it's not well documented, but here's the deal:
The root of the world is a SnapshotCache:
import github.com/datawire/ambassador/pkg/envoy-control-plane/cache,
then refer to cache.SnapshotCache.Snapshot (cache.Snapshot).Snapshots are collected in the SnapshotCache.SnapshotCache can hold configurations for multiple
Envoys, identified by the Envoy nodeID, which must be configured
for the Envoy.The SnapshotCache can only hold go-control-plane configuration
objects, so you have to build these up to hand to the
SnapshotCache.
The gRPC stuff is handled by a Server:
import github.com/datawire/ambassador/pkg/envoy-control-plane/server,
then refer to server.Server.runManagementServer function (largely ripped off from the
go-control-plane tests) gets this running. It takes a
SnapshotCache (cleverly called config for no reason I (Flynn)
understand) and a standard Go gRPCServer as arguments.Server, with the
assistance of the methods in its callback object.Once the Server is running, Envoy can open a gRPC stream to it.
Snapshot
that the Server's SnapshotCache knows about.Snapshot is added to the SnapshotCache, that
Snapshot will get sent to the Envoy.We manage the SnapshotCache by loading Envoy configuration files
on disk:
. (hidden files)*.json files as JSON-encoded protobuf*.pb files as text-encoded protobuf--watch argument we reload whenever any file in
the directory changes. Be careful about updating files
atomically if you use this!You'll need the Go toolchain, and will want to have a functioning envoy.
Then, you can run the ambex CLI using busyambassador:
go run github.com/datawire/ambassador/cmd/busyambassador ambex ARGs...
If you're on a platform other than GNU/Linux, in order to have a
functioning envoy, you may want to run all of this in the builder
shell: make shell.
You'll want to run both ambex and an instance of envoy with a
boostrap config pointing at that `ambex.
First, start the ambex:
go run github.com/datawire/ambassador/cmd/busyambassador ambex ./example/ambex/
or
go run github.com/datawire/ambassador/cmd/busyambassador ambex --watch ./example/ambex/
Second, in another shell, start the envoy:
envoy -l debug -c ./example/envoy/bootstrap-ads.yaml
You should now be able to run some curls in (yet) another shell:
$ curl localhost:8080/hello
Hello ADS!!!
$ curl localhost:8080/get
{
"args": {},
"headers": {
"Accept": "*/*",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "curl/7.54.0",
"X-Envoy-Expected-Rq-Timeout-Ms": "15000"
},
"origin": "72.74.69.156",
"url": "http://httpbin.org/get"
}
Edit and/or add more files to the ./example/ambex/ directory in
order to play with more configurations and see them reload
instantaneously (if you used the --watch flag), or when-triggered
(if you didn't use the --watch flag; trigger a relead by signaling
the process with killall -HUP ambex).
Kill Ambex and Envoy with Ctrl-C.
The Envoy go-control-plane usually refers to
github.com/envoyproxy/go-control-plane, but we've "forked" it
as github.com/datawire/ambassador/pkg/envoy-control-plane in
order to build it against the protobufs for our patched Envoy. ↩