Build your first Helm chart with Docker Desktop on Mac
Hello friends!, this is a beginning on a new journey to explore Kubernetes (K8s) world. In this post, we will try to use Helm, which is the package manager forK8s.
As a habit, I’m describing my working environment which I have tested the content of this blog post.
- macOS Big Sur (Version 11.5.2)
- Docker Desktop Version 4.0.0 (4.0.0.12)
- Kubernetes version 1.21 (both client and server)
- Helm Version “v3.5.4”
Let’s dive in. Go inside an empty directory and execute following command using the Terminal app. Instead of “my-website”, you can provide any name you like.
helm create my-website
Now a directory will be created with the name that you given and inside that you can see structure similar to below.
▶ tree my-website
my-website
├── Chart.yaml
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ ├── serviceaccount.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
I’m not going to describe the purpose of these files and the default content of each and every file, since Helm documentation has done a pretty good job on that.
As default, this helm chart consist with nginx image which means now you have a simple web server application. Next task is running that application in our local Kubernetes environment. Since I do not want to mess with my other work, I create a separate sub-cluster that we call namespace in K8s world. Here also you can provide any name you wish instead of “k8s-lessons”
kubectl create namespace k8s-lessons
If you want to check what are the existing namespaces already created when the Docker Desktop installed and enabled Kubernetes of that, you can run following command.
kubectl get namespace
Now you can deploy your simple web server in that given namespace like below. Here “my-web” is the name given by me for the application.
helm install my-web ./my-website -n k8s-lessons
You can check what K8s components has started, related to your application by running this command.
▶ kubectl get all -n k8s-lessons
NAME READY STATUS RESTARTS AGE
pod/my-web-my-website-6ddd8859bf-fx2p4 1/1 Running 0 5m10sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/my-web-my-website ClusterIP 10.96.30.226 <none> 80/TCP 5m10sNAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-web-my-website 1/1 1 1 5m10sNAME DESIRED CURRENT READY AGE
replicaset.apps/my-web-my-website-6ddd8859bf 1 1 1 5m10s
As you can see from the above output, it has started a Pod, Service, Deployment and a ReplicaSet. In your Pod status, it says that your application is running. But can you access your web site from your browser? No, you cannot, because you have not set an external IP address. You can see that in the Service line in above out put.
Since Helm does not like to put you through trouble on running your default application, they have provided a temporary solution using port forwarding. Those details are available as the output of helm install command. If I share my output, it is like this.
1. Get the application URL by running these commands: export POD_NAME=$(kubectl get pods --namespace k8s-lessons -l "app.kubernetes.io/name=my-website,app.kubernetes.io/instance=my-web" -o jsonpath="{.items[0].metadata.name}") export CONTAINER_PORT=$(kubectl get pod --namespace k8s-lessons $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl --namespace k8s-lessons port-forward $POD_NAME 8080:$CONTAINER_PORT
We will see a better way of doing this. What we are going to do is, create a new service that will communicate external world with our application pod using K8s default LoadBalancer type. You can see the deployment name in an earlier output and you can provide any name for the service as you wish instead of the name that I’ve provided here.
kubectl expose deployment my-web-my-website --type=LoadBalancer --name=my-web-svc -n k8s-lessons
If you check the available services now, you can see the newly created service as well as the service we have used with port forwarding. Apart from that, you can see localhost
has been assigned as the external IP that can communicate with the Pod.
▶ kubectl get svc -n k8s-lessons
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-web-my-website ClusterIP 10.96.30.226 <none> 80/TCP 27m
my-web-svc LoadBalancer 10.105.230.45 localhost 80:32402/TCP 4s
This is a good improvement, but is this the best approach? Before you give an answer, think what will happen if you want to deploy your Helm chart in a different environment. Then you can manually create the service again, which is not good. Then let’s try whether we can set this as a configuration. Before that we will delete the service which we have created just now, in order to verify the configuration that we are going to do is effective.
kubectl delete svc my-web-svc -n k8s-lessons
If you check your localhost
now, you will see that your service has down. As the next step, go to your project directory and find the values.yaml
and open it where you feel comfortable to edit. In that, you will be able to find a service
tag and I want you to change the value for type
as below.
type: LoadBalancer
It’s time to upgrade your Helm chat by executing below command.
▶ helm upgrade -f my-website/values.yaml my-web ./my-website -n k8s-lessons
Release "my-web" has been upgraded. Happy Helming!
NAME: my-web
LAST DEPLOYED: Wed Dec 1 11:31:15 2021
NAMESPACE: k8s-lessons
STATUS: deployed
REVISION: 2
...
I’ll come back to the reason that I’ve put some of the output above at the later part of this post. First we will check our expectation has met with the change we have done.
▶ kubectl get svc -n k8s-lessons
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-web-my-website LoadBalancer 10.96.30.226 localhost 80:30568/TCP 64m
Yes, the service has updated with LoadBalancer
type and also external IP has been set which you can access using your web browser. There are more better approaches we can include but for this post, we will stick to this.
Before ending up, let’s go back to few paragraph above where I’ve mentioned about an output of a command. I want to highlight the REVISION: 2
line. This means K8s is smart enough to keep track of your changes you have done to your Pods. You can see the history using following command.
▶ helm history my-web -n k8s-lessons
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Wed Dec 1 10:27:36 2021 superseded my-website-0.1.0 1.16.0 Install complete
2 Wed Dec 1 11:31:15 2021 deployed my-website-0.1.0 1.16.0 Upgrade complete
If you need, you can rollback to revision 1, which is the very first version that you have once you finished installing the Helm chart. But this will break your service which you have enabled in revision 2. Who cares 😂 try it out for fun, I promise you can rollback to revision 2 again once you understand the concept.
helm rollback my-web 1 -n k8s-lessons
Run the history
command again to see what happened behind the scene. Then you can rollback to revision 2 to have a running application.
Yep, I think this is more than enough for today’s post. I hope you have learned something out of this and keep in touch for more related posts 👍