Create a Kubernetes cluster on CentOS 7
Kubernetes is an open source system developed by Google which automates deployment, operations and scaling of containerized applications. It is a holistic solution for automated delivery offering a wide range of critical features like automatic binpacking, self-healing, auto-scaling, service registry, software load-balancing, automated rollouts, automated rollbacks, secret and configuration management, storage orchestration and batch execution.
It is hands down the best technology I have master recently.
In this article, I will help you setting up your cluster. It is going to take some effort but it’s all worth it.
Let’s get started.
**UPDATE 5th November 2016**
While I still exhort you to read this article for educational purposes, there is now a much easier way to setup a Kubernetes cluster using `kubeadm`. I will write an article on it as soon as possible. In the meantime you can follow the official documentation on [http://kubernetes.io/docs/getting-started-guides/kubeadm/](http://kubernetes.io/docs/getting-started-guides/kubeadm/)
Architecture Overview
The high level architecture of Kubernetes is pretty simple. There is a master which controls one or more nodes where pods are spawned. The kube-apiserver
, the kube-scheduler
and the kube-controller-manager
reside on the master, while the kubelet
and the kube-proxy
reside on the nodes. The kubectl
, the command line interface, can be placed on any machine, even outside the cluster.
In few words, the master monitors the nodes and schedules pods on the nodes by invoking the `kubelet`. The `kube-proxy` enables software load-balancing and the services paradigm.
Data is persisted on etcd, a key-value store accessible through a RESTful API. Networking can be implemented in many different ways as long as it satisfies the Kubernetes requirements. For the scope of this tutorial, we will be using flannel.
This is obviously a very simplistic description. If you wish to dig deeper, just read the official documentation on http://kubernetes.io
Pre-requisites
In order to setup a cluster you need a minimum of 1 VM, i.e. you can run the master and one node on the same machine. In this tutorial I will assume you have at least 2 VMs. However you should be able to follow the same step sequence in both cases.
Setup the master
Disable firewalld
Disable iptables to avoid conflicts with Docker.
systemctl stop firewalld
systemctl disable firewalld
Install ntp
Install the Network Time Protocol to keep the nodes in synch.
yum install ntp
systemctl start ntpd
systemctl enable ntpd
systemctl status ntpd
Install etcd
Install etcd.
yum install etcd
Before launching and enabling the etcd service you need to define its configuration in `/etc/etcd/etcd.conf`. The file contains several lines. You need to make sure the following are uncommented and setted as shown below.
ETCD_NAME=default
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"
Finally launch and enable the service.
systemctl start etcd
systemctl enable etcd
systemctl status etcd
Install the Kubernetes components
You can install the Kubernetes components in several ways. The simplesy is to use yum
`. If you wish to install the latest version or a particular release you need refer to the kubernetes repository itself since it is a bit more complicate. I plan to right a separate post to show you how to do that. For the time being, let’s stick to the simpler approach.
First we install Kubernetes through yum
.
yum install kubernetes
Before starting the services we need to take care of the configuration. Once again make sure the following lines are uncommented and set as shown below.
KUBE_API_ADDRESS="--address=0.0.0.0"
KUBE_API_PORT="--port=8080"
KUBELET_PORT="--kubelet_port=10250"
KUBE_ETCD_SERVERS="--etcd_servers=http://127.0.0.1:2379"
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"
Now we can finally start the kube-apiserver
, kube-controller-manager
and kube-scheduler
.
for SERVICES in kube-apiserver kube-controller-manager kube-scheduler; do
systemctl start $SERVICES
systemctl enable $SERVICES
systemctl status $SERVICES
done
Configure the Flannel network
Before moving away from the master we will create a configuration key in `etcd` defining the flannel network which will be used by the nodes.
etcdctl mk /flannel/network/config '{"Network":"172.17.0.0/16"}'
Setup the node
Disable firewalld
Disable iptables to avoid conflicts with Docker.
systemctl stop firewalld
systemctl disable firewalld
Install ntp
Install the Network Time Protocol to keep the nodes in synch.
yum install ntp
systemctl start ntpd
systemctl enable ntpd
systemctl status ntpd
Install Docker
Install docker. We will start its service later on.
yum install docker
Install Flannel
Install flannel with yum
yum install flannel
Before starting it you need to edit its configuration in /etc/sysconfig/flanneld
. Make sure the following fields are defined.
# Replace `$ETCD_MASTER` with the IP of the master VM.
FLANNEL_ETCD="http://$ETCD_MASTER:2379"
FLANNEL_ETCD_KEY="/flannel/network"
We will start the service later on as well.
Install the Kubernetes components
As for the master, we will use yum
.
yum install kubernetes
We configure the KUBE_MASTER
address in /etc/kubernetes/config
.
# Replace `$KUBE_MASTER` with the IP of your master VM.
KUBE_MASTER="--master=http://$KUBE_MASTER:8080"
We configure the kubelet
in /etc/kubernetes/kubelet
. Make sure to have the following fields uncommented.
KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_PORT="--port=10250"
# Replace $NODE_IP with the IP address of this node
KUBELET_HOSTNAME="--hostname_override=$NODE_IP"
# Replace `$KUBE_MASTER` with the IP of the master VM.
KUBELET_API_SERVER="--api_servers=http://$KUBE_MASTER:8080"
KUBELET_ARGS=""
Finally let’s start all services.
for SERVICES in kube-proxy kubelet docker flanneld; do
systemctl start $SERVICES
systemctl enable $SERVICES
systemctl status $SERVICES
done
Testing the installation while setting up SkyDNS
Check Node(s) state
If the installation went fine, we should be able to see all the nodes we configured as `Ready` from the master.
kubectl get nodes
# Expected output
NAME STATUS AGE
192.168.10.10 Ready 9m
192.168.10.11 Ready 5m
192.168.10.12 Ready 1m
Install Kube-DNS
Kubernetes offers a DNS cluster addon, which assigns DNS names to Services. This is extremely useful because it allows you to develop your application without hardcoding IPs.
Create a file named skydns-svc.yml
with the following content.
apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "KubeDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: 10.254.254.254
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
Now create the Service.
kubectl create -f skydns-svc.yml
kubectl get svc --all-namespaces
# Expected output
NAMESPACE NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes 10.254.0.1 443/TCP 13m
kube-system kube-dns 10.254.254.254 53/UDP,53/TCP 8m
Create a file name skydns-rc.yml
with the following content.
apiVersion: v1
kind: ReplicationController
metadata:
name: kube-dns-v11
namespace: kube-system
labels:
k8s-app: kube-dns
version: v11
kubernetes.io/cluster-service: "true"
spec:
replicas: 1
selector:
k8s-app: kube-dns
version: v11
template:
metadata:
labels:
k8s-app: kube-dns
version: v11
kubernetes.io/cluster-service: "true"
spec:
containers:
- name: etcd
image: gcr.io/google_containers/etcd-amd64:2.2.1
resources:
limits:
cpu: 100m
memory: 500Mi
requests:
cpu: 100m
memory: 50Mi
command:
- /usr/local/bin/etcd
- -data-dir
- /var/etcd/data
- -listen-client-urls
- http://127.0.0.1:2379,http://127.0.0.1:4001
- -advertise-client-urls
- http://127.0.0.1:2379,http://127.0.0.1:4001
- -initial-cluster-token
- skydns-etcd
#volumeMounts:
#- name: etcd-storage
# mountPath: /var/etcd/data
- name: kube2sky
image: gcr.io/google_containers/kube2sky:1.14
command:
- /kube2sky
- --domain=cluster.local
- --kube-master-url=http://192.168.0.20:8080
resources:
limits:
cpu: 100m
memory: 200Mi
requests:
cpu: 100m
memory: 50Mi
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /readiness
port: 8080
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
args:
- --domain=cluster.local
- name: skydns
image: gcr.io/google_containers/skydns:2015-10-13-8c72f8c
resources:
limits:
cpu: 100m
memory: 200Mi
requests:
cpu: 100m
memory: 50Mi
args:
- -machines=http://127.0.0.1:4001
- -addr=0.0.0.0:53
- -ns-rotate=false
- -domain=cluster.local.
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
- name: healthz
image: gcr.io/google_containers/exechealthz:1.0
resources:
limits:
cpu: 10m
memory: 20Mi
requests:
cpu: 10m
memory: 20Mi
args:
- -cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
- -port=8080
ports:
- containerPort: 8080
protocol: TCP
#volumes:
#- name: etcd-storage
# emptyDir: {}
dnsPolicy: Default
Create the replication controller.
kubectl create -f skydns-rc.yml
kubectl get pods --all-namespaces
# Expected output
NAME READY STATUS RESTARTS AGE
kube-dns-v11-tasos 4/4 Running 1 3m
Finally we need to instruct all kubelet
instances (on each node) to make use of the DNS server. Just set the following arguments in the /etc/kubernetes/kubelet
.
KUBELET_ARGS="--cluster-dns=10.254.254.254 --cluster-domain=cluster.local"
Restart the kubelet
on all nodes.
systemctl restart kubelet
Test the DNS server
Create a file busybox.yaml
with the following content.
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
containers:
- image: busybox
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
name: busybox
restartPolicy: Always
Create the pod.
kubectl create -f busybox.yaml
Wait for the pod to be Running
.
kubectl get pods
# Expected output
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 58s
Connect to the pod and perform an nslookup
on the kubernetes
service.
kubectl exec -ti busybox sh
/ # nslookup kubernetes
Server: 10.254.254.254
Address 1: 10.254.254.254
Name: kubernetes
Address 1: 10.254.0.1
Success
Ta-Dah!
Now time for you to explore the power of Kubernetes and Accellerate Your Delivery!