Skip to main content
RunBook Academy

KubernetesCVI · Package Management Anti-PatternsPackage management anti-patterns

Giant values files — splitting for reviewability

Advanced⏱ ~16 minhelm

What you'll learn

  • Recognise giant values files as an anti-pattern
  • Split values files by concern
  • Use helmfile for multi-release management
  • Apply the operational discipline of small focused files

Prerequisites

Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16

Not yet marked complete on this device.

Giant values files are a common anti-pattern. This lesson walks why they are a problem, the fix (split by concern), helmfile for multi-release, and the operational discipline.

Why giant values files are a problem

flowchart LR
    A[500-line values file] --> B[PR review impossible]
    A --> C[Hidden coupling]
    A --> D[Change scope unclear]
    B --> E[Reviewer rubber-stamps]
    C --> F[Changing one thing affects another]
    D --> G[Cannot tell what changed]

The problems:

  • PR review impossible. A 500-line change cannot be reviewed effectively. The reviewer rubber-stamps.
  • Hidden coupling. Fields are scattered; changing one thing may affect another.
  • Change scope unclear. A diff of a 500-line file is hard to interpret.
  • Onboarding difficulty. New team members cannot navigate the file.

The fix: split by concern

# values/01-image.yaml
image:
  repository: myapp
  tag: "1.0.0"
  pullPolicy: IfNotPresent

# values/02-service.yaml
service:
  type: ClusterIP
  port: 80
  targetPort: 8080

# values/03-resources.yaml
resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 500m
    memory: 512Mi

# values/04-ingress.yaml
ingress:
  enabled: true
  className: nginx
  hosts:
    - host: myapp.example.com
      paths:
        - path: /
          pathType: Prefix

# values/05-autoscaling.yaml
autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

# values/06-secrets-ref.yaml
existingSecret: myapp-secrets

Each file is small and focused. A change to the image is a diff in 01-image.yaml; a change to the ingress is a diff in 04-ingress.yaml. The PR reviewer sees exactly what changed.

The naming convention

flowchart LR
    A["values/01-image.yaml"] --> B[Numeric prefix for ordering]
    C["values/image.yaml"] --> D[No ordering but alphabetical]
    E["values/prod.yaml"] --> F[Environment-specific overrides]

Naming conventions:

  • Numeric prefix (01-image.yaml). Orders files; consistent across environments.
  • No prefix (image.yaml). Simpler; ordering by alphabet.
  • Environment suffix (values-prod.yaml). Environment-specific overrides.

The discipline is to pick one convention and stick with it.

helmfile for multi-release

# helmfile.yaml
repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

releases:
  - name: postgresql
    namespace: prod-data
    chart: bitnami/postgresql
    version: 12.1.0
    values:
      - values/postgresql/01-image.yaml
      - values/postgresql/02-storage.yaml
      - values/postgresql-prod.yaml

  - name: myapp
    namespace: prod-app
    chart: oci/myapp
    version: 1.2.3
    values:
      - values/myapp/01-image.yaml
      - values/myapp/04-ingress.yaml
      - values/myapp-prod.yaml

helmfile manages multiple Helm releases with separate values files per release. Each release has its own directory of values files; environment overrides are separate.

Kustomize alternative

For application manifests (not third-party packages), Kustomize provides a cleaner overlay model:

# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base

namespace: prod-app

patches:
  - target:
      kind: Deployment
      name: myapp
    patch: |-
      - op: replace
        path: /spec/replicas
        value: 5

Each environment has its own overlay; the base is shared. The discipline is similar: small, focused overlays per environment.

Quiz

Knowledge check · 4 questions

  1. Q1. Why is a 600-line values file a production risk rather than a style problem?

  2. Q2. Helm accepts multiple `-f` values files, merged left to right.

  3. Q3. Recover from an OOMKill caused by one line buried in a 640-line values file, then make the file reviewable.

    Since revision 22 was deployed at 09:40, 7 of 12 `payments` Pods have restarted with `lastState.terminated.reason: OOMKilled`. `helm get values payments -n prod-app --all` shows `resources.limits.memory: 512Mi` where the previous revision had `4Gi`. The pull request that produced revision 22 touched 12 lines in a 640-line `values-prod.yaml` and carried one approving review.

  4. Q4. What does helmfile give you over a set of `helm upgrade` invocations, and which key in a release entry replaces the repeated `-f` flags?

Passing score: 75%. Answers are checked in this browser.

The operational discipline

Giant values files in production rest on five non-negotiable elements:

  • Split by concern. Each file has a single purpose.
  • Naming convention. Pick one; stick with it.
  • Multiple -f flags. Helm combines them in order.
  • helmfile for multi-release. One declarative spec for all releases.
  • Review each file in PRs. Each diff is small and focused.

The discipline is to keep files small enough to review. A 500-line values file is the anti-pattern; splitting it is the fix.