Kubernetes also written as k8s, is open source solution for management and orchestration of containerized applications. This article assumes that you have a minimally installed CentOS 7 machine as master node and two worker nodes with internet access. Let proceed for installation. Execute following commands on all nodes (master and worker).
Update the Systems
It is always a good approach to install latest updates
yum update -y
Enable EPEL Repository and Install Dependencies
Enable epel repository, install utilities and dependencies.
yum install epel-release yum-utils bash-completion net-tools device-mapper-persistent-data lvm2 -y
Disable SELinux
Disable Selinux.
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
Disable Swap
Disable swap.
free -m && swapoff -a && free -m
sed -i.bak -r 's/(.+ swap .+)/#\1/' /etc/fstab && cat /etc/fstab
Reboot
Reboot the machine to disable Selinux and bring up the latest kernel.
reboot
Add Kubernetes Repository
Add and enable Kubernetes official repository.
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
Add Host Entries
Add host entries or DNS records for name resolution.
cat <<EOF >> /etc/hosts
10.14.7.51 k8s-master.induslevel.com k8s-master
10.14.7.53 k8s-node01.induslevel.com k8s-node01
10.14.7.54 k8s-node02.induslevel.com k8s-node02
EOF
cat /etc/hosts
Add Firewalld Rules
Add firewalld rules on master and worker nodes.
firewall-cmd --permanent --add-port=8285/tcp
firewall-cmd --permanent --add-port=6443/tcp
firewall-cmd --permanent --add-port=2379-2380/tcp
firewall-cmd --permanent --add-port=10250/tcp
firewall-cmd --permanent --add-port=10251/tcp
firewall-cmd --permanent --add-port=10252/tcp
firewall-cmd --permanent --add-port=10255/tcp
firewall-cmd --reload && firewall-cmd --list-all
Tweak Sysctl Parameters
For networking to work, we need to tweak sysctl parameters for routing.
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
Install Packages
Install required packages on all nodes (masters and nodes).
yum install -y kubelet kubeadm kubectl
Enable Docker Repository
We will be using docker as container engine. Enable docker repository.
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
Install Docker
Install docker on all nodes.
yum install docker -y
Enable and Start Docker
Enable and start docker services.
systemctl start docker && systemctl enable docker && systemctl status docker
Start Kubelet
Start kublet service and enable it for startup on system booting on all nodes and master.
systemctl enable kubelet && systemctl start kubelet && systemctl status kubelet
Initialize the Cluster
Initialize the cluster on master.
kubeadm init --apiserver-advertise-address 10.14.7.51 --pod-network-cidr=172.16.0.0/16
Output (Scroll to view full log):
[init] Using Kubernetes version: v1.22.4 [preflight] Running pre-flight checks [WARNING Firewalld]: firewalld is active, please ensure ports [6443 10250] are open or your cluster may not function correctly [preflight] Pulling images required for setting up a Kubernetes cluster [preflight] This might take a minute or two, depending on the speed of your internet connection [preflight] You can also perform this action in beforehand using 'kubeadm config images pull' [certs] Using certificateDir folder "/etc/kubernetes/pki" [certs] Generating "ca" certificate and key [certs] Generating "apiserver" certificate and key [certs] apiserver serving cert is signed for DNS names [kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local rwc-k8s-master1.i2cinc.com] and IPs [10.96.0.1 10.14.7.51] [certs] Generating "apiserver-kubelet-client" certificate and key [certs] Generating "front-proxy-ca" certificate and key [certs] Generating "front-proxy-client" certificate and key [certs] Generating "etcd/ca" certificate and key [certs] Generating "etcd/server" certificate and key [certs] etcd/server serving cert is signed for DNS names [localhost rwc-k8s-master1.i2cinc.com] and IPs [10.14.7.51 127.0.0.1 ::1] [certs] Generating "etcd/peer" certificate and key [certs] etcd/peer serving cert is signed for DNS names [localhost rwc-k8s-master1.i2cinc.com] and IPs [10.14.7.51 127.0.0.1 ::1] [certs] Generating "etcd/healthcheck-client" certificate and key [certs] Generating "apiserver-etcd-client" certificate and key [certs] Generating "sa" key and public key [kubeconfig] Using kubeconfig folder "/etc/kubernetes" [kubeconfig] Writing "admin.conf" kubeconfig file [kubeconfig] Writing "kubelet.conf" kubeconfig file [kubeconfig] Writing "controller-manager.conf" kubeconfig file [kubeconfig] Writing "scheduler.conf" kubeconfig file [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env" [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml" [kubelet-start] Starting the kubelet [control-plane] Using manifest folder "/etc/kubernetes/manifests" [control-plane] Creating static Pod manifest for "kube-apiserver" [control-plane] Creating static Pod manifest for "kube-controller-manager" [control-plane] Creating static Pod manifest for "kube-scheduler" [etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests" [wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s [apiclient] All control plane components are healthy after 7.002213 seconds [upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace [kubelet] Creating a ConfigMap "kubelet-config-1.22" in namespace kube-system with the configuration for the kubelets in the cluster [upload-certs] Skipping phase. Please see --upload-certs [mark-control-plane] Marking the node rwc-k8s-master1.i2cinc.com as control-plane by adding the labels: [node-role.kubernetes.io/master(deprecated) node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers] [mark-control-plane] Marking the node rwc-k8s-master1.i2cinc.com as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule] [bootstrap-token] Using token: k6ft3u.5ybf6kpmxjmr8wwo [bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles [bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to get nodes [bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials [bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token [bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster [bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace [kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key [addons] Applied essential addon: CoreDNS [addons] Applied essential addon: kube-proxy
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following 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
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 10.14.7.51:6443 --token k6ft3u.5ybf6kpmxjmr8wwo
--discovery-token-ca-cert-hash sha256:1939449bb8aec7dae9cf877127c99abb07b5d12515c617603969dcc0ebb795f2
Configure Non-Root User
Create .kube directory to manage the kubernetes with non-root user.
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
Install Flannel CNI
Install Flannel CNI for intercommunication of pods on master.
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
Connect Nodes
Connect nodes with master. Execute the command on worker nodes.
kubeadm join 10.14.7.51:6443 --token k6ft3u.5ybf6kpmxjmr8wwo \
--discovery-token-ca-cert-hash sha256:1939449bb8aec7dae9cf877127c99abb07b5d12515c617603969dcc0ebb795f2
Check Status
Check the status of nodes connectivity using command on master node. Cluster will be configured once node status changes to ready state.
kubectl get nodes -o wide
kubectl get pods --all-namespaces
Deploy Nginx
Now we are going to deploy a nginx container deployment to test out setup.
mkdir -p /root/nginx/ && cd /root/nginx/
cat > /root/nginx/nginx-deployment.yaml<<"EOF"
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.0
ports:
- containerPort: 80
EOF
Create deployment using kubectl command on master node.
kubectl create -f /root/nginx/nginx-deployment.yaml
Check Status of Deployment
Check the status of deployment. Once deployment is complete, we will be creating a service to expose the port of this container.
kubectl get deployments
kubectl describe deployment nginx-deployment
Create Service
Create the new service to expose the nginx port for outside world.
cat > /root/nginx/nginx-service.yaml<<"EOF"
apiVersion: v1
kind: Service
metadata:
name: nginx-service
labels:
run: nginx-service
spec:
type: NodePort
ports:
- port: 80
protocol: TCP
selector:
app: nginx
EOF
Create service using this yaml file.
kubectl create -f /root/nginx/nginx-service.yaml
Check Status of Service
Check the status using following commands.
kubectl get service
kubectl describe service nginx-service
After successful service setup, check the status of service using curl command.
NodePort=$(kubectl describe service nginx-service |grep 'NodePort:'|awk '{print $3}'|awk -F/ '{print $1}') && curl k8s-node01:$NodePort