基於Docker運行彈性集羣的五個關鍵點之:運行高可用模式

當前技術世界的發展形勢就是讓開發人員從繁瑣的應用配置和管理中解放出來,使用容器鏡像來處理複雜的程序運行依賴庫的需求,保證代碼運行環境的一致性。既然這樣的好處是如此清晰,但爲何企業中的基礎設施環境沒有往容器集羣切換呢?關鍵問題仍是風險,新技術意味着未經檢驗的技術和實踐經驗的缺少,這就會帶來不少不可預知的風險。前端

當企業的運維團隊去維護一個彈性的容器集羣時,傳統的軟件部署方式須要向容器遷移,這個過程當中須要有風險預判和規避之道。而Docker和Rancher正是提供瞭解決這些風險問題的解決方案,好比基於Rancher的Catalog功能就能快速的完成一些基礎軟件的部署(好比ElasticSearch)。在風險管理方面,咱們能夠看看基於Docker和Rancher來運行彈性集羣的五個關鍵點:java

  1. 運行Rancher高可用模式 (本文將介紹)mysql

  2. Rancher中使用負載均衡服務git

  3. Rancher中的服務監控和監控檢查github

  4. 開發者自定義針對Rancher的安裝部署web

  5. 討論利用Convoy對數據的管理redis

我本來但願展示一下用一臺老式筆記本部署Rancher Server,而後用docker-machine加入幾個樹莓派節點部署Rancher Agent,這樣來構建一個Rancher集羣。可是這樣會有些問題,就是大部分Docker鏡像都是基於Intel CPU構建的,這會和樹莓派的ARM CPU很不兼容。因此我仍是老老實實的用AWS的虛機來構建Rancher集羣吧。sql

初始安裝,咱們暫時先部署一臺Rancher Server和一臺Rancher Agent,而後再部署一個簡單的多實例應用。docker

圖片描述

上面這張圖展示了個人整個集羣的設置,我選擇AWS是由於我我的比較熟悉,固然你徹底能夠選擇你擅長的雲提供商。數據庫

圖片描述

咱們能夠嘗試建立一個Wordpress,順帶來檢測一下Rancher是否正確部署了。

圖片描述

這樣咱們的應用就運行起來了,試想,若是Rancher Server所在服務器出現故障,或者有網絡中斷問題發生,會對應用產生什麼影響,Wordpress還能繼續接受請求麼?

圖片描述

爲了確認咱們的疑問,我將會按照下面的步驟執行,而後記錄一下其中的運行結果:

  1. 阻斷Rancher Server和Rancher Agent間的網絡

  2. 中止Rancher Server的容器

  3. 瞧一瞧Rancher Server的容器裏面到底有什麼

最終咱們要解決這些問題,那就要看看Rancher HA來怎樣解決這些風險。

阻斷Rancher Server和Rancher Agent間的網絡

進入AWS,而後看我各類犀利的操做:

  1. 阻斷Rancher Server和Rancher Agent間的訪問

  2. 記錄一下發生了什麼

  3. 幹掉幾個WordPress的實例

  4. 恢復原先的網絡

觀察結果

首先,網絡阻斷後沒過多久Rancher Host就出現了reconnecting狀態

圖片描述

此時我依然能夠正常訪問Wordpress的地址,服務沒有中斷,IPSec隧道網絡還存儲,Wordpress實例仍是能夠正常訪問數據庫。

如今咱們要停掉一個Wordpress實例,看看會發生什麼?由於咱們已經沒法從Rancher UI上管理這些容器了,因此仍是到對應的主機上執行docker命令吧。

圖片描述

很遺憾Wordpress容器沒有從新啓動,這有點麻煩了。咱們仍是把Rancher Server弄回來吧,看看它能不能感知到其中一個Wordpress容器已經被停掉了。

在各類犀利的操做和等待以後,Rancher Server與Agent從新鏈接了,Wordpress容器就被從新啓動了。完美~

因此咱們能夠看,Rancher Server仍是可以處理間歇性的網絡問題,能夠實現Rancher Server和Agent的故障重連。可是若是要讓網絡中斷對Rancher的影響進一步減少,那麼部署多個Rancher Server就比較重要了。

咱們仍是回過來,按照先前計劃看看Rancher Server 容器停掉後會發生什麼?咱們會所以失去對這些Rancher Host的管理能力麼?看看如何!

停掉Rancher Server

此次我須要登入到Rancher Server的host上手動中止Rancher Server,其實Rancher Server通常是設置 –restart=always,因此本身有必定的恢復能力。但咱們能夠假設好比磁盤寫滿了後,Rancher Server真的起不來了。

觀察結果

執行docker stop rancher-server以後,Wordpress仍是可以正常工做,可是Rancher UI是不能訪問了,這可不行,得趕忙把Rancher Server弄回來。

再執行docker start rancher-server,Rancher Server啓動後又一切恢復正常,這很酷啊,這是什麼魔法?趕忙着,麻溜地分析起來!

揭開Rancher Server的神祕面紗

咱們來一次對Rancher Server的簡要探究之旅,看一看Rancher Server的Dockerfile。

圖片描述

# Dockerfile contents
FROM ...  
...
...
CMD ["/usr/bin/s6-svscan", "/service"]

咱們能夠看到使用了s6-svscan,它能夠運行指定的目錄結構內的程序,目錄內的主要文件就是Run、Down、Finish。下面這張圖能看到會運行兩個服務cattle(Rancher的核心調度器)和mysql。

圖片描述

其實在容器內部咱們也能夠看到起了哪些服務。

PID TTY      STAT   TIME COMMAND
    1 ?        Ss     0:00 /usr/bin/s6-svscan /service
    7 ?        S      0:00 s6-supervise cattle
    8 ?        S      0:00 s6-supervise mysql
    9 ?        Ssl    0:57 java -Xms128m -Xmx1g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/lib/cattle/logs -Dlogback.bootstrap.level=WARN -cp /usr/share/cattle/1792f92ccdd6495127a28e16a685da7
  135 ?        Sl     0:01 websocket-proxy
  141 ?        Sl     0:00 rancher-catalog-service -catalogUrl library=https://github.com/rancher/rancher-catalog.git,community=https://github.com/rancher/community-catalog.git -refreshInterval 300
  142 ?        Sl     0:00 rancher-compose-executor
  143 ?        Sl     0:00 go-machine-service
 1517 ?        Ss     0:00 bash
 1537 ?        R+     0:00 ps x

咱們能夠看到Rancher的大腦,一個名叫Cattle的Java應用,它須要一個MySQL來存儲對應的數據。這確實很方便,可是咱們發現這樣會有單點故障,全部的數據存儲在一個單點的mysql中。若是對mysql中的數據來一些不禮貌的操做,會發生什麼呢?

破壞MySQL存儲數據
進入容器中執行一些MySQL命令,咱們一塊兒來乾點壞事:

docker exec -it rancher-server bash
$ > mysql
mysql> use cattle;
mysql> SET FOREIGN_KEY_CHECKS = 0;
mysql> truncate service;
mysql> truncate network;

結果是可想而知的,Rancher不記得任何事了,你刪掉一個Wordpress容器,它也不會恢復。

圖片描述

並且我也刪除了network表的數據,Wordpress也不知道如何找到它的MySQL服務了。

圖片描述

顯然,若要在生產環境運行Rancher,咱們須要一個方式來保護Rancher Server的數據,既然如此那咱們就講一下Rancher HA吧。

Rancher HA安裝過程

首先咱們要確保數據的安全,我選擇了AWS的RDS服務,RDS能夠提供一個信賴的MySQL服務,數據安全是能夠保證的。固然你也可使用其餘的,我只是對RDS更熟悉一些。

下面咱們繼續Rancher HA的安裝過程:

圖片描述

按照咱們以前的約定,我是建立了RDS的MySQL實例,而後把它當作外部數據庫和Rancher Server鏈接。

圖片描述

圖片描述

一旦咱們使用了外部數據庫模式,UI上將會打開兩個選項來設置HA。

圖片描述

怎麼辦!選擇困難症啊!不要緊,我來解釋一下每一個選項的含義。

Cluster size,注意這裏怎麼都是奇數?由於在後端,Rancher會設置一個ZooKeeper Quorum保證鎖同步,ZooKeeper推薦奇數集羣,由於偶數節點數量不能提供額外的容錯性。咱們這裏就選擇3個Host吧,這是一個可用和易用的平衡。

Host registration URL,這裏是填寫一個Rancher Cluster入口的FQDN,推薦使用外部負載均衡服務或者DNS服務(round robin策略)。好比圖中我使用的是支持SRV記錄的DNS服務,經過DNS來作三個Rancher Server的負載均衡:

圖片描述

SSL Certificates是列表中的最後一個選項,若是你有域名的SSL證書能夠配置在這裏,不然Rancher會自動生成一個自簽名證書。

全部都填完後,就會給你提供一個rancher-ha.sh的腳原本下載。
有了腳本就能夠到每一個Rancher Server節點上執行了,執行前還須要注意目前只能支持docker v1.10.3。安裝指定版本的Docker Engine,能夠參考下面的方式:

#!/bin/bash
apt-get install -y -q apt-transport-https ca-certificates  
apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D  
echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" > /etc/apt/sources.list.d/docker.list  
apt-get update  
apt-get install -y -q docker-engine=1.10.3-0~trusty

# run the command below to show all available versions
# apt-cache showpkg docker-engine

Docker安裝以後,就要確認一下端口開放了,須要開放哪些端口能夠看這裏,不過若是是第一次安裝,我建議你把端口所有開放吧,省得坑太深被活埋。

一切準備穩當以後,能夠執行腳本,執行後能看到這樣的輸出:

...
ed5d8e75b7be: Pull complete  
ed5d8e75b7be: Pull complete  
7ebc9fcbf163: Pull complete  
7ebc9fcbf163: Pull complete  
ffe47ea37862: Pull complete  
ffe47ea37862: Pull complete  
b320962f9dbe: Pull complete  
b320962f9dbe: Pull complete  
Digest: sha256:aff7c52e52a80188729c860736332ef8c00d028a88ee0eac24c85015cb0e26a7  
Status: Downloaded newer image for rancher/server:latest  
Started container rancher-ha c41f0fb7c356a242c7fbdd61d196095c358e7ca84b19a66ea33416ef77d98511  
Run the below to see the logs

docker logs -f rancher-ha

執行過程當中會下載一些額外的鏡像,畢竟要支持HA特性麼。另外Host的內存建議至少4G,執行完畢後經過docker ps能夠看看都啓動了什麼:

圖片描述

常見的問題和解決方案

正常來講,通常咱們會在日誌中能看到各個成員加入到Rancher HA Cluster中:

time="2016-07-22T04:13:22Z" level=info msg="Cluster changed, index=0, members=[172.30.0.209, 172.30.0.111, ]" component=service  
...
time="2016-07-22T04:13:34Z" level=info msg="Cluster changed, index=3, members=[172.30.0.209, 172.30.0.111, 172.30.0.69]" component=service

但有時候會有意外,好比會看到一些error信息:

time="2016-07-23T14:37:02Z" level=info msg="Waiting for server to be available" component=cert  
time="2016-07-23T14:37:02Z" level=info msg="Can not launch agent right now: Server not available at http://172.17.0.1:18080/ping:" component=service

這個問題產生的背後緣由有不少,我閱讀了一些Github上的issue和各類論壇的帖子,幫你們整理了一些產生此問題的根本緣由。

網絡設置問題

有時候容器自動獲取了節點的錯誤的IP,這時候你須要強制指定正確的IP。

ZooKeeper沒有正常啓動

Zookeeper的容器是分佈在每一個節點上的,若是節點之間的問題致使Zookeeper容器不能通訊,就會致使這個問題,若是要確認這個問題,能夠參考這樣的日誌輸出。

目錄/var/lib/rancher/state下有殘留文件

若是屢次運行Rancher-ha.sh這個腳本,那麼你須要運行前清理一下這個目錄下殘留文件。

屢次嘗試後HA狀態被破壞

刪庫重試,重啓大法好。

機器資源不足

內存至少須要4GB,此外mysql的鏈接數也要足夠,能夠按照每一個HA節點須要50個鏈接數來計算。若是你看到下面的錯誤,那麼此問題確信無疑。

time="2016-07-25T11:01:02Z" level=fatal msg="Failed to create manager" err="Error 1040: Too many connections"

rancher/server版本不匹配

rancher-ha.sh執行的時候默認是下載rancher/server:latest鏡像,若是你沒有host上的鏡像不一致會致使不可思議的問題,最好執行的時候指定版本號。好比:

./rancher-ha.sh rancher/server:

docker0返回了錯誤的IP

這個錯誤具體就是在HA的安裝過程當中會去檢查agent健康狀態,此時它獲取了一個錯誤的docker0 IP地址,由於我先前已經將其設置成了172.17.42.1。

curl localhost:18080/ping
> pong
curl http://172.17.0.1:18080/ping
> curl: (7) Failed to connect to 172.17.0.1 port 18080: Connection refused

個人解決辦法就是重裝了個人AWS虛機,致使獲取docker0 IP錯誤的緣由,我感受多是我在虛機裏屢次安裝了Docker。重裝以後,一切就正常了,我也看到了期待的日誌信息。

HA部署完畢後

咱們終於看到了求之不得的正確日誌輸出,和美好的UI展示:

time="2016-07-24T20:00:11Z" level=info msg="[0/10] [zookeeper]: Starting "  
time="2016-07-24T20:00:12Z" level=info msg="[1/10] [zookeeper]: Started "  
time="2016-07-24T20:00:12Z" level=info msg="[1/10] [tunnel]: Starting "  
time="2016-07-24T20:00:13Z" level=info msg="[2/10] [tunnel]: Started "  
time="2016-07-24T20:00:13Z" level=info msg="[2/10] [redis]: Starting "  
time="2016-07-24T20:00:14Z" level=info msg="[3/10] [redis]: Started "  
time="2016-07-24T20:00:14Z" level=info msg="[3/10] [cattle]: Starting "  
time="2016-07-24T20:00:15Z" level=info msg="[4/10] [cattle]: Started "  
time="2016-07-24T20:00:15Z" level=info msg="[4/10] [go-machine-service]: Starting "  
time="2016-07-24T20:00:15Z" level=info msg="[4/10] [websocket-proxy]: Starting "  
time="2016-07-24T20:00:15Z" level=info msg="[4/10] [rancher-compose-executor]: Starting "  
time="2016-07-24T20:00:15Z" level=info msg="[4/10] [websocket-proxy-ssl]: Starting "  
time="2016-07-24T20:00:16Z" level=info msg="[5/10] [websocket-proxy]: Started "  
time="2016-07-24T20:00:16Z" level=info msg="[5/10] [load-balancer]: Starting "  
time="2016-07-24T20:00:16Z" level=info msg="[6/10] [rancher-compose-executor]: Started "  
time="2016-07-24T20:00:16Z" level=info msg="[7/10] [go-machine-service]: Started "  
time="2016-07-24T20:00:16Z" level=info msg="[8/10] [websocket-proxy-ssl]: Started "  
time="2016-07-24T20:00:16Z" level=info msg="[8/10] [load-balancer-swarm]: Starting "  
time="2016-07-24T20:00:17Z" level=info msg="[9/10] [load-balancer-swarm]: Started "  
time="2016-07-24T20:00:18Z" level=info msg="[10/10] [load-balancer]: Started "  
time="2016-07-24T20:00:18Z" level=info msg="Done launching management stack" component=service  
time="2016-07-24T20:00:18Z" level=info msg="You can access the site at https://" component=service

圖片描述

若是使用了自簽名證書且前端但願經過HTTPS來訪問,那麼你須要把你的證書添加到你的受信任證書中。而後再等待數據庫資源約束調整完畢後,三個節點的服務就徹底運行起來了。

結論

這比原來想象的要多了不少。這就是爲何分佈式系統一直是PHD的研究領域。解決全部的故障點後,我認爲Rancher HA已經開始向頂尖分佈式系統出發啦。

我最終會將Rancher HA的腳本配置成Ansible的一個簡單任務,敬請關注!

附錄

對於任何分佈式系統來講,基本的套路就是統一管理其中產生的狀態和變化,這意味着多個服務須要一個進程來協調更新。

Rancher的處理方式就是把狀態都放倒數據庫中,須要同步狀態時把狀態信息放入到event中,發送event就能夠向其餘組件同步狀態。因此當正在處理一個事件時,它有一個鎖,事件未處理完前數據庫中的狀態是不能被修改的。

在單臺服務器設置中,全部的協調都發生在主機上的內存中。一旦你涉及多服務器HA配置,像zookeeper和redis是必要的。


報名11.6成都Docker技術沙龍
圖片描述

相關文章
相關標籤/搜索