Flux can deploy feature branches to preview environments, but it’s not as simple as just pointing it at a Git branch.

Let’s say you have a Git repository with your application code and a Kubernetes manifest for it. You also have Flux installed in your cluster, watching a specific path in that repo for changes. Normally, Flux would deploy whatever’s in your main branch (or whatever branch you’ve configured) to your production environment.

Now, you want to deploy a feature branch, say feature/new-login, to a staging environment. This isn’t a direct "deploy this branch" operation. Flux works by reconciling the state of your cluster with the desired state defined in Git. To deploy a feature branch, you need to represent that branch’s state within the Git repository that Flux is watching.

Here’s how you’d typically set this up:

  1. Directory Structure in Git: Organize your Git repository so that different environments or deployments have their own dedicated directory. For example:

    /
    ├── production/
    │   └── app.yaml
    ├── staging/
    │   └── app.yaml
    └── preview/
        └── feature-new-login/
            └── app.yaml
    

    In this structure, production/app.yaml might point to the main Docker image tag, staging/app.yaml might point to release-candidate tag, and preview/feature-new-login/app.yaml would point to an image built from your feature/new-login branch.

  2. Flux Kustomization Objects: You’ll have separate Flux Kustomization resources, each watching a different path in your Git repository and targeting a specific Kubernetes namespace or context.

    • Production Kustomization:

      apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
      kind: Kustomization
      metadata:
        name: app-prod
        namespace: flux-system
      spec:
        interval: 5m
        path: ./production
        prune: true
        sourceRef:
          kind: GitRepository
          name: my-app-repo
        targetNamespace: production
      
    • Staging Kustomization:

      apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
      kind: Kustomization
      metadata:
        name: app-staging
        namespace: flux-system
      spec:
        interval: 5m
        path: ./staging
        prune: true
        sourceRef:
          kind: GitRepository
          name: my-app-repo
        targetNamespace: staging
      
    • Preview Kustomization:

      apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
      kind: Kustomization
      metadata:
        name: app-preview-login
        namespace: flux-system
      spec:
        interval: 5m
        path: ./preview/feature-new-login
        prune: true
        sourceRef:
          kind: GitRepository
          name: my-app-repo
        targetNamespace: preview-login
      
  3. Image Tagging Strategy: The key to deploying a specific feature branch is your CI/CD pipeline’s image tagging. When your CI pipeline builds an image from the feature/new-login branch, it should tag that image with something unique and predictable, like my-app:feature-new-login-abcdef123 (where abcdef123 is a Git commit SHA).

  4. Kustomize Overlays or Patches: Inside the preview/feature-new-login/app.yaml (or a Kustomize base it imports), you’ll specify the image tag. A common pattern is to use Kustomize images field or a patches strategic merge to override the default image.

    • Example preview/feature-new-login/kustomization.yaml:
      apiVersion: kustomize.config.k8s.io/v1beta1
      kind: Kustomization
      resources:
      - ../../base # Assuming a common base for all environments
      images:
      - name: my-app
        newName: my-registry/my-app
        newTag: feature-new-login-abcdef123 # This tag comes from CI
      
  5. CI/CD Pipeline: Your CI/CD pipeline needs to:

    • Detect commits to feature/new-login.
    • Build a Docker image.
    • Tag the image with a unique identifier (e.g., commit SHA).
    • Push the image to a registry.
    • Update the preview/feature-new-login/kustomization.yaml file with the new image tag and commit/push this change back to the Git repository that Flux is watching.

When Flux detects the commit to the preview/feature-new-login path, it will see the updated kustomization.yaml, pull the new image tag, and deploy that specific version of your application to the preview-login namespace.

What most people miss is that Flux doesn’t directly "watch" Git branches for deployment. It watches paths within a single Git repository. To deploy different branches or versions, you need to represent those versions as distinct configurations within that watched repository, typically through directory structure and Kustomize. This means your CI/CD pipeline is the orchestrator that tells Flux what to deploy by updating the Git repository.

The next thing you’ll likely run into is managing multiple preview environments for different feature branches simultaneously, which involves a more dynamic approach to path generation and Kustomization management.

Want structured learning?

Take the full Flux course →