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。
(圖片引自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
上面是回滾服務使用的命令。