Cast Off is a Go-based Kubernetes controller that orchestrates node-by-node Cilium pod refreshes after a detected Cilium version change or Cilium ConfigMap change.
Important
Cast Off is currently an early release. Interfaces and behavior may change as the project matures.
Issues can be raised in the Cast Off GitHub repository. External contributions are not expected at this time, and will be considered and welcomed in the future once the project is more mature and stable.
The controller:
- Uses leader election so only one pod is active at a time.
- Stores rollout state in a ConfigMap.
- Processes nodes sequentially: drain node, recycle Cilium pods, wait for readiness, uncordon.
- Monitors
cilium-configandcilium-envoy-configchanges and triggers the same rollout flow when changes are detected. - Tracks config-change rollout state with
config_map_changes_detected,cilium_config_hash, andcilium_envoy_config_hashin the state ConfigMap. - Automatically manages Cilium Envoy safe rollout behavior when
enable-l7-proxy=true, with an explicit override available via configuration. - Resumes in-progress update runs after restart with a 10-second startup delay when
cast_off=false.
cmd/cast-off- Application entrypoint.internal/config- Runtime configuration parsing.internal/controller- Controller state machine and Kubernetes operations.charts/cast-off- Helm chart for deployment.
- Go 1.26+
- Kubernetes cluster access (for runtime execution)
- Helm 3+ (for chart deployment)
- Docker (for container image builds)
Use the Makefile targets from repository root:
make help
make tidy
make test
make buildThis produces a local development binary at:
bin/cast-off
To build a Linux binary suitable for use in a Docker image:
make build-linuxThis produces:
bin/cast-off-linux-amd64
To build for a different architecture:
make build-linux GOARCH=arm64Build using the Dockerfile with Makefile defaults:
make docker-buildBy default this creates:
quay.io/neumanndaniel/cast-off:dev
Override image coordinates:
make docker-build REGISTRY=docker.io REPOSITORY=your-org IMAGE_NAME=cast-off IMAGE_TAG=v1.0.0Push the built image:
make docker-push REGISTRY=docker.io REPOSITORY=your-org IMAGE_NAME=cast-off IMAGE_TAG=v1.0.0Build and push in one step:
make docker-release-multi REGISTRY=docker.io REPOSITORY=your-org IMAGE_NAME=cast-off IMAGE_TAG=v1.0.0make govulncheckmake runOptional kubeconfig path:
go run ./cmd/cast-off --kubeconfig ~/.kube/configThis repository includes a multi-stage Dockerfile at Dockerfile that:
- Builds a static Linux binary with Go 1.26.
- Uses a Chainguard distroless runtime image (
cgr.dev/chainguard/static:latest). - Runs as a non-root user (
65532:65532).
Build directly with Docker:
docker build -t cast-off:latest .Run locally:
docker run --rm cast-off:latestChart location:
charts/cast-off
Lint chart:
helm lint charts/cast-offInstall from OCI registry (recommended):
helm upgrade --install cast-off oci://quay.io/neumanndaniel/cast-off --version 0.0.1 \
--namespace cast-off \
--create-namespacePull first, then install:
helm pull oci://quay.io/neumanndaniel/cast-off --version 0.0.1
helm upgrade --install cast-off ./cast-off-0.0.1.tgz \
--namespace cast-off \
--create-namespaceNote: Registry login is only required for private registries.
Install from local chart source:
helm upgrade --install cast-off charts/cast-off -n cast-off --create-namespaceThis project currently uses a Makefile-only release flow for Helm chart artifacts.
Prerequisites:
- Helm 3.8+ with OCI support
- Registry authentication if pushing (
helm registry login)
Release commands:
# Lint and template validation
make chart-lint
# Local artifacts only (no push)
make chart-release-local RELEASE_VERSION=0.0.1
# Full release including OCI push
make chart-release RELEASE_VERSION=0.0.1Artifacts are created under dist/:
cast-off-<version>.tgzrelease-notes-<version>.mdrelease-<version>/bundle directory
See RELEASE.md for the full release checklist and runbook.
Cast Off persists runtime state in the ConfigMap defined by STATE_CONFIGMAP_NAME (default: cast-off-cilium).
The following list is the complete set of keys used for state management:
deployed_version: Last observed deployed Cilium app version.deployed_release_revision: Last observed deployed Helm release revision.nodes_to_update: JSON array of node names queued for the current update run.cast_off:truewhen idle;falsewhen an update run is active or pending resume.config_map_changes_detected:truewhen the current run was triggered by Cilium ConfigMap changes.helm_release_detected:truewhen the current run was triggered by a Helm release rollout change.update_run_id: Identifier for the current update run; cleared when the run is fully finalized.cilium_config_hash: Last persisted content hash ofcilium-config.cilium_envoy_config_hash: Last persisted content hash ofcilium-envoy-config.
Apache License 2.0