Hello Santhosh
Here I show you how to take a simple piece of golang, build and run it. Then I show you how to containerize it and run it. Finally I take the container and deploy it into Kubernetes in an attempt to simplify the Software lifecycle of going from code to cluster!
Intro
Recently where I work a colleague has started their journy in exploring Site relibility skills but more specifically they have been improving their Dev-ops skills since we tend to wear that hat where I work as well.
During his journey he is handling our Dockerfile and Helm chart dependencies as an excuse to explore how we build custom images and how we configure and deploy tools. I find this a great way to contribute to daily work and being handed a reason to go read some documentation and learn a helm chart a bit better.
At some point our colleague landed on a custom Golang tool we use to ship audit logs from a pub/sub in Google Cloud to an Elasticsearch index. The Go is custom, the Dockerfile is custom and the helm chart is custom. A lot of good questions were asked in an attempt to learn and understand. This got my brain moving into gear generating some questions.
How, do I strip away all the noise of taking code and deploying it into kubernetes? How can I show this in a lean way, with as little steps as possible to convey the point?
For the curious or those that want to follow along, here is the repository. https://github.com/MarkDPierce/hello-santhosh
Hello Santhosh
This is purely a play on ‘Hello-World’ but with a personal touch. Lets get started with our Golang application which will be a super simple web server that will display ‘Hello-Santhosh’ when visited. We will take this code and build it into a container and run said container. We will also ship this image and deploy it into kubernetes.
Lastly. I must admit, I wrote everything in this tutorial but the tone and language did not sit right with me. Maybe it was the beers but I wanted to get more out of it. So I leaned into ChatGPT to help me with the language and educational aspect of the tutorial as well as the conclusion.
Lets Go!
Golang
Golang stands out as a versatile, low-level programming language widely employed in modern-day applications. Engineers turn to Golang to tackle challenges that lack readily available solutions online or on platforms like GitHub.
To begin your journey with Golang, start by installing it. You can find installation instructions. https://golang.org/doc/install
Once installed, create a directory for your project:
1
2
mkdir hello-santhosh
cd hello-santhosh
Within this directory, create a file named main.go
where you’ll craft your code:
1
touch main.go
Now, let’s add the following code to main.go
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello Santhosh!")
}
func main() {
http.HandleFunc("/", handler)
fmt.Println("Server listening on port 8080...")
http.ListenAndServe(":8080", nil)
}
Building Your Application
We’ll create a module for our Golang application. This step is crucial, especially for more complex applications with dependencies, as it ensures that dependencies are appropriately compiled into the application.
Initialize the module with:
1
go mod init hello-santhosh
This command generates a go.mod file, capturing your project’s dependencies.
Golang’s nature as a compiled language offers speed advantages during runtime. However, building complex applications may entail longer build times, and debugging errors can occasionally prove challenging.
Compile your application using:
1
go build -o hello-santhosh
The -o
flag specifies the output file, generating a binary named hello-santhosh
. This binary contains the compiled machine code of your Golang application defined in main.go
.
Running Your Application
Execute your compiled binary with:
1
./hello-santhosh
You’ll see the message:
1
Server listening on port 8080...
Now, open your browser and navigate to http://localhost:8080
to see your application in action
Dockerizing Your Application
Begin by creating a Dockerfile
. This file will utilize the official Golang image for Alpine as a build image, providing a minimalistic OS tailored specifically for building Golang applications.
Before proceeding with building the container, ensure you have the go.mod file. You have several options to obtain this:
- Run
go mod init hello-santhosh
. - Copy
go.mod
from00golang
into01docker
. - Add
RUN go mod init hello-santhosh
to theDockerfile
just before the go build command.
Building the Container
In 00golang
, we successfully built a Golang application and executed it in our shell. However, for applications meant to serve more than your laptop, hosting them in a Docker container offers numerous advantages. This step abstracts the building and running process while providing the flexibility to modify application values, such as input variables.
As a challenge, consider modifying your Golang application to accept the server port as an environment variable. Docker facilitates this by allowing the provision of environment variables as inputs.
For now, let’s focus on building a container image using our Dockerfile:
1
docker build . -t hello-santhosh:0.0.1 -t hello-santhosh:latest -t mdpierce/hello-santhosh:0.0.1
To prepare for the Kubernetes section later, I’ll push this image to my Docker Hub. If you’re logged in with Docker Desktop or have an account, you can follow along by replacing my username with yours:
1
docker push mdpierce/hello-santhosh:0.0.1
Running the Container
To run your container, built using the Dockerfile
and exposing port 8080
, execute the following command:
1
docker run -p 8080:8080 hello-santhosh:0.0.1
Alternatively, you can run it using the latest tag we provided:
1
docker run -p 8080:8080 hello-santhosh:latest
By now, you should understand that with each code build, the semantic version changes, which can be integrated into your scripting, tooling, or actions for building Docker images based on application versions. Additionally, you grasp that input flags and values can be variables at different stages of the process.
Kubernetes Deployment
If you’re using Docker Desktop, I highly recommend enabling Kubernetes for a seamless experience. Follow these steps:
- Open Docker Desktop.
- Navigate to Settings (the cog icon in the top right).
- Under Kubernetes:
- Enable Kubernetes.
- Wait for the process to complete.
Once enabled, you should find an entry for docker-desktop in your kube config. Test this configuration by running:
1
k9s --context docker-desktop
This requires you to have installed the k9s tool. You could also just run
kubectl get nodes --context docker-desktop
Helm Chart
In the chart
directory. You’ll discover the most minimal Helm chart ready to deploy your application.
Deploying Your Application
Navigate to the 02kubernetes
directory and execute the following command to deploy your application:
1
helm install --kube-context docker-desktop hello-santhosh ./hello-santhosh/
Should you make any changes and wish to update the deployment, use the following command:
1
helm upgrade --kube-context docker-desktop -i hello-santhosh ./hello-santhosh/
At this stage, you should be able to port forward the pod using either k9s or kubectl and access it via http://localhost:8080.
Congratulations! You’ve successfully built and deployed an application locally, using Docker, and deployed to Kubernetes. Armed with these concepts, you’re ready to embark on further exploration and refinement. Well done!
Summary and Conclusion
In this tutorial, we embarked on a journey from crafting a Golang application to deploying it locally, within Docker, and finally within a Kubernetes cluster. Let’s recap the key steps and concepts covered:
Golang Basics: We explored the fundamentals of Golang, a powerful language utilized in modern-day applications. We set up a simple web server using Golang’s native libraries.
Dockerization: Leveraging Docker, we containerized our Golang application, encapsulating it with its dependencies into a portable, isolated unit. This process abstracted the building and running of our application, enabling seamless deployment across different environments.
Kubernetes Deployment: With Kubernetes, we orchestrated the deployment of our containerized application within a cluster. Using Helm charts, we streamlined the deployment process, abstracting complexities and ensuring consistency across deployments.
By following these steps, you’ve gained insights into the entire application life cycle, from development to deployment:
Development: Crafting your application logic with Golang, ensuring it meets your requirements.
Containerization: Packaging your application and its dependencies into a Docker container, facilitating consistency and portability.
Orchestration: Deploying your containerized application within a Kubernetes cluster, leveraging Helm charts for simplified management and scalability.
Through this tutorial, you’ve not only mastered the basic concepts of Golang, Docker, and Kubernetes but also gained practical experience in building and deploying applications in real-world scenarios.
Armed with this knowledge, you’re well-equipped to explore and innovate further, leveraging these powerful tools to develop and deploy robust applications efficiently.