Helm In Kubernetes — Part 3: Hand on with Flow Control and Pipelines
We have seen how we can create a simple Helm Chart. This time we are going to take a look at flow control and pipelines in Helm.
At the end of this post, you should be able to:
- Use flow control in Helm template
- Use pipelines in Helm template
If you want to follow along or take a look at the code, you can find it here.
This is the app(2 apps actually) that we want to deploy.
We have app-1
and app-2
— 2 separate Node apps. On /service
path of app-1
, it will curl app-2
root path. Likewise, On /service
path of app-2
, it will curl app-1
root path. Take a look at the content of app-1
as an example. So we need some way to provide environment variable for the request address that we want to curl to our apps.
Key point:
cmd
basically curl whatever we set forREQUEST_ADDRESS
as our environment variable.
Both app-1
and app-2
are ready as Docker image, the image names are leeyoongti/node-web-app-1:1.0.2
and leeyoongti/node-web-app-2:1.0.2
respectively.
Let’s create our Helm Chart first. Run:
helm create node-web-app
Delete everything under the templates folder. Then, copy deployment.yml
and service.yml
inside 02-node-webapp/app-1/yml
folder and paste them inside the templates folder so we don’t have to type everything from scratch.
Next, create 2 files named app-1.values.yaml
and app-2.values.yaml
. We will be using these files to inject values to our templates. Feel free to delete values.yaml
file as we’re not going to use it.
You should end up having something like this in your newly created Helm Chart.
Everything in the templates are hardcoded, let’s change that and define the values in the value files.
Edit app-1.values.yaml
to the following:
A few key points:
- The app is running on port 3000.
- The value for
REQUEST_ADDRESS
has to match whatever we provide when we are deploying the service forapp-2
. Take a look at Line 4 intemplates/service.yaml
, we define the name of the service to be{{ .Values.name }}-service
. So it means, when we are creating ourapp-2.values.yaml
, we have to useapp-2
as the name. - Usually we have to also define the port that we want to request, but
app-2
is running on port 80, which is the default. So we do not have to specify it.
Edit app-2.values.yaml
to the following:
A few key points:
- We define the port for
REQUEST_ADDRESS
because app-1 is running on port 3000 instead of the default 80. service.port
is not defined for app-2. Later we will see intemplates/service.yaml
, we define a default value of 80 for it.
Edit templates/deployment.yaml
to the following:
A few key points to cover here:
|
sign here(Line 8 and Line 22) is known as a pipeline. Pipeline is used to chain a sequence of function together. We use is here to set a default value of 1 to replicas and default value of 80 to container port. So we can choose not to provide value for replicas and it will default to 1. So, for our case,app-1.values.yaml
does not provide value for replicas, so we will be deploying the app with 1 replica.with
is used to specify a scope. Say we haveimage
,tag
andcontainerPort
under thedeployment
scope (Checkapp-1.values.yaml
Line 3–5). We can usewith
so that we do not have to define the value placeholder repeatedly, like so:.Values.deployment.image
,.Values.deployment.tag
,.Values.deployment.containerPort
. We have to close the scope withend
range
is used to loop a list of values. We can define a list of values and use range to loop over them(Checkapp-1.values.yaml
Line 6 — 10). We will close the loop withend
on Line 28.spec.env
is how we define environment variables for our app.
Edit templates/service.yaml
to the following:
A few key points to cover for service.yaml
- On Line 6, we have a
if
keyword. This is to check whetherservice
value is provided. If it is not provided, it will go to theelse
on Line 17. Which means, the output file will include Line 18–23, and not Line 7–15. In another word,service
and all the values nested under it are optional. - Again, we see pipeline and
default
in action to define a default value if the value is not provided. Port and target port will be set to 80 ifservice.port
is not provided. - Here we have something called
quote
. It is used to add quote to the value, i.e.NodePort
will become"NodePort"
.
Now, let’s try installing(deploying) our Helm Chart by running(Make sure you are running the command in the directory that you created your Helm Chart:
// helm install [NAME] [CHART]
helm install node-web-app-1 node-web-app
You will probably see an error like this.
Error: template: node-web-app/templates/deployment.yaml:8:22: executing "node-web-app/templates/deployment.yaml" at <.Values.deployment.replicas>: nil pointer evaluating interface {}.replicas
It says .Values.deployment
is nil, what gives?
If we look back at our deployment.yaml
file on Line 8, the template is expecting us to provide a directory called deployment
, the template never check whether deployment
exists before accessing the replicas
value.
Also, since we deleted values.yaml
, we need to tell Helm which value file we want to use to install the app. So we should run this command instead:
helm install node-web-app-1 node-web-app --values ./node-web-app/app-1.values.yaml
You should see that your deployment has been successfully deployed.
NAME: node-web-app-1
LAST DEPLOYED: Sat May 29 22:55:53 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
Since we deploy our service as NodePort on port 30111(Line 14 in app-1.values.yaml
), we can access it outside the Kubernetes cluster. Run the following command to get your Minikube IP.
minikube ip
Then access app-1 through YOUR_MINIKUBE_APP:30111
, replace YOUR_MINIKUBE_IP
with the IP you get by running the command above.
You should be able to see the following:
Nice! We have successfully deployed app-1. Also if we want to check what is the generated output files before we actually deploy our app, we can run this command:
// helm template [CHART]
// helm template [CHART] --values [VALUE]helm template node-web-app --values ./node-web-app/app-1.values.yaml
But if we try to access /service
(Remember /service
will curl from our app-2
, it will show error on the browser. So let’s deploy our app-2 as well. Run the command:
helm install node-web-app-2 node-web-app --values ./node-web-app/app-2.values.yaml
You should see that your app is successfully deployed. You can check by going to your existing app-1 and go to /service
You can also access app-2 at YOUR_MINIKUBE_IP:30112
as we define the node port of 30112 for app-2.
Conclusion
We have seen how we can deploy 2 different apps by providing different value files to the same Helm Chart. We also learned about how we can use with
, if/else
, and range
to make our template more powerful and flexible.
Thanks for reading! If you like the post, leave a like so other people can see it as well.