Skip to content

Commit 8e51a3d

Browse files
yuzisunnutanix-Hrushikesh
authored andcommitted
fix: check sidecar container for rolling update (envoyproxy#1323)
**Description** Fix previous PR's missing check for sidecar containers when handling envoy gateway deployment/daemonset rolling update. envoyproxy#1263 Signed-off-by: Dan Sun <[email protected]> Signed-off-by: Hrushikesh Patil <[email protected]>
1 parent 337f68d commit 8e51a3d

File tree

4 files changed

+44
-31
lines changed

4 files changed

+44
-31
lines changed

cmd/aigw/translate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ func translateCustomResourceObjects(
236236
gwC := controller.NewGatewayController(fakeClient, fakeClientSet, logr.FromSlogHandler(logger.Handler()),
237237
"docker.io/envoyproxy/ai-gateway-extproc:latest", true, func() string {
238238
return "aigw-translate"
239-
},
239+
}, false,
240240
)
241241
// Create and reconcile the custom resources to store the translated objects.
242242
// Note that the order of creation is important as some objects depend on others.

internal/controller/controller.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,16 @@ func StartControllers(ctx context.Context, mgr manager.Manager, config *rest.Con
9797
if err = ApplyIndexing(ctx, indexer.IndexField); err != nil {
9898
return fmt.Errorf("failed to apply indexing: %w", err)
9999
}
100+
var versionInfo *version.Info
101+
kube := kubernetes.NewForConfigOrDie(config)
102+
versionInfo, err = kube.Discovery().ServerVersion()
103+
if err != nil {
104+
return fmt.Errorf("failed to get server version: %w", err)
105+
}
100106

101107
gatewayEventChan := make(chan event.GenericEvent, 100)
102108
gatewayC := NewGatewayController(c, kubernetes.NewForConfigOrDie(config),
103-
logger.WithName("gateway"), options.ExtProcImage, false, uuid.NewString)
109+
logger.WithName("gateway"), options.ExtProcImage, false, uuid.NewString, isKubernetes133OrLater(versionInfo, logger))
104110
if err = TypedControllerBuilderForCRD(mgr, &gwapiv1.Gateway{}).
105111
WatchesRawSource(source.Channel(
106112
gatewayEventChan,
@@ -196,13 +202,6 @@ func StartControllers(ctx context.Context, mgr manager.Manager, config *rest.Con
196202
}
197203

198204
if !options.DisableMutatingWebhook {
199-
kube := kubernetes.NewForConfigOrDie(config)
200-
var versionInfo *version.Info
201-
versionInfo, err = kube.Discovery().ServerVersion()
202-
if err != nil {
203-
return fmt.Errorf("failed to get server version: %w", err)
204-
}
205-
206205
h := admission.WithCustomDefaulter(Scheme, &corev1.Pod{}, newGatewayMutator(c, kube,
207206
logger.WithName("gateway-mutator"),
208207
options.ExtProcImage,

internal/controller/gateway.go

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,20 @@ const (
4646
// to check if the pods of the gateway deployment need to be rolled out.
4747
func NewGatewayController(
4848
client client.Client, kube kubernetes.Interface, logger logr.Logger,
49-
extProcImage string, standAlone bool, uuidFn func() string,
49+
extProcImage string, standAlone bool, uuidFn func() string, extProcAsSideCar bool,
5050
) *GatewayController {
5151
uf := uuidFn
5252
if uf == nil {
5353
uf = uuid.NewString
5454
}
5555
return &GatewayController{
56-
client: client,
57-
kube: kube,
58-
logger: logger,
59-
extProcImage: extProcImage,
60-
standAlone: standAlone,
61-
uuidFn: uf,
56+
client: client,
57+
kube: kube,
58+
logger: logger,
59+
extProcImage: extProcImage,
60+
standAlone: standAlone,
61+
uuidFn: uf,
62+
extProcAsSideCar: extProcAsSideCar,
6263
}
6364
}
6465

@@ -71,6 +72,9 @@ type GatewayController struct {
7172
// standAlone indicates whether the controller is running in standalone mode.
7273
standAlone bool
7374
uuidFn func() string // Function to generate a new UUID for the filter config.
75+
// Whether to run the extProc container as a sidecar (true) as a normal container (false).
76+
// This is essentially a workaround for old k8s versions, and we can remove this in the future.
77+
extProcAsSideCar bool
7478
}
7579

7680
// Reconcile implements the reconcile.Reconciler for gwapiv1.Gateway.
@@ -469,11 +473,21 @@ func (c *GatewayController) annotateGatewayPods(ctx context.Context,
469473
for _, pod := range pods {
470474
// Get the pod spec and check if it has the extproc container.
471475
podSpec := pod.Spec
472-
for i := range podSpec.Containers {
473-
// If there's an extproc container with the current target image, we don't need to roll out the deployment.
474-
if podSpec.Containers[i].Name == extProcContainerName && podSpec.Containers[i].Image == c.extProcImage {
475-
rollout = false
476-
break
476+
if c.extProcAsSideCar {
477+
for i := range podSpec.InitContainers {
478+
// If there's an extproc sidecar container with the current target image, we don't need to roll out the deployment.
479+
if podSpec.InitContainers[i].Name == extProcContainerName && podSpec.InitContainers[i].Image == c.extProcImage {
480+
rollout = false
481+
break
482+
}
483+
}
484+
} else {
485+
for i := range podSpec.Containers {
486+
// If there's an extproc container with the current target image, we don't need to roll out the deployment.
487+
if podSpec.Containers[i].Name == extProcContainerName && podSpec.Containers[i].Image == c.extProcImage {
488+
rollout = false
489+
break
490+
}
477491
}
478492
}
479493

internal/controller/gateway_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func TestGatewayController_Reconcile(t *testing.T) {
3636
fakeKube := fake2.NewClientset()
3737
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zap.Options{Development: true, Level: zapcore.DebugLevel})))
3838
c := NewGatewayController(fakeClient, fakeKube, ctrl.Log,
39-
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil)
39+
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil, true)
4040

4141
const namespace = "ns"
4242
t.Run("not found must be non error", func(t *testing.T) {
@@ -164,7 +164,7 @@ func TestGatewayController_reconcileFilterConfigSecret(t *testing.T) {
164164
kube := fake2.NewClientset()
165165
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zap.Options{Development: true, Level: zapcore.DebugLevel})))
166166
c := NewGatewayController(fakeClient, kube, ctrl.Log,
167-
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil)
167+
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil, true)
168168

169169
const gwNamespace = "ns"
170170
routes := []aigv1a1.AIGatewayRoute{
@@ -289,7 +289,7 @@ func TestGatewayController_reconcileFilterConfigSecret_SkipsDeletedRoutes(t *tes
289289
kube := fake2.NewClientset()
290290
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zap.Options{Development: true, Level: zapcore.DebugLevel})))
291291
c := NewGatewayController(fakeClient, kube, ctrl.Log,
292-
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil)
292+
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil, true)
293293

294294
const gwNamespace = "ns"
295295
now := metav1.Now()
@@ -400,7 +400,7 @@ func TestGatewayController_bspToFilterAPIBackendAuth(t *testing.T) {
400400
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zap.Options{Development: true, Level: zapcore.DebugLevel})))
401401
c := NewGatewayController(fakeClient, kube, ctrl.Log,
402402

403-
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil)
403+
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil, true)
404404

405405
const namespace = "ns"
406406
for _, bsp := range []*aigv1a1.BackendSecurityPolicy{
@@ -547,7 +547,7 @@ func TestGatewayController_bspToFilterAPIBackendAuth(t *testing.T) {
547547
func TestGatewayController_bspToFilterAPIBackendAuth_ErrorCases(t *testing.T) {
548548
fakeClient := requireNewFakeClientWithIndexes(t)
549549
c := NewGatewayController(fakeClient, fake2.NewClientset(), ctrl.Log,
550-
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil)
550+
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil, true)
551551

552552
ctx := context.Background()
553553
namespace := "test-namespace"
@@ -608,7 +608,7 @@ func TestGatewayController_bspToFilterAPIBackendAuth_ErrorCases(t *testing.T) {
608608
func TestGatewayController_GetSecretData_ErrorCases(t *testing.T) {
609609
fakeClient := requireNewFakeClientWithIndexes(t)
610610
c := NewGatewayController(fakeClient, fake2.NewClientset(), ctrl.Log,
611-
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil)
611+
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil, true)
612612

613613
ctx := context.Background()
614614
namespace := "test-namespace"
@@ -633,7 +633,7 @@ func TestGatewayController_annotateGatewayPods(t *testing.T) {
633633
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zap.Options{Development: true, Level: zapcore.DebugLevel})))
634634
const v2Container = "ai-gateway-extproc:v2"
635635
c := NewGatewayController(fakeClient, kube, ctrl.Log,
636-
v2Container, false, nil)
636+
v2Container, false, nil, true)
637637
t.Run("pod with extproc", func(t *testing.T) {
638638
pod, err := kube.CoreV1().Pods(egNamespace).Create(t.Context(), &corev1.Pod{
639639
ObjectMeta: metav1.ObjectMeta{
@@ -748,7 +748,7 @@ func TestGatewayController_annotateDaemonSetGatewayPods(t *testing.T) {
748748
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zap.Options{Development: true, Level: zapcore.DebugLevel})))
749749
const v2Container = "ai-gateway-extproc:v2"
750750
c := NewGatewayController(fakeClient, kube, ctrl.Log,
751-
v2Container, false, nil)
751+
v2Container, false, nil, true)
752752

753753
t.Run("pod without extproc", func(t *testing.T) {
754754
pod, err := kube.CoreV1().Pods(egNamespace).Create(t.Context(), &corev1.Pod{
@@ -863,7 +863,7 @@ func TestGatewayController_backendWithMaybeBSP(t *testing.T) {
863863
kube := fake2.NewClientset()
864864
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zap.Options{Development: true, Level: zapcore.DebugLevel})))
865865
const v2Container = "ai-gateway-extproc:v2"
866-
c := NewGatewayController(fakeClient, kube, ctrl.Log, v2Container, false, nil)
866+
c := NewGatewayController(fakeClient, kube, ctrl.Log, v2Container, false, nil, true)
867867

868868
_, _, err := c.backendWithMaybeBSP(t.Context(), "foo", "bar")
869869
require.ErrorContains(t, err, `aiservicebackends.aigateway.envoyproxy.io "bar" not found`)
@@ -923,7 +923,7 @@ func TestGatewayController_reconcileFilterMCPConfigSecret(t *testing.T) {
923923
kube := fake2.NewClientset()
924924
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zap.Options{Development: true, Level: zapcore.DebugLevel})))
925925
c := NewGatewayController(fakeClient, kube, ctrl.Log,
926-
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil)
926+
"docker.io/envoyproxy/ai-gateway-extproc:latest", false, nil, true)
927927

928928
const gwNamespace = "ns"
929929
// Two routes with different CreationTimestamp for deterministic order.

0 commit comments

Comments
 (0)