Kubernetes Cluster Setup: Ubuntu 20.04 Guide

by Jhon Lennon 45 views

Hey there, fellow tech enthusiasts! Ever wanted to get your hands dirty with orchestrating containers like a pro? Well, you've come to the right place, guys! Today, we're diving deep into setting up your very own Kubernetes cluster right on Ubuntu 20.04. This isn't just about following a bunch of commands; it's about understanding the magic that makes Kubernetes so powerful and how you can harness it for your projects. We'll break down each step, making sure it's super clear and actionable, even if you're just dipping your toes into the container orchestration world. So, grab your favorite beverage, settle in, and let's get this cluster built!

Why Kubernetes and Why Ubuntu 20.04?

Before we jump into the nitty-gritty, let's chat about why you'd even want a Kubernetes cluster. In today's fast-paced development world, managing applications, especially at scale, can be a real headache. You've got updates, scaling, fault tolerance, and a whole laundry list of other things to worry about. This is where Kubernetes, often abbreviated as K8s, swoops in like a superhero. It's an open-source platform designed to automate the deployment, scaling, and management of containerized applications. Think of it as the ultimate conductor for your container orchestra, ensuring everything runs smoothly, efficiently, and reliably. It allows you to treat your servers as a single pool of resources, abstracting away the underlying infrastructure. This means you can focus more on building awesome applications and less on managing servers.

Now, why Ubuntu 20.04 (Focal Fossa)? Ubuntu has long been a favorite in the server world, and for good reason. It's stable, well-supported, and has a massive community. Setting up Kubernetes on Ubuntu is pretty straightforward because of its robust package management and general ease of use. Ubuntu 20.04 LTS (Long Term Support) provides a stable base for your cluster, meaning you won't have to worry about frequent, disruptive upgrades. It's a reliable foundation for building something as critical as a Kubernetes cluster. Plus, most of the tools and documentation you'll find for Kubernetes are well-tested on Ubuntu environments, making troubleshooting a breeze.

So, to recap, we're building a Kubernetes cluster on Ubuntu 20.04 because Kubernetes gives us the power to manage our applications effortlessly, and Ubuntu 20.04 provides a stable, user-friendly platform to host it all. Pretty sweet combo, right? Let's get building!

Prerequisites: What You'll Need Before You Start

Alright guys, before we start laying bricks for our Kubernetes castle, let's make sure we have all our tools ready. Think of this as your pre-flight checklist. Getting these things in order now will save you a ton of headaches down the line, trust me. We're going to need a few things:

First off, you'll need at least two Ubuntu 20.04 servers. Why two? Well, a Kubernetes cluster typically has at least one control plane node (the brain of the operation) and at least one worker node (where your actual applications will run). For a production-ready setup, you'd want multiple control plane nodes for high availability and multiple worker nodes for scalability. But for learning and testing, two is a great starting point. These servers can be physical machines or virtual machines (VMs) running on your local machine (like with VirtualBox or VMware) or in the cloud (AWS, GCP, Azure, etc.). Make sure they have internet access, as we'll be downloading a lot of packages.

Next up, SSH access to all your servers is crucial. You'll be running commands remotely, so make sure you can SSH into each machine without any issues. It's also highly recommended to set up passwordless SSH between your nodes, especially from the control plane to the worker nodes. This simplifies a lot of the cluster management tasks. You can achieve this using SSH keys. Just generate a key pair on your control plane node and copy the public key to the authorized_keys file on your worker nodes.

We also need to ensure that all nodes have a unique hostname. This is super important for Kubernetes to identify each node correctly. You can check the current hostname using hostnamectl and change it if needed. Also, make sure each node has a static IP address. Dynamic IPs can cause problems with cluster networking, so assigning static IPs is a must.

Here's a crucial one: disable swap on all nodes. Kubernetes doesn't play well with swap memory. It can lead to performance issues and instability. You can temporarily disable swap with sudo swapoff -a and then permanently disable it by commenting out the swap entry in /etc/fstab. We'll go through the exact commands for this.

Finally, you'll need sudo privileges on all your servers. Most of the installation and configuration steps require root access. So, make sure the user you're logged in with has sudo permissions.

So, to sum up, gather your Ubuntu 20.04 servers (at least two), ensure SSH access, unique hostnames, static IPs, disable swap, and have sudo access. Once you've got all that squared away, you're golden and ready to move on to the actual setup. Let's do this!

Setting Up the Control Plane Node

Alright, team, let's get the heart of our Kubernetes cluster beating: the control plane node. This is where all the critical decisions are made, like scheduling pods, managing cluster state, and handling API requests. We'll start by preparing our Ubuntu 20.04 server that will serve as our control plane.

First things first, let's ensure our system is up-to-date. Open up your SSH connection to your chosen control plane server and run these commands:

sudo apt update
sudo apt upgrade -y

This ensures we're working with the latest packages and security patches. Now, we need to make sure our nodes can communicate properly, and for that, we need to configure some kernel modules and sysctl parameters. Run the following:

sudo modprobe overlay
sudo modprobe br_netfilter

sudo sysctl net.bridge.bridge-nf-call-iptables=1
sudo sysctl net.bridge.bridge-nf-call-ip6tables=1
sudo sysctl net.ipv4.ip_forward=1

To make these changes persistent across reboots, we need to add them to a sysctl configuration file. Let's create one:

sudo tee /etc/sysctl.d/kubernetes.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

Then, apply the changes without rebooting:

sudo sysctl --system

Next up, we need to disable swap. As mentioned in the prerequisites, Kubernetes performs much better without swap. Let's turn it off temporarily and then permanently:

sudo swapoff -a
# And to make it permanent, edit the fstab file:
sudo sed -i '/ swap / s/$/#/' /etc/fstab

Now for the core components: container runtime and kubeadm, kubelet, and kubectl. We'll start with the container runtime. Docker is a popular choice, but Containerd is now the default and recommended runtime for Kubernetes. Let's install containerd:

sudo apt install -y containerd

After installation, we need to configure containerd. Generate the default configuration file:

sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml

Now, we need to enable the SystemdCgroup option in the config.toml file. This is important for kubelet to properly manage container resources. Open the file with your favorite editor (like nano or vim):

sudo nano /etc/containerd/config.toml

Find the [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] section and ensure SystemdCgroup is set to true. It should look something like this:

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  ... (other configurations)
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    ... (other configurations)
    SystemdCgroup = true

Save and exit the file. Then, restart containerd to apply the changes:

sudo systemctl restart containerd

Now, let's install kubeadm, kubelet, and kubectl. These are the Kubernetes management tools. We'll add the Kubernetes package repositories first:

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

Update your package list again:

sudo apt-get update

And finally, install the Kubernetes components. We'll pin the version to avoid accidental upgrades to incompatible versions:

sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

We need to prevent kubelet from starting automatically until kubeadm configures it. So, we'll mask it for now:

sudo systemctl mask kubelet
sudo systemctl enable containerd

Alright, the control plane node is almost ready! The last step here is to initialize the Kubernetes cluster using kubeadm. This command bootstraps the control plane. Make sure to replace <POD_CIDR> with a valid CIDR block for your pods, like 10.244.0.0/16 (this is common if you plan to use Flannel for networking later).

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

This command might take a few minutes. Once it's done, you'll see output telling you how to join your worker nodes to the cluster, and crucially, how to configure kubectl for your user. It will also give you commands to run to set up your home directory for kubectl.

Follow the instructions given by kubeadm init to set up kubectl for your regular user. It usually involves commands like these:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Now you can test if kubectl is working:

kubectl get nodes

You should see your control plane node listed, but it will likely be in a NotReady state because we haven't set up a network yet. That's our next big task!

Setting Up Worker Nodes

Fantastic job getting the control plane up and running! Now, let's bring our worker nodes into the fold. These are the machines that will actually run your applications (your containers). You'll need to perform these steps on each of your worker nodes.

Just like with the control plane, we need to ensure our worker nodes are prepped and ready. Start by updating the system:

sudo apt update
sudo apt upgrade -y

We need the same kernel modules and sysctl settings enabled on the worker nodes as we did on the control plane for consistent networking behavior:

sudo modprobe overlay
sudo modprobe br_netfilter

sudo sysctl net.bridge.bridge-nf-call-iptables=1
sudo sysctl net.bridge.bridge-nf-call-ip6tables=1
sudo sysctl net.ipv4.ip_forward=1

# Make them persistent across reboots:
sudo tee /etc/sysctl.d/kubernetes.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system

And, you guessed it, we need to disable swap on the worker nodes as well. No exceptions!

sudo swapoff -a
# Make it permanent:
sudo sed -i '/ swap / s/$/#/' /etc/fstab

We also need the same container runtime, containerd, installed and configured on our worker nodes. If you already installed it on the control plane, you'll do the same here:

sudo apt install -y containerd
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml

Remember to enable SystemdCgroup = true in /etc/containerd/config.toml for containerd:

sudo nano /etc/containerd/config.toml

Find the [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] section and set SystemdCgroup = true. Then restart containerd:

sudo systemctl restart containerd

Finally, we need to install kubelet and kubectl on the worker nodes. We don't need kubeadm on the workers since the control plane handles initialization. We'll use the same Kubernetes repository setup as before:

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update

Now install kubelet and kubectl, and hold the versions:

sudo apt-get install -y kubelet kubectl
sudo apt-mark hold kubelet kubectl

Just like on the control plane, we need to mask kubelet until kubeadm configures it:

sudo systemctl mask kubelet
sudo systemctl enable containerd

Now that all nodes are prepared, it's time to join them to the cluster. Go back to your control plane node. Remember the output from sudo kubeadm init? It provided a kubeadm join command. It looks something like this:

sudo kubeadm join <control-plane-ip>:6443 --token <your-token> \
    --discovery-token-ca-cert-hash sha256:<your-sha256-hash>

Copy this exact command and run it on each of your worker nodes. If you lost your token, you can generate a new one on the control plane node with:

sudo kubeadm token create --print-join-command

After running the join command on each worker node, head back to your control plane node and check the status of your nodes:

kubectl get nodes -o wide

You should now see all your nodes listed, and after a minute or two, they should transition from NotReady to Ready state. If they don't, don't panic! It's usually a networking issue or kubelet not running correctly. Double-check the previous steps on the worker nodes.

Installing a Pod Network Add-on

Awesome! Your nodes are now part of the cluster, but they're still not quite ready for prime time. Why? Because Kubernetes needs a way for pods on different nodes to communicate with each other. This is where a Pod Network Add-on comes in. Think of it as setting up the highways and roads between your different servers so that your application containers can chat.

There are several options for pod network add-ons, like Calico, Flannel, Weave Net, and Cilium. For simplicity and popularity, we'll use Flannel. It's a straightforward and effective CNI (Container Network Interface) plugin.

First, you need to apply the Flannel configuration to your cluster. This is done using kubectl. Make sure you're on your control plane node and have kubectl configured correctly.

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

This command downloads the Flannel manifest and applies it to your Kubernetes cluster. Flannel will deploy its own pods (called