Create a Helm chart for the API
Helm is a package manager for Kubernetes. It helps you define, install, and upgrade even the most complex Kubernetes application.
From the Helm introduction video:
Package Management: Tooling that enables someone who has knowledge of an application and a platform to package up an application so that someone else with who has neither extensive knowledge of the application or the way it needs to be run on the platform can use it.
Watch the video linked above before proceeding.
One of the most important concepts in Helm are charts:
Helm uses a packaging format called charts. A chart is a collection of files that describe a related set of Kubernetes resources. A single chart might be used to deploy something simple, like a memcached pod, or something complex, like a full web app stack with HTTP servers, databases, caches, and so on.
To install Helm you can follow the instructions at https://helm.sh/docs/intro/install.
To store the infrastructure related configurations we are going to create a new
repository named learning-go-api-iac
. Head to GitHub and create one for you.
After, clone it to your machine so we can start building a chart for the API.
To create a chart execute the following command:
mkdir charts && cd charts
helm create learning-go-api
After running the following files and directories will be created:
learning-go-api
├── charts # A directory containing any charts upon which this chart depends
├── Chart.yaml # A YAML file containing information about the chart
├── templates # A directory of templates that, when combined with values,
# will generate valid Kubernetes manifest files
│ ├── deployment.yaml # Template for a deployment (DELETE IF NOT NEEDED)
│ ├── _helpers.tpl # Helper templates to be used in other templates
│ ├── hpa.yaml # Template for auto scaling (DELETE IF NOT NEEDED)
│ ├── ingress.yaml # Template for an ingress (DELETE IF NOT NEEDED)
│ ├── NOTES.txt # OPTIONAL: A plain text file containing short usage notes
│ ├── serviceaccount.yaml # Template for a service account (DELETE IF NOT NEEDED)
│ ├── service.yaml # Template for a service (DELETE IF NOT NEEDED)
│ └── tests # Pod definitions to check the status of the application
└── values.yaml # The default configuration values for this chart
For the current version of our API we will need to define the following k8s resources:
- A Mamespace dedicated to the learning-go-api
- A Service exposing the API and load balancing the traffic to pods
- A Deployment to manage and scale pods
- Several Pods managed by the deployment to run the API containers
- A Secret containing the API key to call the backend financial API
The following diagram illustrates all the resources:
The files generated by the helm create
command build a skeleton for most of
the resources we need.
But we need to do some clean up and change the generated templates to build this solution.
Clean up
We are not going to use some of the files generated by the helm create
command so we can delete them.
rm carts/learning-go-api/templates/ingress.yaml
rm carts/learning-go-api/templates/serviceaccount.yaml
rm carts/learning-go-api/templates/hpa.yaml
Basic configurations
The value.yaml
contains configuration values for this chart.
Let's open it and update a couple of things:
- The
image.repository
should berenato0307/learning-go-api
- The
serviceAccount.create
must be set tofalse
- The
service.type
must beLoadBalancer
and theservice.port
change to9000
- In the
resources
section uncomment the values
We also need to change the Chart.yaml
file and update the following:
appVersion
must match the GitHub tag for thelearning-go-api
, which should be0.0.3
at this moment.
Create the namespace
All k8s resources will be created under a namespace, to allow the isolation from other resources in the cluster.
The namespace will be named learning-go-api
and we can created it by
running the following command:
kubectl create ns learning-go-api
Secrets
We are going to use secrets to store the API key for the currency conversion.
First create a file named secrets.yaml
with the following contents:
apiVersion: v1
kind: Secret
metadata:
name: learning-go-api-secrets
type: Opaque
data:
CURRCONV_API_KEY: <the value of the API key in base64>
Next, create the secret resource by running kubectl apply
:
kubectl apply -f secrets.yaml -n learning-go-api
The result should be:
secret/learning-go-api-secrets created
As this contains sensitive information, delete the secrets.yaml
file:
rm secrets.yaml
Deployment changes
Open the deployment.yaml
and in the containers
list, add the
CURRCONV_API_KEY
environment variable. Additionally also change the container
port to be 8080
, the default port exposed by Gin.
# ...
containers:
- name:
securityContext:
image: ":"
imagePullPolicy:
env: # new
- name: CURRCONV_API_KEY # new
valueFrom: # new
secretKeyRef: # new
name: learning-go-api-secrets # new
key: CURRCONV_API_KEY # new
ports:
- name: http
containerPort: 8080 # change
# ...
Install the chart
To install the chart in the cluster run the following command.
This will create a chart named learning-go-api
, using the definitions found in
carts/learning-go-api
, putting all resources in the learning-go-api
namespace.
helm install learning-go-api carts/learning-go-api --namespace learning-go-api
To check if everything is OK, list the pods for the learning-go-api
namespace:
kubectl -n learning-go-api get pods
You should see something simitar to (the pods must be ready and in the Running
status):
NAME READY STATUS RESTARTS AGE
learning-go-api-6f7b4d9f79-64cpr 1/1 Running 0 84s
If we get the logs from the pod we should see the requests being made by the liveness and readiness probes:
kubectl -n learning-go-api logs learning-go-api-6f7b4d9f79-64cpr
The logs are:
...
[GIN] 2021/12/28 - 20:26:44 | 200 | 30.38µs | 10.244.0.1 | GET "/"
[GIN] 2021/12/28 - 20:26:44 | 200 | 30.89µs | 10.244.0.1 | GET "/"
[GIN] 2021/12/28 - 20:26:54 | 200 | 36.04µs | 10.244.0.1 | GET "/"
[GIN] 2021/12/28 - 20:26:54 | 200 | 36.28µs | 10.244.0.1 | GET "/"
[GIN] 2021/12/28 - 20:27:04 | 200 | 37.859µs | 10.244.0.1 | GET "/"
[GIN] 2021/12/28 - 20:27:04 | 200 | 15.06µs | 10.244.0.1 | GET "/"
[GIN] 2021/12/28 - 20:27:14 | 200 | 33.88µs | 10.244.0.1 | GET "/"
[GIN] 2021/12/28 - 20:27:14 | 200 | 24.8µs | 10.244.0.1 | GET "/"
Testing the deployed API
The service should also be set up, allowing us to access the API.
You can check it by running:
kubectl -n learning-go-api get svc
You'll be able to see something like:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
learning-go-api LoadBalancer 10.96.151.196 172.19.255.200 9000:31144/TCP 21m
Using the EXTERNAL-IP
and the PORT
you would be able to call the API
using httpie
:
http 172.19.255.200:9000
The result should be:
HTTP/1.1 200 OK
Content-Length: 51
Content-Type: application/json; charset=utf-8
Date: Wed, 28 Dec 2021 20:45:52 GMT
{
"message": "Hello, welcome to the learning-go-api"
}
Wrap up
Commit and push everything to GitHub.
Next
The next section is Deploy the API using Flux.