How I build my own kubernetes cluster part. 1
Jun 18, 2023
As part of trying to learn more about Kubernetes, I figured it would be fun to create my own hosting, expose it to the internet and in the process gain some knowledge and experience.
In this post, I'll share tips and cover the entire cluster setup process. I'll also show how to automate deployment and configuration using tools such as Ansible, Cloud-init and Argo CD.
Before starting, let me explain a few important concepts here.
Container
Container is a lightweight and portable unit that packages together an application and its dependencies, libraries, and configuration files needed to run reliably and consistently across different computing environments. Containers provide a way to isolate applications from the underlying system, ensuring that they work the same way regardless of where they are deployed.
One of the most popular containerization technologies is Docker, which allows developers to create, distribute, and run containers easily
Why kubernetes?
The primary purpose of Kubernetes is to simplify the management of containerized applications in a scalable and resilient manner. It allows developers to deploy and manage containers without needing to worry about the underlying infrastructure details. Kubernetes abstracts away the complexities of handling multiple containers, networking, storage, and load balancing, providing a unified API and toolset to manage and automate containerized applications.
In this project we will be using k3s which is lightweight Kubernetes distribution designed by Rancher Labs. It is trimmed of unnecessary cloud integrations and various kinds of drivers. Unlike full Kubernetes it is contained in a single binary complete with all the necessary add-ons such as containerd, flannel, CoreDNS or traefik.
More about k3s: https://k3s.io/ and Kuberentes: https://kubernetes.io/.
Hardware
This is the list of hardware I used.
Installation
I choose Ubuntu Server 64-bit As the operating system for my cluster. To flash up micro SD cards I used Raspberry pi imager.
Next I modify user-data and network-config files within /boot directory. that are part of the cloud-init standard.
This file enable remote access with the SSH key, set the hostname and specify a new user on each node. To get a ssh keys pair use ssh-keygen command
After a boot It will assign a static ip address for each Pi.
To make it easier to access nodes from my computer, I added below configuration to my ~/.ssh/config file:
Ansible
To make the configuration faster I'm going to use ansible. You can find more about ansible at: https://www.ansible.com/
Let's create our inventory.yml file:
This file is used to define host groups that Ansible will manage.
Next I'll setup ansible.cfg file:
Lastly we are going to check if Ansible is working fine and can connect to all nodes. To do that you can use ping module specified by -m flag
Os setting
Updating system:
If you don't plan to use snap, you can just remove it to get some free resources
Since the Raspberry PIs in the cluster are configured as a headless server, reserved GPU Memory can be set to lowest possible (16M). To set gpu memory edit boot/firmware/config.txt by adding at the end:
Get the vxlan support. Starting with Ubuntu 21.10, vxlan support on Raspberry Pi has been moved into a separate kernel module. https://docs.k3s.io/installation/requirements?os=pi
Enable cgroups:
Reboot the Raspberry Pi
Fan control
Due to the fact that my cluster, will run for many days, I decided to purchase more robust cooling heat sink with a fan. The aim is to reduce throthling and increase the life span of the PI’s.
I wrote a simple program in python which sets the speed of the fans based on the current temperature:
We need to install required python libraries.
To keep the program running even after a reboot you can create systemd service
Upload program to server:
Upload the service in similar manner:
Enable service:
Installing kubernetes
Control plane (pi1)
To install k3s on the master node execute the following command:
After installation obtain node token:
Workers
We will use ansible to join rest nodes to our cluster. Replace <node token> with a node token previously obtained:
Now wait for nodes to join the cluster:
Kubeconfig
We want to copy kubeconfig file from cluster to communicate with the Kubernetes cluster's API server from our computer:
Edit kubeconfig on computer
Networking
In K3s, key network components such as CoreDNS, Traefik Ingress Controller, Flannel and ServiceLB are pre-configured by default.
MetalLB
For bare-metal clusters, Kubernetes does not offer network load balancer implementations (LoadBalancer services) by default. However other options are available, such as NodePort and externalIPs, but both of these options have significant downsides for production use, which makes bare-metal clusters second-class citizens in the Kubernetes ecosystem.
MetalLB addresses these problems by offering a network load balancer implementation that integrates with standard network equipment. This allows external services in bare-metal clusters to run as efficiently as in cloud clusters.
How MetalLB works
MetalLB can work in two modes, BGP and Layer 2. In layer 2 mode, a node advertises a service to the local network, appearing to the network as a machine with multiple IP addresses. The main benefit of using layer 2 mode in building a Kubernetes cluster is its universality, as it operates on any Ethernet network without the need for special hardware or advanced routers.
In BGP mode, each node in your cluster establishes a BGP peering session with your network routers, and uses that peering session to advertise the IPs of external cluster services. More About metalb: https://metallb.universe.tf/
MetalLB installation
Install metalb using helm:
You need to deploy the following manifest as MetalLB requires an IP range to use for external IPs:
Now services that use LoadBalancer should have an external IP assigned to them:
Traefik
Traefik will be used as Ingress Controller for the cluster. Normally traefik is bundled with k3s by default, but I disabled It during installation, so it can be installed manually to have full control over the version and its initial configuration.
Traefik's purpose is to handle network traffic by routing HTTP/HTTPS requests to the appropriate services and exposing them to the outside world through domain
Instalation
Add helm repo, get the latest charts from the repository and create namespace:
Create traefik-values.yml file:
Install Traefik:
Basic authentication
We will later need to secure access to our kubernetes apps exposed by traefik (longhorn ui, prometheus).
The Traefik BasicAuth middleware can be utilized for basic HTTP authentication: