打造高可用 Kubernetes 集群
學習如何在裸機上建立高可用 Kubernetes 集群

文章目錄
- 請參照先前的安裝教學確保沒有任何東西遺漏。
 
Kubernetes 仰賴 etcd 來儲存整個集群的相關資訊,若要建立一個完整的 Kubernetes 集群,我們勢必要先從 etcd 集群開始著手來建立可靠的高可用的 key-value 儲存空間,而一旦 etcd 集群建立後,其內部機制回會自動把儲存的資料同步至其他的 etcd 節點。
service etcd stop
首先將 etcd 執行檔複製到各節點上並執行它們。
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
etcd 集群建立後,可以透過 etcdctl ls 來查看目前儲存的設定
$ etcdctl ls
/registry
Flannel 可以在不同節點間建立所謂的 overlay network,讓 Kubernetes 的 Pod 可以在多個節點間互相溝通傳輸。由於 Flannel 透過 etcd 來儲存自身相關的網路設定,因此在建立 etcd 集群後我們必須重建整個 Flannel 的網路來確保網路的暢通。
- 重建 flannel 設定
 
首先我們到各節點上,執行下面的指令
# 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
執行後 /coreos.com/network/subnets 會出現各節點的網路相關資訊,透過這些資訊 Flannel 才能讓封包在 Kubernetes 之間相互傳輸。
$ 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"}}
接下來我們需要將 kube-apiserver、kube-controller-manager、kube-scheduler 的執行檔複製到各個我們希望當作主節點的機器上並執行。
/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"
在前述的步驟中儘管我們執行多個 kube-apiserver服務,但由於在其他服務設定檔中仍只能設定單一個 api 端點位址,因此我們仍有機會遇到單節點故障 (single point of failure) 的問題。所以我們必須在每個節點執行 Pound 當作本地端的 api 代理來連線到多個 api 端點,確保任意端點出現異常時服務仍能夠正常執行。
由於 Kubernetes 底層溝通會需要 RESTful 的 PATCH,因此我們需要安裝 Pound 2.7+ 的版本來確保功能正常。
- Ubuntu 16.04+
 
$ sudo apt-get install pound
- Ubuntu 14.04
 
從 Pound 官方網站 下載 2.7.tar.gz 來編譯
$ wget http://www.apsis.ch/pound/Pound-2.7.tgz
$ tar -zxvf Pound-2.7.tgz
$ cd Pound-2.7
$ configure && make
- 修改 
/etc/pound/pound.cfg中的 backend ip 及 port - 自行編譯者須自行建立該檔案
 
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 腳本 
/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
- 將 
/etc/default/kube-apiserver內的預設 Port 從8080改成8081 
--insecure-port=8081
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
當我們使用 kubectl exec 會發生以下的情況
$ kubectl exec -it <pod> bash
error: Timeout occured
原因在於 Kubernetes 使用 SPDY 建立連線到該 Pod 所在的節點,而目前 Pound 尚未支持 SPDY,因此必須用下述指令取代
- ip: api 端點 ip
 - port: api 端點 port 而不是本地代理的 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/
 
相關文章
- Kubernetes 兩步安裝一次上手
 - Kubernetes Service 深度剖析 - 標籤對於 Service 的影響
 - 從 Google Kubernetes Engine 移除節點
 - Kubernetes Service 深度剖析 - 存取路徑差異
 - Kubernetes Service 概念詳解
 
文章內容的轉載、重製、發佈,請註明出處: https://tachingchen.com/tw/
Twitter
Google+
Facebook
Reddit
LinkedIn
StumbleUpon
Pinterest
Email