My Amateur Experience with Kubernetes
Introduction⌗
Recently, I had to work on a project that required me to learn Kubernetes within 30 days. This was not the typical way to learn Kubernetes, as I had to learn it on my own, due to work-related requirements. In this article, I will share my experience and the journey that I took to learn Kubernetes.
Getting Started with Minikube: My first Kubernetes installation was done using a VM instance. I had Virt-Manager on my system, as I was preparing for RHCSA. I started Minikube by running the command minikube dashboard
instead of minikube start which was not technically correct, but it worked for me. I watched it run with all those emojis and stuff, which was both exciting and kind of dorky.
Learning MySQL and Springboot: Instead of starting with the basics of Kubernetes, I dived right in and started with MySQL and Springboot. I looked up some basic how-to guides on deploying MySQL and Springboot in Kubernetes, which recommended using the Spring Initializr to create a Springboot application. All I had to do was click on generate.
Creating a Docker Image: To create a custom Docker image, I used Docker. There is already an OpenJDK image available on Docker Hub, so I made sure I had the right JDK version (in my case, JDK 8), and I chose a lightweight image based on Alpine Linux. I wrote a Dockerfile that pulled the base image of JDK8-Alpine, copied my Springboot application into the image, and exposed the necessary ports. I created a Docker image with the command docker build -t <dockerhub-username>/custom-image
and I had the Docker image ready with me. To test it out, I created a simple docker-compose.yml file and ran the command “docker-compose up -d,” which launched it in detached mode. I checked the webpage by going to http://localhost:<port>
and checked if it’s working or not.
Creating a Kubernetes Manifest: I followed the rest of the guide by creating a Kubernetes manifest. I thought that typing the whole manifest instead of copy/pasting might give me some insight into how to type a manifest, but it didn’t work out as planned. I kept getting errors due to missing indentation or white space that I might have added by mistake. Typing the manifest with so many indentations felt like a nightmare. Eventually, I just deleted what I typed and replaced it by copying and pasting it from the tutorial I was following. And it worked!
Adding Angular Application: Now that I had the Springboot in Kubernetes, I decided to do the same with Angular application. I went to search for a tutorial with Angular Springboot in Kubernetes and followed it. Since everything was already there in the tutorial, it was fairly easy but took a bit of trial and error to get the Angular application working.
Learning New Concepts: There were some concepts that I didn’t know yet, like what services are, or what NodePort or ClusterIP are, but I didn’t care for now. I blindly followed the tutorial and got the Angular application working as well. I then tried again with a different tutorial, and it was during this time that I got a bit of a hang of it and started to understand what I was doing.
Starting the Project and Setting up the Database: So, I finally got to the real deployment this time. I was given the task to build a docker image and deploy it. It was quite exciting to get hands-on experience with something practical like this. The good thing was that I didn’t have to worry too much about messing up because it was all being done locally on my laptop using minikube. However, I was on a tight deadline and had to work quickly.
To start off, I created a mysql manifest. I didn’t bother with creating secrets or anything like that. I simply used the variables like root password, db_HOST, and all that in the manifest as one does in docker-compose.yml. I know that’s not the right way to do it, but I was feeling the pressure and had to get things done by the end of the day. It turns out that I needed an exact copy of the database for the spring application to work. I had to use the kubectl port-forward command and install DBeaver to access it. With the help of my colleague, we set up the database, which frankly was kind of annoying. Why would anyone require a database as a dependency?
Building the Spring Boot Application and Docker Image: After that, one of my colleagues provided me with a pre-built jar file of the Spring Boot application. I used the same Dockerfile that I had used in PART I for building the spring boot application. I used the split window feature in VSCode and used the tutorial spring boot manifest as a template. I followed it thoroughly, but soon I realized that there was an issue. The spring boot application required a custom URL. After searching online for a bit, I added a variable as an argument in the Dockerfile, re-created the docker image, and pushed it to Docker Hub. This way, I could add the spring datasource details and change them as required.
Deploying the Spring Boot Manifest and Troubleshooting: Deploying a Spring boot manifest was really annoying. Typing the manifest was not that bad, but there was a minor issue where although the Springboot application was deployed, it kept crashing for some reason. I checked the logs, and I kept getting the error message “communication link failure”. This basically meant that Springboot application was not able to access the database on MySQL. I spent two days straight with one of my colleagues who has worked on the application to figure out the issue. (She is a java developer and barely knows how Kubernetes worked) but I must say, she also spent some time with me to understand the fundamentals of Kubernetes and she is very smart (just wanted to give her a shoutout.). Anyways, we finally found the issue in the JDBC URL, which was missing the “&allowpublickeyretrieval” string at the end. As soon as I added this to the MySQL database in Kubernetes and tried again, it worked. It was very frustrating, but the satisfaction that we got when it finally worked made me feel kind of invincible, and being the noob I am, I wanted more of it.
I didn’t have the complete setup for the application and I knew it would take days to set up. So, my colleague provided me with a pre-built jar file. After that, I created a docker image of the Angular application and deployed it on Docker using a simple docker-compose.yml file to check if it worked.
Once I verified that the application was working in Docker, I created a kubernetes manifest for the Angular application with a service for it. This was a significant milestone for me as I had to go through many tutorials to understand the process. However, I faced an unexpected issue when I deployed the kubernetes manifest and checked the website with kubectl port-forward. Although the website was accessible, there was no data in it.
I spent a considerable amount of time investigating the issue and trying different solutions to resolve it, but nothing worked. I eventually realized that I might need an ingress service to fetch the details from the database. It was not an easy fix, and I had to search for creating an ingress service between the Spring Boot and Angular applications. During the process, I encountered another challenge where I could only access the website if I used the command kubectl port-forward. I wanted to access the website without using that command every time, so I had to deal with a load balancer as well.
Creating the ingress was a bit challenging, and I had to seek help from (another shout-out) Deaddy
who assisted me in understanding the process. After successfully deploying the ingress, I could see all the data, and the website was now dynamic instead of static, which was a great achievement. I also deployed the load balancer, which allowed me to access the website directly using the IP Address and port.
Finally, I edited my hosts
file and assigned a domain name to the URL, and now I had an actual website working on Kubernetes (without an SSL certificate). It was a thrilling experience to overcome the challenges and deploy the Angular application on Kubernetes, and I was happy to have achieved my goal.
Challenges⌗
These are some of the challenges I faced while learning Kubernetes:
Lack of understanding of Kubernetes basics: Directly diving in to MySQL and Springboot before learning the basics of Kubernetes. This approach may have made it difficult to understand how Kubernetes works and how it can be used to manage containers effectively.
Copying instead of understanding: I had difficulty with creating Kubernetes manifests and eventually copying and pasting them from a tutorial. While this approach may work initially, it may be challenging to modify or debug Kubernetes manifests without a fundamental understanding of them.
Trial and error approach: I used a trial and error approach to get the Angular application working in Kubernetes. While this may have been successful, it is a time-consuming and inefficient approach to problem-solving.
Time constraints: I had to learn Kubernetes within 30 days, which may have put pressure on me resulting in to take shortcuts or not fully understand the concepts before moving on to the next step. This may have affected the overall quality of the learning experience too.
Conclusion⌗
In conclusion, this experience has taught me a lot about the importance of attention to detail and taking the time to properly configure each aspect of the application.
It was also my first time working with a team and this also made me more productive in general and I had a lot of fun working on it.
While it was frustrating at times, the feeling of satisfaction when everything finally came together was worth it. I am excited to continue learning and expanding my skills in this field.