1. 程式人生 > >docker實戰2 (docker swarm的應用,docker叢集的構建,在docker叢集中部署服務的建立與更新)

docker實戰2 (docker swarm的應用,docker叢集的構建,在docker叢集中部署服務的建立與更新)

前言:

在之前曾寫過一個關於docker叢集建立的教程,但是不夠深入,只是停留到叢集的初始化和節點加入上,這次具體到服務,並詳細講解其中的原理。而且總結了很多自己做的過程中所踩過的很多坑(比如映象的digest問題)。在查閱資料的過程還了解到了谷歌的kubernetes和swarm是一個類似的東西,準備在之後開一篇入門的坑,畢竟谷歌的東西還是很有意思的。

叢集拓撲:

這裡寫圖片描述
Linux版本:Red Hat Enterprise Linux Server release 7.3 (Maipo
docker版本:

Client:
 Version:      17.03.0-ce
 API version
: 1.26 Go version: go1.7.5 Git commit: 3a232c8 Built: Tue Feb 28 08:10:07 2017 OS/Arch: linux/amd64 Server: Version: 17.03.0-ce API version: 1.26 (minimum version 1.12) Go version: go1.7.5 Git commit: 3a232c8 Built: Tue Feb 28 08:10:07 2017 OS/Arch: linux/amd64 Experimental: false

一.建立docker swarm叢集

官方文件中對應的部分:docker swarm官方
這一部是關於docker這個服務的叢集,並不是我們容器所涉及服務的叢集

docker swarm init --advertise-addr 172.25.3.250

只用這條命令就可以建立以172.25.3.250為manager的docker叢集,–advertise-addr不是必須的,但是當你的計算機上有多個網絡卡時候就要指定了。

docker swarm join --token ***** ip:2377

別的機器想要加入這個docker叢集使用上面的命令就可以了。

[
[email protected]
~]# docker swarm join-token worker To add a worker to this swarm, run the following command: docker swarm join \ --token SWMTKN-1-4jlxqqc9jg39a7ll5npktriayhnk040vuunhcwj2h6ntvcy3j0-3x6za4vgrabq5ydivyxvd6kma \ 172.25.3.250:2377 [[email protected] ~]# docker swarm join-token manager To add a manager to this swarm, run the following command: docker swarm join \ --token SWMTKN-1-4jlxqqc9jg39a7ll5npktriayhnk040vuunhcwj2h6ntvcy3j0-602yfdl0qc5zmhcvo1etytu7y \ 172.25.3.250:2377

根據token的不同,我們來區分加入叢集的是manager節點還是普通的系節點。

[root@foundation3 ~]# docker swarm join-token manager --quiet
SWMTKN-1-4jlxqqc9jg39a7ll5npktriayhnk040vuunhcwj2h6ntvcy3j0-602yfdl0qc5zmhcvo1etytu7y

通過加入–quiet引數可以只輸出token,在需要儲存token的時候還是十分有用的。

二.在docker叢集中部署服務

1.部署服務前注意

按照本教程做的小夥伴,建議每臺機器都可以連線外網,可以從docker映象倉庫下載映象。原因在稍後解釋。
講到下載映象,可能很多兄弟要說下載映象速度太慢了從Docker Hub上,這裡我推薦一個國內的映象加速器非常好用DaoCloud – 企業級雲端計算領域的創新領導者
這裡寫圖片描述
註冊賬號後進入自己的使用者介面,在右上角點選我上圖畫圈處,進入加速器介面。
這裡寫圖片描述
直接輸入這個所指示的命令即可配置加速器。如果使用他指示的命令配置失敗的也可以手動配置

[[email protected] docker]# pwd
/etc/docker
[[email protected] docker]# ls
daemon.json  key.json  test1.tar  test2.tar
[[email protected] docker]# 

編寫daemon.json檔案(下面的*替換成你的私有映象地址)

"registry-mirrors":["http://**********"]

現在就可以暢快的pull映象了,我們本次需要的映象是Nginx的映象。

[[email protected] docker]# docker search nginx
NAME                                     DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                                    Official build of Nginx.                        6085      [OK]       
jwilder/nginx-proxy                      Automated Nginx reverse proxy for docker c...   1038                 [OK]
richarvey/nginx-php-fpm                  Container running Nginx + PHP-FPM capable ...   381                  [OK]
jrcs/letsencrypt-nginx-proxy-companion   LetsEncrypt container to use with nginx as...   182                  [OK]
webdevops/php-nginx                      Nginx with PHP-FPM                              78                   [OK]
million12/nginx-php                      Nginx + PHP-FPM 5.5, 5.6, 7.0 (NG), CentOS...   77                   [OK]

通過這裡我們可以看到很多nginx的映象,根據stars數量我們可以選擇最可靠的映象,在這裡我們要強調一個事情,就是docker 的tag。我們建議我們使用的每個映象都要帶上tag,比如我列出我的幾個Nginx映象

[root@foundation3 docker]# docker images | grep nginx
nginx                         1.12                17daebd00e2c        2 weeks ago         109 MB
nginx                         1.13                3448f27c273f        2 weeks ago         109 MB

這些tag並不是預設的latest,因為這個預設的tag會造成很多困擾,因為很多時候那個帶latest的映象並不一定是”latest”,這會很讓人困擾。那麼既然我們使用映象要帶tag但是根據上search出的官方docker映象資訊並沒有tag資訊,怎麼辦呢,我建議大家在查詢需要下載的映象時去映象的官網檢視下,但是DockerHub官網訪問速度太慢,這時還是用我們國內的這個docker映象源。
這裡寫圖片描述
通過這裡提供的介面我們可以看到Docker Hub的映象資訊
這裡寫圖片描述
進入nginx的詳情頁後我們就可以看到具體的tag了。比如我們想下載1.12.0版本的nginx映象可以使用的tag就有 stable,1.12等

docker pull nginx:1.12

現在都配置好後,我們在manager,node1,node2上將nginx:1.12和nginx:1.13映象均pull下來。如果你只是在manager上pull下來會導致部署服務失敗。

2.部署單節點服務

[root@foundation3 docker]# docker service create --name web_t nginx:1.12 

這條命令讓我們在manager節點上部署了一個Nginx容器。

[root@foundation3 docker]# docker service ls
ID            NAME   MODE        REPLICAS  IMAGE
gy0slheb99he  web_t  replicated  1/1       nginx:1.12

通過REPLICAS專案可以看到叢集節點的啟動狀況,”/”左面是叢集中啟動的個數,”/”右面是叢集節點的總個數。

[[email protected] docker]# docker service ps web_t
ID            NAME     IMAGE       NODE                         DESIRED STATE  CURRENT STATE          ERROR  PORTS
6qzlzycuageu  web_t.1  nginx:1.12  Nored.example.com  Running        Running 4 minutes ago      

docker service ps可以看到叢集節點具體執行在哪臺機器上。執行時間等。本次是單節點叢集,我們可以看到,容器就執行在本機上。

3.部署多節點叢集

[[email protected] docker]# docker service create --replicas 3 --name web_a nginx:1.12

新增–replicas 3就是代表叢集的個數變為3。manager會將容器平均分配到三個節點上

[root@foundation3 docker]# docker service ls
ID            NAME   MODE        REPLICAS  IMAGE
q8dsqiesl347  web_a  replicated  3/3       nginx:1.12

通過docker service ls 可以看到三個節點均運行了起來。

[[email protected] docker]# docker service ps web_a
ID            NAME     IMAGE       NODE                         DESIRED STATE  CURRENT STATE          ERROR  PORTS
5pavjoz2f7wi  web_a.1  nginx:1.12  worker1.mo.com               Running        Running 6 minutes ago         
ug3hbmlfy95g  web_a.2  nginx:1.12  foundation3.ilt.example.com  Running        Running 6 minutes ago         
94dyllk3k1sg  web_a.3  nginx:1.12  worker2.mo.com               Running        Running 6 minutes ago         

通過docker service ps 可以看到nginx容器分別執行在三臺不同的主機上,為了證明他在另一臺主機上執行,我們登陸其中的worker1.mo.com

[root@worker2 ~]# docker ps
CONTAINER ID        IMAGE                                                                           COMMAND                  CREATED             STATUS              PORTS               NAMES
ed905660baeb        nginx@sha256:0d71ff22db29a08ac7399d1b35b0311c5b0cbe68d878993718275758811f652a   "nginx -g 'daemon ..."   29 minutes ago      Up 29 minutes       80/tcp              web_a.3.94dyllk3k1sgy44fha1ho0kss
e5423ea1a6aa        

可以看到在docker2上這個容器正在執行。

4.部署服務過程踩過的坑(解釋為什麼每個節點都要從DockerHub上pull映象)

我在第一次部署服務的時候由於node1,node2無法聯網,所以將Manager上pull下來的映象直接save成了tar包,在node1,node2上使用load匯入這個tar包後部署的nginx服務,但是發現容器只能在manager上執行,接下來問題重現。
將你的node1與node2與外網的連線斷開

[root@worker2 ~]# ls | grep nginx_1.12.tar 
nginx_1.12.tar

這個是Nginx映象的tar包我們將他匯入到node1和node2上。在這之前刪掉原本有的nginx映象

docker rmi nginx:1.12

匯入映象

[root@worker2 ~]# docker load -i nginx_1.13.tar 
Loaded image: nginx:1.12
f12c15fc56f1: Loading layer [==================================================>] 52.75 MB/52.75 MB
08e6bf75740d: Loading layer [==================================================>] 3.584 kB/3.584 kB
Loaded image ID: sha256:17daebd00e2c95abb02cd48bcbf562c1993460d40d626501f23985126ea26b21
Loaded image ID: sha256:3448f27c273f3122fc554d7acf33796efb4df2ad9886efc092c3bfe716e897b7

現在開始重新部署服務

[[email protected] images]# docker service create --replicas 3 --name web nginx:1.12
x4s7b1iccoebir6avpdnwjcb2

檢視叢集狀態

[[email protected] images]# docker service ps web
ID            NAME       IMAGE       NODE                         DESIRED STATE  CURRENT STATE            ERROR                             PORTS
gf040hgh3krc  web.1      nginx:1.12  foundation3.ilt.example.com  Running        Preparing 3 seconds ago                                    
jradnn5lgvxl  web.2      nginx:1.12  worker2.mo.com               Ready          Rejected 1 second ago    "No such image: [email protected]:0…"  
tez20wghmtpf   \_ web.2  nginx:1.12  worker2.mo.com               Shutdown       Rejected 3 seconds ago   "No such image: [email protected]:0…"  
yge4dufnmozw  web.3      nginx:1.12  worker1.mo.com               Ready          Rejected 1 second ago    "No such image: [email protected]:0…"  
esprx0otnwj5   \_ web.3  nginx:1.12  worker1.mo.com               Shutdown       Rejected 2 seconds ago   "No such image: [email protected]:0…" 

可以看到明明在node1,node2上load nginx:1.12的映象了怎麼會建立失敗呢。根據ps的顯示node1,node2拒絕了的原因是沒有nginx的映象,仔細看後發現後面還有個@sha….,我們猜測是不是由於我們匯入的映象的@後面的值和manager上的不一致導致node1,node2拒絕建立的呢。
現在就引出了一個問題,就是我們如何確定nginx:1.12映象就是官方給的那個映象呢,根據後面的tag嗎,顯然不夠安全,這時就需要一個類似於hash簽名的東西來標記,但在docker這裡這個值叫digests。我們檢視下manager上nginx:1.12的digests。

[root@foundation3 images]# docker images  --digests|grep nginx
nginx                         1.12                sha256:0d71ff22db29a08ac7399d1b35b0311c5b0cbe68d878993718275758811f652a   17daebd00e2c        2 weeks ago         109 MB

再看下node2上的nginx:1.12映象的digests呢

[root@worker2 ~]# docker images --digests
REPOSITORY          TAG                 DIGEST              IMAGE ID            CREATED             SIZE
nginx               1.12                <none>              17daebd00e2c        2 weeks ago         109 MB

可以看到是一個none。看到這裡我想大家應該明白為什麼重新部署的這次服務失敗了,因為雖然我們自己可以確定那個nginx映象是我們自己save再load過去的,但是docker無法解析根據這個tag解析出digests所以認為映象不同,導致服務建立失敗。
解決方法:目前只能讓你的所有節點都連上網,如果你的映象在save過程沒有出錯的話,那麼我們現在將node1,node2連上外網,再重新部署叢集node1,node2上的docker就會自己去DockerHub上查詢tag對應的digests了,也就部署成功了。但是有些環境下,我們的節點無法連線外網該怎麼辦呢,目前還沒有解決,解決之後我會馬上更新告訴大家。本部分涉及的像digests這些知識點在Docker官網連結

三.建立服務時的詳細引數配置與更新部署的服務

1.將主機中的檔案掛載到服務中

[[email protected] tmp]# docker service create --name web --mount type=bind,src=/tmp/in_in,dst=/ini  nginx:1.12

將本機中的/tmp/in_in檔案掛載到容器中的/ini上。這個引數與docker run中的-v差不多,但是要記住指定type。
type型別(圖片引自Docker官網)
只讀掛載

[[email protected] ~]# docker service create --mount type=bind,src=/tmp/in_in,dst=/in,ro=true --name web nginx:1.12

預設掛載是讀寫掛載的,如果你不希望容器修改資料,請加上ro=true引數。

2.建立時更新方法的配置

docker service create \
  --replicas 12 \
  --name my_web \
  --update-delay 10s \
  --update-parallelism 2 \
  --update-failure-action continue \
  nginx:1.12

上面是建立了一個節點的docker叢集,通過指定”–update-delay”來確定每組更新的間隔,”–update-parallelism”來確定同時更新的容器數量,”–update-failure-action continue”來卻id那個當更新失敗時候執行的操作,是繼續允許還是不繼續。

 docker service update \
  --rollback \
  --update-delay 0s
  web

上面是回滾服務使用的命令。