Claude Code for Helm Charts: Kubernetes Package Templating and Chart Development — Claude Skills 360 Blog
Blog / DevOps / Claude Code for Helm Charts: Kubernetes Package Templating and Chart Development
DevOps

Claude Code for Helm Charts: Kubernetes Package Templating and Chart Development

Published: July 21, 2026
Read time: 9 min read
By: Claude Skills 360

Helm charts package Kubernetes applications as reusable, configurable units. The templating language is powerful but verbose — generating correct helpers, validating values, and structuring charts for multiple environments requires knowing patterns that Claude Code applies automatically.

Chart Structure

Create a Helm chart for our Node.js API.
Supports: multiple environments via values overrides, horizontal pod autoscaling,
configmaps from config files, secrets from external secrets operator.
my-api/
├── Chart.yaml
├── values.yaml              # Defaults
├── values-staging.yaml      # Staging overrides
├── values-production.yaml   # Production overrides
├── templates/
│   ├── _helpers.tpl         # Reusable template fragments
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── hpa.yaml
│   ├── configmap.yaml
│   ├── serviceaccount.yaml
│   └── externalsecret.yaml
└── tests/
    └── deployment_test.yaml
# Chart.yaml
apiVersion: v2
name: my-api
description: Node.js API service
type: application
version: 0.1.0
appVersion: "1.0"

dependencies:
  - name: common
    version: "2.x.x"
    repository: https://charts.bitnami.com/bitnami
    condition: common.enabled
# values.yaml — all defaults
replicaCount: 1

image:
  repository: your-registry/my-api
  pullPolicy: IfNotPresent
  tag: ""  # Overridden at deploy time

serviceAccount:
  create: true
  annotations: {}

service:
  type: ClusterIP
  port: 80
  targetPort: 3000

ingress:
  enabled: false
  className: nginx
  annotations: {}
  hosts:
    - host: api.example.com
      paths:
        - path: /
          pathType: Prefix
  tls: []

resources:
  limits:
    cpu: 500m
    memory: 256Mi
  requests:
    cpu: 100m
    memory: 128Mi

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 10
  targetCPUUtilizationPercentage: 70

config:
  LOG_LEVEL: info
  NODE_ENV: production

externalSecrets:
  enabled: false
  secretStoreName: vault-backend
  refreshInterval: 1h
  secrets: []
  # - secretKey: DATABASE_URL
  #   remoteRef:
  #     key: my-api/database
  #     property: url

livenessProbe:
  httpGet:
    path: /health
    port: http
  initialDelaySeconds: 15
  periodSeconds: 20

readinessProbe:
  httpGet:
    path: /health/ready
    port: http
  initialDelaySeconds: 5
  periodSeconds: 10

Helpers Template

# templates/_helpers.tpl
{{/*
Expand the name of the chart.
*/}}
{{- define "my-api.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this.
*/}}
{{- define "my-api.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 applied to all resources.
*/}}
{{- define "my-api.labels" -}}
helm.sh/chart: {{ include "my-api.chart" . }}
{{ include "my-api.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels — used for Service/Deployment matching.
*/}}
{{- define "my-api.selectorLabels" -}}
app.kubernetes.io/name: {{ include "my-api.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
Image tag — uses .Values.image.tag if set, otherwise .Chart.AppVersion.
*/}}
{{- define "my-api.image" -}}
{{- $tag := .Values.image.tag | default .Chart.AppVersion }}
{{- printf "%s:%s" .Values.image.repository $tag }}
{{- end }}

{{/*
Validate required values.
*/}}
{{- define "my-api.validateValues" -}}
{{- if and .Values.externalSecrets.enabled (not .Values.externalSecrets.secretStoreName) }}
{{- fail "externalSecrets.secretStoreName is required when externalSecrets.enabled is true" }}
{{- end }}
{{- end }}

Deployment Template

# templates/deployment.yaml
{{- include "my-api.validateValues" . }}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "my-api.fullname" . }}
  labels:
    {{- include "my-api.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "my-api.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      annotations:
        # Force pod restart when configmap changes
        checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
      labels:
        {{- include "my-api.selectorLabels" . | nindent 8 }}
    spec:
      serviceAccountName: {{ include "my-api.serviceAccountName" . }}
      containers:
        - name: {{ .Chart.Name }}
          image: {{ include "my-api.image" . }}
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: http
              containerPort: {{ .Values.service.targetPort }}
              protocol: TCP
          envFrom:
            - configMapRef:
                name: {{ include "my-api.fullname" . }}
            {{- if .Values.externalSecrets.enabled }}
            - secretRef:
                name: {{ include "my-api.fullname" . }}-secrets
            {{- end }}
          livenessProbe:
            {{- toYaml .Values.livenessProbe | nindent 12 }}
          readinessProbe:
            {{- toYaml .Values.readinessProbe | nindent 12 }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}

Chart Testing

# tests/deployment_test.yaml
suite: deployment tests
templates:
  - deployment.yaml
  - configmap.yaml

tests:
  - it: should create a deployment with default values
    asserts:
      - isKind:
          of: Deployment
      - equal:
          path: spec.replicas
          value: 1
      - matchRegex:
          path: spec.template.spec.containers[0].image
          pattern: "your-registry/my-api:.*"

  - it: should not set replicas when autoscaling is enabled
    set:
      autoscaling.enabled: true
    asserts:
      - notExists:
          path: spec.replicas

  - it: should include secret envFrom when externalSecrets enabled
    set:
      externalSecrets.enabled: true
      externalSecrets.secretStoreName: vault
    template: deployment.yaml
    asserts:
      - contains:
          path: spec.template.spec.containers[0].envFrom
          content:
            secretRef:
              name: RELEASE-NAME-my-api-secrets

  - it: should fail when externalSecrets enabled without secretStoreName
    set:
      externalSecrets.enabled: true
    asserts:
      - failedTemplate:
          errorMessage: "externalSecrets.secretStoreName is required"
# Install helm-unittest plugin and run tests
helm plugin install https://github.com/helm-unittest/helm-unittest
helm unittest my-api/

Environment-Specific Deployments

# Deploy to staging
helm upgrade --install my-api-staging ./my-api \
  --namespace staging \
  --create-namespace \
  --values ./my-api/values-staging.yaml \
  --set image.tag=1.5.2

# Deploy to production (manual approval step in your pipeline)
helm upgrade --install my-api-production ./my-api \
  --namespace production \
  --values ./my-api/values-production.yaml \
  --set image.tag=1.5.2 \
  --atomic \          # Rollback automatically on failure
  --timeout 5m

For ArgoCD to manage Helm chart deployments via GitOps, see the GitOps guide. For the ingress configuration these charts reference, see the Kubernetes guide. The Claude Skills 360 bundle includes Helm skill sets for chart development, testing, and multi-environment strategies. Start with the free tier to try Helm chart scaffolding.

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free