Flux Bootstrap Migration
Assuming you have a cluster bootstrapped with the Flux CLI or the Terraform Provider, you can migrate to an operator-managed Flux with zero downtime.
Install the Flux Operator
Install the Flux Operator in the same namespace where Flux is deployed, for example using Helm:
helm install flux-operator oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator \
--namespace flux-system
Or by using an alternative installation method described in the installation guide.
Create a Flux Instance
Create a FluxInstance
resource named flux in the flux-system
namespace using
the same configuration as for flux bootstrap
.
For example, if you have bootstrapped the cluster with the following command:
flux bootstrap github \
--owner=my-org \
--repository=my-fleet \
--branch=main \
--path=clusters/my-cluster
The equivalent FluxInstance
configuration would look like this:
apiVersion: fluxcd.controlplane.io/v1
kind: FluxInstance
metadata:
name: flux
namespace: flux-system
spec:
distribution:
version: "2.x"
registry: "ghcr.io/fluxcd"
components:
- source-controller
- kustomize-controller
- helm-controller
- notification-controller
cluster:
type: kubernetes
multitenant: false
networkPolicy: true
domain: "cluster.local"
sync:
kind: GitRepository
url: "ssh://[email protected]/my-org/my-fleet.git"
ref: "refs/heads/main"
path: "clusters/my-cluster"
pullSecret: "flux-system"
Kustomize patches
Note that if you have customized the Flux manifests, you should copy the Kustomize patches
from flux-system/kustomization.yaml
in the FluxInstance
under .spec.kustomize.patches
.
For more information, see the instance customization guide.
Apply the FluxInstance
resource to the cluster:
kubectl apply -f flux-instance.yaml
Once the resource is reconciled, the operator will take over the management of the Flux components, the Flux GitRepository and Kustomization.
To verify that the migration was successful, check the status of the FluxInstance
:
kubectl -n flux-system get fluxinstance flux
Running the trace command should result in a "Not managed by Flux" message:
flux trace kustomization flux-system
Cleanup the repository
To finalize the migration, remove the Flux manifests from the Git repository:
- Checkout the main branch of the Flux repository that was used to bootstrap the cluster.
- Delete the
flux-system
directory from the repositoryclusters/my-cluster
directory. - Optionally, place the
FluxInstance
YAML manifest in theclusters/my-cluster
directory. - Commit and push the changes to the Flux repository.
Automating Flux Operator upgrades
If the Flux Operator is installed with Helm, you can automate the upgrade process using a Flux HelmRelease
:
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
name: flux-operator
namespace: flux-system
spec:
interval: 10m
url: oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator
ref:
semver: '*'
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: flux-operator
namespace: flux-system
spec:
interval: 10m
releaseName: flux-operator
chartRef:
kind: OCIRepository
name: flux-operator
Commit and push the manifest to the Flux repository, and the operator will be automatically upgraded when a new Helm chart version is released.
Migration from Git to OCI artifacts
To decouple the Flux reconciliation from Git and use OCI artifacts as the delivery mechanism for the cluster desired state, the following procedure can be followed:
- Migrate the Flux custom resources such as Flux
Kustomization
andHelmRelease
to useOCIRepository
assourceRef
. - Create a repository in a container registry that both the CI tooling and Flux can access.
- Create a CI workflow that reacts to changes in the Git repository and publishes the Kubernetes manifests to the OCI repository.
- Configure the
FluxInstance
to use the OCI repository as the source of the cluster desired state.
To exemplify the migration, we will use GitHub but the same procedure can be applied to GitLab, Azure DevOps and other providers.
Prepare the Flux manifests
Create a new branch called oci-artifacts
in the Git repository that was used for bootstrap.
Update all the Flux Kustomization
manifests to use OCIRepository
instead of GitRepository
:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
spec:
sourceRef:
kind: OCIRepository
name: flux-system
If you have HelmRelease
resources using a GitRepository
, update them to use OCIRepository
.
Commit and push the changes to the oci-artifacts
branch.
Publish the manifests to the OCI repository
Create a GitHub Actions workflow that uses the Flux CLI to publish the manifests to GitHub Container Registry:
name: publish-artifact
on:
workflow_dispatch:
push:
branches:
- 'main'
- 'oci-artifacts'
permissions:
packages: write
jobs:
flux-push:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Flux CLI
uses: fluxcd/flux2/action@main
- name: Push immutable artifact
run: |
flux push artifact \
oci://ghcr.io/${{ github.repository }}/manifests:$(git rev-parse --short HEAD) \
--source="$(git config --get remote.origin.url)" \
--revision="$(git branch --show-current)@sha1:$(git rev-parse HEAD)" \
--creds flux:${{ secrets.GITHUB_TOKEN }} \
--path="./"
- name: Tag artifact as latest
run: |
flux tag artifact \
oci://ghcr.io/${{ github.repository }}/manifests:$(git rev-parse --short HEAD) \
--creds flux:${{ secrets.GITHUB_TOKEN }} \
--tag latest
Commit and push the workflow to the oci-artifacts
branch.
Run the workflow manually in the GitHub UI and verify that the manifests are published to the GitHub Container Registry with:
flux pull artifact oci://ghcr.io/my-org/my-fleet/manifests:latest \
--creds flux:${GITHUB_TOKEN} \
--output-dir ./manifests
Create the image pull secret
Create an image pull secret in the flux-system
namespace that contains
a GitHub token with read access to the GitHub Container Registry:
flux create secret oci ghcr-auth \
--url=ghcr.io \
--username=flux \
--password=${GITHUB_TOKEN}
Update the FluxInstance to use OCI artifacts
Update the FluxInstance
to use OCIRepository
and the image pull secret:
apiVersion: fluxcd.controlplane.io/v1
kind: FluxInstance
metadata:
name: flux
namespace: flux-system
spec:
sync:
kind: OCIRepository
url: "oci://ghcr.io/my-org/my-fleet/manifests"
ref: "latest"
path: "clusters/my-cluster"
pullSecret: "ghcr-auth"
Commit and push the FluxInstance
changes to the oci-artifacts
branch and
wait for the GitHub workflow to publish the manifests.
Apply the FluxInstance
to the cluster and verify that the operator has reconfigured
Flux to use the OCIRepository
:
kubectl apply -f flux-instance.yaml
kubectl -n flux-system wait fluxinstance/flux --for=condition=Ready
flux get source oci flux-system
flux get kustomization flux-system
Finally, merge the oci-artifacts
branch into main
and delete the oci-artifacts
branch.
The GitHub Actions workflow will continue to publish the manifests to the GitHub Container Registry
on every push to the main
branch and Flux will reconcile the cluster state accordingly.