TL;DR: Helm uses templates and variables to make Kubernetes applications easier to configure and implement across different environments.

Comparing plain Kubernetes YAML files with Helm-templated YAML highlights why Helm is a widely used package manager and templating tool for Kubernetes.

The Core Difference

  • Plain YAML (Static): Every value is hardcoded. To deploy to different environments, you must manually copy, paste, and modify files (or use search-and-replace scripts).

  • Helm YAML (Dynamic): Values are parameterized using placeholders ({{ .Values... }}). A single template generates customized manifests based on a separate values.yaml file.

Code Comparison

    1. Plain Kubernetes Deployment (deployment.yaml)

To change the image tag or memory limits for staging vs. production, you have to maintain completely separate copies of this file or edit it directly before applying.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-web-app-prod
  labels:
    app: my-web-app
    env: production
spec:
  replicas: 5
  selector:
    matchLabels:
      app: my-web-app
  template:
    metadata:
      labels:
        app: my-web-app
    spec:
      containers:
        - name: web
          image: myregistry.azurecr.io/web-app:v2.1.0
          resources:
            limits:
              memory: "1Gi"
              cpu: "500m"
          ports:
            - containerPort: 8080
    1. Helm Templated Deployment (templates/deployment.yaml)

Notice how hardcoded values are replaced with variables and template logic.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-{{ .Values.environment }}
  labels:
    app: {{ .Values.appName }}
    env: {{ .Values.environment }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Values.appName }}
  template:
    metadata:
      labels:
        app: {{ .Values.appName }}
    spec:
      containers:
        - name: web
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          resources:
            limits:
              memory: {{ .Values.resources.limits.memory | quote }}
              cpu: {{ .Values.resources.limits.cpu | quote }}
          ports:
            - containerPort: {{ .Values.service.targetPort }}

Accompanying values.yaml File. All user-configurable variables live in a clean, centralized configuration file:

appName: my-web-app
environment: production
replicaCount: 5

image:
  repository: myregistry.azurecr.io/web-app
  tag: v2.1.0

service:
  targetPort: 8080

resources:
  limits:
    memory: "1Gi"
    cpu: "500m"

This is the simplified idea.

Helm provides considerably more than variables. It has a template engine, chart structure, dependency management, release management, and other features for packaging and deploying Kubernetes applications.

Helm 3 is the current major version and introduced a different architecture from Helm 2, including the removal of Tiller.

For this article, however, the main idea is simple, Kubernetes YAML describes the desired resources. Helm templates make those resources configurable and reusable. values.yaml provides the configuration values.

Helm renders the templates into Kubernetes manifests and manages them as a release.


Back to Certified Cloud Native Platform Engineering Associate Preparation