Continuous Integration, Delivery, and Deployment of Microservices: A Hands-on Guide
Continuous Delivery with Helm
As a brief reminder, our goal in this part of the guide is to create a CI/CD pipeline for our microservice. This pipeline will build and test our application, create a Docker image, and deploy it to Kubernetes using Argo CD. Helm is used to package our application, and Argo CD will use it to deploy to the cluster.
Whenever we need to deploy a new version of our application, we simply update the Helm chart and push it to our GitHub repository. GitHub Actions will then create a new release with the latest version of our application. With the help of Argo CD, we can deploy the new version of our application to our Kubernetes cluster.
If Helm is not installed on your workspace server, follow the instructions in the official documentation.
Let's move to the next step: creating a new Helm chart.
cd $HOME/cicd/
mkdir -p charts/cicd-flask
helm create charts/cicd-flask
By executing the commands above, Helm will create a new directory named "cicd-flask" with the various files and directories that constitute a Helm chart. Here is the updated file tree of our repository:
.
├── .git
├── .github
│  └── workflows
│  └── main.yml
├── app
│  ├── Dockerfile
│  ├── app.py
│  ├── requirements.txt
│  └── test_app.py
└── charts
└── cicd-flask
├── .helmignore
├── Chart.yaml
├── charts
├── templates
│  ├── NOTES.txt
│  ├── _helpers.tpl
│  ├── deployment.yaml
│  ├── hpa.yaml
│  ├── ingress.yaml
│  ├── service.yaml
│  ├── serviceaccount.yaml
│  └── tests
│  └── test-connection.yaml
└── values.yaml
If you need to modify the default values of our Helm chart, edit the values file (values.yaml).
The values defined in the file are used in the templates to generate the Kubernetes manifests. For example, the replicaCount value is used in the deployment template to set the number of replicas.
# deployment.yaml
...
spec:
# Checks if autoscaling is not enabled in the values file
{{- if not .Values.autoscaling.enabled }}
# Sets the replica count based on the values file
replicas: {{ .Values.replicaCount }}
{{- end }}
...
The replicaCount value will be replaced with the value defined in the values file:
# values.yaml
..
replicaCount: 1
..
Later, after we finish setting up our Helm chart, we can deploy it using the Helm CLI. At this point, the values can be overridden by providing a custom values file when installing the chart or by providing individual values using the --set flag.
Here is an example (we won't use the commands below for now, as we will use Argo CD to deploy our application):
# provide a custom values file
helm \
install \
cicd-flask \
charts/cicd-flask \
--values charts/cicd-flask/values.yaml
# provide individual values
helm \
install \
cicd-flask \
charts/cicd-flask \
--set replicaCount=2
Otherwise, without providing a custom values file or individual values (just by executing helm install cicd-flask charts/cicd-flask), the default values will be used.
This is why we will proceed with the default values for now.
cat << EOF > charts/cicd-flask/values.yaml
replicaCount: 1
image:
repository: ${DOCKER_USERNAME}/${DOCKER_REPOSITORY_NAME}
pullPolicy: IfNotPresent
tag: "latest"
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
create: true
annotations: {}
name: ""
service:
type: ClusterIP
port: 5000
ingress:
enabled: true
className: ""
annotations:
kubernetes.io/ingress.class: nginx
hosts:
- host: flask.${INGRESS_IP}.nip.io
paths:
- path: /tasks
pathType: Prefix
tls: []
httpRoute:
enabled: false
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
EOF
Note that DOCKER_USERNAME and DOCKER_REPOSITORY_NAME should already be defined in your environment variables if you followed the previous steps. Otherwise, the last values file will have empty configurations (e.g., image.repository: /).
CI/CD pipelines are typically used to deliver to multiple environments. For instance, you might have a staging environment and a production environment. For each environment, you may need to use different values. Let's create another values file for our staging environment.
cp \
charts/cicd-flask/values.yaml \
charts/cicd-flask/values-staging.yaml
To customize the values in the "values-staging.yaml" file, you can adjust the number of replicas or the image tag, among other things.
Example: Change the number of replicas from 1 to 2.
sed -i 's/replicaCount: 1/replicaCount: 2/g' \
charts/cicd-flask/values-staging.yaml
Remove the Gateway API HTTPRoute template generated by helm create. We rely on a classic Ingress, so this file may introduce duplicate port definitions. We can safely remove it.
rm charts/cicd-flask/templates/httproute.yaml
Now, edit the deployment.yaml file to update the default livenessProbe and readinessProbe, using /tasks as the path instead of /.
Here is the updated file that we will use:
cat << EOF > charts/cicd-flask/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
# Uses a predefined Helm function to get
# a full name composed of the release name
# and the chart name
name: {{ include "cicd-flask.fullname" . }}
labels:
# Inserts labels defined in the
# "cicd-flask.labels" template
{{- include "cicd-flask.labels" . | nindent 4 }}
spec:
# Checks if autoscaling is not enabled
# in the values file
{{- if not .Values.autoscaling.enabled }}
# Sets the replica count based on the values file
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
# Inserts selector labels defined in the
# "cicd-flask.selectorLabels" template
{{- include "cicd-flask.selectorLabels" . | nindent 6 }}
template:
metadata:
# Checks if podAnnotations are provided in the values file
{{- with .Values.podAnnotations }}
annotations:
# Converts the podAnnotations to YAML
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
# Inserts selector labels defined in the
# "cicd-flask.selectorLabels" template
{{- include "cicd-flask.selectorLabels" . | nindent 8 }}
spec:
# Checks if imagePullSecrets are provided
# in the values file
{{Cloud-Native Microservices With Kubernetes - 2nd Edition
A Comprehensive Guide to Building, Scaling, Deploying, Observing, and Managing Highly-Available Microservices in KubernetesEnroll now to unlock all content and receive all future updates for free.
