Flux integration
This page covers the Flux configuration, dependency control, and image automation for the custom mx-validator container.
Email relay series
- Email relay
- Architecture
- Manifests
- Flux integration - You are here
- Operations
Two-repo GitOps pattern
The email relay follows a two-repo pattern where Flux config and app manifests are separated:
Flux config structure
The Flux configuration lives in your flux-config repo under clusters/my-cluster/email-relay/.
clusters/my-cluster/email-relay/
├── kustomization.yaml # Kustomize wrapper
├── source.yaml # GitRepository for app repo
├── 00-kustomization-ns.yaml # Namespace Kustomization
├── 10-kustomization-app.yaml # App Kustomization (dependsOn: ns)
└── prod/
├── kustomization.yaml
├── 20-mx-validator-images.yaml # ImageRepository + ImagePolicy
├── 30-image-automation.yaml # ImageUpdateAutomation
└── secrets/
└── mx-validator-registry.yaml # Registry credentials
GitRepository source
# clusters/my-cluster/email-relay/source.yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: email-relay
namespace: flux-system
spec:
interval: 5m
timeout: 60s
url: ssh://git-ssh.example.local/your-org/email-relay.git
ref:
branch: main
secretRef:
name: flux-ssh-auth
ignore: |
/*
!/k8s/
The ignore pattern tells Flux to only watch the k8s/ directory.
Namespace Kustomization
# clusters/my-cluster/email-relay/00-kustomization-ns.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: email-relay-ns
namespace: flux-system
spec:
interval: 10m
prune: true
sourceRef:
kind: GitRepository
name: email-relay
namespace: flux-system
path: ./k8s/prod
# Only apply namespace resource
patches:
- patch: |
- op: remove
path: /resources/1
- op: remove
path: /resources/1
# ... remove all except namespace
target:
kind: Kustomization
timeout: 2m
App Kustomization
# clusters/my-cluster/email-relay/10-kustomization-app.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: email-relay
namespace: flux-system
spec:
dependsOn:
- name: email-relay-ns
interval: 10m
timeout: 5m
prune: true
wait: true
sourceRef:
kind: GitRepository
name: email-relay
namespace: flux-system
path: ./k8s/prod
targetNamespace: email-relay
decryption:
provider: sops
secretRef:
name: sops-age
Key points:
| Setting | Value | Purpose |
|---|---|---|
dependsOn | email-relay-ns | Wait for namespace |
sourceRef | email-relay | The app repo GitRepository |
path | ./k8s/prod | Apply manifests from this path |
decryption.provider | sops | Decrypt SOPS-encrypted secrets |
Image automation
The mx-validator is a custom image built in your CI pipeline. Flux can automatically update the deployment when new images are pushed.
ImageRepository
Scans your container registry for new mx-validator tags.
# clusters/my-cluster/email-relay/prod/20-mx-validator-images.yaml
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
name: mx-validator-prod-repo
namespace: flux-system
spec:
image: registry.example.local/your-org/mx-validator
interval: 1m
secretRef:
name: mx-validator-prod-registry
ImagePolicy
Selects which tags to deploy based on a pattern.
# clusters/my-cluster/email-relay/prod/20-mx-validator-images.yaml (continued)
---
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
name: mx-validator-prod-policy
namespace: flux-system
spec:
imageRepositoryRef:
name: mx-validator-prod-repo
filterTags:
pattern: '^prod-(?P<date>[0-9]{8})\.(?P<build>[0-9]+)$'
extract: '$date$build'
policy:
numerical:
order: asc
This policy:
- Matches tags like
prod-20260131.1,prod-20260131.2 - Extracts
202601311,202601312for numerical sorting - Selects the highest (most recent) tag
ImageUpdateAutomation
Automatically commits updated image tags to the app repo.
# clusters/my-cluster/email-relay/prod/30-image-automation.yaml
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageUpdateAutomation
metadata:
name: email-relay-prod-automation
namespace: flux-system
spec:
interval: 1m
sourceRef:
kind: GitRepository
name: email-relay
git:
checkout:
ref:
branch: main
commit:
author:
name: FluxCD
email: fluxcd@example.local
messageTemplate: '{{range .Changed.Changes}}{{print .OldValue}} -> {{println .NewValue}}{{end}} [skip ci]'
push:
branch: main
update:
strategy: Setters
path: ./k8s/prod
Deployment image marker
Add a marker comment to enable automatic updates:
# In 20-deployment.yaml
containers:
- name: mx-validator
image: registry.example.local/your-org/mx-validator:prod-20260131.1 # {"$imagepolicy": "flux-system:mx-validator-prod-policy"}
The {"$imagepolicy": ...} comment tells Flux which ImagePolicy controls this image.
Registry credentials
For private registries, create a secret with credentials:
# clusters/my-cluster/email-relay/prod/secrets/mx-validator-prod-registry.yaml
apiVersion: v1
kind: Secret
metadata:
name: mx-validator-prod-registry
namespace: flux-system
type: kubernetes.io/dockerconfigjson
stringData:
.dockerconfigjson: |
{
"auths": {
"registry.example.local": {
"username": "deploy-token-username",
"password": "deploy-token-password"
}
}
}
This secret must also be created in the email-relay namespace as mx-validator-registry for the pod to pull the image. Use a sealed secret or SOPS encryption.
Kustomize wrapper
# clusters/my-cluster/email-relay/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- source.yaml
- 00-kustomization-ns.yaml
- 10-kustomization-app.yaml
- prod
# clusters/my-cluster/email-relay/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- 20-mx-validator-images.yaml
- 30-image-automation.yaml
- secrets/mx-validator-prod-registry.yaml
Deployment commands
After committing both repos:
# 1. Commit and push the app repo
cd /path/to/email-relay
git add .
git commit -m "Add email-relay manifests"
git push
# 2. Commit and push flux-config
cd /path/to/flux-config
git add clusters/my-cluster/{kustomization.yaml,email-relay}
git commit -m "Add email-relay via Flux"
git push
# 3. Reconcile Flux
flux reconcile source git flux-system -n flux-system
flux reconcile kustomization flux-system -n flux-system --with-source
# 4. Watch deployment progress
flux get kustomizations -n flux-system | grep email-relay
kubectl get pods -n email-relay -w
Verification
# Check Flux Kustomizations
flux get kustomizations -n flux-system | grep email-relay
# Expected:
# email-relay-ns main@sha1:... False True Applied revision: ...
# email-relay main@sha1:... False True Applied revision: ...
# Check image automation
flux get images repository -n flux-system | grep mx-validator
flux get images policy -n flux-system | grep mx-validator
# Check current image
kubectl get deployment -n email-relay email-relay \
-o jsonpath='{.spec.template.spec.containers[0].image}'
Troubleshooting
ImageRepository not scanning
Check if registry credentials are correct:
# Check ImageRepository status
flux get images repository mx-validator-prod-repo -n flux-system
# Check for auth errors
kubectl describe imagerepository mx-validator-prod-repo -n flux-system
ImageUpdateAutomation not committing
Check if the GitRepository has write access:
# Check automation status
flux get images update email-relay-prod-automation -n flux-system
# The deploy key needs write access to the repo
Force reconciliation
# Reconcile the source
flux reconcile source git email-relay -n flux-system
# Reconcile the app Kustomization
flux reconcile kustomization email-relay -n flux-system --with-source
# Trigger image scan
flux reconcile image repository mx-validator-prod-repo -n flux-system