Spring Boot CI/CD on Kubernetes using Terraform, Ansible and GitHub: Part 12

Martin Hodges
7 min readNov 7, 2023

--

Part 12 Using ArgoCD to deploy your Spring Boot Application

This is part of a series of articles that creates a project to implement automated provisioning of cloud infrastructure in order to deploy a Spring Boot application to a Kubernetes cluster using CI/CD. In this final part we use ArgoCD to automatically deploy your Spring Boot Application to your Kubernetes cluster.

Follow from the start — Introduction

In the previous article we saw how to automatically take a Spring Boot application from code to a Docker image ready to deploy in your Kubernetes cluster.

The question now is how does this image get into your cluster automatically? The answer is ArgoCD.

You can find the files described in this article in the argocd folder of this repository:
https://github.com/MartinHodges/Quick-Queue-IaC/tree/part12

You can find the files described in this article in the .github folder of this repository:ArgoCD is a Continuous Deployment (CD) tool that allows you to monitor and control your cluster. We will use it to deploy our application when there is an update to the Quick-Queue-Deployment repository.

ArgoCD

ArgoCD runs on the Kubernetes cluster. To install it there are a number of steps:

  1. Install on Kubernetes cluster
  2. Install Argo CD Command Line Interface (CLI)
  3. Obtain the admin password
  4. Set up port forwarding

Install on Kubernetes cluster

Installation takes place on your master node. There are a number of scripts that will help you install and use ArgoCD. Create a folder called argocd and cd into it.

Create install_argocd.sh:

#!/bin/bash
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Make it executable with chmod +x install_argocd.sh.

Run the script to install ArgoCD.

Create port_fwd_argocd.sh:

#!/bin/bash
kubectl port-forward svc/argocd-server -n argocd 8080:443

This will port forward ArgoCD’s port 443 to the nodes port 8080. Make it executable and then run it with:

./port_fwd_argocd.sh &

To access ArgoCD you need to install the ArgoCD CLI tools. Create install_argocd_cli.sh:

#!/bin/bash

curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd

Make it executable and run it.

You can now use the command line interface to obtain the password.

Create argocd_pw.sh:

#!/bin/bash

argocd admin initial-password -n argocd

Make this executable and then run it. this will display the temporary password created during the installation. There is also a note to advise you to change this.

This completes the set up on the master node.

Accessing ArgoCD

Now you have ArgoCD running on your cluster, you now need to access it using the browser on your development machine.

From your development machine, set up port forwarding of port 8080 to your local machine with:

ssh kates@<master public IP address> -i ~/.ssh/qq_rsa -L 8080:localhost:8080

You can now visit http://localhost:8080 in your browser. You will get a warning about the connection not being private as we are not using a known CA certificate. Accept the warning and continue to the site.

You will then be asked to log in. Use admin and the password you obtained above.

Configuring ArgoCD

Now you have logged in to ArgoCD you can now set it up to deploy your application.

The process is:

  • Set up your connection to your repositories
  • Create an application
  • Refresh that application
  • Synchronise your application

After this your application will be running on your cluster.

Repository Connections

Your ArgoCD needs to be able to access your Quick-Queue-Deployment GitHub repository. You do this by creating a connection to it.

Note that if you create a connection and it fails to connect, you cannot edit it but you need to disconnect it and start again.

To set up ArgoCD to access your repository, you need to create a Personal Access Token within GitHub under your Account -> Settings -> <>Developer Settings -> Personal access tokens -> Fine-grained tokens.

Create a token with access to only your K8s-Deployment repository. It only needs read access to your contents plus any defaults that GitHub requires. After clicking Generate token, you will be shown a token starting with github_pat_. You will only be shown this once and you cannot access it again.

Now, in ArgoCD, select Settings in the lefthand menu panel and then select the Repositories card.

Click + Connect Repo. Select the via HTTPS connection method.

For project, select default. ArgoCD can manage multiple projects at once but for now we are just going to use the default project set up when ArgoCD is created.

Enter the Repository URL. You can get this from GitHub as the HTTPS clone URL. It will be of the form: https://github.com/<username>/K8s-Deployment.git.

Enter your GitHub username and then use the personal access token you created earlier as the password.

All other options can be left as they are.

Now click CONNECT. ArgoCD will now attempt to access your GitHub repository.

Create Application

Now you can create an application for ArgoCD to manage.

Click on Applications on the lefthand menu. Now click on + NEW APP.

Enter:

  • Name = Quick Queue
  • Project = default
  • Sync Policy = Automatic (will poll GitHub every 3 minutes)
  • Prune Resource = ticked (ensures any resource not required are removed)
  • Self Heal = ticked (ensures any manual changes are reversed)
  • Prune Last = ticked
  • Auto-Create Namespace = ticked
  • Repository = select the connection you created earlier
  • Revision = main
  • Path = qqapp
  • Cluster URL = https://kubernetes.default.svc
  • Namespace = default
  • Direct Recurse = ticked

Click CREATE.

Congratulations! So long as you have not made any errors in your files, you should now have a Spring Boot application running in your Kubernetes cluster along with your postgres database.

Now, whenever you change anything (including your Kubernetes configuration or GitHub workflow) within your Spring Boot application and you push it to main, you will see:

  • Your application compiled and built
  • Your Docker image created and pushed to Docker Hub
  • Your application updated in ArgoCD — well, not quite

Currently ArgoCD is set up to require you to trigger a refresh from the GitHub repository.

Refresh vs Sync

These two terms are sometimes confusing.

Refresh — this refers to whether the manifest files that ArgoCD has are the same as the latest version defined in the application repository (in this example that is on the main branch). When refreshing, ArgoCD downloads the manifest files from GitHub.

Note: by default ArgoCD will refresh every 3 minutes but you can manually refresh at any time.

Sync — this refers to whether the deployment in the cluster matches the manifests currently in ArgoCD. When selecting Sync, ArgoCD will (if necessary) redeploy the application. It will do this according to the manifest files. Generally this is done as a rolling upgrade such that the application is always running, ie: without any downtime.

When a sync occurs, there is an option to prune (ie: remove/delete) any resources that are not required.

You can try this out. Change the number of replicas in your k8s/deployment.yml file in your Spring Boot application from 1 to 2. Commit your changes and push back to GitHub.

After a few minutes you will see your build Action complete. You can then go to ArgoCD and click REFRESH. ArgoCD will now start up two Pods and then close and delete the original Pod. This will leave you with this:

You can see that ArgoCD is showing your application, including:

  • 1 quick-queue Application
  • 1 qqapp Deployment
  • 1 qqapp Replica Set
  • 2 qqapp Pods
  • 1 qqapp Service
  • 1 qqapp Endpoint
  • 1 qqapp Endpoint slice

If you delete a Pod (click on its 3 dot menu), and click Ok in the dialog box that appears, you will see that Kubernetes will start another Pod before deleting the Pod you selected. This ensure that, at any time, you will always have two instances running.

This is pretty neat.

Accessing Application Logs

As you now have two instances of your application running, you may be wondering how you view the logs of these two instances.

If you click on either of the Pods you will see a slide out panel appear with everything you need to know about your Pods.

Under the SUMMARY tab there is a lot of interesting information. In particular, if you scroll down to the bottom, you will see the full manifest for this Pod. This includes a lot more than you specified due to the application of defaults and key-value pairs used by Kubernetes itself. By looking through this live manifest, you can get an idea of the options available to you.

Under the EVENTS tab you can see what Kubernetes did to create this pod and any events that have happened since. You will see which node the pod was scheduled on, the image used to create it and details about its container. It is here that you can diagnose problems if your Pod does not start.

Under the LOGS tab you will find your application logs. You will see the familiar Spring Boot banner and all the start up steps. Finally you should see that Tomcat has been started and how long it took for your application to start.

Testing

Remember that we created a NodePort service attached to the external address of the master node? If you click on the svc box and look at its manifest, you will find the external IP address and the port. You can now curl this from your development machine and you should have full access to your application!

curl <service external IP address>:30191/api/v1/queues

Summary

In this article we finished our Continuous Deployment (CD) pipeline by installing ArgoCD and have it deploy our manifest files from the deployment repository in GitHub, created by the first part of our CD pipeline.

We now have a fully functional Spring Boot Application running on our Kubernetes cluster.

In the final article in this series, we will look at where we can go from here.

Series Introduction

Previous — Deploying Spring Boot Application with Continuous deployment

Next — Epilogue — where to from here

--

--