A lightweight Envoy xDS control plane with REST API support to dynamically manage clusters and routes. Implemented in Go using Envoy Go Control Plane v3.

data refactor the database middle layer to better orgranize the sql types 3 months ago
internal fix storage dump 3 months ago
static refactor the database middle layer to better orgranize the sql types 3 months ago
test add secret manipluation 4 months ago
.gitignore support adding resources 4 months ago
Dockerfile fix deployment issue 4 months ago
Makefile add allow upsert flag 3 months ago
README.md inital commit 4 months ago
build_image.sh add secret manipluation 4 months ago
docker-compose.yml fix storage dump 3 months ago
envoy.yaml add rotation init code 4 months ago
go.mod refactor code 4 months ago
go.sum refactor code 4 months ago
main.go refactor code 4 months ago
save.json Add database persistence and consistency check between in-memory cache and DB. 4 months ago
README.md

Envoy Control Plane

A lightweight Envoy xDS control plane with REST API support to dynamically manage clusters and routes. Implemented in Go using Envoy Go Control Plane v3.


Features

  • Dynamic xDS snapshot management (clusters & routes)
  • REST API to:
    • Add/remove clusters
    • Add/remove routes
    • Load/save snapshot to JSON files
  • Optional initial snapshot from file at startup
  • Runs an xDS gRPC server compatible with Envoy
  • Fully compatible with types.Resource and Envoy v3 snapshot APIs

Prerequisites

  • Go 1.21+
  • Envoy 1.30+ (or compatible)
  • Ensure GOPATH is set and dependencies are downloaded via go mod tidy

Project Structure

├── internal
│   ├── snapshot.go      # SnapshotManager for clusters/routes
│   ├── rest_api.go      # REST API for managing snapshots
│   └── ...              # other helpers
├── main.go              # Main entry: starts gRPC + REST servers
├── go.mod
└── go.sum

Build

# Clone repo
git clone <repo-url>
cd envoy-control-plane

# Download dependencies
go mod tidy

# Build binary
make all

Binary will be located at bin/xds-server.


Run

./bin/xds-server \
    -port=18000 \
    -rest-port=8080 \
    -nodeID=test-node \
    -snapshot-file=snapshot.json

Flags

Flag Description Default
-port xDS gRPC server port 18000
-rest-port REST API port 8080
-nodeID Node ID for snapshot test-id
-snapshot-file Optional JSON file to load initial snapshot ""

REST API

The REST server allows dynamic control over clusters and routes.

Add Cluster

POST /add-cluster

{
  "name": "cluster1"
}

Response:

{
  "cuid": "cluster1"
}

Remove Cluster

POST /remove-cluster

{
  "name": "cluster1"
}

Response: 200 OK


Add Route

POST /add-route

{
  "name": "route1",
  "cluster": "cluster1",
  "path_prefix": "/api"
}

Response:

{
  "route": "route1"
}

Remove Route

POST /remove-route

{
  "name": "route1"
}

Response: 200 OK


Load Snapshot From File

POST /load-snapshot

{
  "path": "snapshot.json"
}

Response: 200 OK


Save Snapshot To File

POST /save-snapshot

{
  "path": "snapshot.json"
}

Response: 200 OK


Snapshot JSON Format

{
  "envoy.config.cluster.v3.Cluster": [
    {
      "name": "cluster1",
      "connect_timeout": "5s",
      "lb_policy": "ROUND_ROBIN",
      "cluster_discovery_type": { "type": "EDS" }
    }
  ],
  "envoy.config.route.v3.RouteConfiguration": [
    {
      "name": "route1",
      "virtual_hosts": [
        {
          "name": "vh-route1",
          "domains": ["*"],
          "routes": [
            {
              "match": { "prefix": "/api" },
              "route": { "cluster": "cluster1" }
            }
          ]
        }
      ]
    }
  ]
}

Each top-level key is the full type URL of the resource. Clusters and routes can be added dynamically via REST or preloaded from a snapshot JSON file.


Connecting Envoy

Configure Envoy with:

dynamic_resources:
  ads_config:
    api_type: GRPC
    grpc_services:
      - envoy_grpc:
          cluster_name: xds_cluster
  cds_config: {}
  lds_config: {}
  • Set xds_cluster to point to your control plane gRPC server (e.g., localhost:18000)
  • Envoy will pull clusters and routes dynamically

License

Apache 2.0 License