Skip to content

feat(infra): replace Envoy Gateway with DOKS-native Cilium Gateway API - #29

Merged
jonathandieu merged 2 commits into
mainfrom
feat/cilium-gateway-migration
Jul 19, 2026
Merged

feat(infra): replace Envoy Gateway with DOKS-native Cilium Gateway API#29
jonathandieu merged 2 commits into
mainfrom
feat/cilium-gateway-migration

Conversation

@jonathandieu

Copy link
Copy Markdown
Owner

Summary

  • Removes Envoy Gateway from the infrastructure AppSet. DOKS 1.33+ manages the cilium GatewayClass and Gateway API CRDs natively, so a separate controller is no longer needed.
  • Adds charts/infrastructure/cilium-gateway/: a lightweight chart that creates a single Gateway per cluster. LB annotations are passed via spec.infrastructure.annotations, which Cilium applies atomically at Service creation -- no CCM ordering race.
  • Switches all workload HTTPRoute objects to parentRef: public / cilium-gateway-system.
  • Enables cloudflare.proxied: true in external-dns so DNS records route through Cloudflare.
  • Stage cluster override sets gateway.create: true and wires in the Terraform-provisioned LB ID.

Fixes the Envoy Gateway CCM loop that has been causing 422 errors and keeping public ingress down on stage since 2026-07-09.

Closes #28.

Test plan

  • Merge to main; ArgoCD syncs cilium-gateway-stage-do-atl1 and creates the Gateway in cilium-gateway-system
  • Confirm kubectl get gateway public -n cilium-gateway-system shows Programmed: True
  • Confirm kubectl get svc -n cilium-gateway-system shows the LB with the expected external IP
  • Check analytics.dieu.dev, meals.dieu.dev, changedetection.dieu.dev resolve and return 200
  • Confirm no new 422 errors in the DO LB event log

Envoy Gateway's create-then-patch Service approach causes a CCM race on DO
clusters: CCM starts creating a new LB before the adoption annotation lands,
then hits a 422 loop. Cilium applies spec.infrastructure.annotations atomically
so CCM sees the adoption annotation on first reconciliation.

- Remove envoy-gateway from the infra appset; DOKS 1.33+ manages the cilium
  GatewayClass and Gateway API CRDs natively -- no chart needed for either
- Add charts/infrastructure/cilium-gateway/: creates one Gateway per cluster
  with an lbAnnotations passthrough for provider-specific LB adoption
- Switch all workload HTTPRoutes to parentRef public/cilium-gateway-system
- Enable cloudflare.proxied: true in external-dns

Stage override enables the Gateway and sets lb_id to the Terraform-provisioned
LB (confirmed from terraform output lb_id).

Closes #28.

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

This PR migrates cluster ingress from the Envoy Gateway controller to the DOKS-native Cilium Gateway API setup, aiming to eliminate the DigitalOcean CCM LB adoption race that’s been causing 422 errors and ingress downtime.

Changes:

  • Replaces the infrastructure ApplicationSet entry for Envoy Gateway with a new cilium-gateway app/namespace.
  • Introduces a lightweight cilium-gateway Helm chart that can create a Gateway (and optionally a GatewayClass) and passes LB annotations via spec.infrastructure.annotations.
  • Updates workload HTTPRoute resources to attach to Gateway public in cilium-gateway-system, and enables Cloudflare proxying in external-dns.

Reviewed changes

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

Show a summary per file
File Description
clusters/stage-do-atl1/overrides/cilium-gateway.yaml Enables Gateway creation on stage and configures DO LB adoption annotations.
charts/workloads/plausible/templates/httproute.yaml Re-points Plausible HTTPRoute parentRef to the new Cilium Gateway.
charts/workloads/mealie/templates/httproute.yaml Re-points Mealie HTTPRoute parentRef to the new Cilium Gateway.
charts/workloads/changedetection/templates/httproute.yaml Re-points Changedetection HTTPRoute parentRef to the new Cilium Gateway.
charts/infrastructure/external-dns/values.yaml Enables cloudflare.proxied: true for external-dns-managed records.
charts/infrastructure/cilium-gateway/values.yaml Adds default configuration for the new Cilium Gateway chart (GatewayClass/Gateway + TLS + LB annotations).
charts/infrastructure/cilium-gateway/templates/gatewayclass.yaml Conditionally creates the cilium GatewayClass when self-managed.
charts/infrastructure/cilium-gateway/templates/gateway.yaml Conditionally creates the Gateway with listeners and spec.infrastructure.annotations passthrough.
charts/infrastructure/cilium-gateway/Chart.yaml Defines the new Helm chart metadata.
argocd/apps/infrastructure/appset.yaml Swaps envoy-gateway for cilium-gateway in infra AppSet.

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

Comment on lines +6 to +9
gateway:
# Off by default; enable per-cluster in clusters/<name>/overrides/cilium-gateway.yaml.
create: false
name: public
Comment on lines +1 to +4
gateway:
create: true
lbAnnotations:
kubernetes.digitalocean.com/load-balancer-id: "f0f43b4a-d2cd-4f82-a4f1-4bebccd2b3ac"
Comment on lines +10 to +13
# Provider-specific annotations passed through to spec.infrastructure.annotations,
# which Cilium applies atomically at Service creation -- no CCM ordering race.
# DO example: kubernetes.digitalocean.com/load-balancer-id: "<terraform output lb_id>"
# AWS example: service.beta.kubernetes.io/aws-load-balancer-type: external
@github-actions

Copy link
Copy Markdown

Helm template diff

diff -u --recursive --label base --label head base head
--- base
+++ head
@@ -67,8 +67,8 @@
   name: release
 spec:
   parentRefs:
-    - name: envoy-gateway
-      namespace: envoy-gateway-system
+    - name: public
+      namespace: cilium-gateway-system
   hostnames:
     - changes.dieu.dev
   rules:
Only in /tmp/head: cilium-gateway.yaml
diff -u --recursive --label base --label head base head
--- base
+++ head
@@ -74,8 +74,8 @@
   name: release
 spec:
   parentRefs:
-    - name: envoy-gateway
-      namespace: envoy-gateway-system
+    - name: public
+      namespace: cilium-gateway-system
   hostnames:
     - recipes.dieu.dev
   rules:
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: RTJaUkZydE1pS08xVG5QWTB3ZDBZd2NUcGd6NTMxQXlHME9BeVdLcG1uZk9mSU11eG9ZOWFDNlFjczhuV0lCNW95MmJqRzNLeHgxeEhUNU42SkhXc01PMFJD
+  SECRET_KEY_BASE: VjF2aWhrOFN3RzJkbldzWTNtNmphWm5YTFh4b2NNN1R3anlJYnFmYnVWZVZWWFZxQUtsZlE2alVhSU1EdjZZOENrRUIzVjZRVWs3UjJxbVdVeXdkRXc0Z2pM
   TOTP_VAULT_KEY: ZHN4dmJuM2p4RGQxNmF6MlFwc1g1QjhPK2xseGpRMlNKRTJpNUJ6eDM4ST0=
   DATABASE_URL: cG9zdGdyZXM6Ly9wb3N0Z3Jlczpwb3N0Z3Jlc0BwbGF1c2libGUtYW5hbHl0aWNzLXBvc3RncmVzcWw6NTQzMi9wbGF1c2libGVfZGI=
   CLICKHOUSE_DATABASE_URL: aHR0cDovL2NsaWNraG91c2U6cGFzc3dvcmRAcGxhdXNpYmxlLWFuYWx5dGljcy1jbGlja2hvdXNlOjgxMjMvcGxhdXNpYmxlX2V2ZW50c19kYg==
@@ -1005,8 +1005,8 @@
   name: release
 spec:
   parentRefs:
-    - name: envoy-gateway
-      namespace: envoy-gateway-system
+    - name: public
+      namespace: cilium-gateway-system
   hostnames:
     - analytics.dieu.dev
   rules:

@jonathandieu
jonathandieu merged commit 5070c18 into main Jul 19, 2026
3 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.

fix(ingress): migrate from Envoy Gateway to DOKS-native Cilium Gateway API

2 participants