Feat/helm charts#182
Conversation
Adds two Helm charts to complement the existing kustomize-based installation: - charts/cloudflare-operator: installs the controller Deployment, CRDs, RBAC (manager, leader-election, metrics-auth, metrics-reader roles), and ServiceAccount. CRDs are copied verbatim from config/crd/bases/ to avoid the symlink packaging failure that blocked the earlier WIP PR (adyanth#143). - charts/cloudflare-tunnels: renders ClusterTunnel CRs from a values list, centralising shared settings (protocol, rolling strategy, cloudflared args including --edge-ip-version auto, hard pod anti-affinity) so individual tunnel definitions only supply name and domain. Also adds: - make helm-sync-crds target (hooked into the existing manifests target) to keep chart CRDs in sync with controller-gen output, preventing drift. - helm/chart-releaser-action job in release.yml to publish both charts to GitHub Pages on version tags. Closes adyanth#108
Add publish-charts job to the CI workflow that packages both Helm charts and pushes them to oci://ghcr.io/<owner>/charts using helm push. Uses github.repository_owner so the registry path is correct regardless of which fork the workflow runs in — no hardcoded paths. Triggers on pushes to main and feat/helm-charts (for branch testing), and on version tags alongside the existing chart-releaser job.
Replace the freeform args list in cloudflare-tunnels/values.yaml with explicit protocol and edgeIpVersion fields. The template now constructs the cloudflared args internally from these values, ensuring correctness and preventing invalid combinations. Adds fail validations for both fields: - protocol: must be one of http2, h2mux, auto - edgeIpVersion: must be one of auto, 4, 6 - replicas: must be >= 1 Updates getting-started.md with a full Helm installation section covering both the cloudflare-operator and cloudflare-tunnels charts, including a values reference table.
…om tag Update all actions to their current latest releases: - actions/checkout: v4 -> v6.0.2 - azure/setup-helm: v4 -> v5.0.0 - docker/login-action: v1/v3 -> v4.1.0 - docker/metadata-action: v3 -> v6.0.0 - docker/setup-qemu-action: v1 -> v4.0.0 - docker/setup-buildx-action: v1 -> v4.0.0 - docker/build-push-action: v2 -> v7.1.0 - peter-evans/dockerhub-description: v3 -> v5.0.0 - helm/chart-releaser-action: v1.6.0 -> v1.7.0 - actions/setup-go: already on v5 (current latest major) Add 'Derive chart version' step to publish-charts job: when triggered by a version tag (e.g. v0.14.0) the tag is used as both --version and --app-version in helm package, ensuring the OCI chart version matches the operator release. On branch pushes the Chart.yaml version is used as-is.
… sync with Makefile VERSION
| labels: ${{ steps.meta.outputs.labels }} | ||
| - name: Docker Hub Description | ||
| if: github.event.ref_type == 'tag' || github.event_name == 'workflow_dispatch' | ||
| uses: peter-evans/dockerhub-description@v3 |
There was a problem hiding this comment.
appreciate you didn't set this up but it would produce meaningful security guarantees if we switch to a hash for actions
There was a problem hiding this comment.
Done ✔️ I'll disclaim though that there's a lot of them so I let Claude do these updates for me. All seems to be working though.
| $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases | ||
|
|
||
| .PHONY: helm-sync-crds | ||
| helm-sync-crds: ## Sync CRD YAMLs from config/crd/bases into charts/cloudflare-operator/crds/ |
There was a problem hiding this comment.
possibly I missed it, but we'll want some kind of CI time check to ensure that this has been run. something that runs the makefile command, and asserts that doing so doesn't produce a diff
There was a problem hiding this comment.
I've added a step to the lint workflow that should do this and give a helpful message if it fails
| @@ -0,0 +1,111 @@ | |||
| --- | |||
| apiVersion: apiextensions.k8s.io/v1 | |||
There was a problem hiding this comment.
something just occurred to me, could these be symlinks?
|
one comment occurred to me and no idea if it works. LGTM |
Summary
Adds two Helm charts to
charts/, published tooci://ghcr.io/adyanth/chartsvia an updated release workflow.charts/cloudflare-operator— installs the operator: Deployment, CRDs, RBAC, ServiceAccount, webhook Service, and a self-signed cert-manager Certificate for the conversion webhook.charts/cloudflare-tunnels— rendersClusterTunnelCRs from a values list. Shared settings (protocol,edgeIpVersion, rolling strategy, anti-affinity) are defined once indefaultsand can be overridden per tunnel. Individual entries only neednameanddomain.Design decisions
CRDs in
/crds— copied verbatim fromconfig/crd/bases/, not symlinked.make helm-sync-crds(hooked intomake manifests) keeps them in sync automatically.appVersionfromMakefile—make helm-sync-versions(also hooked intomake manifests) writesVERSIONintoChart.yaml, keeping a single source of truth.Structured values over raw
args—protocolandedgeIpVersionare first-class values; the template builds the correctcloudflaredargument sequence and validates both fields at render time.QUIC as default protocol — QUIC reconnects in under a second via 0-RTT; HTTP/2 TCP can take 10–20s due to SYN-retry backoff during Cloudflare edge rotation. Operators who need HTTP/2 can set
defaults.protocol: http2.Webhook TLS — the operator crashes without TLS certs at startup. The chart provisions a self-signed cert-manager
Issuer+Certificateby default (webhook.certManager.enabled: true), which can be disabled to supply the Secret manually.OCI publishing —
release.ymlgains apublish-chartsjob usinghelm push. Chart version comes fromChart.yamlon branch pushes and from the git tag on releases.On RBAC maintenance
The previous Helm PR (#143) stalled partly on this. The RBAC in
templates/rbac.yamlis derived directly from the existingconfig/rbac/manifests that controller-gen already maintains — it isn't hand-authored from scratch. Re-syncing is needed when roles change, but that's the same review thatconfig/rbac/already gets on any controller change.The kubebuilder
helm-v1-alphaplugin (noted by @adyanth) could replace this long-term via full autogeneration, but it's currently alpha and requires a more significant build toolchain change. This chart gets something working now with an explicit, reviewable sync point.Testing
Both charts have been deployed to a live 3-node k3s cluster via Flux HelmReleases backed by the OCI registry, running stably across multiple domains with pod anti-affinity and QUIC connections verified in cloudflared logs.
Notes
— fixed by bumping CONTROLLER_TOOLS_VERSION to v0.21.0.make manifestscurrently fails to buildcontroller-genunder Go 1.24 due to a bug ingolang.org/x/tools@v0.24.0charts/cloudflare-operator/crds/have been updated as a result of the above but contain only cosmetic changes.