Skip to content

Instantly share code, notes, and snippets.

@fcaldarelli
Last active August 10, 2024 15:52
Show Gist options
  • Save fcaldarelli/85243f89ae4da63ed8853924f939b528 to your computer and use it in GitHub Desktop.
Save fcaldarelli/85243f89ae4da63ed8853924f939b528 to your computer and use it in GitHub Desktop.
Install Kubernetes on Debian

Install Kubernetes on Debian (>= 11)

The goal of this tutorial is to install a kubernetes cluster using Debian 11 or above.

This tutorial covers also as creating a single node cluster (step 7).

1. Prerequisites

Before starting the installation process, ensure you have:

  • Debian 12 or 11 machines (one master and one worker node or a single master node).
  • Root or sudo access on all machines.
  • At least 2 GB of RAM and 2 CPUs per machine.
  • A stable internet connection for downloading packages.

2. Environment preparation

sudo apt update 
sudo apt upgrade 
sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release

3. Disable swap

Now you must disable swap to allow kubernetes installation.

If you can't or don't want to reboot the machine, temporarely disable the swap with this command:

sudo swapoff -a

check that swap if off with:

sudo swapon

if the command does not return anything, the swap is off.

But you need to disable permanently the swap to ensure that it is disable also after a reboot.

3.1 - Comment entry in /etc/fstab

Find the line in /etc/fstab referring to swap, and comment it. This command should be enough:

sudo sed -i '/\s\+none\s\+swap\s\+/s/^/#/' /etc/fstab

Verify if /etc/fstab row with swap type is commented

3.2 - Disable permanently systemd

Debian needs to disable swap also in systemd:

sudo systemctl mask --now swap.target

Now you could reboot your system and launch swapon to see if the swap if off after a reboot.

4. Install Docker Engine

4.1 - Add Docker's official GPG key:

sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

4.2 - Add the repository to Apt sources:

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

4.3 - Install the Docker packages.

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

4.4 - Verify that the installation is successful by running the hello-world image:

sudo docker run hello-world

4.5 - Enable and start docker service

sudo systemctl enable docker
sudo systemctl start docker

4.6 - Replace cfgroup containerd config to systemd

Default package containerd configuration is minimal and does not set cfgroup value to true for systemd.

So, to apply full containerd configuration launch this command as root user:

containerd config default > /etc/containerd/config.toml

search the key SystemdCgroup=false under [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] section, and set the value to true.

sudo sed -i 's/SystemdCgroup\s*=\s*false/SystemdCgroup = true/' /etc/containerd/config.toml

Now, restart containerd service with:

sudo systemctl restart containerd

Source: https://docs.docker.com/engine/install/debian/

5. Install and setup kubectl

5.1 - Update the apt package index and install packages needed to use the Kubernetes apt repository:

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

5.2 - Download the public signing key for the Kubernetes package repositories. The same signing key is used for all repositories so you can disregard the version in the URL:

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

5.3 - Add the appropriate Kubernetes apt repository. If you want to use Kubernetes version different than v1.30, replace v1.30 with the desired minor version in the command below:

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

5.4 - Update apt package index, then install kubectl:

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

5.5 - Enable kubelet service:

sudo systemctl enable --now kubelet

6. Install the kubernetes cluster

6.1 - Initialize the control plane

sudo kubeadm init

6.2 - Enable kube config for regular user

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

6.3 - Install config network interface

kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

7. Single node Kubernetes cluster (OPTIONAL)

By default, your cluster will not schedule Pods on the control plane nodes for security reasons. If you want to be able to schedule Pods on the control plane nodes, for example for a single machine Kubernetes cluster, run:

kubectl taint nodes --all node-role.kubernetes.io/control-plane:NoSchedule-

Check if taint is removed with

kubectl describe node | grep Taint

8. Install load balancer: metallb

If you are installing the load balancer inside the master node, you must apply previous point to remove NoSchedule pods from master node.

Apply the manifest:

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml

Then prepare the IPAddressPool config:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: cheap
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.18/32

where address can be a single ip (this example) or a subnet (ex. 192.168.10.0/24, 42.176.25.64/30) or multiple rows.

Source: https://metallb.universe.tf/configuration/_advanced_ipaddresspool_configuration/

9. Try the cluster: install nginx

9.1 - Create nginx deployment

Write the content to nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

9.2 - Apply the deployment

kubectl apply -f nginx-deployment.yaml

9.3 - Create nginx service

Write the content to nginx-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: default
  annotations:
    metallb.universe.tf/allow-shared-ip: "publicip-192.168.1.18"  
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

In this example, I have just one available ip 192.168.1.18, otherwise the section annotations can be removed:

annotations:
   metallb.universe.tf/allow-shared-ip: "publicip-192.168.1.18"  

Source: https://metallb.universe.tf/usage/

Go to http://192.168.1.18 to show nginx welcome page.

10. Try the cluster: another install nginx service

10.1 - Create nginx deployment

Write the content to nginx2-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx2-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx2
  template:
    metadata:
      labels:
        app: nginx2
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

10.2 - Apply the deployment

kubectl apply -f nginx2-deployment.yaml

10.3 - Create nginx service

Write the content to nginx2-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx2-service
  namespace: default
  annotations:
    metallb.universe.tf/allow-shared-ip: "publicip-192.168.1.18"  
spec:
  type: LoadBalancer
  selector:
    app: nginx2
  ports:
    - protocol: TCP
      port: 81
      targetPort: 80

In this example, I have just one available ip 192.168.1.18, otherwise the section annotations can be removed:

annotations:
   metallb.universe.tf/allow-shared-ip: "publicip-192.168.1.18"  

Source: https://metallb.universe.tf/usage/

Go to http://192.168.1.18:81 (port 81) to show nginx welcome page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment