Bob's Journey into Advanced Helm: Mastering Charts

Bob and Josie dive into advanced Helm charting, mastering dynamic environments, service dependencies, and templating techniques. Discover how to streamline Kubernetes deployments with reusable configurations and smart templates in this next step of their tech journey!

Bob's Journey into Advanced Helm: Mastering Charts

Bob leans back in his chair, staring at the screen. "Alright, I've got the basics down. I can deploy my app with Helm. But how do I make my charts adapt to different environments? And what about adding other services? I don't want to manually edit files for every change."

Josie, who seems to have a sixth sense for Bob's struggles, wanders over. "Dynamic Helm charts, Bob. That's your next step. Let me walk you through it."

Bob listens intently as Josie begins explaining.

📂 Code Repository: Explore the complete code and configurations for this article on GitHub.

View Repository on GitHub

Dynamic Environments

"First" Josie starts, "you’ll want to use Helm values files effectively. That's where environment-specific configurations come into play".

She points to Bob's screen. "See here? You can create separate values files for each environment ... like production or staging ... and use those to customise your deployment"

Josie demonstrates by creating two files:

values.production.yaml:

replicaCount: 5
resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "1Gi"
    cpu: "1"

values.staging.yaml:

replicaCount: 2
resources:
  requests:
    memory: "256Mi"
    cpu: "250m"
  limits:
    memory: "512Mi"
    cpu: "500m"

Bob raises an eyebrow. "So, I can just apply these files depending on where I’m deploying?"

"Exactly" Josie confirms. "But remember ... Helm always loads values.yaml first if it exists. Any other file, like values.production.yaml, will overlay on top of it. You might want to check out this 🔗Helm Values Gotchas article to avoid surprises."

Bob nods, making the following notes:

  • Values files adapt charts to specific environments
  • values.yaml serves as the base configuration
  • Environment overlays, like values.production.yaml, simplify customisation

Managing Service Dependencies

Bob looks at the new chart. "What if my app relies on something like Redis or PostgreSQL? Do I need to deploy those manually?"

Josie shakes her head. "That's what Helm dependencies are for. Let me show you."

She updates Bob's Chart.yaml file:

dependencies:
  - name: redis
    version: 16.12.0
    repository: https://charts.bitnami.com/bitnami

"We're telling Helm to pull in the Redis chart" Josie explains. "Now, run this command to download it."

helm dependency update

She then opens the values.yaml file.

redis:
  auth:
    password: "supersecurepassword"

"Just configure it here, and Helm handles the rest. It'll make sure Redis is deployed and ready before your app starts. The one thing to remember here is the values for dependencies need to be listed under the name of the chart, in this case redis.*."

Bob tries it out, watching as Redis spins up seamlessly.

Bob leans back, his brain buzzing with new knowledge. "This is great. But what if I make a mistake? These charts are getting pretty complex."

Josie grins. "That's why you review and simplify. Avoid over-complicated configurations, keep things secure, and test thoroughly. The more you practice, the better you'll get at mastering Helm."

Bob notes down some points for later:

  • Helm dependencies streamline multi-service deployments
  • Define dependencies in Chart.yaml and configure in values.yaml
  • Helm ensures proper order, reducing manual setup

Advanced Helm Templating

Bob’s mind races as he types. "Alright, so I can handle dynamic environments and dependencies. But what if I need to deploy multiple components of an app ... like a frontend, backend, and worker pods ... all from a single chart?"

Josie nods approvingly. "Advanced templating, Bob. That's where Helm really shines. You can use a single chart to dynamically generate multiple deployments based on a reusable apps block"

She begins crafting an example. "Here’s how you do it. Start by defining an apps block in your values.yaml file."

apps:
  - name: frontend
    enabled: true
    replicas: 3
    image:
      repository: myapp/frontend
      tag: v1.0
  - name: backend
    enabled: true
    replicas: 2
    image:
      repository: myapp/backend
      tag: v1.0
  - name: worker
    enabled: true
    replicas: 1
    image:
      repository: myapp/worker
      tag: v1.0

Josie continues, "Now, update your deployment template to iterate over this block dynamically."

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.global.releaseName }}-{{ .name }}
  labels:
    app: {{ .name }}
spec:
  replicas: {{ .replicas }}
  selector:
    matchLabels:
      app: {{ .name }}
  template:
    metadata:
      labels:
        app: {{ .name }}
    spec:
      containers:
        - name: {{ .name }}
          image: {{ .image.repository }}:{{ .image.tag }}
          ports:
            - containerPort: 80

Bob leans in. "This .Values.apps block feeds into the template, so I can define each app's specifics without duplicating the YAML?"

"Exactly" Josie says. "You can loop through apps using Helm's range function."

{{- range .Values.apps }}
{{- if .enabled }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .name }}
spec:
  replicas: {{ .replicas }}
  template:
    spec:
      containers:
        - name: {{ .name }}
          image: {{ .image.repository }}:{{ .image.tag }}
{{- end }}
{{- end }}

Bob tests it out, deploying his chart. "It works! Frontend, backend, and worker pods are all deployed without a single line of repetitive YAML."

Josie smiles. "Welcome to the world of advanced Helm templating, Bob. With these techniques, you can handle even the most complex deployments with elegance."

Bob sits back, satisfied with his dynamic deployments. But as he reviews his app's storage requirements, another thought crosses his mind. "Josie, could I use this same approach for other Kubernetes resources, like dynamically creating PersistentVolumeClaims for my apps?"

Josie smiles. "Exactly, Bob. The beauty of Helm is that once you understand the templating, you can apply it to any resource. Let me show you how."

She starts by adding a volumes block to the values.yaml file.

volumes:
  - name: app-frontend-storage
    enabled: true
    storageClassName: fast
    accessModes:
      - ReadWriteOnce
    resources:
      requests:
        storage: 5Gi
  - name: app-backend-storage
    enabled: true
    storageClassName: standard
    accessModes:
      - ReadWriteOnce
    resources:
      requests:
        storage: 10Gi
  - name: app-worker-storage
    enabled: false
    storageClassName: standard
    accessModes:
      - ReadWriteMany
    resources:
      requests:
        storage: 1Gi

"Here" she explains, "we define a list of volumes with all the necessary attributes, including an enabled flag to control which ones get created."

Next, Josie updates the PVC template:

{{- range .Values.volumes }}
{{- if .enabled }}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: {{ .name }}
spec:
  storageClassName: {{ .storageClassName }}
  accessModes:
    {{- range .accessModes }}
    - {{ . }}
    {{- end }}
  resources:
    requests:
      storage: {{ .resources.requests.storage }}
{{- end }}
{{- end }}

Bob leans forward. "So this loops through the volumes list, and only creates PVCs where enabled: true?"

"Exactly" Josie confirms. "You can handle as many PVCs as you need without duplicating YAML. Just add or adjust entries in the volumes block, and Helm does the rest."

Bob quickly tests it out. "The PVCs for the frontend and backend are created, but not for the worker. Perfect!"

Josie grins. "Now you see, Bob. This templating technique isn't just for deployments. It’s a powerful pattern you can apply to any Kubernetes resource."

  • Dynamic templates eliminate YAML duplication
  • Use reusable blocks (apps, volumes) for flexibility
  • Flags like enabled provide fine-grained control

Bob leans back, a confident smile spreading across his face. "Josie, I can't believe how much I've learned. Dynamic environments, managing dependencies, advanced templating, and now even storage ... all of this from a single chart."

Josie nods. "You've done well, Bob. Remember, the key to mastering Helm is practising and refining. Whether you're scaling apps, deploying across environments, or managing complex dependencies, these techniques will give you the flexibility and control you need."

Bob jots down a final note: Experiment with integrating CI/CD pipelines and explore tools like Helmfile for managing multi-chart deployments.

As he closes his laptop, Bob realises this isn't just about Helm charts ... it's about building scalable, efficient systems that make life easier for developers everywhere.