Install Helm CLI
Follow the instruction at https://helm.sh/docs/intro/install/
sudo apt-get install curl gpg apt-transport-https --yes
curl -fsSL https://packages.buildkite.com/helm-linux/helm-debian/gpgkey | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/helm.gpg] https://packages.buildkite.com/helm-linux/helm-debian/any/ any main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm
Artifact Hub
Artifact hub hosts publicly available helm chart to deploy the application to your kubernates.
https://artifacthub.io/
helm repo command
helm maintains a local cache of all the helm chart you downloaded, the command will add a helm chart info to your local cache
helm repo add bitnami https://charts.bitnami.com/bitnami
To list your local cache
helm repo list
To update your local cache
helm repo update
To search helm chart from your local(the cache is located $HOME/.cache/helm/repository
helm search repo wordpress
To search helm chart from artifacthub
helm search hub wordpress
To show a specific helm chart
helm show chart bitnami/wordpress
annotations:
category: CMS
images: |
- name: apache-exporter
image: docker.io/bitnami/apache-exporter:1.0.10-debian-12-r55
- name: os-shell
image: docker.io/bitnami/os-shell:12-debian-12-r50
- name: wordpress
image: docker.io/bitnami/wordpress:6.8.2-debian-12-r4
licenses: Apache-2.0
tanzuCategory: application
apiVersion: v2
appVersion: 6.8.2
dependencies:
- condition: memcached.enabled
name: memcached
repository: oci://registry-1.docker.io/bitnamicharts
version: 7.x.x
- condition: mariadb.enabled
name: mariadb
repository: oci://registry-1.docker.io/bitnamicharts
version: 22.x.x
- name: common
repository: oci://registry-1.docker.io/bitnamicharts
tags:
- bitnami-common
version: 2.x.x
description: WordPress is the world's most popular blogging and content management
platform. Powerful yet simple, everyone from students to global corporations use
it to build beautiful, functional websites.
home: https://bitnami.com
icon: https://dyltqmyl993wv.cloudfront.net/assets/stacks/wordpress/img/wordpress-stack-220x234.png
keywords:
- application
- blog
- cms
- http
- php
- web
- wordpress
maintainers:
- name: Broadcom, Inc. All Rights Reserved.
url: https://github.com/bitnami/charts
name: wordpress
sources:
- https://github.com/bitnami/charts/tree/main/bitnami/wordpress
version: 26.0.0
From the above detailed output of the show command about the helm chart, you can use the following keywords defined in the helm chart to do the search
keywords:
- application
- blog
- cms
- http
- php
- web
- wordpress
helm search repo blog
NAME CHART VERSION APP VERSION DESCRIPTION
bitnami/ghost 25.0.4 6.0.5 Ghost is an open source publishing platform des...
bitnami/wordpress 26.0.0 6.8.2 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...
bitnami/drupal 23.0.0 11.2.3 Drupal is one of the most versatile open source...
bitnami/joomla 20.0.4 5.1.2 DEPRECATED Joomla! is an award winning open sou...
helm search repo will only lists the latest version of the chart if you do not specify --versions. To list all the versions.
neilwu@A8:~$ helm search repo wordpress --versions
NAME CHART VERSION APP VERSION DESCRIPTION
bitnami/wordpress 26.0.0 6.8.2 WordPress is the world's most popular blogging ...
bitnami/wordpress 25.0.26 6.8.2 WordPress is the world's most popular blogging ...
bitnami/wordpress 25.0.25 6.8.2 WordPress is the world's most popular blogging ...
bitnami/wordpress 25.0.24 6.8.2 WordPress is the world's most popular blogging ...
bitnami/wordpress 25.0.23 6.8.2 WordPress is the world's most popular blogging ...
bitnami/wordpress 25.0.15 6.8.2 WordPress is the world's most popular blogging ...
To remove a cached helm chart repo
helm repo remove bitnami
Installing wordpress helm chart in your local kubernates
- Make sure your local kubernates is up and running
neilwu@A8:~$ kubectl version
Client Version: v1.32.2
Kustomize Version: v5.5.0
Server Version: v1.32.2
If you see the above output, it means your local kubernates is up and running.
- Make sure your current kubernates cluster is the current context The kubectl config current-context command is used to display the name of the Kubernetes context currently in use by kubectl. This context determines which Kubernetes cluster and user kubectl interacts with.
neilwu@A8:~$ kubectl config current-context
docker-desktop
- Install a helm chart
Command format
helm install [name] [helm chart name] --version=[version]
For example, to install wordpress helm chart
helm install my-wp binami/wordpress --version=24.1.18
neilwu@A8:~$ helm install my-wp binami/wordpress --version=24.1.18
NAME: my-wp
LAST DEPLOYED: Sun Sep 28 08:06:47 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: wordpress
CHART VERSION: 24.1.18
APP VERSION: 6.7.2
Check the running pods
neilwu@A8:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
cassandra-6bfbff8548-qd8n7 1/1 Running 0 34h
my-wp-mariadb-0 1/1 Running 0 78s
my-wp-wordpress-bffd47846-fgr8b 1/1 Running 0 78s
postgres-795cdc86bf-wkwvj 1/1 Running 0 18h
Name prefixed with my-wp is all the pods with the installation.
Explore the installed helm chart : wordpress
Check the services
neilwu@A8:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cassandra-service NodePort 10.97.53.48 <none> 9042:31082/TCP 33h
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 43h
my-wp-mariadb ClusterIP 10.111.188.197 <none> 3306/TCP 4m40s
my-wp-mariadb-headless ClusterIP None <none> 3306/TCP 4m40s
my-wp-wordpress LoadBalancer 10.98.5.196 <pending> 80:31248/TCP,443:30684/TCP 4m40s
postgres ClusterIP 10.103.92.34 <none> 6432/TCP 18h
ClusterIP is the default Service type that provides a stable, internal, virtual IP address for a set of Pods within the cluster, allowing other applications to access the service without external exposure. It functions as a load balancer, distributing incoming traffic to the various Pods that match the service's label selector, ensuring reliable communication and enabling applications to connect to services using a consistent, internal endpoint
NodePort service provides external access to a Kubernetes service by opening a dedicated, high-numbered port on every node in the cluster, typically in the 30000-32767 range. Traffic sent to this port on any node is then forwarded by the kube-proxy to the service's internal port and then to one of its backend pod.
LoadBalancer is a hardware device or software application that distributes incoming network traffic and workloads across multiple servers, acting as an intermediary to prevent any single server from becoming overloaded. This distribution ensures maximum resource utilization, reduces response times, improves application availability and reliability, and provides seamless maintenance for servers and applications.
Check the secret
neilwu@A8:~$ kubectl get secret
NAME TYPE DATA AGE
my-wp-mariadb Opaque 2 13m
my-wp-wordpress Opaque 1 13m
sh.helm.release.v1.my-wp.v1 helm.sh/release.v1 1 13m
sh.helm.release.v1.postgres.v1 helm.sh/release.v1 1 18h
neilwu@A8:~$ kubectl describe secret my-wp-wordpress
Name: my-wp-wordpress
Namespace: default
Labels: app.kubernetes.io/instance=my-wp
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=wordpress
app.kubernetes.io/version=6.7.2
helm.sh/chart=wordpress-24.1.18
Annotations: meta.helm.sh/release-name: my-wp
meta.helm.sh/release-namespace: default
Type: Opaque
Data
====
wordpress-password: 10 bytes
Open a NodePort on the cluster node
neilwu@A8:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cassandra-service NodePort 10.97.53.48 <none> 9042:31082/TCP 37h
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 47h
my-wp-mariadb ClusterIP 10.111.188.197 <none> 3306/TCP 3h53m
my-wp-mariadb-headless ClusterIP None <none> 3306/TCP 3h53m
my-wp-wordpress LoadBalancer 10.98.5.196 <pending> 80:31248/TCP,443:30684/TCP 3h53m
postgres ClusterIP 10.103.92.34 <none> 6432/TCP 21h
neilwu@A8:~$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
cassandra 1/1 1 1 39h
my-wp-wordpress 1/1 1 1 3h57m
postgres 1/1 1 1 21h
Now expose the deployment as a service(a type of NodePort)
neilwu@A8:~$ kubectl expose deploy my-wp-wordpress --type=NodePort --name my-wp
service/my-wp exposed
neilwu@A8:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cassandra-service NodePort 10.97.53.48 <none> 9042:31082/TCP 37h
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 47h
my-wp NodePort 10.101.50.141 <none> 8080:32195/TCP,8443:30926/TCP 10s
my-wp-mariadb ClusterIP 10.111.188.197 <none> 3306/TCP 3h59m
my-wp-mariadb-headless ClusterIP None <none> 3306/TCP 3h59m
my-wp-wordpress LoadBalancer 10.98.5.196 <pending> 80:31248/TCP,443:30684/TCP 3h59m
postgres ClusterIP 10.103.92.34 <none> 6432/TCP 21h
Now wordpress is exposed to your host machine
my-wp NodePort 10.101.50.141 <none> 8080:32195/TCP,8443:30926/TCP 10s
You can use http://127.0.0.1:32195 to access wordpress home page hosted in a pod and http://localhost:32195/wp-admin is the admin console.
Explore the installed wordpress application
kubectl get secret
neilwu@A8:~$ kubectl get secret
NAME TYPE DATA AGE
my-wp-mariadb Opaque 2 4h37m
my-wp-wordpress Opaque 1 4h37m
neilwu@A8:~$ kubectl describe secret my-wp-wordpress
Name: my-wp-wordpress
Namespace: default
Labels: app.kubernetes.io/instance=my-wp
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=wordpress
app.kubernetes.io/version=6.7.2
helm.sh/chart=wordpress-24.1.18
Annotations: meta.helm.sh/release-name: my-wp
meta.helm.sh/release-namespace: default
Type: Opaque
Data
====
wordpress-password: 10 bytes
wordpress-password is a 10 bytes long strings. Now it is time to decrypted
neilwu@A8:~$ kubectl get secret my-wp-wordpress -o jsonpath='{.data.wordpress-password}' | base64 -d
czrKG2tiamneilwu@A8:~$
Eventually the username/password for the admin page http://localhost:32195/wp-admin will be
- username user
- password czrKG2tiam
Uninstalling your helm chart
neilwu@A8:~$ helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
my-wp default 1 2025-09-28 08:06:47.682168282 -0400 EDT deployed wordpress-24.1.18 6.7.2
postgres default 1 2025-09-27 14:07:17.321804979 -0400 EDT deployed postgres-0.1.0 1.16.0
Now uninstall my-wp
neilwu@A8:~$ helm uninstall my-wp
release "my-wp" uninstalled
neilwu@A8:~$ helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
postgres default 1 2025-09-27 14:07:17.321804979 -0400 EDT deployed postgres-0.1.0 1.16.0
neilwu@A8:~$ kubectl get pod
NAME READY STATUS RESTARTS AGE
cassandra-6bfbff8548-qd8n7 1/1 Running 0 39h
postgres-795cdc86bf-wkwvj 1/1 Running 0 22h
Now check services
neilwu@A8:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cassandra-service NodePort 10.97.53.48 <none> 9042:31082/TCP 38h
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d
my-wp NodePort 10.101.50.141 <none> 8080:32195/TCP,8443:30926/TCP 60m
postgres ClusterIP 10.103.92.34 <none> 6432/TCP 22h
There is still one service left called my-wp which we created manually. We need to delete this manually created in the kubectl expose command.
To delete, issues kubectl delete svc my-wp
neilwu@A8:~$ kubectl delete svc my-wp
service "my-wp" deleted
neilwu@A8:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cassandra-service NodePort 10.97.53.48 <none> 9042:31082/TCP 38h
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d
postgres ClusterIP 10.103.92.34 <none> 6432/TCP 23h
To completely delete a helm chart, this is not the end. we also need to check if there are any pv(persistence volumn) and pvc(persistence volumn claim)
neilwu@A8:~$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
pvc-774e680d-e1a6-4a5b-8b3a-f8acc6c1b9a3 4Gi RWO Delete Bound default/postgres-persistent-volume-claim hostpath <unset> 23h
pvc-ba1c49f0-bdca-4da1-bbf0-7d00bc1d2579 8Gi RWO Delete Bound default/data-my-wp-mariadb-0 hostpath <unset> 5h5m
neilwu@A8:~$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
data-my-wp-mariadb-0 Bound pvc-ba1c49f0-bdca-4da1-bbf0-7d00bc1d2579 8Gi RWO hostpath <unset> 5h6m
postgres-persistent-volume-claim Bound pvc-774e680d-e1a6-4a5b-8b3a-f8acc6c1b9a3 4Gi RWO hostpath <unset> 23h
The output shows data-my-wp-mariadb-0 is the one to be deleted.
Before deletion, check kubernates storage class
neilwu@A8:~$ kubectl describe storageclass
Name: hostpath
IsDefaultClass: Yes
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"storage.k8s.io/v1","kind":"StorageClass","metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"},"name":"hostpath"},"provisioner":"docker.io/hostpath","reclaimPolicy":"Delete","volumeBindingMode":"Immediate"}
,storageclass.kubernetes.io/is-default-class=true
Provisioner: docker.io/hostpath
Parameters: <none>
AllowVolumeExpansion: <unset>
MountOptions: <none>
ReclaimPolicy: Delete
ReclaimPolicy is set to Delete. It mains the pv can be reclaimed by delete action.
neilwu@A8:~$ kubectl delete pvc data-my-wp-mariadb-0
persistentvolumeclaim "data-my-wp-mariadb-0" deleted
neilwu@A8:~$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
pvc-774e680d-e1a6-4a5b-8b3a-f8acc6c1b9a3 4Gi RWO Delete Bound default/postgres-persistent-volume-claim hostpath <unset> 23h
neilwu@A8:~$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
postgres-persistent-volume-claim Bound pvc-774e680d-e1a6-4a5b-8b3a-f8acc6c1b9a3 4Gi RWO hostpath <unset> 23h
Top comments (0)