01 · Who owns this?
Ownership is decided per object, not per namespace.
Every workload in the cluster is classified from its own metadata:
reconciled by a Flux v2 HelmRelease or Kustomization, still on a
legacy Flux v1 release, installed by Helm 3 by hand, installed by
Tiller, owned by an operator, or applied with kubectl
and forgotten.
Helm 3, Tiller and kubectl-applied objects are adoption candidates. Objects owned by an
operator get an informational issue instead: a raw copy would fight
the operator for ownership.
02 · Read the release record
A Tiller release still remembers what it installed.
Helm 2 kept each release as a ConfigMap in the Tiller namespace; Helm
3 keeps a Secret per revision. The assistant decodes the latest
deployed revision: chart name, chart version, and the values it was
installed with.
Here: shop/orders-api, chart
orders-api@2.4.1, deployed five years ago, controller
gone. The workload is frozen at its last apply.
03 · Or read the live object
For hand-applied manifests, the cluster is the source.
A Deployment applied with kubectl has no release record,
so the declaration is rebuilt from the live object itself. Fields
the API server writes (status,
managedFields, uid,
resourceVersion, timestamps, the last-applied
annotation) are stripped. What remains is what someone asked for.
04 · A home Flux actually reads
A file in git is not the same as a file Flux applies.
The new file is placed in a directory that one of your Flux
Kustomizations reconciles, and added to that directory's
kustomization.yaml when it lists resources explicitly.
If the only covering Kustomization turns out to reconcile a
different repository, the whole proposal is held for review: a
manifest nobody applies is worse than none, because it looks done.
05 · No second copy
Adopting must not mean installing twice.
Before emitting, the chart is rendered with helm template
and compared with what already runs elsewhere in the cluster: CRD
names, cluster-wide RBAC on the same resources, webhook
configurations and the services they call.
Any collision drops the diff and turns the finding into an issue
with the conflict report. This check exists because two copies of
one operator competing on the same CRDs is a real outage shape.
06 · Can Flux fetch it?
The chart source must resolve, and the version must not go backwards.
The HelmRelease's sourceRef must point at a
HelmRepository, GitRepository or OCIRepository that exists in git
(or is created in the same MR, once), the pinned version must be
published, and it must not be older than what runs live. A provable
dead end blocks the MR.
Credential-shaped values found in the old release are moved out to
an ExternalSecret instead of being committed.
07 · Prove the first reconcile is a no-op In development
Compare the proposal with what is running, field by field.
A release record can drift from the cluster: a replica count scaled
by hand, a memory limit patched down during an incident. Adopting
the stored values would quietly undo those fixes.
A detector compares the adoption's values with the live workloads
(replicas, resources, images) and lists every divergence. It is
built and ships switched off, report-only; turning it on, then
making it a gate, are the next steps.
08 · Safe to hand over
The HelmRelease must not be able to uninstall what it adopts.
On an adoption, Flux's default install remediation (retry, then
uninstall on failure) would delete the running workload after a
slow rollout. Proposals that combine install retries with a default
timeout over multi-replica workloads are flagged, and a remediation
that would delete live objects is called out as divergent.
Roadmap The Helm 3 ownership
annotations Tiller-era objects need before Flux can take them over
are written into the MR as numbered pre-merge steps.