Kubernetes - High Availability
Learn how to create high availability Kubernetes cluster
Table of Contents
- Please checkout previous installation tutorial to make sure that nothing lost
Kubernetes use etcd as backend storage to keep cluster information. If we want to have a high availability of Kubernetes cluster, we need to set up etcd cluster as our reliable distributed key-value storage. Once we setup the etcd cluster, it will help us to populate data to whole etcd cluster.
service etcd stop
sudo /opt/bin/etcd --name <node name> -data-dir <path to etcd data dir> \
--initial-advertise-peer-urls http://<node ip>:4000 \
--listen-peer-urls http://<node ip>:4000 \
--listen-client-urls http://127.0.0.1:4001,http://<node ip>:4001 \
--advertise-client-urls http://<node ip>:4001 \
--initial-cluster-token etcd-cluster-1 \
--initial-cluster <node1 name>=http://<node1 ip>:4000,<node2 name>=http://<node2 ip>:4000,<node3 name>=http://<node3 ip>:4000 \
--initial-cluster-state new
- Example:
- infra0: 10.211.55.14
- infra1: 10.211.55.15
- infra2: 10.211.55.16
# infra0
sudo /opt/bin/etcd --name infra0 -data-dir /opt/etcd --initial-advertise-peer-urls http://10.211.55.14:4000 --listen-peer-urls http://10.211.55.14:4000 --listen-client-urls http://127.0.0.1:4001,http://10.211.55.14:4001 --advertise-client-urls http://10.211.55.14:4001 --initial-cluster-token etcd-cluster-1 --initial-cluster infra0=http://10.211.55.14:4000,infra1=http://10.211.55.15:4000,infra2=http://10.211.55.16:4000 --initial-cluster-state new
# infra1
sudo /opt/bin/etcd --name infra1 -data-dir /opt/etcd --initial-advertise-peer-urls http://10.211.55.15:4000 --listen-peer-urls http://10.211.55.15:4000 --listen-client-urls http://127.0.0.1:4001,http://10.211.55.15:4001 --advertise-client-urls http://10.211.55.15:4001 --initial-cluster-token etcd-cluster-1 --initial-cluster infra0=http://10.211.55.14:4000,infra1=http://10.211.55.15:4000,infra2=http://10.211.55.16:4000 --initial-cluster-state new
# infra2
sudo /opt/bin/etcd --name infra2 -data-dir /opt/etcd --initial-advertise-peer-urls http://10.211.55.16:4000 --listen-peer-urls http://10.211.55.16:4000 --listen-client-urls http://127.0.0.1:4001,http://10.211.55.16:4001 --advertise-client-urls http://10.211.55.16:4001 --initial-cluster-token etcd-cluster-1 --initial-cluster infra0=http://10.211.55.14:4000,infra1=http://10.211.55.15:4000,infra2=http://10.211.55.16:4000 --initial-cluster-state new
Once we create etcd cluster, we can use etcdctl ls
to checkout current config in etcd
$ etcdctl ls
/registry
Flannel is a backend overlay network for Kubernetes and it uses etcd as config storage. After create the etcd cluster, we need to generate the config for flannel.
- rebuild flannel config entry
Go to each node and execute following command
# following command can be find at kubernetes/cluster/ubuntu/util.sh
# it will rebuild flannel network config entry
FLANNEL_NET="172.16.0.0/16" KUBE_CONFIG_FILE="config-default.sh" DOCKER_OPTS="" ~/kube/reconfDocker.sh ai
and now /coreos.com/network/subnets
should contains all nodes network interface information
$ etcdctl ls /coreos.com/network/subnets
/coreos.com/network/subnets/172.16.92.0-24
/coreos.com/network/subnets/172.16.80.0-24
/coreos.com/network/subnets/172.16.2.0-24
$ etcdctl get /coreos.com/network/subnets/172.16.2.0-24
{"PublicIP":"10.211.55.15","BackendType":"vxlan","BackendData":{"VtepMAC":"22:f2:fc:58:41:72"}}
To enable Kubernetes high availability, we need to copy the binaries kube-apiserver
, kube-controller-manager
, kube-scheduler
to each node we want it to be the master and launch.
/etc/default/kube-apiserver
KUBE_APISERVER_OPTS=" --apiserver-count=<number of apiserver> --insecure-bind-address=0.0.0.0 --insecure-port=8080 --etcd-servers=http://127.0.0.1:4001 --logtostderr=true --service-cluster-ip-range=192.168.3.0/24 --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,SecurityContextDeny,ResourceQuota --service-node-port-range=30000-32767 --advertise-address=<node ip, e.g 10.211.55.14> --client-ca-file=/srv/kubernetes/ca.crt --tls-cert-file=/srv/kubernetes/server.cert --tls-private-key-file=/srv/kubernetes/server.key"
/etc/default/kube-controller-manager
KUBE_CONTROLLER_MANAGER_OPTS=" --master=127.0.0.1:8080 --root-ca-file=/srv/kubernetes/ca.crt --service-account-private-key-file=/srv/kubernetes/server.key --v=2 --leader-elect=true --logtostderr=true"
/etc/default/kube-scheduler
KUBE_SCHEDULER_OPTS=" --logtostderr=true --master=127.0.0.1:8080 --v=2 --leader-elect=true"
At previouse step, we launch multiple kube-apiserver
, however, we may encounter the single point of failure because there is still only one api server in config. Now, we gonna use Pound to set up an local api proxy that points to multiple api servers so that we can escape from SPOF.
Kubernetes use a new RESTful method PATCH
that only supported by Pound 2.7
, we need to install 2.7 or higher on all nodes in the cluster.
- For Ubuntu 16.04+
$ sudo apt-get install pound
- For Ubuntu 14.04
Please go to the Pound official site to download the 2.7.tar.gz and compile it.
$ wget http://www.apsis.ch/pound/Pound-2.7.tgz
$ tar -zxvf Pound-2.7.tgz
$ cd Pound-2.7
$ configure && make
or download from here if you trust me. lol
$ wget https://tachingchen.com/2016/07/15/Kubernetes-High-Availability/pound-bin.tar
- change backend ip and port in
/etc/pound/pound.cfg
User "www-data"
Group "www-data"
LogLevel 1
## check backend every X secs:
Alive 1
## use hardware-accelleration card supported by openssl(1):
#SSLEngine "<hw>"
# poundctl control socket
Control "/var/run/pound/poundctl.socket"
ListenHTTP
Address 0.0.0.0
Port 8080
xHTTP 1
Service
BackEnd
Address x.x.x.x
Port 8081
End
BackEnd
Address y.y.y.y
Port 8081
End
BackEnd
Address z.z.z.z
Port 8081
End
End
End
- upstart script for manual installation
/etc/init.d/pound
#! /bin/sh
### BEGIN INIT INFO
# Provides: pound
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Should-Start: $named
# Should-Stop: $named
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: reverse proxy and load balancer
# Description: reverse proxy, load balancer and
# HTTPS front-end for Web servers
### END INIT INFO
#
# pound - reverse proxy, load-balancer and https front-end for web-servers
PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/pound
DESC="reverse proxy and load balancer"
NAME=pound
# Exit if the daemon does not exist (anymore)
test -f $DAEMON || exit 0
. /lib/lsb/init-functions
# Check if pound is configured or not
if [ -f "/etc/default/pound" ]
then
. /etc/default/pound
if [ "$startup" != "1" ]
then
log_warning_msg "$NAME will not start unconfigured."
log_warning_msg "Please configure; afterwards, set startup=1 in /etc/default/pound."
exit 0
fi
else
log_failure_msg "/etc/default/pound not found"
exit 1
fi
# The real work of an init script
case "$1" in
start)
log_daemon_msg "Starting $DESC" "$NAME"
if [ ! -d "/var/run/pound" ]
then
mkdir -p /var/run/pound
fi
start_daemon $DAEMON $POUND_ARGS
log_end_msg $?
;;
stop)
log_daemon_msg "Stopping $DESC" "$NAME"
killproc $DAEMON
log_end_msg $?
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
killproc $DAEMON
start_daemon $DAEMON $POUND_ARGS
echo "."
;;
status)
pidofproc $DAEMON >/dev/null
status=$?
if [ $status -eq 0 ]; then
log_success_msg "$NAME is running"
else
log_success_msg "$NAME is not running"
fi
exit $status
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload|status}"
exit 1
;;
esac
# Fallthrough if work done.
exit 0
- Change default port
8080
to8081
in/etc/default/kube-apiserver
--insecure-port=8081
restart related Kubernetes components
sudo service kube-apiserver restart
sudo service kube-controller-manager restart
sudo service kubelet restart
sudo service kube-proxy restart
sudo service kube-scheduler restart
sudo service pound restart
You will encounter such situation when you try to execute kubectl exec
$ kubectl exec -it <pod> bash
error: Timeout occured
It’s because Kubernetes use SPDY, which is not supported by Pound yet, as underlying communication protocol to connect to the node that container runs on, so you need to use following command instead:
- ip: api server ip
- port: api server port not proxy port
$ kubectl -s <ip>:<port> exec -it <pod> bash
$ kubectl -s 127.0.0.1:8081 exec -it <pod> bash
- http://kubernetes.io/docs/admin/high-availability/
- https://coreos.com/etcd/docs/latest/clustering.html
- http://www.apsis.ch/pound/
See Also
- Kubernetes - Two Steps Installation
- Kubernetes - Installation
- Rolling Updates with Kubernetes Deployments
- Kubernetes - Pod
- Adopting Container and Kubernetes in Production
To reproduce, republish or re-use the content,
please attach with link: https://tachingchen.com/
Twitter
Google+
Facebook
Reddit
LinkedIn
StumbleUpon
Pinterest
Email