GitOps Workflows
Deploy by changing your manifests, not by running kubectl against a cluster. KSail packages your
source directory as a versioned OCI artifact and a built-in GitOps engine (Flux or
ArgoCD) continuously reconciles the cluster to match. This is the workflow KSail is built around, and the
same two commands carry you from laptop to production.
The GitOps loop
Section titled “The GitOps loop”edit k8s/ ──► ksail workload push ──► ksail workload reconcile ──► Flux/ArgoCD applies ▲ (compile + (tell the engine │ └──────────────── push OCI artifact) to pull & apply) ──────────────┘ksail workload pushcompiles your source directory (spec.workload.sourceDirectory, defaultk8s) into an OCI artifact and pushes it tospec.cluster.localRegistry.registry.ksail workload reconciletriggers the in-cluster GitOps engine to pull that artifact and apply it, then waits for the rollout to converge.
Deploy with GitOps
Section titled “Deploy with GitOps”-
Choose the engine at init. Pick Flux or ArgoCD when you scaffold the project:
Terminal window ksail cluster init --gitops-engine Flux --local-registry localhost:5050This wires a GitOps engine and a local OCI registry into
ksail.yaml:# ksail.yaml (excerpt)spec:cluster:gitOpsEngine: FluxlocalRegistry:registry: localhost:5050workload:sourceDirectory: k8s -
Create the cluster.
ksail cluster createprovisions the cluster, installs the engine, and bootstraps it to watch your registry — no separateflux bootstrapstep required.Terminal window ksail cluster create -
Push and reconcile. Edit manifests under
k8s/, then ship them:Terminal window ksail workload push # compile k8s/ and push the OCI artifactksail workload reconcile # tell the engine to pull and apply it -
Watch it converge.
Terminal window ksail workload get pods -A
Every change from now on is the same two commands — or just a git push once you wire push/reconcile
into CI/CD.
Validate before you ship
Section titled “Validate before you ship”ksail workload validate and ksail workload scan are offline CI gates — they check your manifests
without a cluster, so they run anywhere:
ksail workload validate # schema (kubeconform) + Flux ${var} substitutionksail workload scan --framework nsa --compliance-threshold 80 # Kubescape security posturevalidateruns schema validation and resolves Flux post-build (${var}) substitutions, catching bad manifests before they reach a cluster.scanruns Kubescape against a framework (e.g.--framework nsa) and can fail the gate below a--compliance-threshold.
See Workload Management and CI/CD Integration for the full gate.
Multiple environments
Section titled “Multiple environments”One repository drives many clusters: keep a config per environment (ksail.yaml, ksail.prod.yaml, …)
and target each command with --config:
ksail --config ksail.prod.yaml workload validate # check prod's manifests offlineksail --config ksail.prod.yaml workload pushksail --config ksail.prod.yaml workload reconcile--config is the backbone of multi-environment work — same workflow everywhere, one config per cluster.
See the Multi-Environment guide.
As a project grows, the flat k8s/ directory becomes a layered Kustomize repository (shared bases/ →
provider overlays → per-cluster overlays), with each cluster’s spec.workload.kustomizationFile pointing
at its overlay and a Flux dependency chain reconciling bootstrap → infrastructure-controllers → infrastructure → apps in order. See Project Structure & GitOps Layout
for the full layout.
OCI artifact tag
Section titled “OCI artifact tag”spec.workload.tag sets the OCI artifact tag used by both workload push and GitOps reconciliation (Flux
OCIRepository / ArgoCD Application):
spec: workload: tag: v1.2.3 # default: devThe tag is resolved differently depending on the context:
- Push (
ksail workload push): CLIoci://ref >spec.workload.tag> registry-embedded tag >dev. - Reconciliation (Flux / ArgoCD):
spec.workload.tag> registry-embedded tag >dev.
ksail cluster update detects when the live GitOps sync ref (Flux OCIRepository tag or ArgoCD
targetRevision) has drifted from the configured spec.workload.tag and reconciles it in-place — no
manual intervention required. See Declarative Configuration
for the full spec.workload reference.
Bootstrap → GitOps handoff (Flux)
Section titled “Bootstrap → GitOps handoff (Flux)”KSail’s Flux install is a bootstrap seed, not a steady-state owner. Because Flux must exist before it
can sync anything, ksail cluster create installs the flux-operator Helm chart and creates a
FluxInstance CR so the operator can start reconciling your repository. Once your repository declares
those same resources, the repository becomes the steady-state owner and KSail defers to it — so the
two never flap against each other.
Seed-if-absent operator
Section titled “Seed-if-absent operator”On every cluster create/update, KSail checks the flux-operator Helm release before installing:
- If the release is already owned by a GitOps controller (its Helm storage Secret carries a Flux
helm.toolkit.fluxcd.io/namelabel, or an ArgoCDargocd.argoproj.io/managed-bylabel), KSail skips the install and printsflux-operator: skipping install — release "flux-operator" is managed by <controller>. This means a repo-declaredflux-operatorHelmRelease owns the version, and repeated KSail runs never downgrade or flap it. - Otherwise KSail seeds (or upgrades to) its configured/pinned version, exactly as before.
For your HelmRelease to be adopted, it must target Helm release flux-operator in namespace
flux-system (the release KSail seeds). Flux then adopts that release on its next reconcile.
Repo-declared FluxInstance
Section titled “Repo-declared FluxInstance”If your source directory declares a FluxInstance named flux in flux-system (or one labelled
app.kubernetes.io/managed-by: ksail), KSail reads its spec.distribution block and seeds the
FluxInstance with that distribution version (and registry/artifact when present) instead of its
built-in default — so the seed matches what Flux will reconcile. KSail always keeps its own computed
spec.sync block (the OCI source pointing at your registry), so GitOps sync keeps working after
bootstrap regardless of what the repo’s FluxInstance specifies for sync.
Pinning the seed from ksail.yaml
Section titled “Pinning the seed from ksail.yaml”If you do not want to maintain a full HelmRelease/FluxInstance in the repo, pin the seed versions directly (Renovate-trackable):
spec: workload: flux: operatorVersion: 0.50.0 # flux-operator Helm chart version to seed (empty = KSail's pinned version) distributionVersion: 2.x # FluxInstance spec.distribution.version to seed (empty = KSail's default)Precedence: a repo-declared FluxInstance distribution version > spec.workload.flux.distributionVersion
> KSail’s default. For the operator, spec.workload.flux.operatorVersion sets the seed version, but a
repo-owned flux-operator release always wins (KSail defers to it as above). ksail cluster update
detects and reconciles a changed distributionVersion in-place. See
Declarative Configuration for the full spec.workload.flux
reference.
How reconcile recovers and reports
Section titled “How reconcile recovers and reports”ksail workload reconcile does more than trigger a sync — it self-heals common failures and surfaces
diagnostics so you rarely need to reach for kubectl.
Automatic HelmRelease recovery
Section titled “Automatic HelmRelease recovery”Before polling Kustomizations, reconcile detects HelmReleases stuck in a non-recoverable state
(Ready=False with a failure reason such as InstallFailed/UpgradeFailed, or Stalled=True) and
suspends-then-resumes each one so the helm-controller retries — no manual kubectl patch workaround
needed. HelmReleases with DependencyNotReady are skipped (transient, they resolve on their own), and
individual reset failures are logged but do not abort reconciliation.
Automatic failure diagnostics
Section titled “Automatic failure diagnostics”When reconcile fails, KSail collects and displays a targeted diagnostic report instead of leaving you to
investigate by hand:
- Failing GitOps resources — Flux Kustomizations, HelmReleases, and OCIRepositories (or ArgoCD Applications) with their condition reason and message (only non-ready resources are shown)
- Failing pods — non-ready pods in the GitOps namespace
- Recent warning events — all Kubernetes warning events from the GitOps namespace in the last 5 minutes
Diagnostics are best-effort with a 15-second timeout. If the cluster is unreachable, the section is silently skipped so the original reconciliation error stays prominent.
Excluding long-running Kustomizations (Flux only)
Section titled “Excluding long-running Kustomizations (Flux only)”Some Flux Kustomizations are intentionally long-running and should not block command completion. Exclude
them from progress monitoring with either an annotation or a CLI flag — they are still applied, they just
don’t block reconcile:
# annotation on the Kustomizationmetadata: annotations: ksail.devantler.tech/reconcile-exclude: "true"# CLI flag (repeatable, comma-separated)ksail workload reconcile --exclude my-kustomizationksail workload reconcile --exclude "kust-a, kust-b"This is Flux-specific and does not affect ArgoCD Application reconciliation.
Automatic retry
Section titled “Automatic retry”Both workload push and workload reconcile retry on transient failures: up to 3 attempts with
exponential backoff starting at 5s (capped at 30s) — so retries wait 5s after the first failure and 10s
after the second. Retryable conditions come from the shared netretry.IsRetryable predicate (HTTP 429,
5xx, connection refused, i/o timeout, unexpected EOF, no such host, TCP resets, context deadline exceeded,
and similar), and a warning is printed on each attempt. For reconcile, a --timeout is a per-attempt
bound — total runtime can reach maxAttempts × timeout plus backoff.
Related
Section titled “Related”- Deliver with GitOps — the guided first run of this workflow.
- Project Structure & GitOps Layout — how
k8s/grows into a layered repository. - Multi-Environment Workflows — driving many clusters with
--config. - CI/CD Integration — wiring
validate/scan/push/reconcileinto pipelines. - Secret Management — encrypting secrets in your GitOps source.
- ArgoCD ApplicationSet — multi-environment GitOps with ArgoCD.
- Tenant Management — onboard teams with GitOps sync resources.