Charts

In the previous chapters when dealing with Kubernetes, we learned how to create and manage a bunch of different Kubernetes components and applications by using yaml files. As you can imagine handling multiple yaml files for every single application can get quite cumbersome once you have more than just two or three deployments in parallel. It’s a lot of steps you have to take to get everything up and running, and handling versioning between the different moving parts can be difficult at times.

To make it short: Similar to Docker where we packaged all our dependencies into one Dockerfile, it would be convenient to be able to package all the different components of a kubernetes application (deployment.yaml, service.yaml, …) into one configuration and deploy that configuration as a single step. This is where helm steps in.

Exercise - The components of a helm chart

An empty helm chart has already been created for the postgresdb. You can go ahead and list it’s contents with the tree command.

tree postgresdb/helmchart/

This should display output similar to this:

helmchart
├── charts
├── Chart.yaml
├── templates
└── values.yaml

2 directories, 2 files

As you can see, a minimal helm chart consist of four parts:

  • The Chart.yaml contains metadata like the name of the chart or the version of the application.
  • The values.yaml file is used to store parameters which can later be injected into the template files.
  • The templates directory contains all of your kubernetes .yaml files like deployment and service definitions.
  • The charts directory contains all of the dependencies of your chart.
Info

Don’t worry about the empty templates/ and charts/ directories for now, we are going to put files in there soon!

Exercise - Taking a look at the Chart.yaml file

Let’s start by looking at the Chart.yaml file that is already there.

cat postgresdb/helmchart/Chart.yaml

apiVersion: v1
appVersion: "1.0"
name: postgresdb
description: postgresdb
version: 0.1.0

As you can see there is not much going on in this file. We declare the version of the chart and the application and we give the chart a name and a description.

Exercise - Add templates to our chart

To make the chart do anything we have to provide it with templates. When we finally deploy the chart, helm will look into the templates/ directory and deploy every kubernetes resource definition it finds.

cp postgres.yaml postgresdb/helmchart/templates/

cp postgres-service.yaml postgresdb/helmchart/templates/

Warning

You may still have an instance of a postgres deployment running from previous exercises. To avoid name conflicts please change all postgresdb values of name and app in postgresdb/helmchart/templates/postgres.yaml and postgresdb/helmchart/templates/postgres-service.yaml to helm-postgresdb.

Your postgresdb/helmchart/ directory should look like this now:

postgresdb/helmchart/
├── charts
├── Chart.yaml
├── templates
│   └── postgres-service.yaml
│   └── postgres.yaml
└── values.yaml

2 directories, 4 files

And that’s it, in the next step we can look at deploying the newly created chart!

Exercise - Deploying our first helm chart

In the previous step we created a minimal helm chart with two templates, the postgresdb deployment and the postgresdb service. To install this chart on a kubernetes cluster all we have to do is run the helm install command:

helm install postgres ./postgresdb/helmchart/

Output

You should see console output similar to this:

NAME: postgres
LAST DEPLOYED: Thu Jan 29 14:16:37 2026
NAMESPACE: <your_namespace>
STATUS: deployed
REVISION: 1
TEST SUITE: None

As you can see we successfully deployed a helm chart with the name postgres.

Exercise - Listing helm releases

What we have just created is called a release. A release is just one of many possible deployed instances of a helm chart. We can list all releases by running helm list which in our case should produce output like this:

NAME            NAMESPACE               REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
postgres        <your_namespace>        1               2026-01-29 14:16:37.517790785 +0100 CET deployed        postgresdb-0.1.0        1.0

Exercise - Verifying the release

To verify that the release was installed successfully we can run kubectl get svc,deploy,po and watch helm deploy our database. It should list the following resources:

NAME                      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/helm-postgresdb   ClusterIP   10.0.255.204   <none>        5432/TCP   56s

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/helm-postgresdb   1/1     1            1           56s

NAME                                   READY   STATUS    RESTARTS   AGE
pod/helm-postgresdb-74dd68db99-gr7xg   1/1     Running   0          56s

Alternatively you can use helm status <release name> to show the status of a given release.

Running helm status postgres should render output similar to this:

NAME: postgres
LAST DEPLOYED: Thu Jan 29 14:16:37 2026
NAMESPACE: <your_namespace>
STATUS: deployed
REVISION: 1
TEST SUITE: None

Exercise - Postgres cleanup

Similar to helm install we can run helm uninstall <release name> to uninstall a release. Please go ahead and uninstall our postgresdb release!

Solution
release "postgres" uninstalled

Exercise - Helm repositories

We already learned about the concept of repositories in the Docker section where we used repositories to store our images and make them accessible for the public. Helm uses the same concept to manage charts and allows us to use

helm install

to install a chart from a public repository.

For reference, the CNCF is building a web-based application that enables finding, installing, and publishing packages and configurations for CNCF projects, also including Helm charts. It is called Artifact Hub .

To install a helm chart from a remote source we have to take a few steps:

  1. Add the helm repository with helm repo add <repository url>
  2. Fetch updates from the remote repositories with helm repo update
  3. Install the chart with helm install <repository/chart>

Please run the following commands to install a simple WordPress deployment from its public repository:

  1. helm repo add bitnami https://charts.bitnami.com/bitnami

    Output
    "bitnami" has been added to your repositories
  2. helm repo update

    Output
    Hang tight while we grab the latest from your chart repositories...
    ...Successfully got an update from the "bitnami" chart repository
    Update Complete. ⎈Happy Helming!⎈
  3. helm search repo wordpress

    Output
    NAME                    CHART VERSION   APP VERSION     DESCRIPTION
    bitnami/wordpress       28.1.2          6.9.0           WordPress is the world's most popular blogging ...
    bitnami/wordpress-intel 2.1.31          6.1.1           DEPRECATED WordPress for Intel is the most popu...
  4. helm search repo --versions bitnami/wordpress

    Output
    NAME                    CHART VERSION   APP VERSION     DESCRIPTION
    bitnami/wordpress       28.1.2          6.9.0           WordPress is the world's most popular blogging ...
    bitnami/wordpress       28.1.0          6.9.0           WordPress is the world's most popular blogging ...
    bitnami/wordpress       28.0.4          6.9.0           WordPress is the world's most popular blogging ...
    bitnami/wordpress       28.0.3          6.9.0           WordPress is the world's most popular blogging ...
    bitnami/wordpress       28.0.2          6.9.0           WordPress is the world's most popular blogging ...
    bitnami/wordpress       28.0.1          6.8.3           WordPress is the world's most popular blogging ...
    bitnami/wordpress       28.0.0          6.8.3           WordPress is the world's most popular blogging ...
    bitnami/wordpress       27.2.1          6.8.3           WordPress is the world's most popular blogging ...
    bitnami/wordpress       27.2.0          6.8.3           WordPress is the world's most popular blogging ...
    bitnami/wordpress       27.1.8          6.8.3           WordPress is the world's most popular blogging ...
    ... a long list of possible versions ...
  5. helm install wordpress bitnami/wordpress --version 28.1.2

    Output
    NAME: wordpress
    LAST DEPLOYED: Thu Jan 29 14:27:09 2026
    NAMESPACE: <your_namespace>
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    NOTES:
    CHART NAME: wordpress
    CHART VERSION: 28.1.2
    APP VERSION: 6.9.0
    
    ⚠ WARNING: Since August 28th, 2025, only a limited subset of images/charts are available for free.
       Subscribe to Bitnami Secure Images to receive continued support and security updates.
       More info at https://bitnami.com and https://github.com/bitnami/containers/issues/83267
    
    ** Please be patient while the chart is being deployed **
    
    Your WordPress site can be accessed through the following DNS name from within your cluster:
    
       wordpress.<your_namespace>.svc.cluster.local (port 80)
    
    To access your WordPress site from outside the cluster follow the steps below:
    
    1. Get the WordPress URL by running these commands:
    
    NOTE: It may take a few minutes for the LoadBalancer IP to be available.
          Watch the status with: 'kubectl get svc --namespace <your_namespace> -w wordpress'
    
       export SERVICE_IP=$(kubectl get svc --namespace <your_namespace> wordpress --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
       echo "WordPress URL: http://$SERVICE_IP/"
       echo "WordPress Admin URL: http://$SERVICE_IP/admin"
    
    2. Open a browser and access WordPress using the obtained URL.
    
    3. Login with the following credentials below to see your blog:
    
    echo Username: user
    echo Password: $(kubectl get secret --namespace <your_namespace> wordpress -o jsonpath="{.data.wordpress-password}" | base64 -d)
    WARNING: Rolling tag detected (bitnami/wordpress:latest), please note that it is strongly recommended to avoid using rolling tags in a production environment.
    +info https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html
    WARNING: Rolling tag detected (bitnami/apache-exporter:latest), please note that it is strongly recommended to avoid using rolling tags in a production environment.
    +info https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html
    WARNING: Rolling tag detected (bitnami/os-shell:latest), please note that it is strongly recommended to avoid using rolling tags in a production environment.
    +info https://techdocs.broadcom.com/us/en/vmware-tanzu/application-catalog/tanzu-application-catalog/services/tac-doc/apps-tutorials-understand-rolling-tags-containers-index.html
    
    WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs:
    - resources
    +info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/

Why this specific version? Well, this version was last tested by us, and we don’t want to just blindly install latest, do we?

Again, you can verify the proper creation of the deployment by running kubectl get svc,deploy,po, which among other things should list the following:

Output
NAME                                 TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
service/wordpress                    LoadBalancer   10.0.244.46    40.119.152.147   80:30188/TCP,443:31410/TCP   2m22s
service/wordpress-mariadb            ClusterIP      10.0.182.215   <none>           3306/TCP                     2m22s
service/wordpress-mariadb-headless   ClusterIP      None           <none>           3306/TCP                     2m22s

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/wordpress   1/1     1            1           2m21s

NAME                             READY   STATUS    RESTARTS   AGE
pod/wordpress-76f7c87c8b-8kj8g   1/1     Running   0          2m21s
pod/wordpress-mariadb-0          1/1     Running   0          2m21s

You can now access your WordPress site in your browser or by running

curl --silent http://<your_wordpress_LoadBalancer_IP>/ | grep "<title>"

using the IP declared by the service/wordpress. The curl statement should output

$ curl --silent http://40.119.152.147/ | grep "<title>"
<title>User&#039;s Blog!</title>

Exercise - Wordpress cleanup

Congratulations, you just deployed a helm chart from a public chart repository! In the next chapter we are going to look at configuring charts via command line parameters and custom values files. For now you can go ahead and uninstall the wordpress release again.

helm uninstall wordpress

Watch via kubectl get svc,deploy,po how the resources will get deleted. Does anything remain?

Solution

Well, yes. Per default the wordpress chart will persist the database storage, cf. kubectl get pvc. This normally makes sense, but here in our context it will prevent a clean reinstallation of this chart, so now let’s ensure the storage gets dropped as well:

kubectl delete pvc data-wordpress-mariadb-0