Kubernetes Master High Availability 高級實踐

才雲科技雲開源高級工程師唐繼元受邀DBAplus社羣,在線分享《Kubernetes Master High Availability 高級實踐》,介紹如何構建Kubernetes Master High Availability環境。node

如下是分享實錄:git

你們好,我是才雲科技的唐繼元,今天給你們帶來一篇技術分享,本次分享我將爲你們介紹如何構建Kubernetes Master High Availability環境。這次分享內容是我在工做中經驗總結,若是有不正確的或者須要改進的地方,歡迎各位大神指正。
相信你們對容器、docker和kubernetes這些概念並不陌生。下面進入本次分享的正題。
Kubernetes做爲容器編排管理系統,經過Scheduler、ReplicationController等組件實現了應用層的高可用,可是針對Kubernetes集羣,還須要實現Master組件的高可用。
本次分享論述的Master高可用方案主要基於社區的高可用方案(連接)的實踐,可是社區的高可用方案中採用的GCE的External Loadbalancer,並未論述如何實現External Loadbalancer,並且也並無將Kubernetes集羣組件容器化。因此,咱們的高可用方案在社區高可用方案的基礎之上進行了以下兩個方面的提高:github

第一,除了kubelet以外,Kubernetes全部組件容器化;
第二,經過haproxy和keepalived構建Loadbalancer實現Master的高可用。
下面咱們分四個章節來詳細論述Kubernetes Master High Availability環境的搭建。web

  1. HA Master總體架構docker

  2. 核心技術點和難點後端

  3. 實踐中的遇到的那些坑api

  4. 社區關於HA Master的將來發展服務器

HA Master總體架構

咱們已經成功將支持Master High Availability的Kubernetes集羣部署到企業私有云平臺,底層採用的是Ubuntu 14.04操做系統。下面是一個典型的部署環境:網絡

clipboard.png

Static Pods是由其所在節點上的kubelet直接管理,而不須要經過Apiserver來監視它們。Static Pods的資源類型只能是Pod,並且不與任何的Replication Controller相關聯,它們徹底由kubelet來監視,而且當它們異常中止的時候由該kubelet負責重啓它們。架構

(haproxy, keepalived):這裏表示咱們將haproxy和keepalived放置在同一個pod中。

1.1.kubelet對static pod高可用的支持

咱們須要爲kubelet進程配置一個manifests監視目錄:

--config=/etc/kubernetes/manifests

若是有新的yaml/manifest文件添加到該目錄,kubelet則根據yaml/manifest文件建立一個新的static pod;

若是咱們把某個yaml/manifest文件從該目錄刪除,kubelet則會刪除由該yaml/manifest文件所產生的static pod;

若是該目錄下的yaml/manifest文件有更新,kubelet則會刪除原來的static pod,而根據更新後的yaml/manifest文件從新建立一個新的static pod;

若是manifests目錄下的文件沒有任何變化,可是其下某個yaml/manifest文件所產生的static pod錯誤退出或者被誤刪後,kubelet仍然會根據該yaml/manifest文件從新建立一個新的static pod。

這樣,kubelet在必定程度上保證了static pod的高可用。

1.2.kubelet進程的高可用

kubelet經過manifests監視目錄保證了staticpod的高可用,可是若是kubelet進程自己錯誤退出或者被誤刪後,誰來負責從新啓動kubelet進程呢?

在Linux系統中,咱們能夠經過Monit、Upstart、Systemd、Supervisor等工具實現對服務的監控保證服務的高可用。

在Ubuntu 14.04操做系統中,咱們將kubelet作成系統服務,利用Upstart來保證kubelet服務的高可用,下面是kubelet服務基於Upstart的服務啓動腳本/etc/init/kubelet.conf:

clipboard.png

其中:
respawn: 該命令設置服務或任務異常中止時將自動啓動。除stop命令外的中止都是異常中止。
respawn limit: 該命令設置服務或任務異常中止後重啓次數和間隔時間。

1.3.Master High Availability Kubernetes總體架構圖

從架構圖中咱們能夠看到:
1) Upstart保證docker服務和kubelet服務的高可用,而Kubernetes的其餘組件將以staticpod的方式由kubelet保證高可用。
2)兩臺lb節點經過haproxy和keepalived構建出一個ExternalLoadbalancer,並提供VIP供客戶端訪問。
3) Haproxy配置成「SSLTermination」方式,外網client經過HTTPS請求訪問集羣,而內網client則能夠經過HTTPS/HTTP請求訪問。
4) Kubernetes高可用集羣經過flannelstatic pod構建一個Overlay網絡,使集羣中的docker容器可以經過Kubernetes Cluster IP進行通訊。

核心技術點和難點

2.1.運行在特權模式的組件
Kubernetes集羣中的一些組件須要經過內核模塊來爲集羣提供服務,所以這些組件須要運行在特權模式下,以便能訪問相應的內核模塊。

2.1.1.開啓特權模式
爲了支持docker容器在特權模式下運行,咱們須要開啓Kubernetes集羣的特權模式權限:

--allow-privileged=true

這裏主要體如今kubelet服務和apiserver服務。
1) Kubelet service
kubelet服務須要開啓特權模式權限,以便容許docker容器向kubelet請求以特權模式運行。
2) Apiserver static pod
apiserver static pod須要開啓特權模式權限,以便運行在特權模式下的docker容器可以訪問apiserver服務。

2.1.2.運行在特權模式下的docker容器
運行在特權模式下的docker容器,在yaml文件中須要添加以下字段:

securityContext:
     privileged: true

這裏主要體如今kubeproxy服務、flannel服務和keepalived服務。
1) Kubeproxy static pod
kubeproxy須要經過Iptables設置防火牆規則。
2) Flannel static pod
flannel須要訪問vxlan、openvswitch等路由數據報文。
3) Keepalived static pod
keepalived須要訪問IP_VS內核模塊來創建VIP。

2.2.Static pod必須運行在主機網絡下
如上所述的這些以static pod形式存在的Kubernetes集羣組件,必須工做在主機網絡下:

hostNetwork: true

雖然Overlay網絡是爲了讓不一樣節點間的docker容器進行通訊,而上述以staticpod形式存在的組件也都是docker容器,可是它們之間的心跳和信息交流都須要經過主機網絡而不是相似於flannel等的Overlay網絡。理由以下:
1)這些static pods不一樣於應用的pods,它們的穩定保障了Kubernetes集羣的穩定性,它們之間的心跳和信息交流都是經過它們配置文件中的靜態IP地址進行的,而docker/flannel網絡是動態的,咱們沒法保證docker/flannel網絡中IP地址的穩定性,同時也沒法事先知道IP地址。
2) kubeproxy、flannel、haproxy須要經過主機網絡修改路由規則,從而使主機上的服務能被其餘主機訪問。
3) haproxy須要將外網請求重定向到內網後端服務器上,也必須須要主機網絡。

2.3.External Loadbalancer部署要點
對於如何配置haproxy和keepalived,網絡上有很是多的資源,因此這裏不在論述。下面咱們來分析一下部署過程當中的一些要點。
External Loadbalancer由至少兩臺lb node組成,經過haproxy和keepalived pod實現Master的負載均衡,對外提供統一的VIP。
咱們能夠將haproxy和keepalived分別放置在不一樣的pod中,也能夠將它們放置在同一個pod中。考慮到keepalived須要監測haproxy的狀態,咱們會把haproxy和keepalived放在一塊兒作成一個loadbalancerpod。

2.3.1.lb node配置
1)使能內核IPVS模塊
因爲keepalived須要經過IPVS模塊實現路由轉發,因此咱們須要使能內核IPVS模塊。
從Linux內核版本2.6起,ip_vs code已經被整合進了內核中,所以,只要在編譯內核的時候選擇了ipvs的功能,Linux即能支持LVS。所以咱們只須要配置操做系統啓動時自動加載IPVS模塊:

echo "ip_vs" >> /etc/modules
echo "ip_vs_rr" >> /etc/modules
echo "ip_vs_wrr" >> /etc/modules

咱們能夠經過以下命令查看ip_vs模塊是否成功加載:

lsmod | grep ip_vs

若是沒有加載,咱們能夠經過modprobe命令加載該模塊:

modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr

2)修改內核參數
爲了使keepalived將數據包轉發到真實的後端服務器,每個lb node都須要開啓IP轉發功能

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf

另外,keepalived設置的VIP有可能爲非本地IP地址,因此咱們還須要使能非本地IP地址綁定功能:

echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf

2.3.2.keepalived監測haproxy狀態的方法
對於普通進程來講, keepalived進程能夠經過「killall -0 haproxy」命令檢測haproxy進程是否正常運行(注: Sending the signal 0 to a given PID just checksif any process with the given PID is running)。
然而在docker容器環境下,各容器都有本身的PidNamespace和NetworkNamespace,咱們就須要開啓haproxy的健康檢查頁面,而後keepalived經過健康檢查頁面的URL來檢測haproxy目前是否正常運行。
haproxy健康檢查頁面配置:

listen  admin_stats
       bind  0.0.0.0:80
       log  global
       mode  http
       maxconn  10
       stats  enable
       #Hide  HAPRoxy version, a necessity for any public-facing site
       stats  hide-version
       stats  refresh 30s
       stats  show-node
       stats  realm Haproxy\ Statistics
       stats  auth caicloud:caicloud
       stats  uri /haproxy?stats

keepalived對haproxy的狀態檢測:

vrrp_script check_script {
 script  "/etc/keepalived/check_haproxy.py  http://caicloud:caicloud@127.0.0.1/haproxy?stats"
 interval 5 # check every 5 seconds
 weight 5
 fall 2 # require 2 fail for KO
 rise 1 # require 1 successes for OK
}

2.3.3.haproxy SSL配置
haproxy代理ssl配置有兩種方式:
1) haproxy自己提供SSL證書,後面的web服務器走正常的http協議;
2) haproxy自己只提供代理,直接轉發client端的HTTPS請求到後端的web服務器。注意:這種模式下「mode」必須是「tcp」模式, 即僅支持4層代理。
考慮到:第一,用戶親和性訪問須要7層代理的支持;第二,loadbalancer和master走的都是集羣內網。因此本實踐採用了第一種方式,配置以下:

frontend frontend-apiserver-https
        #  Haproxy enable SSL
        bind  *:443 ssl crt /etc/kubernetes/master-loadblancer.pem
        option  forwardfor
        default_backend  backend-apiserver-http

2.3.4.haproxy配置:haproxy.cfg

clipboard.png
clipboard.png

2.3.5.keepalived配置:keepalived.conf
1) lb-1上keepalived配置

clipboard.png
clipboard.png

2) lb-2上keepalived配置
lb-2跟lb-1的配置差很少,除了下面兩個字段:

state BACKUP
 priority 97

2.4.flannel網絡設置
2.4.1Master節點flannel網絡設置
對於Master節點,須要等待Etcd Pod集羣啓動完後,先在Master上建立Flannel網絡,而後Flannel Pod客戶端才能夠從Etcd中獲取到各個Master節點的IP網段,獲取到IP網段後會在主機上產生文件:「/var/run/flannel/subnet.env」,而後根據該文件修改docker啓動參數:

.  /var/run/flannel/subnet.env 
DOCKER_OPTS="$DOCKER_OPTS  --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU}"

並重啓docker服務。

2.4.2非Master節點flannel網絡設置
對於非Master節點,待Loadbalancer起來以後,Node節點可以訪問Apiserver以後,Flannel Pod客戶端才能從Etcd獲取到該Node節點的IP網段,而且一樣會在主機上產生文件:「/var/run/flannel/subnet.env」。而後修改docker啓動參數,並重啓docker服務。

3.實踐中的遇到的那些坑

3.1.官網「haproxy docker image」的坑
Docker Hub上「haproxy image」的「docker-entrypoint.sh」內容以下:

clipboard.png

問題就出在「haproxy-systemd-wrapper」。若是運行命令:「haproxy -f/etc/haproxy/haproxy.cfg」, 而實際上運行的是通過「haproxy-systemd-wrapper」包裝後的命令:

clipboard.png

執行命令「haproxy -f /etc/haproxy/haproxy.cfg」時,真正執行的是:「/usr/local/sbin/haproxy -p /run/haproxy.pid -f /etc/haproxy/haproxy.cfg -Ds」,對於「-Ds」選項, 官網是這麼描述的:

clipboard.png

原來,「haproxy」通過「haproxy-systemd-wrapper」包裝後在後臺執行,而docker container不容許進程後臺執行,不然docker容器將該啓動命令執行完後就退出了。官網image的這個坑很大。
因此,當咱們用官網「haproxy image」的時候,就須要用haproxy的徹底路徑來執行。好比在yaml文件中:

clipboard.png

3.2.haproxy container exited with 137
首先137退出碼錶示,其餘進程向haproxy container發起了「kill」信號,致使haproxy container退出,容器日誌以下

[WARNING] 155/053036 (1) : Setting tune.ssl.default-dh-param to 1024 by  default, if your workload permits it you should set it to at least 2048.  Please set a value >= 1024 to make this warning disappear.

其次,當經過「docker run」命令執行haproxy container,使用的命令與yaml文件中的同樣,並且照樣輸出上述的「WARNING」,可是容器卻不退出。

而後,無奈之下,我試着先將這個「WARNING」解決:這個錯誤是因爲haproxy.cfg中添加了SSL證書致使的, 能夠經過設置參數「default-dh-param」解決:

global
       ...
       # turn  on stats unix socket
       stats  socket /run/haproxy.stats
       tune.ssl.default-dh-param  2048
frontend frontend-apiserver-https
       #  Haproxy enable SSL
       bind  *:443 ssl crt /etc/kubernetes/master-loadbalancer.pem
       ...

當我解決這個「WARNING」以後,奇蹟出現了,haproxy container奇蹟般的正常運行了。原來在容器的世界,一個「WARNING」也不能疏忽。

社區關於HA Master的將來發展

熟悉kubelet配置參數的都知道,咱們在給kubelet配置apiserver的時候,能夠經過「--api-servers」指定多個:

--api-servers=http://m1b:8080,http://m1c:8080,http://m2a:8080,http://m2b:8080,http://m2c:8080

這看起來彷佛已經作到apiserver的高可用配置了,可是實際上當第一個apiserver掛掉以後, 不能成功的鏈接到後面的apiserver,也就是說目前仍然只有第一個apiserver起做用。
若是上述問題解決以後, 彷佛不須要額外的loadbalancer也能實現master的高可用了,可是,除了kubelet須要配置apiserver,controllermanager和scheduler都須要配置apiserver,目前咱們還只能經過「--master」配置一個apiserver,沒法支持多個apiserver。
社區後續打算支持multi-master配置,實現Kubernetes Master的高可用,並且計劃在Kubernetes 1.4版本中合入。
即便未來社區實現了經過multi-master配置的高可用方式,本次分享的MasterHigh Availability仍然很是有意義,由於在私有云場景中,ExternalLoadbalancer除了實現Master的高可用和負載均衡外,還能夠針對Worker Node實現Nodeport請求的負載均衡,從而不只實現了應用的高可用訪問,同時也大大提升了應用的訪問速度和性能。
參考連接:
連接
連接好了,以上是本次分享的全部內容,歡迎你們批評指正,同時也但願能爲你們帶來些收益。

相關文章
相關標籤/搜索