To launch a Kubernetes cluster can be a daunting task because it has multiple components. But, don't worry about that. You will create your own Kubernetes cluster from scratch after go through this wiki. If you are new with Kubernetes, highly recommanded that get a high-level overview of Kubernetes by reading Getting Started with Kubernetest.
There are many tools that can be used to launch a Kubernetes cluster. Most of that are capable of doing the heavy lifting for you. With these powerful tools, everyone can launch a Kubenetes cluster easily, fastly. Some of the most popular tools include:
In this tutorial, I will show you how to launch a kubernetes cluster via kubeadm step-by-step.
Kubeadm is a command-line tool used to bootstrap a Kubernetes cluster. It automates many of the manual processes involved in setting up a Kubernetes cluster, such as creating a cluster, configuring the control plane, and joining worker nodes to the cluster. It can be used to create a cluster on any infrastructure
that supports running Kubernetes, including on-premise data centers, cloud providers, and virtual machines. Using kubeadm, you can easily create a Kubernetes cluster with a single command, and then customize it to meet your specific requirements.
In this wiki, I will demonstrate how to bootstrapping a Kubernetes cluster which include one control plane node and three worker nodes step by step using kubeadm
tool.
Prepare 4 VMs which install with Debian 11 OS with 2 CPUs and 4 GB RAM, all VM details show in table below:
Hostname | Role | IP | OS | Spec |
---|---|---|---|---|
wildsre-k8s-control-plane | Control Plane | 172.16.100.10 | Debian 11 | 2c4g |
wildsre-k8s-worker-node-1 | Worker Node | 172.16.100.11 | Debian 11 | 2c4g |
wildsre-k8s-worker-node-2 | Worker Node | 172.16.100.12 | Debian 11 | 2c4g |
wildsre-k8s-worker-node-3 | Worker Node | 172.16.100.13 | Debian 11 | 2c4g |
Important
Swap disabled in all VM in order for the kubelet to work properly.
sudo swapoff -a
will disable swapping temporarily.
To make this change persistent across reboots, make sure swap is disablein config files/etc/fstab
.Setup the hostname resolv via
/etc/hosts
file.
cat >> /etc/hosts << EOF
172.16.100.10 wildsre-k8s-control-plane
172.16.100.11 wildsre-k8s-worker-node-1
172.16.100.12 wildsre-k8s-worker-node-2
172.16.100.13 wildsre-k8s-worker-node-3
EOF
Dockershim
has been removed from the Kubernetes project as of release 1.24. Using Docker Engine as CRI for kubernetes, need to using the cri-dockerd adapter to integrate Docker Engine with Kubernetes.
# Uninstall any such older versions before attempting to install a new version
> apt-get remove docker docker-engine docker.io containerd runc
# Setup the repository
> apt-get install ca-certificates curl gnupg lsb-release
> mkdir -m 0755 -p /etc/apt/keyrings
> curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
> echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker Engine
> apt update
> apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Download the `get-docker.sh` script and run
> curl -fsSL https://get.docker.com -o get-docker.sh
> sh ./get-docker.sh
# Check Docker Engine Version
> docker version
Client: Docker Engine - Community
Version: 23.0.1
API version: 1.42
(...)
Server: Docker Engine - Community
Engine:
Version: 23.0.1
API version: 1.42 (minimum version 1.12)
Go version: go1.19.5
Git commit: bc3805a
Built: Thu Feb 9 19:46:54 2023
OS/Arch: linux/amd64
(...)
# Download the cri-dockerd tarball
> wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.1/cri-dockerd-0.3.1.amd64.tgz
# Unzip the tarball
> tar xvf cri-dockerd-0.3.1.amd64.tgz
# Install cri-dockerd
> mv cri-dockerd/cri-dockerd /usr/local/bin/
# Verify cri-dockerd
> cri-dockerd --version
cri-dockerd 0.3.1 (7e528b98)
# Download and Setup for systemd
> wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.service
> wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.socket
> mv cri-docker.socket cri-docker.service /etc/systemd/system/
> sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
# Start and enable the cri-dockerd
> systemctl daemon-reload
> systemctl enable cri-docker.service
> systemctl enable --now cri-docker.socket
# Update the apt package index and install packages needed to use the Kubernetes apt repository
> apt-get update
> apt-get install -y apt-transport-https ca-certificates curl
# Download the Google Cloud public signing key
> curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
# Add the Kubernetes apt repository
> echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | tee /etc/apt/sources.list.d/kubernetes.list
# Update apt package index, install kubelet, kubeadm and kubectl, and pin their version
> apt-get update
> apt-get install -y kubelet kubeadm kubectl
> apt-mark hold kubelet kubeadm kubectl
Only run on Control Plane Node
# Init the control plane node
> kubeadm init --cri-socket /run/cri-dockerd.sock --pod-network-cidr=10.244.0.0/16
> mkdir -p $HOME/.kube
> cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
> chown $(id -u):$(id -g) $HOME/.kube/config
The parameters explanation:
--cri-socket
: Path to the CRI socket to connect. In our case, we are using the cri-dockerd as the CRI, so the value should be the cri-dcokerd.sock. Else, the kubeadm will try to using the Containerd as the CRI by default.--pod-network-cidr
: Specify range of IP addresses for the pod network. In our case, specify the cidr as '10.244.0.0/16' because we will use the flannel network plugin as CNI in our cluster.> kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
Only run on Worker Nodes
> kubeadm join --token <token> <control-plane-host>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>
# If you don't have the value of --token, you can get it by running the fllowing command on the control-plane node
> kubeadm token list
# If you don't have the value of --discovery-token-ca-cert-hash, you can get it by running the following command chain on the control-plane node
> openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
> kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
wildsre-k8s-control-plane Ready control-plane 0d v1.26.3 172.16.10.10 <none> Debian GNU/Linux 11 (bullseye) 5.10.0-21-amd64 docker://23.0.1
wildsre-k8s-worker-node-1 Ready <none> 0d v1.26.3 172.16.10.11 <none> Debian GNU/Linux 11 (bullseye) 5.10.0-21-amd64 docker://23.0.1
wildsre-k8s-worker-node-2 Ready <none> 0d v1.26.3 172.16.10.12 <none> Debian GNU/Linux 11 (bullseye) 5.10.0-21-amd64 docker://23.0.1
wildsre-k8s-worker-node-3 Ready <none> 0d v1.26.3 172.16.10.13 <none> Debian GNU/Linux 11 (bullseye) 5.10.0-21-amd64 docker://23.0.1
Create the YAML hello-world-web-application.yaml
file for the web application
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-deploy
spec:
replicas: 2
selector:
matchLabels:
app: hello-world
minReadySeconds: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-pod
image: nginx:1.21.6
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: hello-deploy-svc
labels:
app: hello-world
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: hello-world
Apply the Yaml config file to cluster
# Apply and Check
> kubectl apply -f hello-world-web-application.yaml
deployment.apps/hello-deploy created
service/hello-deploy-svc created
> kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/hello-deploy-749ffdf85-ljbmn 1/1 Running 0 7s
pod/hello-deploy-749ffdf85-sxh42 1/1 Running 0 7s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/hello-deploy-svc ClusterIP 10.111.214.44 <none> 80/TCP 7s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 864s
# Access the application via Service
> curl -I 10.111.214.44
HTTP/1.1 200 OK
Server: nginx/1.21.6
Date: Mon, 15 May 2023 00:05:39 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 25 Jan 2022 15:03:52 GMT
Connection: keep-alive
ETag: "61f01158-267"
Accept-Ranges: bytes
Overall, your first Kubernetes cluster had bootstrap successfully, you can do lots of practice with the cluster and get more deep dive in Kubernetes.
Create the Kubernetes cluster is the first step for exploring the containerization. I hope this wiki can help you to build your own kubernetes cluster. The choice of what tools you will using depends on-demand.
If you're a developer, you want to experience the feature of kubernetes, I recommand that you using minikube
to deploy the cluster, it's high-efficiency.
If you're a Devops/SRE, I highly recommand that using the kubeadm
to create the cluster, in order to get a well know of the components within the cluster.
Let's learn kubernetes together, and go further. Any questions, leave me comments below.