Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flag to run a dummy xDS server and envoy-sidecar configurer #222

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ on:
env:
REGISTRY: quay.io
IMAGE_NAME: ${{ github.repository }}
IMAGE_NAME_ENVOY_CONFIGURER: ${{ github.repository }}/envoy-sidecar/configurer

jobs:
docker:
Expand Down Expand Up @@ -44,3 +45,16 @@ jobs:
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Extract envoy/configurer metadata (tags, labels) for Docker
id: meta-envoy-configurer
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_ENVOY_CONFIGURER }}
- name: Build and push Docker image for envoy configurer
if: github.actor != 'dependabot[bot]'
uses: docker/build-push-action@v5
with:
context: ./envoy-sidecar/configurer
push: true
tags: ${{ steps.meta-envoy-configurer.outputs.tags }}
labels: ${{ steps.meta-envoy-configurer.outputs.labels }}
54 changes: 27 additions & 27 deletions controller/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestReconcileServices_LabelledService(t *testing.T) {
"./test-resources/labelled_service.yaml",
"./test-resources/endpointslice.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
client,
[]kube.Client{},
Expand All @@ -60,7 +60,7 @@ func TestReconcileServices_LabelledService(t *testing.T) {
}
assert.Equal(t, 1, len(snap.GetResources(resource.ListenerType)))
assert.Equal(t, 1, len(snap.GetResources(resource.ClusterType)))
assert.Equal(t, 1, len(snap.GetResources(resource.RouteType)))
assert.Equal(t, 2, len(snap.GetResources(resource.RouteType))) // Includes all_kube_routes
// Verify the default round robin policy is set on the clusters
for _, cl := range snap.GetResources(resource.ClusterType) {
cluster, err := xds.UnmarshalResourceToCluster(cl)
Expand All @@ -82,7 +82,7 @@ func TestReconcileServices_LabelledServiceLbPolicy(t *testing.T) {
"./test-resources/labelled_service_ring_hash_balancer.yaml",
"./test-resources/endpointslice.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
client,
[]kube.Client{},
Expand All @@ -103,7 +103,7 @@ func TestReconcileServices_LabelledServiceLbPolicy(t *testing.T) {
}
assert.Equal(t, 1, len(snap.GetResources(resource.ListenerType)))
assert.Equal(t, 1, len(snap.GetResources(resource.ClusterType)))
assert.Equal(t, 1, len(snap.GetResources(resource.RouteType)))
assert.Equal(t, 2, len(snap.GetResources(resource.RouteType))) // Includes all_kube_routes
// Verify the correct lb policy (ring hash) is set on the clusters
for _, cl := range snap.GetResources(resource.ClusterType) {
cluster, err := xds.UnmarshalResourceToCluster(cl)
Expand All @@ -119,7 +119,7 @@ func TestReconcileServices_LabelledServiceInvalidLbPolicy(t *testing.T) {
"./test-resources/labelled_service_invalid_balancer.yaml",
"./test-resources/endpointslice.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
client,
[]kube.Client{},
Expand All @@ -140,7 +140,7 @@ func TestReconcileServices_LabelledServiceInvalidLbPolicy(t *testing.T) {
}
assert.Equal(t, 1, len(snap.GetResources(resource.ListenerType)))
assert.Equal(t, 1, len(snap.GetResources(resource.ClusterType)))
assert.Equal(t, 1, len(snap.GetResources(resource.RouteType)))
assert.Equal(t, 2, len(snap.GetResources(resource.RouteType))) // Includes all_kube_routes
// Verify the default round robin policy is set on the clusters
for _, cl := range snap.GetResources(resource.ClusterType) {
cluster, err := xds.UnmarshalResourceToCluster(cl)
Expand All @@ -156,7 +156,7 @@ func TestReconcileServices_XdsService(t *testing.T) {
"./test-resources/xds_service.yaml",
"./test-resources/endpointslice.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
client,
[]kube.Client{},
Expand All @@ -177,7 +177,7 @@ func TestReconcileServices_XdsService(t *testing.T) {
}
assert.Equal(t, 1, len(snap.GetResources(resource.ListenerType)))
assert.Equal(t, 1, len(snap.GetResources(resource.ClusterType)))
assert.Equal(t, 1, len(snap.GetResources(resource.RouteType)))
assert.Equal(t, 2, len(snap.GetResources(resource.RouteType))) // Includes all_kube_routes
// Verify the default round robin policy is set on the clusters
for _, cl := range snap.GetResources(resource.ClusterType) {
cluster, err := xds.UnmarshalResourceToCluster(cl)
Expand All @@ -199,7 +199,7 @@ func TestReconcileServices_XdsServiceNotExistent(t *testing.T) {
"./test-resources/xds_service_not_existent.yaml",
"./test-resources/endpointslice.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
client,
[]kube.Client{},
Expand Down Expand Up @@ -233,7 +233,7 @@ func TestReconcileServices_XdsServiceDelete(t *testing.T) {
"./test-resources/xds_service.yaml",
"./test-resources/endpointslice.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
client,
[]kube.Client{},
Expand All @@ -254,7 +254,7 @@ func TestReconcileServices_XdsServiceDelete(t *testing.T) {
}
assert.Equal(t, 1, len(snap.GetResources(resource.ListenerType)))
assert.Equal(t, 1, len(snap.GetResources(resource.ClusterType)))
assert.Equal(t, 1, len(snap.GetResources(resource.RouteType)))
assert.Equal(t, 2, len(snap.GetResources(resource.RouteType))) // Includes all_kube_routes
// Verify we will have one Endpoint resource in the snapshot
snap, err = snapshotter.EndpointsSnapshot(testNodeID)
if err != nil {
Expand Down Expand Up @@ -284,7 +284,7 @@ func TestReconcileLocalEndpointSlice_SnapOnUpdate(t *testing.T) {
"./test-resources/xds_service.yaml",
"./test-resources/endpointslice.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
client,
[]kube.Client{},
Expand All @@ -304,7 +304,7 @@ func TestReconcileLocalEndpointSlice_SnapOnUpdate(t *testing.T) {
}
assert.Equal(t, 1, len(snap.GetResources(resource.ListenerType)))
assert.Equal(t, 1, len(snap.GetResources(resource.ClusterType)))
assert.Equal(t, 1, len(snap.GetResources(resource.RouteType)))
assert.Equal(t, 2, len(snap.GetResources(resource.RouteType))) // Includes all_kube_routes
snap, err = snapshotter.EndpointsSnapshot(testNodeID)
if err != nil {
t.Fatal(err)
Expand All @@ -318,7 +318,7 @@ func TestReconcileLocalEndpointSlice_NotFound(t *testing.T) {
"./test-resources/endpointslice.yaml",
)
client.EndpointSliceApiError(kubeerror.NewNotFound(schema.GroupResource{Resource: "endpointslice"}, "foo"))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
client,
[]kube.Client{},
Expand All @@ -345,7 +345,7 @@ func TestReconcileLocalEndpointSlice_NonXdsService(t *testing.T) {
client := kube.NewClientMock(
"./test-resources/endpointslice.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
client,
[]kube.Client{},
Expand Down Expand Up @@ -373,7 +373,7 @@ func TestReconcileServices_XdsServiceWithRemoteEndpoints(t *testing.T) {
remoteClient := kube.NewClientMock(
"./test-resources/endpointslice-remote.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
localClient,
[]kube.Client{remoteClient},
Expand All @@ -394,7 +394,7 @@ func TestReconcileServices_XdsServiceWithRemoteEndpoints(t *testing.T) {
}
assert.Equal(t, 1, len(snap.GetResources(resource.ListenerType)))
assert.Equal(t, 1, len(snap.GetResources(resource.ClusterType)))
assert.Equal(t, 1, len(snap.GetResources(resource.RouteType)))
assert.Equal(t, 2, len(snap.GetResources(resource.RouteType))) // Includes all_kube_routes
// Verify we will have 1 Endpoint resource in the snapshot containing
// addresses from both local(2) and remote(2). 4 lbEndpoint addresses in
// total. Also verify that all priorities are set to 0.
Expand Down Expand Up @@ -436,7 +436,7 @@ func TestReconcileServices_XdsServiceWithRemoteEndpoints_NoRemoteEndpoints(t *te
remoteClient := kube.NewClientMock(
"./test-resources/endpointslice-remote.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
localClient,
[]kube.Client{remoteClient},
Expand All @@ -457,7 +457,7 @@ func TestReconcileServices_XdsServiceWithRemoteEndpoints_NoRemoteEndpoints(t *te
}
assert.Equal(t, 1, len(snap.GetResources(resource.ListenerType)))
assert.Equal(t, 1, len(snap.GetResources(resource.ClusterType)))
assert.Equal(t, 1, len(snap.GetResources(resource.RouteType)))
assert.Equal(t, 2, len(snap.GetResources(resource.RouteType))) // Includes all_kube_routes
// Verify we will have 1 Endpoint resource in the snapshot containing
// only local client addresses.
snap, err = snapshotter.EndpointsSnapshot(testNodeID)
Expand Down Expand Up @@ -487,7 +487,7 @@ func TestReconcileServices_XdsServiceWithOnlyRemoteEndpoints(t *testing.T) {
remoteClient := kube.NewClientMock(
"./test-resources/endpointslice-remote.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
localClient,
[]kube.Client{remoteClient},
Expand All @@ -508,7 +508,7 @@ func TestReconcileServices_XdsServiceWithOnlyRemoteEndpoints(t *testing.T) {
}
assert.Equal(t, 1, len(snap.GetResources(resource.ListenerType)))
assert.Equal(t, 1, len(snap.GetResources(resource.ClusterType)))
assert.Equal(t, 1, len(snap.GetResources(resource.RouteType)))
assert.Equal(t, 2, len(snap.GetResources(resource.RouteType))) // Includes all_kube_routes
// Verify we will have 1 Endpoint resource in the snapshot containing
// only remote addresses (2).
snap, err = snapshotter.EndpointsSnapshot(testNodeID)
Expand Down Expand Up @@ -539,7 +539,7 @@ func TestReconcileServices_XdsServiceWithRemoteEndpointsAndLocalPriority(t *test
remoteClient := kube.NewClientMock(
"./test-resources/endpointslice-remote.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
localClient,
[]kube.Client{remoteClient},
Expand All @@ -560,7 +560,7 @@ func TestReconcileServices_XdsServiceWithRemoteEndpointsAndLocalPriority(t *test
}
assert.Equal(t, 1, len(snap.GetResources(resource.ListenerType)))
assert.Equal(t, 1, len(snap.GetResources(resource.ClusterType)))
assert.Equal(t, 1, len(snap.GetResources(resource.RouteType)))
assert.Equal(t, 2, len(snap.GetResources(resource.RouteType))) // Includes all_kube_routes
// Verify we will have 1 Endpoint resource in the snapshot containing
// addresses for local endpoints with priority 0 and for remote ones
// with priority 1.
Expand Down Expand Up @@ -601,7 +601,7 @@ func TestReconcileServices_XdsServiceWithOnlyRemoteEndpointsAndLocalPriority(t *
remoteClient := kube.NewClientMock(
"./test-resources/endpointslice-remote.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
localClient,
[]kube.Client{remoteClient},
Expand All @@ -622,7 +622,7 @@ func TestReconcileServices_XdsServiceWithOnlyRemoteEndpointsAndLocalPriority(t *
}
assert.Equal(t, 1, len(snap.GetResources(resource.ListenerType)))
assert.Equal(t, 1, len(snap.GetResources(resource.ClusterType)))
assert.Equal(t, 1, len(snap.GetResources(resource.RouteType)))
assert.Equal(t, 2, len(snap.GetResources(resource.RouteType))) // Includes all_kube_routes
// Verify we will have 1 Endpoint resource in the snapshot containing
// addresses for remote endpoints with priority 0, regardless of
// PriorityStrategy set to local-first.
Expand Down Expand Up @@ -656,7 +656,7 @@ func TestReconcileLocalEndpointSlices_XdsServiceWithEmptyLocalEndpoints(t *testi
remoteClient := kube.NewClientMock(
"./test-resources/endpointslice-remote.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
localClient,
[]kube.Client{remoteClient},
Expand Down Expand Up @@ -700,7 +700,7 @@ func TestReconcileServices_XdsServiceWithRingHash(t *testing.T) {
"./test-resources/xds_service_ring_hash_balancing.yaml",
"./test-resources/endpointslice.yaml",
)
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0))
snapshotter := xds.NewSnapshotter("", testSnapshotterListenPort, float64(0), float64(0), false)
controller := NewController(
client,
[]kube.Client{},
Expand Down
7 changes: 7 additions & 0 deletions envoy-sidecar/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Tooling to deploy envoy as a sidecar and use it with the xDS server

This is in a very experimental stage and definitely not production ready.

It includes a small app to be used as an initContainer to produce envoy config
based on a map of xDS services and local ports and a kustomize base to deploy a
Kyverno mutating rule for the initContainer and the envoy sidecar.
1 change: 1 addition & 0 deletions envoy-sidecar/configurer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
configurer
13 changes: 13 additions & 0 deletions envoy-sidecar/configurer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM golang:1.21-alpine AS build
WORKDIR /go/src/github.com/utilitywarehouse/semaphore-xds/envoy-sidecar/configurer
COPY . /go/src/github.com/utilitywarehouse/semaphore-xds/envoy-sidecar/configurer
ENV CGO_ENABLED=0
RUN \
apk --no-cache add git upx \
&& go build -ldflags='-s -w' -o /semaphore-xds-envoy-configurer . \
&& upx /semaphore-xds-envoy-configurer

FROM alpine:3.18
COPY --from=build /semaphore-xds-envoy-configurer /semaphore-xds-envoy-configurer
COPY --from=build /go/src/github.com/utilitywarehouse/semaphore-xds/envoy-sidecar/configurer/templates /templates
ENTRYPOINT [ "/semaphore-xds-envoy-configurer" ]
12 changes: 12 additions & 0 deletions envoy-sidecar/configurer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# semaphore-xds-envoy-configurer

Expects an environment variable named `ENVOY_SIDECAR_TARGETS` in the form of a
comma separated list of xDS listeners. For example:

`ENVOY_SIDECAR_TARGETS="<xds-address1>,<xds-address2>"`
`XDS_SERVER_ADDRESS`="semaphore-xds.sys-semaphore.svc.cluster.local"
`XDS_SERVER_PORT`="18000"

It generates envoy config to point listeners on the specified local ports to
the respective xDS dynamic resources in order for envoy to be able to proxy
traffic to the configured services.
Loading
Loading