home / skills / mjunaidca / mjs-agent-skills / helm-charts

This skill creates and manages Helm charts for Kubernetes deployments, packaging applications with Chart.yaml, values.yaml, and templates for reliable rollout.

npx playbooks add skill mjunaidca/mjs-agent-skills --skill helm-charts

Review the files below or copy the command above to add this skill to your agents.

Files (3)
SKILL.md
8.2 KB
---
name: helm-charts
description: Creates and manages Helm charts for Kubernetes deployments. This skill should be used when packaging applications for Kubernetes using Helm, creating Chart.yaml, values.yaml, and templates. It covers chart structure, templating, dependencies, and deployment patterns. Use this skill for Phase IV+ Kubernetes deployments.
---

# Helm Charts Skill

## Overview

Helm is the package manager for Kubernetes. It packages Kubernetes manifests into reusable **charts** that can be versioned, shared, and deployed with customizable values.

## Core Concepts

### What is a Helm Chart?

A chart is a collection of files that describe a related set of Kubernetes resources:

```
mychart/
├── Chart.yaml          # Chart metadata (name, version, dependencies)
├── values.yaml         # Default configuration values
├── charts/             # Dependency charts
├── templates/          # Kubernetes manifest templates
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── configmap.yaml
│   ├── secret.yaml
│   ├── _helpers.tpl    # Template helpers
│   └── NOTES.txt       # Post-install notes
└── .helmignore         # Files to ignore when packaging
```

### Key Files

| File | Purpose |
|------|---------|
| `Chart.yaml` | Metadata: name, version, appVersion, dependencies |
| `values.yaml` | Default configuration values (overridable) |
| `templates/` | Go-templated Kubernetes manifests |
| `_helpers.tpl` | Reusable template snippets |

## Chart.yaml Structure

```yaml
apiVersion: v2                    # Helm 3 uses v2
name: taskflow                    # Chart name
description: TaskFlow Platform    # Short description
type: application                 # application or library
version: 1.0.0                    # Chart version (SemVer)
appVersion: "1.0.0"               # Application version

# Dependencies (optional)
dependencies:
  - name: postgresql
    version: "12.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled
```

## values.yaml Pattern

```yaml
# Global settings
global:
  imageRegistry: ""
  imagePullSecrets: []

# Per-service configuration
api:
  replicaCount: 1
  image:
    repository: taskflow/api
    tag: "latest"
    pullPolicy: IfNotPresent
  service:
    type: ClusterIP
    port: 8000
  resources:
    limits:
      cpu: 500m
      memory: 512Mi
    requests:
      cpu: 100m
      memory: 128Mi
  env:
    DATABASE_URL: ""
    SSO_URL: "http://sso:3001"

# Feature flags
postgresql:
  enabled: true
  auth:
    postgresPassword: "postgres"
    database: "taskflow"
```

## Template Syntax

### Accessing Values

```yaml
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "taskflow.fullname" . }}
  labels:
    {{- include "taskflow.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.api.replicaCount }}
  selector:
    matchLabels:
      {{- include "taskflow.selectorLabels" . | nindent 6 }}
  template:
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.api.image.repository }}:{{ .Values.api.image.tag }}"
          ports:
            - containerPort: {{ .Values.api.service.port }}
          env:
            - name: DATABASE_URL
              value: {{ .Values.api.env.DATABASE_URL | quote }}
```

### Helper Templates (_helpers.tpl)

```yaml
{{/*
Expand the name of the chart.
*/}}
{{- define "taskflow.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
*/}}
{{- define "taskflow.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "taskflow.labels" -}}
helm.sh/chart: {{ include "taskflow.chart" . }}
{{ include "taskflow.selectorLabels" . }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "taskflow.selectorLabels" -}}
app.kubernetes.io/name: {{ include "taskflow.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
```

## Essential Commands

### Create New Chart
```bash
helm create mychart
```

### Install Chart
```bash
# From local directory
helm install my-release ./mychart

# With custom values file
helm install my-release ./mychart --values custom-values.yaml

# With inline value overrides
helm install my-release ./mychart \
  --set api.replicaCount=3 \
  --set api.image.tag=v2.0.0

# To specific namespace (create if needed)
helm install my-release ./mychart \
  --namespace production \
  --create-namespace

# Dry run (preview without installing)
helm install my-release ./mychart --dry-run --debug
```

### Upgrade Release
```bash
helm upgrade my-release ./mychart --values new-values.yaml
```

### Rollback
```bash
helm rollback my-release 1  # Rollback to revision 1
```

### Uninstall
```bash
helm uninstall my-release
```

### List Releases
```bash
helm list
helm list --all-namespaces
```

### Debug Templates
```bash
# Render templates without installing
helm template my-release ./mychart

# Debug with computed values
helm template my-release ./mychart --debug
```

## Multi-Service Chart Pattern

For TaskFlow (api, sso, web, mcp-server), use a single chart with multiple templates:

```
helm/taskflow/
├── Chart.yaml
├── values.yaml
├── templates/
│   ├── _helpers.tpl
│   ├── NOTES.txt
│   ├── api/
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   └── configmap.yaml
│   ├── sso/
│   │   ├── deployment.yaml
│   │   └── service.yaml
│   ├── web/
│   │   ├── deployment.yaml
│   │   └── service.yaml
│   ├── mcp-server/
│   │   ├── deployment.yaml
│   │   └── service.yaml
│   └── ingress.yaml
```

## ConfigMap and Secrets

### ConfigMap Template
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "taskflow.fullname" . }}-config
data:
  SSO_URL: {{ .Values.sso.url | quote }}
  API_URL: {{ .Values.api.url | quote }}
```

### Secret Template (from values)
```yaml
apiVersion: v1
kind: Secret
metadata:
  name: {{ include "taskflow.fullname" . }}-secrets
type: Opaque
data:
  database-url: {{ .Values.secrets.databaseUrl | b64enc | quote }}
  openai-api-key: {{ .Values.secrets.openaiApiKey | b64enc | quote }}
```

## Health Checks Pattern

```yaml
spec:
  containers:
    - name: api
      livenessProbe:
        httpGet:
          path: /health
          port: 8000
        initialDelaySeconds: 30
        periodSeconds: 10
      readinessProbe:
        httpGet:
          path: /health
          port: 8000
        initialDelaySeconds: 5
        periodSeconds: 5
```

## Ingress Pattern

```yaml
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ include "taskflow.fullname" . }}
  annotations:
    {{- toYaml .Values.ingress.annotations | nindent 4 }}
spec:
  ingressClassName: {{ .Values.ingress.className }}
  rules:
    - host: {{ .Values.ingress.host }}
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: {{ include "taskflow.fullname" . }}-api
                port:
                  number: 8000
          - path: /
            pathType: Prefix
            backend:
              service:
                name: {{ include "taskflow.fullname" . }}-web
                port:
                  number: 3000
{{- end }}
```

## Common Gotchas

1. **Quote strings in templates**: Use `{{ .Values.foo | quote }}` for strings
2. **Indentation matters**: Use `nindent` for proper YAML formatting
3. **Resource names**: Keep under 63 characters (K8s limit)
4. **Image pull policy**: Use `IfNotPresent` in production, `Always` in dev
5. **Secrets**: Never commit real secrets to values.yaml

## Resources

Refer to `references/` for:
- `chart-patterns.md` - Advanced templating patterns
- `values-structure.md` - Values.yaml organization guide

Refer to `assets/` for:
- `base-chart/` - Complete starter chart template

Overview

This skill creates and manages Helm charts for Kubernetes deployments, providing templates, values structure, and packaging patterns to produce repeatable, versioned releases. It focuses on Chart.yaml, values.yaml, template helpers, dependencies, and multi-service chart layouts. Use it to package applications for Phase IV+ Kubernetes environments with clear deployment and upgrade workflows.

How this skill works

The skill generates chart scaffolding and edits Chart.yaml and values.yaml to capture metadata, default configuration, and dependency declarations. It builds templated Kubernetes manifest files under templates/, including helper templates (_helpers.tpl) for consistent names and labels, and creates ConfigMap and Secret templates that encode values safely. It also provides command patterns for install, upgrade, rollback, dry-run, and template debugging to validate computed manifests before deployment.

When to use it

  • Packaging an application or multi-service stack for deployment to Kubernetes using Helm
  • Creating reusable, versioned releases with configurable defaults and environment overrides
  • Managing chart dependencies such as bundled databases or third-party charts
  • Standardizing naming, labels, and selector patterns across services
  • Preparing production-ready charts with health checks, ingress, and resource limits

Best practices

  • Keep Chart.yaml semantic (chart version vs appVersion) and declare dependencies explicitly
  • Place defaults in values.yaml and avoid committing real secrets; use external secret stores when possible
  • Use helper templates for consistent naming, labels, and selector logic to avoid duplication
  • Quote values in templates and use nindent to preserve YAML indentation
  • Validate templates with helm template --debug and use dry-run installs before production
  • Keep resource names under 63 characters and set sensible resource requests/limits and probes

Example use cases

  • Create a single Helm chart for a multi-service platform (api, web, sso) with per-service templates and shared helpers
  • Package an application with a bundled PostgreSQL dependency controlled by a values flag
  • Produce environment-specific overrides (staging/production) using separate values files and --set for small patches
  • Generate ConfigMap and Secret templates that reference values.yaml and base64-encode secrets on render
  • Implement ingress rules that route multiple service paths behind a single host using values-driven paths and annotations

FAQ

How do I avoid committing secrets into the chart?

Keep secrets out of values.yaml. Use external secret managers or pass sensitive values at install time with --set or Helm secrets tooling, and ensure .helmignore excludes local secret files.

When should I use a single chart for multiple services versus separate charts?

Use a single chart when services are tightly coupled and released together. Use separate charts if services have independent lifecycles, teams, or scaling requirements.