This post aims to show how to build a self hosted Kubernetes cluster composed from a master node and 2 or more worker nodes.
Also, this post assumes that all machines are running Ubuntu 16.04.5 LTS version, however most of the commands may run on older or newer versions.
Foremost, we must install docker on every node. There are 2 ways to install Docker: using Official Ubuntu Repositories and the Official Docker Way. I usually follow the installation steps provided in the official Docker documentation rather from Ubuntu repositories, as it is always possible to install a very specific version or the very latest version.
sudo apt-get install -y \ apt-transport-https \ ca-certificates \ curl \ gnupg2 \ software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" sudo apt-get update sudo apt-get install -y docker-ce=18.06.1~ce~3-0~ubuntu
Add the current user to the docker group in order to run docker commands as non-root user. Don’t forget to log out and log back in order this to have effect.
sudo groupadd docker sudo usermod -aG docker $USER sudo systemctl enable docker
Install Kubernetes dependencies
These steps must be performed on all nodes as well. They will install the following dependencies:
- kubeadm – tool that will allow us to build the k8s cluster. Helps in initiating the master node and joining the cluster for worker nodes
- kubelet – is the agent that runs on every node. It constantly monitors the pods that were created by k8s and ensures that they are healthy and running
- kubectl – CLI used to interact with Kubernetes clusters by performing various actions
Therefore run the following:
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main" sudo apt-get update sudo apt-get -y install kubeadm kubelet kubectl
Kubernetes aims for performance by utilizing resources as much as possible and it does not need swap as it will slow things down, hence we need to disable swap.
sudo swapoff -a
Initialize master node
We will be initializing the k8s master node from a config file. Save the below content in a file named kubeadm.yaml and replace the
apiVersion: kubeadm.k8s.io/v1alpha3 kind: InitConfiguration apiEndpoint: advertiseAddress: 0.0.0.0 # IP address the kubeapi server will run on bindPort: 6443 # port the kubeapi server will listen on --- apiVersion: kubeadm.k8s.io/v1alpha3 kind: ClusterConfiguration apiServerCertSANs: - <master_node_ip> # adds and extra name for API server and issues a certificate for it networking: podSubnet: 10.244.0.0/16 controlPlaneEndpoint: <master_node_ip>:6443 # sets the endpoint that nodes use to communicate within the cluster
Having the config file, we can now initialize the master node.
kubeadm init --config=kubeadm.yaml
If the master node has been initialized successfully, you should see an output of the following:
... Your Kubernetes master has initialized successfully! To start using your cluster, you need to run (as a 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 You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the addon options listed at: http://kubernetes.io/docs/admin/addons/ You can now join any number of machines by running the following on each node as root: kubeadm join <master_node_ip>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>
As the installer suggests, run below commands in order to point kubectl to issue commands against the newly created cluster.
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
Install a CNI
Container Network Interface defines a specification on how to configure network interfaces for Linux containers. There are a few libraries that abide this (e.g. calico, flannel, weave) and they act as a bridge for communication between nodes within the Kubernetes cluster. In this case we’ll go with calico.
On the master node run the following:
kubectl apply -f https://docs.projectcalico.org/v3.2/getting-started/kubernetes/installation/hosted/rbac-kdd.yaml kubectl apply -f https://docs.projectcalico.org/v3.2/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
Depending on the environment it may take some time to set up everything. Verify that the network has built up without errors and that all pods are running with:
kubectl get pods --all-namespaces
Join Kubernetes cluster
To join the Kubernetes cluster, on every node that will act as an worker run the kubeadm join command alongside the tokens, that was returned when the master node was initialized.
sudo su kubeadm join <master_node_ip>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash> exit
Great, now the worker nodes joined the cluster and we have a fully functional Kubernetes cluster. To double check that run:
kubectl get nodes
that should return something similar to this:
NAME STATUS ROLES AGE VERSION master Ready master 4m v1.13.2 worker001 Ready <none> 2m v1.13.2 worker002 Ready <none> 2m v1.13.2