Gitless GitOps CD lab with Flux
This lab shows a minimal gitless GitOps continuous delivery flow using Flux, an OCI registry, and a simple NGINX app. Flux watches an OCI artifact in a registry instead of a Git repository, then applies the manifests to the cluster through an OCIRepository and Kustomization.
Goal
Deploy a simple app to Kubernetes where:
- CI or a workstation packages Kubernetes YAML into an OCI artifact and pushes it to a registry.
- Flux source-controller watches that OCI artifact using the OCIRepository CRD [web:1].
- Flux kustomize-controller applies the content to the cluster through a Kustomization that references the OCIRepository.
This is useful when you want declarative reconciliation without depending on Git as the runtime source of truth, especially for edge or disconnected clusters that can reach a registry more easily than a Git service.
Architecture
- Build an OCI artifact from Kubernetes manifests with
flux push artifactor equivalent OCI tooling. - Push the artifact to a registry such as Harbor or GHCR.
- Create an
OCIRepositoryinflux-systemthat points at the registry artifact. - Create a
Kustomizationthat uses thatOCIRepositoryas its source. - Flux polls the registry, detects new tags or digests, fetches the artifact, and reconciles the cluster.
What to confirm first
Run these checks on the target cluster:
If ocirepositories.source.toolkit.fluxcd.io exists, the cluster has the CRD needed for Flux to monitor OCI sources. If source-controller and kustomize-controller are present in flux-system, the core control-plane pieces for this lab are likely in place.
Demo flow
Use these namespaces:
- flux-system for Flux sources and reconciliation objects.
- demo-app for the application workload.
The app will be a simple NGINX Deployment and Service.
Example app manifests
We will create application manifests in the following manner:
-
Create the
DeploymentmanifestsapiVersion: apps/v1 kind: Deployment metadata: name: demo-nginx namespace: demo-app spec: replicas: 1 selector: matchLabels: app: demo-nginx template: metadata: labels: app: demo-nginx spec: containers: - name: nginx image: nginx:1.27-alpine ports: - containerPort: 80 readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 3 periodSeconds: 5 -
Create the
Servicemanifest -
Create the
Kustomizationmanifest
Package the manifests as an OCI artifact
Create the namespace first:
Package and push the manifests to your OCI registry. Flux documents building and publishing Kubernetes manifests as OCI artifacts that can later be consumed by OCIRepository. An example using GHCR looks like this:
flux push artifact oci://ghcr.io/YOUR_ORG/demo-manifests:0.1.0 \
--path=./app \
--source="$(pwd)" \
--revision="demo@sha1:$(git rev-parse --short HEAD 2>/dev/null || echo manual)"
If you are using Harbor, the shape is the same, for example:
flux push artifact oci://harbor.example.com/gitops/demo-manifests:0.1.0 \
--path=./app \
--source="lab-demo" \
--revision="demo@sha1:manual"
Flux objects
-
Access the NKP cluster and create the following Flux resources
-
Create the
OCIRepositorymanifestThis tells Flux to poll the registry artifact on a schedule and fetch the referenced OCI content.
-
Create the
KustomizationmanifestThis tells Flux to apply the unpacked OCI artifact contents into the cluster by using the
OCIRepositoryas the source instead of aGitRepository.
Private registry auth
If the registry is private, create an OCI pull secret. Flux supports authenticated OCI access through a secret reference on the OCIRepository.
flux create secret oci regcred \
--url=ghcr.io \
--username=YOUR_USER \
--password=YOUR_TOKEN \
--namespace=flux-system \
--export > regcred.yaml
kubectl apply -f regcred.yaml
Then add the secret reference:
Apply the Flux resources
Check reconciliation:
Flux will report the fetched revision for the OCI source, and the Kustomization status will show whether the manifests were applied successfully.
Demo update story
A simple demo sequence:
- Push version
0.1.0with one NGINX replica. - Show Flux reconciling and the app becoming ready.
- Change
replicas: 2indeployment.yaml. - Push version
0.2.0of the OCI artifact. - Update
ref.taginOCIRepositoryto0.2.0, or use a semver selector if you want Flux to track versions automatically where supported. - Show the rollout to two replicas.
Optional security angle
Flux documentation also supports verifying OCI artifacts with Cosign or Notation before reconciliation, which is a strong talking point for supply-chain controls. A high-level message for the customer is that OCI-based delivery can combine image-style registry governance, signatures, and admission policies with GitOps-style reconciliation.
Take away
This demo packages Kubernetes manifests as an OCI artifact and stores them in a container registry. Flux watches that registry through an OCIRepository, then applies the manifests with a Kustomization. The result is a Gitless runtime delivery flow that still preserves declarative reconciliation, and it is a strong fit for edge or intermittently connected clusters that already rely on an OCI registry.