Skip to content

feat: support infra deployment in the gateway namespace #5137

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

Merged
merged 26 commits into from
Apr 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
86109a2
wip: feat: support infra deployment in the gateway namespace
cnvergence Jan 23, 2025
a7bbb4f
add helm rbac for infra namespaced mode
cnvergence Feb 11, 2025
316bc22
add helm testdata for namespaced mode
cnvergence Feb 11, 2025
83d1aaf
check for gateway namespace mod in infra volumes
cnvergence Feb 11, 2025
57180e0
mount serviceaccount token to envoy pod
cnvergence Feb 12, 2025
ff8b499
support gateway namespaces in kubernetes predicate funcs
cnvergence Feb 12, 2025
b9b30dd
add bootstrap config for credential injector and jwt interceptor in s…
cnvergence Mar 12, 2025
139f530
add the cluster role if deploy mode is set without watched namespaces
cnvergence Mar 12, 2025
cc24e5e
add helm clusterrole
cnvergence Mar 12, 2025
4c2bb6d
fix tests
cnvergence Mar 24, 2025
f8d0bcd
update grpc xds server and share eg ca cert in the infra configmap
cnvergence Apr 15, 2025
c198bfe
fix tests
cnvergence Apr 15, 2025
20e56ca
lint code
cnvergence Apr 15, 2025
3f71f3a
update stls config for xds server in namespace mode
cnvergence Apr 22, 2025
0c64a64
update codgen
cnvergence Apr 22, 2025
d520d8a
update stls+jwt config
cnvergence Apr 22, 2025
a5d8e86
move to token review API for jwt validation
cnvergence Apr 24, 2025
e03dd69
remove old func
cnvergence Apr 24, 2025
f0ecfc8
go lint
cnvergence Apr 24, 2025
63a3e51
Update testdata
cnvergence Apr 25, 2025
826de23
check for serviceaccount group in the tokenReview groups slice
cnvergence Apr 25, 2025
77ebebb
fix tests
cnvergence Apr 25, 2025
1ef7776
update testdata
cnvergence Apr 29, 2025
5bc031f
Add initial token validation, add tests and review changes
cnvergence Apr 29, 2025
91c297b
lint code
cnvergence Apr 30, 2025
bbddde9
add zone envvar
cnvergence Apr 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 8 additions & 0 deletions api/v1alpha1/envoygateway_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@
len(e.Provider.Kubernetes.Watch.Namespaces) > 0
}

// GatewayNamespaceMode returns true if controller uses gateway namespace mode for infra deployments.
func (e *EnvoyGateway) GatewayNamespaceMode() bool {
Copy link
Member

@zhaohuabing zhaohuabing Apr 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, non-blocking: this might just be a personal preference, but I would prefer a clearer name to make it easier to read. For example: IsInfraDeployedInGatewayNamespace or ShouldInfraDeployedInGatewayNamespace. This also applies to other places using the same name.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am okay with changing the name, however, I would like to keep a shorter name, just like GatewayNamespaceMode

return e.Provider != nil &&
e.Provider.Kubernetes != nil &&
e.Provider.Kubernetes.Deploy != nil &&
*e.Provider.Kubernetes.Deploy.Type == KubernetesDeployModeTypeGatewayNamespace

Check warning on line 109 in api/v1alpha1/envoygateway_helpers.go

View check run for this annotation

Codecov / codecov/patch

api/v1alpha1/envoygateway_helpers.go#L105-L109

Added lines #L105 - L109 were not covered by tests
}

// DefaultLeaderElection returns a new LeaderElection with default configuration parameters.
func DefaultLeaderElection() *LeaderElection {
return &LeaderElection{
Expand Down
47 changes: 47 additions & 0 deletions charts/gateway-helm/templates/_rbac.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,50 @@ resources:
verbs:
- update
{{- end }}

{{- define "eg.rbac.infra.basic" -}}
- apiGroups:
- ""
resources:
- serviceaccounts
- services
- configmaps
verbs:
- create
- get
- delete
- deletecollection
- patch
- apiGroups:
- apps
resources:
- deployments
- daemonsets
verbs:
- create
- get
- delete
- deletecollection
- patch
- apiGroups:
- autoscaling
- policy
resources:
- horizontalpodautoscalers
- poddisruptionbudgets
verbs:
- create
- get
- delete
- deletecollection
- patch
{{- end }}

{{- define "eg.rbac.infra.tokenreview" -}}
- apiGroups:
- authentication.k8s.io
resources:
- tokenreviews
verbs:
- create
{{- end }}
67 changes: 32 additions & 35 deletions charts/gateway-helm/templates/infra-manager-rbac.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
{{ if .Values.config.envoyGateway.provider.kubernetes }}
{{ $kube := .Values.config.envoyGateway.provider.kubernetes }}
{{ if and (not $kube.watch) ($kube.deploy) (eq $kube.deploy.type "GatewayNamespace") }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "eg.fullname" $ }}-cluster-infra-manager
labels:
{{- include "eg.labels" $ | nindent 4 }}
rules:
{{ include "eg.rbac.infra.basic" . }}
{{ include "eg.rbac.infra.tokenreview" . }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "eg.fullname" $ }}-cluster-infra-manager
labels:
{{- include "eg.labels" $ | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: '{{ include "eg.fullname" $ }}-cluster-infra-manager'
subjects:
- kind: ServiceAccount
name: 'envoy-gateway'
namespace: '{{ $.Release.Namespace }}'
---
{{ end }}
{{ end }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
Expand All @@ -6,41 +37,7 @@ metadata:
labels:
{{- include "eg.labels" . | nindent 4 }}
rules:
- apiGroups:
- ""
resources:
- serviceaccounts
- services
- configmaps
verbs:
- create
- get
- delete
- deletecollection
- patch
- apiGroups:
- apps
resources:
- deployments
- daemonsets
verbs:
- create
- get
- delete
- deletecollection
- patch
- apiGroups:
- autoscaling
- policy
resources:
- horizontalpodautoscalers
- poddisruptionbudgets
verbs:
- create
- get
- delete
- deletecollection
- patch
{{ include "eg.rbac.infra.basic" . }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{{ $watchedNamespaces := list }}
{{ if .Values.config.envoyGateway.provider.kubernetes }}
{{ $kube := .Values.config.envoyGateway.provider.kubernetes }}
{{ if and ($kube.watch) ($kube.deploy) (eq $kube.deploy.type "GatewayNamespace") }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "eg.fullname" $ }}-infra-manager-tokenreview
labels:
{{- include "eg.labels" $ | nindent 4 }}
rules:
{{ include "eg.rbac.infra.tokenreview" . }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "eg.fullname" $ }}-infra-manager-tokenreview
labels:
{{- include "eg.labels" $ | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: '{{ include "eg.fullname" $ }}-infra-manager-tokenreview'
subjects:
- kind: ServiceAccount
name: 'envoy-gateway'
namespace: '{{ $.Release.Namespace }}'
{{ if $kube.watch.namespaces }}
{{ if gt (len $kube.watch.namespaces) 0 }}
{{ $watchedNamespaces = $kube.watch.namespaces }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ if gt (len $watchedNamespaces) 0 }}
{{ range $_, $ns := $watchedNamespaces }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "eg.fullname" $ }}-namespaced-infra-manager
namespace: {{ $ns | quote }}
labels:
{{- include "eg.labels" $ | nindent 4 }}
rules:
{{ include "eg.rbac.infra.basic" . }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "eg.fullname" $ }}-namespaced-infra-manager
namespace: {{ $ns | quote }}
labels:
{{- include "eg.labels" $ | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: '{{ include "eg.fullname" $ }}-namespaced-infra-manager'
subjects:
- kind: ServiceAccount
name: 'envoy-gateway'
namespace: '{{ $.Release.Namespace }}'
---
{{- end }}
{{- end }}
4 changes: 2 additions & 2 deletions internal/cmd/certgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
func outputCertsForKubernetes(ctx context.Context, cli client.Client, cfg *config.Server,
updateSecrets bool, certs *crypto.Certificates,
) error {
secrets, err := kubernetes.CreateOrUpdateSecrets(ctx, cli, kubernetes.CertsToSecret(cfg.Namespace, certs), updateSecrets)
secrets, err := kubernetes.CreateOrUpdateSecrets(ctx, cli, kubernetes.CertsToSecret(cfg.ControllerNamespace, certs), updateSecrets)

Check warning on line 100 in internal/cmd/certgen.go

View check run for this annotation

Codecov / codecov/patch

internal/cmd/certgen.go#L100

Added line #L100 was not covered by tests
log := cfg.Logger

if err != nil {
Expand All @@ -121,7 +121,7 @@
return nil
}

webhookConfigName := fmt.Sprintf("%s.%s", topologyWebhookNamePrefix, cfg.Namespace)
webhookConfigName := fmt.Sprintf("%s.%s", topologyWebhookNamePrefix, cfg.ControllerNamespace)
webhookCfg := &admissionregistrationv1.MutatingWebhookConfiguration{}
if err := cli.Get(ctx, client.ObjectKey{Name: webhookConfigName}, webhookCfg); err != nil {
return fmt.Errorf("failed to get mutating webhook configuration: %w", err)
Expand Down
4 changes: 2 additions & 2 deletions internal/cmd/certgen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func TestPatchTopologyWebhook(t *testing.T) {
caseName: "Update caBundle",
webhook: &admissionregistrationv1.MutatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s.%s", topologyWebhookNamePrefix, cfg.Namespace),
Name: fmt.Sprintf("%s.%s", topologyWebhookNamePrefix, cfg.ControllerNamespace),
},
Webhooks: []admissionregistrationv1.MutatingWebhook{{ClientConfig: admissionregistrationv1.WebhookClientConfig{}}},
},
Expand All @@ -77,7 +77,7 @@ func TestPatchTopologyWebhook(t *testing.T) {
caseName: "No-op",
webhook: &admissionregistrationv1.MutatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s.%s", topologyWebhookNamePrefix, cfg.Namespace),
Name: fmt.Sprintf("%s.%s", topologyWebhookNamePrefix, cfg.ControllerNamespace),
},
Webhooks: []admissionregistrationv1.MutatingWebhook{{ClientConfig: admissionregistrationv1.WebhookClientConfig{CABundle: []byte("foo")}}},
},
Expand Down
2 changes: 0 additions & 2 deletions internal/cmd/egctl/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,6 @@ func TestExtractSubResourcesConfigDump(t *testing.T) {
}

func TestLabelSelectorBadInput(t *testing.T) {
podNamespace = "default"

cases := []struct {
name string
args []string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ infraIR:
gateway.envoyproxy.io/owning-gateway-name: eg
gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway-system
name: envoy-gateway-system/eg
namespace: ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this correct?

xdsIR:
envoy-gateway-system/eg:
accessLog:
Expand Down
4 changes: 2 additions & 2 deletions internal/crypto/certgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ func GenerateCerts(cfg *config.Server) (*Certificates, error) {
egProvider := cfg.EnvoyGateway.GetEnvoyGatewayProvider().Type
switch egProvider {
case egv1a1.ProviderTypeKubernetes:
egDNSNames = kubeServiceNames(DefaultEnvoyGatewayDNSPrefix, cfg.Namespace, cfg.DNSDomain)
envoyDNSNames = append(envoyDNSNames, fmt.Sprintf("*.%s", cfg.Namespace))
egDNSNames = kubeServiceNames(DefaultEnvoyGatewayDNSPrefix, cfg.ControllerNamespace, cfg.DNSDomain)
envoyDNSNames = append(envoyDNSNames, fmt.Sprintf("*.%s", cfg.ControllerNamespace))
default:
// Kubernetes is the only supported Envoy Gateway provider.
return nil, fmt.Errorf("unsupported provider type %v", egProvider)
Expand Down
16 changes: 8 additions & 8 deletions internal/envoygateway/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ const (
type Server struct {
// EnvoyGateway is the configuration used to startup Envoy Gateway.
EnvoyGateway *egv1a1.EnvoyGateway
// Namespace is the namespace that Envoy Gateway runs in.
Namespace string
// ControllerNamespace is the namespace that Envoy Gateway runs in.
ControllerNamespace string
// DNSDomain is the dns domain used by k8s services. Defaults to "cluster.local".
DNSDomain string
// Logger is the logr implementation used by Envoy Gateway.
Expand All @@ -44,11 +44,11 @@ type Server struct {
// New returns a Server with default parameters.
func New(logOut io.Writer) (*Server, error) {
return &Server{
EnvoyGateway: egv1a1.DefaultEnvoyGateway(),
Namespace: env.Lookup("ENVOY_GATEWAY_NAMESPACE", DefaultNamespace),
DNSDomain: env.Lookup("KUBERNETES_CLUSTER_DOMAIN", DefaultDNSDomain),
Logger: logging.DefaultLogger(logOut, egv1a1.LogLevelInfo),
Elected: make(chan struct{}),
EnvoyGateway: egv1a1.DefaultEnvoyGateway(),
ControllerNamespace: env.Lookup("ENVOY_GATEWAY_NAMESPACE", DefaultNamespace),
DNSDomain: env.Lookup("KUBERNETES_CLUSTER_DOMAIN", DefaultDNSDomain),
Logger: logging.DefaultLogger(logOut, egv1a1.LogLevelInfo),
Elected: make(chan struct{}),
}, nil
}

Expand All @@ -57,7 +57,7 @@ func (s *Server) Validate() error {
switch {
case s == nil:
return errors.New("server config is unspecified")
case len(s.Namespace) == 0:
case len(s.ControllerNamespace) == 0:
return errors.New("namespace is empty string")
}
if err := validation.ValidateEnvoyGateway(s.EnvoyGateway); err != nil {
Expand Down
6 changes: 3 additions & 3 deletions internal/envoygateway/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ func TestValidate(t *testing.T) {
Provider: egv1a1.DefaultEnvoyGatewayProvider(),
},
},
Namespace: "",
ControllerNamespace: "",
},
expect: false,
},
{
name: "unspecified envoy gateway",
cfg: &Server{
Namespace: "test-ns",
Logger: logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo),
ControllerNamespace: "test-ns",
Logger: logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo),
},
expect: false,
},
Expand Down
2 changes: 1 addition & 1 deletion internal/extension/registry/extension_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@

return &Manager{
k8sClient: cli,
namespace: cfg.Namespace,
namespace: cfg.ControllerNamespace,

Check warning on line 80 in internal/extension/registry/extension_manager.go

View check run for this annotation

Codecov / codecov/patch

internal/extension/registry/extension_manager.go#L80

Added line #L80 was not covered by tests
extension: *extension,
}, nil
}
Expand Down
5 changes: 3 additions & 2 deletions internal/gatewayapi/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@
GlobalRateLimitEnabled: r.EnvoyGateway.RateLimit != nil,
EnvoyPatchPolicyEnabled: r.EnvoyGateway.ExtensionAPIs != nil && r.EnvoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy,
BackendEnabled: r.EnvoyGateway.ExtensionAPIs != nil && r.EnvoyGateway.ExtensionAPIs.EnableBackend,
Namespace: r.Namespace,
ControllerNamespace: r.ControllerNamespace,
GatewayNamespaceMode: r.EnvoyGateway.GatewayNamespaceMode(),

Check warning on line 161 in internal/gatewayapi/runner/runner.go

View check run for this annotation

Codecov / codecov/patch

internal/gatewayapi/runner/runner.go#L160-L161

Added lines #L160 - L161 were not covered by tests
MergeGateways: gatewayapi.IsMergeGatewaysEnabled(resources),
WasmCache: r.wasmCache,
ListenerPortShiftDisabled: r.EnvoyGateway.Provider != nil && r.EnvoyGateway.Provider.IsRunningOnHost(),
Expand Down Expand Up @@ -312,7 +313,7 @@
func (r *Runner) loadTLSConfig(ctx context.Context) (tlsConfig *tls.Config, salt []byte, err error) {
switch {
case r.EnvoyGateway.Provider.IsRunningOnKubernetes():
salt, err = hmac(ctx, r.Namespace)
salt, err = hmac(ctx, r.ControllerNamespace)
if err != nil {
return nil, nil, fmt.Errorf("failed to get hmac secret: %w", err)
}
Expand Down
6 changes: 3 additions & 3 deletions internal/gatewayapi/securitypolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -905,14 +905,14 @@
// HMAC secret is generated by the CertGen job and stored in a secret
// We need to rotate the HMAC secret in the future, probably the same
// way we rotate the certs generated by the CertGen job.
hmacSecret := resources.GetSecret(t.Namespace, oidcHMACSecretName)
hmacSecret := resources.GetSecret(t.ControllerNamespace, oidcHMACSecretName)
if hmacSecret == nil {
return nil, fmt.Errorf("HMAC secret %s/%s not found", t.Namespace, oidcHMACSecretName)
return nil, fmt.Errorf("HMAC secret %s/%s not found", t.ControllerNamespace, oidcHMACSecretName)

Check warning on line 910 in internal/gatewayapi/securitypolicy.go

View check run for this annotation

Codecov / codecov/patch

internal/gatewayapi/securitypolicy.go#L910

Added line #L910 was not covered by tests
}
hmacData, ok := hmacSecret.Data[oidcHMACSecretKey]
if !ok || len(hmacData) == 0 {
return nil, fmt.Errorf(
"HMAC secret not found in secret %s/%s", t.Namespace, oidcHMACSecretName)
"HMAC secret not found in secret %s/%s", t.ControllerNamespace, oidcHMACSecretName)

Check warning on line 915 in internal/gatewayapi/securitypolicy.go

View check run for this annotation

Codecov / codecov/patch

internal/gatewayapi/securitypolicy.go#L915

Added line #L915 was not covered by tests
}

return &ir.OIDC{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ infraIR:
gateway.envoyproxy.io/owning-gateway-name: gateway-1
gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
name: envoy-gateway/gateway-1
namespace: envoy-gateway-system
xdsIR:
envoy-gateway/gateway-1:
accessLog:
Expand Down
1 change: 1 addition & 0 deletions internal/gatewayapi/testdata/accesslog.out.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ infraIR:
gateway.envoyproxy.io/owning-gateway-name: gateway-1
gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
name: envoy-gateway/gateway-1
namespace: envoy-gateway-system
xdsIR:
envoy-gateway/gateway-1:
accessLog:
Expand Down
Loading
Loading