Flux GitOps Platform
The homelab Kubernetes platform uses Flux ResourceSets for centralized, declarative management of Helm releases and configurations.
Platform Files Overview
| File | Purpose |
|---|---|
helm-charts.yaml | ResourceSet defining all Helm releases |
namespaces.yaml | ResourceSet defining all namespaces |
config.yaml | ResourceSet for config Kustomizations |
kustomization.yaml | Generates ConfigMap from chart values |
charts/ | Helm values files (one per release) |
config/ | Non-Helm resources organized by subsystem |
Adding a New Helm Release
Step 1: Add to helm-charts.yaml
Add an entry to the inputs array:
inputs:
- name: "my-new-chart" # Unique release name (kebab-case)
namespace: "my-namespace" # Target namespace
chart:
name: "actual-chart-name" # Chart name in repository
version: "1.0.0" # Pinned version
url: "https://example.com/charts" # Helm repository URL
dependsOn: [cilium] # Array of release names this depends on
For OCI registries:
chart:
name: "app-template"
version: "3.6.1"
url: "oci://ghcr.io/bjw-s/helm" # Prefix with oci://
Step 2: Create Values File
Create charts/<release-name>.yaml with Helm values:
# yaml-language-server: $schema=<chart-schema-url> --- # Helm values for the chart replicas: 1 image: repository: myapp tag: v1.0.0
Step 3: Add to kustomization.yaml
Add the values file to the configMapGenerator:
configMapGenerator:
- name: platform-values
files:
# ... existing entries
- charts/my-new-chart.yaml
Step 4: Add Config Resources (Optional)
If the chart needs additional resources (secrets, configs), add to config/:
config/my-new-chart/ ├── kustomization.yaml ├── secret.yaml └── config.yaml
Then reference in config.yaml ResourceSet.
ResourceSet Template Syntax
The resourcesTemplate uses Go text/template with << >> delimiters:
resourcesTemplate: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: << inputs.name >>
namespace: << inputs.provider.namespace >>
spec:
<<- if inputs.dependsOn >>
dependsOn:
<<- range $dep := inputs.dependsOn >>
- name: << $dep >>
<<- end >>
<<- end >>
chart:
spec:
chart: << inputs.chart.name >>
version: << inputs.chart.version >>
Template Functions
- •
<< inputs.field >>- Access input field - •
<<- if condition >>- Conditional (with-to trim whitespace) - •
<<- range $item := inputs.array >>- Loop over array - •
hasPrefix "oci://" inputs.chart.url- String prefix check
Variable Substitution
Flux substitutes variables from the flux-system ConfigMap:
# In values file
ingress:
hosts:
- host: grafana.${internal_domain} # Substituted at reconciliation
# Available variables
${cluster_name} # dev, integration, live
${cluster_id} # Numeric cluster ID
${internal_domain} # internal.dev.tomnowak.work
${external_domain} # External domain
Dependency Management
Release Dependencies
inputs:
- name: "grafana"
dependsOn: [kube-prometheus-stack, promtail] # Waits for these
ResourceSet Dependencies
spec:
dependsOn:
- apiVersion: fluxcd.controlplane.io/v1
kind: ResourceSet
name: platform-namespaces # Waits for namespaces ResourceSet
Debugging Flux
Check ResourceSet Status
kubectl get resourcesets -n flux-system kubectl describe resourceset platform-resources -n flux-system
Check HelmRelease Status
kubectl get helmreleases -A kubectl describe helmrelease <name> -n <namespace>
Check Reconciliation Logs
kubectl logs -n flux-system deploy/flux-controller -f | grep <release-name>
Force Reconciliation
flux reconcile helmrelease <name> -n <namespace> flux reconcile kustomization flux-system -n flux-system
Common Issues
| Symptom | Cause | Solution |
|---|---|---|
waiting for dependencies | Dependency not ready | Check dependsOn releases |
values key not found | Missing values file | Add to kustomization.yaml configMapGenerator |
chart not found | Wrong chart name/URL | Verify chart exists in repository |
namespace not found | Namespace not created | Add to namespaces.yaml |
Best Practices
- •Pin versions: Always specify exact chart versions
- •Declare dependencies: Use
dependsOnto ensure ordering - •Use substitution: Never hardcode domains or cluster names
- •Values per release: One values file per HelmRelease
- •Minimal values: Only override what you need to change
OCI Registry Specifics
When using OCI registries like GHCR:
chart: name: "app-template" # Just the chart name version: "3.6.1" url: "oci://ghcr.io/bjw-s/helm" # Registry URL with oci:// prefix
The ResourceSet template automatically detects OCI URLs and sets type: oci on the HelmRepository.