Skill

SkillsDevOps & Infrastructure › Containers & orchestration

helm-chart-scaffolding

Design, organize, and manage Helm charts for templating and packaging Kubernetes applications with reusable configurations. Use when creating Helm charts, packaging Kubernetes applications, or implementing templated deployments.

Freerisk: medium
helmchartscaffoldingdockergokubernetes

The full skill

— name: helm-chart-scaffolding description: Design, organize, and manage Helm charts for templating and packaging Kubernetes applications with reusable configurations. Use when creating Helm charts, packaging Kubernetes applications, or implementing templated deployments. — # Helm Chart Scaffolding Comprehensive guidance for creating, organizing, and managing Helm charts for packaging and deploying Kubernetes applications. ## Purpose This skill provides step-by-step instructions for building production-ready Helm charts, including chart structure, templating patterns, values management, and validation strategies. ## When to Use This Skill Use this skill when you need to: – Create new Helm charts from scratch – Package Kubernetes applications for distribution – Manage multi-environment deployments with Helm – Implement templating for reusable Kubernetes manifests – Set up Helm chart repositories – Follow Helm best practices and conventions ## Helm Overview **Helm** is the package manager for Kubernetes that: – Templates Kubernetes manifests for reusability – Manages application releases and rollbacks – Handles dependencies between charts – Provides version control for deployments – Simplifies configuration management across environments ## Step-by-Step Workflow ### 1. Initialize Chart Structure **Create new chart:** “`bash helm create my-app “` **Standard chart structure:** “` my-app/ ├── Chart.yaml # Chart metadata ├── values.yaml # Default configuration values ├── charts/ # Chart dependencies ├── templates/ # Kubernetes manifest templates │ ├── NOTES.txt # Post-install notes │ ├── _helpers.tpl # Template helpers │ ├── deployment.yaml │ ├── service.yaml │ ├── ingress.yaml │ ├── serviceaccount.yaml │ ├── hpa.yaml │ └── tests/ │ └── test-connection.yaml └── .helmignore # Files to ignore “` ### 2. Configure Chart.yaml **Chart metadata defines the package:** “`yaml apiVersion: v2 name: my-app description: A Helm chart for My Application type: application version: 1.0.0 # Chart version appVersion: "2.1.0" # Application version # Keywords for chart discovery keywords: – web – api – backend # Maintainer information maintainers: – name: DevOps Team email: [email protected] url: https://github.com/example/my-app # Source code repository sources: – https://github.com/example/my-app # Homepage home: https://example.com # Chart icon icon: https://example.com/icon.png # Dependencies dependencies: – name: postgresql version: "12.0.0" repository: "https://charts.bitnami.com/bitnami" condition: postgresql.enabled – name: redis version: "17.0.0" repository: "https://charts.bitnami.com/bitnami" condition: redis.enabled “` **Reference:** See `assets/Chart.yaml.template` for complete example ### 3. Design values.yaml Structure **Organize values hierarchically:** “`yaml # Image configuration image: repository: myapp tag: "1.0.0" pullPolicy: IfNotPresent # Number of replicas replicaCount: 3 # Service configuration service: type: ClusterIP port: 80 targetPort: 8080 # Ingress configuration ingress: enabled: false className: nginx hosts: – host: app.example.com paths: – path: / pathType: Prefix # Resources resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m" # Autoscaling autoscaling: enabled: false minReplicas: 2 maxReplicas: 10 targetCPUUtilizationPercentage: 80 # Environment variables env: – name: LOG_LEVEL value: "info" # ConfigMap data configMap: data: APP_MODE: production # Dependencies postgresql: enabled: true auth: database: myapp username: myapp redis: enabled: false “` **Reference:** See `assets/values.yaml.template` for complete structure ### 4. Create Template Files **Use Go templating with Helm functions:** **templates/deployment.yaml:** “`yaml apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "my-app.fullname" . }} labels: {{- include "my-app.labels" . | nindent 4 }} spec: {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} {{- end }} selector: matchLabels: {{- include "my-app.selectorLabels" . | nindent 6 }} template: metadata: labels: {{- include "my-app.selectorLabels" . | nindent 8 }} spec: containers: – name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: – name: http containerPort: {{ .Values.service.targetPort }} resources: {{- toYaml .Values.resources | nindent 12 }} env: {{- toYaml .Values.env | nindent 12 }} “` ### 5. Create Template Helpers **templates/\_helpers.tpl:** “`yaml {{/* Expand the name of the chart. */}} {{- define "my-app.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Create a default fully qualified app name. */}} {{- define "my-app.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} {{- $name := default .Chart.Name .Values.nameOverride }} {{- if contains $name .Release.Name }} {{- .Release.Name | trunc 63 | trimSuffix "-" }} {{- else }} {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} {{- end }} {{- end }} {{- end }} {{/* Common labels */}} {{- define "my-app.labels" -}} helm.sh/chart: {{ include "my-app.chart" . }} {{ include "my-app.selectorLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} {{/* Selector labels */}} {{- define "my-app.selectorLabels" -}} app.kubernetes.io/name: {{ include "my-app.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} “` ### 6. Manage Dependencies **Add dependencies in Chart.yaml:** “`yaml dependencies: – name: postgresql version: "12.0.0" repository: "https://charts.bitnami.com/bitnami" condition: postgresql.enabled “` **Update dependencies:** “`bash helm dependency update helm dependency build “` **Override dependency values:** “`yaml # values.yaml postgresql: enabled: true auth: database: myapp username: myapp password: changeme primary: persistence: enabled: true size: 10Gi “` ### 7. Test and Validate **Validation commands:** “`bash # Lint the chart helm lint my-app/ # Dry-run installation helm install my-app ./my-app –dry-run –debug # Template rendering helm template my-app ./my-app # Template with values helm template my-app ./my-app -f values-prod.yaml # Show computed values helm show values ./my-app “` **Validation script:** “`bash #!/bin/bash set -e echo "Linting chart…" helm lint . echo "Testing template rendering…" helm template test-release . –dry-run echo "Checking for required values…" helm template test-release . –validate echo "All validations passed!" “` **Reference:** See `scripts/validate-chart.sh` ### 8. Package and Distribute **Package the chart:** “`bash helm package my-app/ # Creates: my-app-1.0.0.tgz “` **Create chart repository:** “`bash # Create index helm repo index . # Upload to repository # AWS S3 example aws s3 sync . s3://my-helm-charts/ –exclude "*" –include "*.tgz" –include "index.yaml" “` **Use the chart:** “`bash helm repo add my-repo https://charts.example.com helm repo update helm install my-app my-repo/my-app “` ### 9. Multi-Environment Configuration **Environment-specific values files:** “` my-app/ ├── values.yaml # Defaults ├── values-dev.yaml # Development ├── values-staging.yaml # Staging └── values-prod.yaml # Production “` **values-prod.yaml:** “`yaml replicaCount: 5 image: tag: "2.1.0" resources: requests: memory: "512Mi" cpu: "500m" limits: memory: "1Gi" cpu: "1000m" autoscaling: enabled: true minReplicas: 3 maxReplicas: 20 ingress: enabled: true hosts: – host: app.example.com paths: – path: / pathType: Prefix postgresql: enabled: true primary: persistence: size: 100Gi “` **Install with environment:** “`bash helm install my-app ./my-app -f values-prod.yaml –namespace production “` ### 10. Implement Hooks and Tests **Pre-install hook:** “`yaml # templates/pre-install-job.yaml apiVersion: batch/v1 kind: Job metadata: name: {{ include "my-app.fullname" . }}-db-setup annotations: "helm.sh/hook": pre-install "helm.sh/hook-weight": "-5" "helm.sh/hook-delete-policy": hook-succeeded spec: template: spec: containers: – name: db-setup image: postgres:15 command: ["psql", "-c", "CREATE DATABASE myapp"] restartPolicy: Never “` **Test connection:** “`yaml # templates/tests/test-connection.yaml apiVersion: v1 kind: Pod metadata: name: "{{ include "my-app.fullname" . }}-test-connection" annotations: "helm.sh/hook": test spec: containers: – name: wget image: busybox command: ['wget'] args: ['{{ include "my-app.fullname" . }}:{{ .Values.service.port }}'] restartPolicy: Never “` **Run tests:** “`bash helm test my-app “` ## Common Patterns ### Pattern 1: Conditional Resources “`yaml {{- if .Values.ingress.enabled }} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ include "my-app.fullname" . }} spec: # … {{- end }} “` ### Pattern 2: Iterating Over Lists “`yaml env: {{- range .Values.env }} – name: {{ .name }} value: {{ .value | quote }} {{- end }} “` ### Pattern 3: Including Files “`yaml data: config.yaml: | {{- .Files.Get "config/application.yaml" | nindent 4 }} “` ### Pattern 4: Global Values “`yaml global: imageRegistry: docker.io imagePullSecrets: – name: regcred # Use in templates: image: {{ .Values.global.imageRegistry }}/{{ .Values.image.repository }} “` ## Best Practices 1. **Use semantic versioning** for chart and app versions 2. **Document all values** in values.yaml with comments 3. **Use template helpers** for repeated logic 4. **Validate charts** before packaging 5. **Pin dependency versions** explicitly 6. **Use conditions** for optional resources 7. **Follow naming conventions** (lowercase, hyphens) 8. **Include NOTES.txt** with usage instructions 9. **Add labels** consistently using helpers 10. **Test installations** in all environments ## Troubleshooting **Template rendering errors:** “`bash helm template my-app ./my-app –debug “` **Dependency issues:** “`bash helm dependency update helm dependency list “` **Installation failures:** “`bash helm install my-app ./my-app –dry-run –debug kubectl get events –sort-by='.lastTimestamp' “` ## Related Skills – `k8s-manifest-generator` – For creating base Kubernetes manifests – `gitops-workflow` – For automated Helm chart deployments