To bootstrap a minimal K8S cluster for testing purpose, kubeadm is a very interesting tool. The goal of this blog is not to explain to you the K8S architecture or the components but only the deployment part. using kubeadm.

The final architecture of our cluster will be the following:


Docker Installation

The first step is to install Docker on each cluster node:

yum install yum-utils device-mapper-persistent-data lvm2
yum-config-manager \
--add-repo \

yum update && yum install docker-ce-18.06.2.ce
mkdir /etc/docker

cat > /etc/docker/daemon.json <<EOF
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
"storage-driver": "overlay2",
"storage-opts": [
mkdir -p /etc/systemd/system/docker.service.d
systemctl daemon-reload
systemctl restart docker


Kubeadm Installation

Before installing Kubernetes components some pre-requisites need to be configured within your cluster nodes.

Disable SWAP devices
[email protected] ~]$ cat /proc/swaps
Filename				Type		Size	Used	Priority
/dev/dm-1                               partition	5242876	0	-1

[[email protected] ~]$ sudo swapoff -a

Remove any matching reference found in /etc/fstab & Reboot the system for changes taking effect.

Set SELinux in permissive mode (effectively disabling it)
[[email protected] ~]$ sudo setenforce 0
[[email protected] ~]$ sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
[email protected] ~]$ sudo sed -i 's/^SELINUX=permissive$/SELINUX=disabled/' /etc/selinux/config
Hostname configuration
[[email protected] ~]$ hostnamectl set-hostname docker-manager000
[[email protected] ~]$ hostname
Network connectivity

Modify the /etc/hosts of each server as following:

[[email protected] ~]$ cat /etc/hosts localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost6 localhost6.localdomain6 localhost6.localdomain

xx.xx.x.xx	docker-manager000
xx.xx.x.xx	docker-worker000
xx.xx.x.xx	docker-worker001


Installing kubeadm, kubelet and kubectl

First, configure the Kubernetes repository for downloading the latest stable version of Kubernetes:

cat < /etc/yum.repos.d/kubernetes.repo

Then install packages:

[[email protected] ~]$ sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
[[email protected] ~]$ sudo systemctl enable --now kubelet


Install NTP service
[[email protected] containerd]$ yum install ntp
[[email protected] containerd]$ systemctl start ntpd
[[email protected] containerd]$ systemctl enable ntpd
Ensure net.bridge.bridge-nf-call-iptables is set to 1 in your sysctl config for proper traffic routing
[[email protected] ~]$ cat <  /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

Manually settings:
[[email protected] ~]$ sudo sysctl net.bridge.bridge-nf-call-iptables=1
[[email protected] ~]$ sudo sysctl net.bridge.bridge-nf-call-ip6tables=1

[[email protected] ~]$ sysctl --system
Make sure that the br_netfilter module is loaded
[[email protected] ~]$ lsmod | grep br_netfilter (to check)
[[email protected] ~]$ modprobe br_netfilter (to load)


Initialize your cluster using Kubeadm

The kubadm command will install you all control plane components (api server + etcd + scheduler + controller-manager)

[[email protected] ~]$ sudo kubeadm init --pod-network-cidr=

Copy-paste the join command with the token and keep it for the next steps.

Install a pod network add-on: Calico
kubectl apply -f

Import the kube config in your home before start using your cluster.

[[email protected] ~]$ mkdir -p $HOME/.kube
[[email protected] ~]$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[[email protected] ~]$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
Join your cluster and run the following on Workers side

From each worker nodes, you can now execute the join command as following:

sudo kubeadm join xx.xx.x.xx:6443 --token vv2iva.yt241t7epiu7i4iz \
    --discovery-token-ca-cert-hash sha256:558ec4a25cd39185fd753aba81748569f033af9c15e48dcdf3d10206eecdf177

On the master, check the cluster status:

[[email protected] ~]$ kubectl get nodes -o wide
docker-manager000   Ready    master   20d   v1.14.2   xx.xx.x.xx            CentOS Linux 7 (Core)   3.10.0-957.12.2.el7.x86_64   docker://18.9.6
docker-worker000    Ready       20d   v1.14.1   xx.xx.x.xx            CentOS Linux 7 (Core)   3.10.0-957.10.1.el7.x86_64   docker://18.9.5
docker-worker001    Ready       20d   v1.14.1   xx.xx.x.xx            CentOS Linux 7 (Core)   3.10.0-957.10.1.el7.x86_64   docker://18.9.5

List all pods within the kube-system namespace:

[[email protected] ~]$ kubectl get pods -n kube-system -o wide
NAME                                        READY   STATUS    RESTARTS   AGE     IP               NODE                NOMINATED NODE   READINESS GATES
calico-kube-controllers-6894d6f4f4-jtwnn    1/1     Running   5          20d   docker-manager000              
calico-node-9586j                           1/1     Running   6          20d     xx.xx.x.xx       docker-manager000              
calico-node-lc6vh                           1/1     Running   3          20d     xx.xx.x.xx       docker-worker000               
calico-node-ph9j7                           1/1     Running   3          20d     xx.xx.x.xx       docker-worker001               
coredns-fb8b8dccf-cxfcq                     1/1     Running   4          11d   docker-manager000              
coredns-fb8b8dccf-pf879                     1/1     Running   5          11d   docker-worker001               
etcd-docker-manager000                      1/1     Running   6          20d     xx.xx.x.xx       docker-manager000              
kube-apiserver-docker-manager000            1/1     Running   2          11d     xx.xx.x.xx       docker-manager000              
kube-controller-manager-docker-manager000   1/1     Running   2          11d     xx.xx.x.xx       docker-manager000              
kube-proxy-j8v2b                            1/1     Running   2          11d     xx.xx.x.xx       docker-worker000               
kube-proxy-jp5dr                            1/1     Running   2          11d     xx.xx.x.xx       docker-worker001               
kube-proxy-z57xx                            1/1     Running   2          11d     xx.xx.x.xx       docker-manager000              
kube-scheduler-docker-manager000            1/1     Running   2          11d     xx.xx.x.xx       docker-manager000              

Your cluster is now up and running! You can start your first deployment 🙂

Thumbnail [60x60]