I’m a Senior Software Engineer living in Berlin. Shifting limits based on quality and robustness. Cutting-edge software development. Defining durable and flexible interfaces. Creating rich and intuitive user experiences.

Deploy a custom Helm Chart on a local Kubernetes Cluster

When experimenting with Kubernetes locally, combining Podman as the container runtime, k3d/k3s as the lightweight Kubernetes distribution, and Helm as the package manager provides a powerful, self-contained environment. Adding Traefik as a load balancer and ingress controller lets you simulate real-world traffic routing, complete with host-based routing and dashboards.

This article walks through setting up such an environment, deploying Traefik, and creating a custom Helm chart for a simple sample application.

1. Preparing Podman

On macOS, Podman runs inside a VM. Start by allocating resources and initializing the machine:

podman machine init \
--cpus 8 \
--disk-size 100 \
--memory 8092
podman machine start

This provides the container runtime that k3d will use to host the Kubernetes cluster.

2. Creating a k3d/k3s Cluster

Next, create a new cluster using k3d. In this setup, we’ll expose ports for HTTP, HTTPS, and a Traefik dashboard, while disabling the default Traefik that ships with k3s (so we can install our own):

k3d cluster create traefik \
--port 80:80@loadbalancer \
--port 443:443@loadbalancer \
--port 8000:8000@loadbalancer \
--k3s-arg "--disable=traefik@server:0"

Check the cluster:

kubectl cluster-info --context k3d-traefik

3. Installing Traefik with Helm

With the cluster ready, install Traefik via its Helm chart. This will enable the dashboard and set up Kubernetes Gateway API support:

helm repo add traefik https://traefik.github.io/charts
helm repo update
helm install traefik traefik/traefik --wait \
--set ingressRoute.dashboard.enabled=true \
--set ingressRoute.dashboard.matchRule='Host(`dashboard.localhost`)' \
--set ingressRoute.dashboard.entryPoints={web} \
--set providers.kubernetesGateway.enabled=true \
--set gateway.listeners.web.namespacePolicy.from=All

Inspect the installed GatewayClass to confirm Traefik is registered:

kubectl describe gatewayclasses.gateway.networking.k8s.io traefik

Once ready, open the dashboard:

open http://dashboard.localhost/dashboard/

4. Creating a Custom Helm Chart

Now that the cluster and Traefik ingress are working, let’s package a small sample application with Helm. We’ll use Traefik’s whoami container, which simply responds with request information.

Scaffold a new chart:

helm create whoami

By default, helm create generates a full set of example templates (ConfigMaps, Ingress, HPA, tests, etc.). For a minimal chart, you can clear them out and start fresh:

rm whoami/templates/*

This leaves you with an empty templates/ directory that you can populate only with the manifests you need.

values.yaml

Here we define the app name, image, replicas, and service port:

name: whoami
replicaCount: 2
image: traefik/whoami
service:
port: 80

Deployment

A simple deployment pulling values from values.yaml:

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Values.name }}
template:
metadata:
labels:
app: {{ .Values.name }}
spec:
containers:
- name: {{ .Values.name }}
image: {{ .Values.image }}
ports:
- containerPort: 80

Service

Expose the pods internally with a ClusterIP service:

# templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.name }}
spec:
ports:
- port: {{ .Values.service.port }}
selector:
app: {{ .Values.name }}

IngressRoute

Route external requests via Traefik. This maps http://whoami.localhost to the service:

# templates/ingress-route.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: {{ .Values.name }}
spec:
entryPoints:
- web
routes:
- match: Host(`{{ .Values.name }}.localhost`)
kind: Rule
services:
- name: {{ .Values.name }}
port: {{ .Values.service.port }}

5. Deploy and Verify

Install the chart:

helm install whoami ./whoami

(Optionally run with --debug --dry-run first to inspect the rendered manifests.)

Check the generated manifests:

helm get manifest whoami

Now, open http://whoami.localhost in your browser. You should see output like:

Hostname: whoami-xxxxxxxxxx-xxxxx
IP: 10.42.x.x

This confirms your app is deployed, load-balanced, and routed through Traefik.

6. Cleanup

When you’re finished testing, it’s good practice to tear down the resources you created so your local environment stays clean.

First, uninstall the Helm release for your sample application:

helm uninstall whoami

If you also want to remove Traefik:

helm uninstall traefik

Finally, delete the entire k3d cluster:

k3d cluster delete traefik

This will stop and remove all containers, networks, and volumes associated with the cluster. If you want to reclaim resources used by the Podman VM, you can also stop or remove it:

podman machine stop
# or remove it completely:
podman machine rm

With that, your environment is back to a clean state, ready for your next Kubernetes experiment.

Conclusion

By combining Podman, k3d/k3s, Traefik, and Helm, you can simulate a production-like Kubernetes environment entirely on your laptop.

  • Podman provides the container runtime.
  • k3d/k3s runs a lightweight Kubernetes cluster.
  • Traefik acts as an ingress controller and load balancer.
  • Helm allows you to package, configure, and deploy applications.

The whoami example demonstrates the complete lifecycle: from cluster creation to ingress routing. With this foundation, you can now adapt charts for your own services, experiment with Kubernetes Gateway API, and iterate on deployments locally before promoting them to larger environments.