YAML/Helm Standards¶
Purpose: YAML and Helm chart standards for this repository.
Scope¶
This document covers: YAML formatting, Helm chart conventions, Kustomize patterns, and validation tools.
Related: - Python Style Guide - Python scripting conventions - Shell Script Standards - Bash conventions
Quick Reference¶
| Aspect | Standard |
|---|---|
| Indentation | 2 spaces |
| Line length | 120 characters max |
| Linter | yamllint |
| Helm | helm lint, helm template |
| Kustomize | kustomize build --enable-helm |
yamllint Configuration¶
Create .yamllint.yml at repo root:
YAML
extends: default
rules:
line-length:
max: 120
allow-non-breakable-inline-mappings: true
indentation:
spaces: 2
indent-sequences: consistent
truthy:
check-keys: false
comments:
min-spaces-from-content: 1
document-start: disable
empty-lines:
max: 2
Usage:
Bash
# Lint all YAML files
yamllint .
# Lint specific directory
yamllint apps/
Helm Chart Conventions¶
Chart Structure¶
Text Only
charts/<chart-name>/
├── Chart.yaml
├── values.yaml
├── templates/
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ └── ...
└── charts/ # Nested charts (if needed)
Validation Commands¶
Bash
# Lint chart
helm lint charts/<chart-name>/
# Template with values (dry-run)
helm template <release> charts/<chart-name>/ -f values.yaml
# Validate rendered output
helm template <release> charts/<chart-name>/ | kubectl apply --dry-run=client -f -
values.yaml Conventions¶
YAML
# GOOD - Commented sections, logical grouping
# =============================================================================
# Application Configuration
# =============================================================================
app:
name: my-app
replicas: 3
# Resource limits (adjust for environment)
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
# BAD - No structure, no comments
app:
name: my-app
replicas: 3
cpu: 100m
memory: 128Mi
Kustomize Patterns¶
Overlay Structure¶
Text Only
apps/<app>/
├── base/
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ └── service.yaml
└── overlays/
├── dev/
│ └── kustomization.yaml
├── staging/
│ └── kustomization.yaml
└── prod/
└── kustomization.yaml
kustomization.yaml Template¶
YAML
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
# Environment-specific patches
patches:
- path: ./patches/replicas.yaml
target:
kind: Deployment
name: my-app
Patch Types¶
| Type | Use Case | Example |
|---|---|---|
| Strategic Merge | Add/modify fields | patches/extend-rbac.yaml |
| JSON Patch | Precise operations | patches/remove-field.yaml |
| Delete | Remove resources | $patch: delete annotation |
Strategic Merge Patch:
YAML
# patches/extend-rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: my-role
rules:
- apiGroups: ["custom.io"]
resources: ["widgets"]
verbs: ["get", "list"]
Delete Patch:
YAML
# patches/delete-resource.yaml
$patch: delete
apiVersion: v1
kind: ConfigMap
metadata:
name: unused-config
Formatting Rules¶
Quoting Strings¶
YAML
# GOOD - Quote strings that look like other types
enabled: "true" # String, not boolean
port: "8080" # String, not integer
version: "1.0" # String, not float
# GOOD - No quotes for actual typed values
enabled: true # Boolean
port: 8080 # Integer
replicas: 3 # Integer
# BAD - Ambiguous without context
version: 1.0 # Parsed as float, might lose precision
Multi-line Strings¶
YAML
# GOOD - Literal block scalar (preserves newlines)
script: |
#!/bin/bash
set -euo pipefail
echo "Hello"
# GOOD - Folded block scalar (folds newlines to spaces)
description: >
This is a long description that will be
folded into a single line with spaces.
# BAD - Escaped newlines (hard to read)
script: "#!/bin/bash\nset -euo pipefail\necho \"Hello\""
Comments¶
YAML
# Section header (full line)
# =============================================================================
# Database Configuration
# =============================================================================
database:
host: localhost # Inline comment (1 space before #)
port: 5432
# Subsection comment
credentials:
username: admin
Template Best Practices¶
Use include for Reusable Snippets¶
YAML
# templates/_helpers.tpl
{{- define "app.labels" -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
# templates/deployment.yaml
metadata:
labels:
{{- include "app.labels" . | nindent 4 }}
Whitespace Control¶
YAML
# GOOD - Use {{- and -}} to control whitespace
{{- if .Values.enabled }}
apiVersion: v1
kind: ConfigMap
{{- end }}
# BAD - Extra blank lines in output
{{ if .Values.enabled }}
apiVersion: v1
{{ end }}
Required Values¶
YAML
# Fail fast if required value missing
image: {{ required "image.repository is required" .Values.image.repository }}
Validation Workflow¶
Pre-commit Checks¶
Bash
# 1. Lint YAML
yamllint .
# 2. Lint Helm charts
for chart in charts/*/Chart.yaml; do
helm lint "$(dirname "$chart")"
done
# 3. Build Kustomize overlays
kustomize build apps/<app>/ --enable-helm > /dev/null
CI Pipeline Example¶
YAML
# .github/workflows/validate.yaml (example)
- name: Lint YAML
run: yamllint .
- name: Lint Helm
run: |
for chart in charts/*/Chart.yaml; do
helm lint "$(dirname "$chart")"
done
- name: Validate Kustomize
run: |
for kust in apps/*/kustomization.yaml; do
kustomize build "$(dirname "$kust")" --enable-helm > /dev/null
done
Format Decision Tree¶
Text Only
What are you configuring?
├─ Kubernetes manifests
│ ├─ Single environment? → Plain YAML
│ ├─ Multiple environments, small changes? → Kustomize overlays
│ └─ Complex templating needed? → Helm chart
├─ Application config
│ ├─ Needs comments? → YAML
│ └─ Machine-generated? → JSON
├─ CI/CD pipeline
│ └─ → YAML (platform-specific: GitHub Actions, GitLab CI)
└─ Data/records
└─ → JSON or JSONL (see json-jsonl-standards.md)
Helm vs Kustomize¶
| Use Helm When | Use Kustomize When |
|---|---|
| Complex conditional logic | Simple overlay changes |
| Parameterized charts for distribution | Environment-specific patches |
| Need Helm ecosystem (repositories, hooks) | Already have plain manifests |
| Charts will be shared/published | Internal-only deployments |
| Need computed values | Static configuration changes |
Common Errors¶
| Symptom | Cause | Fix |
|---|---|---|
mapping values not allowed |
Missing space after colon | key: value not key:value |
found duplicate key |
Repeated YAML key | Remove duplicate |
could not find expected ':' |
Unquoted special chars | Quote the value |
helm: values don't align |
Incorrect indentation | Use 2 spaces |
Error: YAML parse error |
Tab characters | Convert tabs to spaces |
nil pointer evaluating |
Missing value in Helm | Use default or required |
| Kustomize "resource not found" | Wrong path in resources | Check relative paths |
| Boolean parsed as string | "true" vs true |
Remove quotes for boolean |
Anti-Patterns¶
| Name | Pattern | Why Bad | Instead |
|---|---|---|---|
| Tab Indentation | Using tabs | YAML spec requires spaces | 2 spaces |
| Anchor Abuse | Complex <<: *anchor chains |
Hard to debug | Duplicate with comments |
| Unquoted Versions | version: 1.0 |
Parsed as float | version: "1.0" |
| Inline JSON | data: {"key": "value"} |
Hard to read | Multi-line YAML |
| No Comments | values.yaml without docs | Users guess meanings | Section comments |
| Hardcoded Secrets | password: hunter2 |
Security risk | External secret reference |
AI Agent Guidelines¶
When AI agents write YAML/Helm for this repo:
| Guideline | Rationale |
|---|---|
ALWAYS run yamllint before committing |
Catches formatting issues |
| ALWAYS quote version strings | Prevents float parsing |
ALWAYS use helm template to verify |
Catches rendering errors |
| NEVER use tabs | YAML spec violation |
| NEVER hardcode secrets in values | Security risk |
PREFER \| for multi-line strings |
Preserves formatting |
PREFER required over silent defaults |
Fail fast on missing values |
Summary¶
- Use 2-space indentation, 120 char line limit
- Run
yamllinton all YAML files - Use
helm lintandhelm templatefor charts - Use Kustomize patches for environment customizations
- Quote strings that look like numbers or booleans
- Use
|for multi-line strings - Document values.yaml with section comments
- Use
{{- include ... }}for reusable templates - Choose Helm vs Kustomize based on decision tree
- Check Common Errors table for troubleshooting