diff --git a/charts/gateway-helm/templates/envoy-proxy-topology-injector-webhook.yaml b/charts/gateway-helm/templates/envoy-proxy-topology-injector-webhook.yaml index 000c62e24c..159c4e591c 100644 --- a/charts/gateway-helm/templates/envoy-proxy-topology-injector-webhook.yaml +++ b/charts/gateway-helm/templates/envoy-proxy-topology-injector-webhook.yaml @@ -1,4 +1,19 @@ {{- if .Values.topologyInjector.enabled }} + +{{ $watchedNamespaces := list }} +{{ $gatewayNamespaceMode := false}} +{{- if .Values.config.envoyGateway.provider.kubernetes }} +{{- $kube := .Values.config.envoyGateway.provider.kubernetes }} +{{- $gatewayNamespaceMode = and ($kube.deploy) (eq $kube.deploy.type "GatewayNamespace") }} +{{- if $kube.watch }} +{{- if $kube.watch.namespaces }} +{{- if gt (len $kube.watch.namespaces) 0 }} +{{- $watchedNamespaces = $kube.watch.namespaces }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} + apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: @@ -28,10 +43,21 @@ webhooks: apiGroups: [""] apiVersions: ["v1"] resources: ["pods/binding"] + {{- if not $gatewayNamespaceMode }} namespaceSelector: matchExpressions: - key: kubernetes.io/metadata.name operator: In values: - {{ .Release.Namespace }} + {{- else if gt (len $watchedNamespaces) 0 }} + namespaceSelector: + matchExpressions: + - key: kubernetes.io/metadata.name + operator: In + values: + {{- range $watchedNamespaces }} + - {{ . | quote }} + {{- end }} + {{- end }} {{- end }} \ No newline at end of file diff --git a/internal/provider/kubernetes/kubernetes.go b/internal/provider/kubernetes/kubernetes.go index ac19c145aa..23770bcb25 100644 --- a/internal/provider/kubernetes/kubernetes.go +++ b/internal/provider/kubernetes/kubernetes.go @@ -127,6 +127,7 @@ func New(ctx context.Context, restCfg *rest.Config, svrCfg *ec.Server, resources mgr.GetWebhookServer().Register("/inject-pod-topology", &webhook.Admission{ Handler: &ProxyTopologyInjector{ Client: mgr.GetClient(), + Logger: svrCfg.Logger.WithName("proxy-topology-injector"), Decoder: admission.NewDecoder(mgr.GetScheme()), }, }) diff --git a/internal/provider/kubernetes/topology_injector.go b/internal/provider/kubernetes/topology_injector.go index f507c72989..b0569e5aa0 100644 --- a/internal/provider/kubernetes/topology_injector.go +++ b/internal/provider/kubernetes/topology_injector.go @@ -12,23 +12,28 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "github.com/envoyproxy/gateway/internal/gatewayapi" + "github.com/envoyproxy/gateway/internal/logging" "github.com/envoyproxy/gateway/internal/metrics" ) type ProxyTopologyInjector struct { client.Client Decoder admission.Decoder + + Logger logging.Logger } func (m *ProxyTopologyInjector) Handle(ctx context.Context, req admission.Request) admission.Response { + logger := m.Logger + logger.V(1).Info("receive injector request", "request", req) + binding := &corev1.Binding{} if err := m.Decoder.Decode(req, binding); err != nil { - klog.Error(err, "decoding binding failed", "request.ObjectKind", req.Object.Object.GetObjectKind()) + logger.Error(err, "decoding binding failed", "request.ObjectKind", req.Object.Object.GetObjectKind()) topologyInjectorEventsTotal.WithFailure(metrics.ReasonError).Increment() return admission.Allowed("internal error, skipped") } @@ -45,28 +50,31 @@ func (m *ProxyTopologyInjector) Handle(ctx context.Context, req admission.Reques pod := &corev1.Pod{} if err := m.Get(ctx, podName, pod); err != nil { - klog.Error(err, "get pod failed", "pod", podName.String()) + logger.Error(err, "get pod failed", "pod", podName.String()) topologyInjectorEventsTotal.WithFailure(metrics.ReasonError).Increment() return admission.Allowed("internal error, skipped") } // Skip non-proxy pods if !hasEnvoyProxyLabels(pod.Labels) { - klog.V(1).Info("skipping pod due to missing labels", "pod", podName) + logger.V(1).Info("skipping pod due to missing labels", "pod", podName) topologyInjectorEventsTotal.WithStatus(statusNoAction).Increment() return admission.Allowed("skipped") } + logger = logger.WithValues("pod", podName) + nodeName := types.NamespacedName{ Name: binding.Target.Name, } node := &corev1.Node{} if err := m.Get(ctx, nodeName, node); err != nil { - klog.Error(err, "get node failed", "node", node.Name) + logger.Error(err, "get node failed", "node", node.Name) topologyInjectorEventsTotal.WithFailure(metrics.ReasonError).Increment() return admission.Allowed("internal error, skipped") } + logger = logger.WithValues("node", node) if zone, ok := node.Labels[corev1.LabelTopologyZone]; ok { if binding.Annotations == nil { @@ -74,14 +82,17 @@ func (m *ProxyTopologyInjector) Handle(ctx context.Context, req admission.Reques } binding.Annotations[corev1.LabelTopologyZone] = zone } else { + logger.V(1).Info("Skipping injection due to missing topology label on node") return admission.Allowed("Skipping injection due to missing topology label on node") } marshaledBinding, err := json.Marshal(binding) if err != nil { - klog.Errorf("failed to marshal Pod Binding: %v", err) + logger.Error(err, "failed to marshal Pod Binding") return admission.Allowed(fmt.Sprintf("failed to marshal binding, skipped: %v", err)) } + + topologyInjectorEventsTotal.WithSuccess().Increment() return admission.PatchResponseFromRaw(req.Object.Raw, marshaledBinding) } diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index c7de5de62e..2d2ae0ffaa 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -66,7 +66,6 @@ func TestE2E(t *testing.T) { skipTests = append(skipTests, tests.HTTPWasmTest.ShortName, tests.OCIWasmTest.ShortName, - tests.ZoneAwareRoutingTest.ShortName, // Skip RateLimit tests because they are not supported in GatewayNamespaceMode tests.RateLimitCIDRMatchTest.ShortName, diff --git a/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config-watch.out.yaml b/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config-watch.out.yaml index a288660e2f..beb980a598 100644 --- a/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config-watch.out.yaml +++ b/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config-watch.out.yaml @@ -1010,4 +1010,5 @@ webhooks: - key: kubernetes.io/metadata.name operator: In values: - - envoy-gateway-system + - "default" + - "app-ns" diff --git a/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config.out.yaml b/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config.out.yaml index 5e59c262db..b026f34bb8 100644 --- a/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config.out.yaml +++ b/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config.out.yaml @@ -756,9 +756,3 @@ webhooks: apiGroups: [""] apiVersions: ["v1"] resources: ["pods/binding"] - namespaceSelector: - matchExpressions: - - key: kubernetes.io/metadata.name - operator: In - values: - - envoy-gateway-system diff --git a/tools/make/helm.mk b/tools/make/helm.mk index 21797c33ba..8ac9d3bb48 100644 --- a/tools/make/helm.mk +++ b/tools/make/helm.mk @@ -56,7 +56,7 @@ helm-generate.%: envsubst < charts/${CHART_NAME}/values.tmpl.yaml > ./charts/${CHART_NAME}/values.yaml; \ fi helm dependency update charts/${CHART_NAME} - helm lint charts/${CHART_NAME} + helm lint charts/${CHART_NAME} || exit 1 # The jb does not support self-assigned jsonnetfile, so entering working dir before executing jb. @if [ ${CHART_NAME} == "gateway-addons-helm" ]; then \