Skip to content

Commit 9d8289f

Browse files
sam-heilbronjenshusoloio-bulldozer[bot]npolshakova
authored
edge/regression: enable experimental k8s gateway controller (#9174)
* start gg controller from setup syncer * use same helmignore values, deleted unused file * copy helm templates over * debug * auto-provision * run codegen * comment out v2 install/uninstall * gloo-gateway: re-use ControlPlane server and cache (#9166) * First pass at re-uusing xds cache * scale down glood * fix connection with control plane * update NodeHash impelentations * fix test * update log line --------- Co-authored-by: soloio-bulldozer[bot] <48420018+soloio-bulldozer[bot]@users.noreply.github.com> * add a changelog * unit tests for AggregateNodeHash * comment out * add comment about alpha api * add desc * deployer: fix compile errors' * clean up old xds code * protect against npe * fix lint errors * deployer_test: simplify assertion * remove v2 glooctl check * boostrap: support turning on/off the k8s gateway controller * fmt * fix comment * control feature by env variable, turn off for all existing tests * disable gateway2 in helm tests for now * add gg crds * remove gw crds from chart * apply crds in setup-kind * re-enable EnableK8sGatewayController * conformance test script * Revert "re-enable EnableK8sGatewayController" This reverts commit f41133b. * use values file * create ns * try with prefixes * only delete own snapshots * try to re-enable gg * Revert "try to re-enable gg" This reverts commit b1f005c. * [DNM] Helm and other merge cleanup (#9171) * remove extra options * remove readyz * use same context * Revert "use same context" This reverts commit 71f6801. * revert changes * check err * controlplane: remove unused helm templates, values, helper functions, use gloo serviceaccount * delete unused deployer templates * remove controlPlane helpers * use right service account name --------- Co-authored-by: soloio-bulldozer[bot] <48420018+soloio-bulldozer[bot]@users.noreply.github.com> * clean up helm values and scripts * delete gateway2 cmd * remove glood check * re-enable gg in most tests * get translator name from proxy * enable experimental k8s controller in gloo kube2e tests * Add kubeutils for port-fowarding, not yet used * enable experimental k8s controller in kube2e tests * fix typo in env.go * create StartFunc concept * cleanup gw controller * remove extra logs * fall back to GE, add port back to logs * Revert "fall back to GE, add port back to logs" This reverts commit f4e1f59. * Revert "get translator name from proxy" This reverts commit 16c7d76. * add back log, use existing const * enable experimental k8s controller ALL kube2e tests * goimports * undo local change for gloo kube tests * cleanup * casing * cleanup controller code * add changelog * fix builder * small cleanup * fix func signature * undo context changes * move contants to controller package * move to the builder pattern entirely * define constants externally, try to avoid import cycle * pass context explicitly * goimports * improve logging in start_func * log at end of ExecuteAsynchronousStartFuncs * add log line at end of RunGloo * remove kubeutils - dead code * prefer property object over builder pattern --------- Co-authored-by: Jenny Shu <[email protected]> Co-authored-by: soloio-bulldozer[bot] <48420018+soloio-bulldozer[bot]@users.noreply.github.com> Co-authored-by: npolshakova <[email protected]> Co-authored-by: Jenny Shu <[email protected]>
1 parent 456c63b commit 9d8289f

File tree

19 files changed

+249
-198
lines changed

19 files changed

+249
-198
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
changelog:
2+
- type: NON_USER_FACING
3+
issueLink: https://github.com/solo-io/solo-projects/issues/5663
4+
resolvesIssue: false
5+
description: >-
6+
Ensure that the k8s gateway controller can be run at the same time as the rest of the classic edge setup code.
7+
Enable the experimental controller API to be executed during edge regression tests to prove that this works.

projects/gateway2/controller/controller.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,11 @@ func (c *controllerBuilder) watchGw(ctx context.Context) error {
8787
log := log.FromContext(ctx)
8888

8989
log.Info("creating deployer", "ctrlname", c.cfg.ControllerName, "server", c.cfg.ControlPlane.GetBindAddress(), "port", c.cfg.ControlPlane.GetBindPort())
90-
d, err := deployer.NewDeployer(c.cfg.Mgr.GetScheme(), c.cfg.Dev, c.cfg.ControllerName, c.cfg.ControlPlane.GetBindPort())
90+
d, err := deployer.NewDeployer(c.cfg.Mgr.GetScheme(), &deployer.Inputs{
91+
ControllerName: c.cfg.ControllerName,
92+
Dev: c.cfg.Dev,
93+
Port: c.cfg.ControlPlane.GetBindPort(),
94+
})
9195
if err != nil {
9296
return err
9397
}
@@ -124,15 +128,15 @@ func (c *controllerBuilder) watchGw(ctx context.Context) error {
124128
buildr.Owns(clientObj, opts...)
125129
}
126130

127-
gwreconciler := &gatewayReconciler{
131+
gwReconciler := &gatewayReconciler{
128132
cli: c.cfg.Mgr.GetClient(),
129133
scheme: c.cfg.Mgr.GetScheme(),
130134
className: c.cfg.GWClass,
131135
autoProvision: c.cfg.AutoProvision,
132136
deployer: d,
133137
kick: c.cfg.Kick,
134138
}
135-
err = buildr.Complete(gwreconciler)
139+
err = buildr.Complete(gwReconciler)
136140
if err != nil {
137141
return err
138142
}
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,53 @@
11
package controller
22

33
import (
4-
"os"
4+
"context"
55

6-
"github.com/solo-io/gloo/projects/gloo/pkg/bootstrap"
6+
"github.com/solo-io/gloo/projects/gateway2/wellknown"
7+
8+
"sigs.k8s.io/controller-runtime/pkg/log/zap"
79

810
"github.com/solo-io/gloo/projects/gateway2/controller/scheme"
911
"github.com/solo-io/gloo/projects/gateway2/discovery"
1012
"github.com/solo-io/gloo/projects/gateway2/secrets"
1113
"github.com/solo-io/gloo/projects/gateway2/xds"
14+
"github.com/solo-io/gloo/projects/gloo/pkg/bootstrap"
1215
"github.com/solo-io/gloo/projects/gloo/pkg/syncer/sanitizer"
1316
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
1417
ctrl "sigs.k8s.io/controller-runtime"
1518
"sigs.k8s.io/controller-runtime/pkg/healthz"
16-
"sigs.k8s.io/controller-runtime/pkg/log/zap"
17-
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
1819
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
1920
apiv1 "sigs.k8s.io/gateway-api/apis/v1"
2021
)
2122

23+
const (
24+
// AutoProvision controls whether the controller will be responsible for provisioning dynamic
25+
// infrastructure for the Gateway API.
26+
AutoProvision = true
27+
)
28+
2229
var (
30+
gatewayClass = apiv1.ObjectName(wellknown.GatewayClassName)
31+
2332
setupLog = ctrl.Log.WithName("setup")
2433
)
2534

26-
type ControllerConfig struct {
27-
// The name of the GatewayClass to watch for
28-
GatewayClassName string
29-
GatewayControllerName string
30-
Release string
31-
AutoProvision bool
32-
Dev bool
33-
35+
type StartConfig struct {
36+
Dev bool
3437
ControlPlane bootstrap.ControlPlane
3538
}
3639

37-
func Start(cfg ControllerConfig) {
38-
setupLog.Info("xxxxx starting gw2 controller xxxxxx")
40+
// Start runs the controllers responsible for processing the K8s Gateway API objects
41+
// It is intended to be run in a goroutine as the function will block until the supplied
42+
// context is cancelled
43+
func Start(ctx context.Context, cfg StartConfig) error {
3944
var opts []zap.Opts
4045
if cfg.Dev {
4146
setupLog.Info("starting log in dev mode")
4247
opts = append(opts, zap.UseDevMode(true))
4348
}
4449
ctrl.SetLogger(zap.New(opts...))
50+
4551
mgrOpts := ctrl.Options{
4652
Scheme: scheme.NewScheme(),
4753
PprofBindAddress: "127.0.0.1:9099",
@@ -54,19 +60,17 @@ func Start(cfg ControllerConfig) {
5460
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), mgrOpts)
5561
if err != nil {
5662
setupLog.Error(err, "unable to start manager")
57-
os.Exit(1)
63+
return err
5864
}
5965

6066
// TODO: replace this with something that checks that we have xds snapshot ready (or that we don't need one).
6167
mgr.AddReadyzCheck("ready-ping", healthz.Ping)
6268

63-
ctx := signals.SetupSignalHandler()
64-
6569
glooTranslator := newGlooTranslator(ctx)
6670
var sanz sanitizer.XdsSanitizers
6771
inputChannels := xds.NewXdsInputChannels()
6872
xdsSyncer := xds.NewXdsSyncer(
69-
cfg.GatewayControllerName,
73+
wellknown.GatewayControllerName,
7074
glooTranslator,
7175
sanz,
7276
cfg.ControlPlane.SnapshotCache,
@@ -77,48 +81,31 @@ func Start(cfg ControllerConfig) {
7781
)
7882
if err := mgr.Add(xdsSyncer); err != nil {
7983
setupLog.Error(err, "unable to add xdsSyncer runnable")
80-
os.Exit(1)
84+
return err
8185
}
8286

83-
// sam-heilbron: I don't think this is necessary, as we should have a shared cache
84-
if cfg.Dev {
85-
go xdsSyncer.ServeXdsSnapshots()
86-
}
87-
88-
var gatewayClassName apiv1.ObjectName = apiv1.ObjectName(cfg.GatewayClassName)
89-
90-
gwcfg := GatewayConfig{
87+
gwCfg := GatewayConfig{
9188
Mgr: mgr,
92-
GWClass: gatewayClassName,
93-
Dev: cfg.Dev,
94-
ControllerName: cfg.GatewayControllerName,
95-
AutoProvision: cfg.AutoProvision,
89+
GWClass: gatewayClass,
90+
ControllerName: wellknown.GatewayControllerName,
91+
AutoProvision: AutoProvision,
9692
ControlPlane: cfg.ControlPlane,
9793
Kick: inputChannels.Kick,
9894
}
99-
err = NewBaseGatewayController(ctx, gwcfg)
100-
101-
if err != nil {
95+
if err = NewBaseGatewayController(ctx, gwCfg); err != nil {
10296
setupLog.Error(err, "unable to create controller")
103-
os.Exit(1)
97+
return err
10498
}
10599

106-
err = discovery.NewDiscoveryController(ctx, mgr, inputChannels)
107-
if err != nil {
100+
if err = discovery.NewDiscoveryController(ctx, mgr, inputChannels); err != nil {
108101
setupLog.Error(err, "unable to create controller")
109-
os.Exit(1)
102+
return err
110103
}
111104

112-
err = secrets.NewSecretsController(ctx, mgr, inputChannels)
113-
if err != nil {
105+
if err = secrets.NewSecretsController(ctx, mgr, inputChannels); err != nil {
114106
setupLog.Error(err, "unable to create controller")
115-
os.Exit(1)
116-
}
117-
118-
setupLog.Info("starting manager")
119-
if err := mgr.Start(ctx); err != nil {
120-
setupLog.Error(err, "problem running manager")
121-
os.Exit(1)
107+
return err
122108
}
123109

110+
return mgr.Start(ctx)
124111
}

projects/gateway2/deployer/builder.go

-98
This file was deleted.

projects/gateway2/deployer/deployer.go

+40-23
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ import (
99
"io/fs"
1010
"path/filepath"
1111

12+
"github.com/solo-io/gloo/pkg/version"
13+
"github.com/solo-io/gloo/projects/gateway2/helm"
14+
1215
"github.com/solo-io/gloo/projects/gloo/pkg/defaults"
1316

14-
"github.com/solo-io/gloo/projects/gateway2/helm"
1517
"github.com/solo-io/gloo/projects/gateway2/ports"
1618
"golang.org/x/exp/slices"
1719
"helm.sh/helm/v3/pkg/action"
@@ -36,28 +38,38 @@ type gatewayPort struct {
3638
TargetPort uint16 `json:"targetPort"`
3739
}
3840

41+
// A Deployer is responsible for deploying proxies
3942
type Deployer struct {
40-
dev bool
41-
chart *chart.Chart
42-
scheme *runtime.Scheme
43-
controllerName string
44-
port int
43+
chart *chart.Chart
44+
scheme *runtime.Scheme
45+
46+
inputs *Inputs
4547
}
4648

47-
// NewDeployer builds a Deployer or returns an error if one could not be constructed
48-
// A Deployer is responsible for deploying proxies
49-
// NOTE: This constructor is flawed, as it will fall subject to the telescoping constructor anti-pattern as we
50-
// add more properties. We should migrate to using just the builder
51-
func NewDeployer(scheme *runtime.Scheme, dev bool, controllerName string, xdsPort int) (*Deployer, error) {
52-
deployerOptions := []Option{
53-
WithScheme(scheme),
54-
WithChartFs(helm.GlooGatewayHelmChart),
55-
WithControllerName(controllerName),
56-
WithXdsServer(xdsPort),
57-
WithDevMode(dev),
49+
// Inputs is the set of options used to configure the gateway deployer deployment
50+
type Inputs struct {
51+
ControllerName string
52+
Dev bool
53+
Port int
54+
}
55+
56+
// NewDeployer creates a new gateway deployer
57+
func NewDeployer(scheme *runtime.Scheme, inputs *Inputs) (*Deployer, error) {
58+
helmChart, err := loadFs(helm.GlooGatewayHelmChart)
59+
if err != nil {
60+
return nil, err
61+
}
62+
// simulate what `helm package` in the Makefile does
63+
if version.Version != version.UndefinedVersion {
64+
helmChart.Metadata.AppVersion = version.Version
65+
helmChart.Metadata.Version = version.Version
5866
}
5967

60-
return BuildDeployer(deployerOptions...)
68+
return &Deployer{
69+
scheme: scheme,
70+
chart: helmChart,
71+
inputs: inputs,
72+
}, nil
6173
}
6274

6375
func (d *Deployer) GetGvksToWatch(ctx context.Context) ([]schema.GroupVersionKind, error) {
@@ -128,14 +140,19 @@ func (d *Deployer) renderChartToObjects(ctx context.Context, gw *api.Gateway) ([
128140
"type": "LoadBalancer",
129141
},
130142
"xds": map[string]any{
131-
// This creates a limitation that the Deployer can only work when the ControlPlane is installed to the gloo-system
132-
// namespace. We can address this in a follow-up, and we should be able to identify the namespace of the control plane programmatically
143+
// The xds host/port MUST map to the Service definition for the Control Plane
144+
// This is the socket address that the Proxy will connect to on startup, to receive xds updates
145+
//
146+
// NOTE: The current implementation in flawed in multiple ways:
147+
// 1 - This assumes that the Control Plane is installed in `gloo-system`
148+
// 2 - The port is the bindAddress of the Go server, but there is not a strong guarantee that that port
149+
// will always be what is exposed by the Kubernetes Service.
133150
"host": fmt.Sprintf("gloo.%s.svc.%s", defaults.GlooSystem, "cluster.local"),
134-
"port": d.port,
151+
"port": d.inputs.Port,
135152
},
136153
},
137154
}
138-
if d.dev {
155+
if d.inputs.Dev {
139156
vals["develop"] = true
140157
}
141158
log := log.FromContext(ctx)
@@ -200,7 +217,7 @@ func (d *Deployer) GetObjsToDeploy(ctx context.Context, gw *api.Gateway) ([]clie
200217

201218
func (d *Deployer) DeployObjs(ctx context.Context, objs []client.Object, cli client.Client) error {
202219
for _, obj := range objs {
203-
if err := cli.Patch(ctx, obj, client.Apply, client.ForceOwnership, client.FieldOwner(d.controllerName)); err != nil {
220+
if err := cli.Patch(ctx, obj, client.Apply, client.ForceOwnership, client.FieldOwner(d.inputs.ControllerName)); err != nil {
204221
return fmt.Errorf("failed to apply object %s %s: %w", obj.GetObjectKind().GroupVersionKind().String(), obj.GetName(), err)
205222
}
206223
}

0 commit comments

Comments
 (0)