Skip to content

fix(infra): skip envoy-gateway's bundled CRDs, they conflict with our own - #23

Merged
jonathandieu merged 2 commits into
mainfrom
fix-envoy-gateway-crd-channel-conflict
Jul 9, 2026
Merged

fix(infra): skip envoy-gateway's bundled CRDs, they conflict with our own#23
jonathandieu merged 2 commits into
mainfrom
fix-envoy-gateway-crd-channel-conflict

Conversation

@jonathandieu

@jonathandieu jonathandieu commented Jul 9, 2026

Copy link
Copy Markdown
Owner

envoy-gateway-stage-do-atl1 has failed to sync since yesterday, retrying 270+ times:

customresourcedefinitions.apiextensions.k8s.io "grpcroutes.gateway.networking.k8s.io" is forbidden:
ValidatingAdmissionPolicy 'safe-upgrades.gateway.networking.k8s.io' denied request:
Installing experimental CRDs on top of standard channel CRDs is prohibited by default.

Root cause

gateway-helm's bundled CRDs are hardcoded to the "experimental" Gateway API channel (verified against the actual chart tarball - every CRD carries that annotation, no values toggle exists to change it, no condition on the crds subchart dependency to disable it either).

Stage already has "standard" channel Gateway API CRDs, from our own dedicated gateway-api-crds appset (pulls directly from kubernetes-sigs/gateway-api upstream at v1.2.1, config/crd/standard, cloud-agnostic, on every cluster). envoy-gateway's own bundled copy just conflicts with it.

Platform never hit this because its envoy-gateway CRDs happened to install successfully first (before this repo's gateway-api-crds appset existed there), so every sync since has been a no-op update rather than a fresh install attempt.

Why this isn't DOKS/Cilium-specific, and why we're keeping envoy-gateway rather than switching to Cilium's own Gateway API

This is a known, acknowledged upstream tension, not a DOKS quirk: envoyproxy/gateway#7238 - Envoy Gateway still defaults to the experimental channel for historical reasons (2022, when standard channel lacked features), and by the maintainers' own words it now "installs unsupported experimental CRDs like ListenerSet into clusters unnecessarily."

DOKS's Cilium ships a working Gateway API implementation for free, but EKS and GKE don't have an equivalent free option (GKE has its own separate, non-Cilium native controller; EKS has no default Cilium at all; AKS's managed Cilium doesn't expose Gateway API config). Since EKS/DOKS/GKE are all real near-term targets for dieu.dev, keeping one portable, self-installed implementation (Envoy Gateway) that works identically on all three is worth the one-time setup cost here, versus juggling a different native Gateway API story per cloud.

Fix

helm.skipCrds: true on envoy-gateway's Application source, in its own dedicated envoy-gateway ApplicationSet rather than a list entry in the shared infrastructure one.

envoy-gateway needed to move out of the shared appset because ArgoCD ApplicationSets can't template boolean fields (documented: "This field may NOT be templated, because it is a boolean field"). A per-item skipCrds: {{ .skipCrds }} broke argocd-validate's raw-YAML parse (unquoted {{ }} reads as a YAML flow mapping), and quoting it would only have traded that for a real Application-admission failure instead ("skipCrds in body must be of type boolean: 'string'" - a documented failure others have hit the same way). Its own appset (same clusters: {} generator and override-file pattern as the shared one) lets skipCrds: true be a real, non-templated boolean.

Deliberately not disabling CRD installation and hoping the CNI already provides them - that would only work by accident on DOKS and leaves EKS with no Gateway API CRDs if its CNI doesn't provide them. skipCrds instead relies on our own portable gateway-api-crds appset, which runs on every cluster regardless of cloud/CNI.

What we lose vs. what we don't

Only genuinely experimental-only types are affected: TCPRoute/UDPRoute/TLSRoute/ListenerSet. GRPCRoute is not one of them - it graduated to the standard channel in Gateway API v1.1 (2024) and is already included in our gateway-api-crds appset's v1.2.1 bundle (verified directly against the upstream repo's config/crd/standard directory at that tag). Envoy Gateway's own Gateway object already lists GRPCRoute as a supported kind on both listeners today.

… own

envoy-gateway-stage-do-atl1 has failed to sync since yesterday, retrying
270+ times:

  customresourcedefinitions.apiextensions.k8s.io "grpcroutes..." is
  forbidden: ValidatingAdmissionPolicy 'safe-upgrades...' denied request:
  Installing experimental CRDs on top of standard channel CRDs is
  prohibited by default.

gateway-helm's bundled CRDs are hardcoded to the "experimental" Gateway
API channel (verified against the actual chart - every CRD in its
bundle carries that annotation, no values toggle exists to change it,
no condition on the crds subchart dependency to disable it either).
Stage already has "standard" channel Gateway API CRDs from our own
dedicated gateway-api-crds appset (pulls directly from
kubernetes-sigs/gateway-api upstream, cloud-agnostic, on every
cluster) - envoy-gateway's own copy just conflicts with it.

Platform never hit this because its envoy-gateway CRDs happened to
install successfully first, so every sync since has been a no-op
update rather than a fresh install attempt.

Not disabling CRD installation and hoping the CNI already provides
them - that would only work by accident on DOKS and could leave EKS
with no Gateway API CRDs at all. skipCrds relies on our own portable
gateway-api-crds appset instead, which runs on every cluster regardless
of cloud/CNI.
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

Helm template diff

diff -u --recursive --label base --label head base head
--- base
+++ head
@@ -218,7 +218,7 @@
     app.kubernetes.io/managed-by: Helm
 type: Opaque
 data:
-  SECRET_KEY_BASE: V3BHYVFHR3k3S0Q3STJzMmFheU9DOWNOQUVxT0puaWZmSmNLd2ZmSDRQN3d2eUx2QnBGRExtSEZlQ3ozR3dWUUZJWThJdkJNQ1o5MW1BWnBjUWxnYjNPUGVk
+  SECRET_KEY_BASE: dGpqV2E4aEF5N2dmRXNmWkd3em1kd20zVmwxTG8wZlc4VVlDdUNHdUZOcGpINGdyZkU2SjdsRDVlMjF2eGNEbGVHZnZsRFJtbTFSNEVscjk2VlhRbHFacWJ0
   TOTP_VAULT_KEY: ZHN4dmJuM2p4RGQxNmF6MlFwc1g1QjhPK2xseGpRMlNKRTJpNUJ6eDM4ST0=
   DATABASE_URL: cG9zdGdyZXM6Ly9wb3N0Z3Jlczpwb3N0Z3Jlc0BwbGF1c2libGUtYW5hbHl0aWNzLXBvc3RncmVzcWw6NTQzMi9wbGF1c2libGVfZGI=
   CLICKHOUSE_DATABASE_URL: aHR0cDovL2NsaWNraG91c2U6cGFzc3dvcmRAcGxhdXNpYmxlLWFuYWx5dGljcy1jbGlja2hvdXNlOjgxMjMvcGxhdXNpYmxlX2V2ZW50c19kYg==

@jonathandieu jonathandieu self-assigned this Jul 9, 2026
@jonathandieu
jonathandieu marked this pull request as ready for review July 9, 2026 12:01
@jonathandieu
jonathandieu requested a review from Copilot July 9, 2026 12:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Updates the infrastructure ApplicationSet to prevent envoy-gateway from installing its bundled Gateway API CRDs, avoiding conflicts with the repo’s dedicated gateway-api-crds installation (standard channel CRDs).

Changes:

  • Adds a per-app skipCrds flag to the infrastructure ApplicationSet list generator.
  • Enables helm.skipCrds: true specifically for envoy-gateway, leaving other infrastructure apps unchanged.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread argocd/apps/infrastructure/appset.yaml
…lated

ArgoCD ApplicationSets can't template boolean fields (documented -
"This field may NOT be templated, because it is a boolean field").
skipCrds: {{ .skipCrds }} in the shared infrastructure appset's list
generator broke argocd-validate's raw-YAML parse (unquoted {{ }} reads
as a YAML flow mapping) - and quoting it would have "fixed" that only
to fail for real at Application admission instead
("skipCrds in body must be of type boolean: 'string'", a documented
failure others have hit the same way).

envoy-gateway now gets its own ApplicationSet (same clusters: {}
generator, same value-file/override pattern as the shared one) so
skipCrds: true can be a real, non-templated boolean.
@jonathandieu
jonathandieu requested a review from Copilot July 9, 2026 12:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Comment on lines +17 to +23
- repoURL: https://github.com/jonathandieu/dieubernetes
targetRevision: HEAD
ref: values
# chart source: umbrella chart with base values + optional cluster override
- repoURL: https://github.com/jonathandieu/dieubernetes
targetRevision: HEAD
path: charts/infrastructure/envoy-gateway
Comment on lines +11 to +12
metadata:
name: "envoy-gateway-{{ .name }}"
@jonathandieu
jonathandieu merged commit 65e66a9 into main Jul 9, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants