在本次練習中,你將體驗到 Docker 的容器編排功能。首先你需要在單個主機上部署一個簡單的應用程序,并了解其工作機制。然后,通過配置 Docker Swarm 模式,你將學習到怎樣在多個主機上部署相同的簡單應用程序。最后,你將看到如何對應用的規模進行擴容、縮容,以及如何將工作負載在不同的主機之間轉移。
(譯者注:登錄原網站可使用在線練習資源)
難度:入門級時間:約 30 分鐘
任務:
- [第一節 - 容器編排是什么](# 第一節:容器編排是什么 "第一節 - 容器編排是什么")
- [第二節 - 配置 Docker Swarm 模式](# 第二節:配置 -Docker-Swarm- 模式 "第二節 - 配置 Docker Swarm 模式")
- [第三節 - 跨多主機部署應用](# 第三節:跨多主機部署應用 "第三節 - 跨多主機部署應用")
- [第四節 - 應用擴容縮容](# 第四節:應用擴容縮容 "第四節 - 應用擴容縮容")
- [第五節 - 排空節點并重新調度容器](# 第五節:排空節點并重新調度容器 "第五節 - 排空節點并重新調度容器")
- [清理工作](# 清理工作 "清理工作")
第一節:容器編排是什么
那么問題來了,到底什么是容器編排呢?還是用一個例子加以說明吧。假設你有一個大流量的應用,并且要求具有高可用性。為滿足這些需要,你通常希望在至少 3 臺機器上進行部署,以便在主機發生故障時,你的應用程序仍可從其他至少兩臺計算機訪問。顯然,這只是一個例子,你的用例可能有自己的要求,但相信你已經明白意思了。
在沒有容器編排技術的情況下,部署應用程序通常非常耗時且容易出錯,因為你必須手動 SSH 到每臺計算機,啟動應用程序,然后不斷監視以確保程序按預期運行。
但有了編排工具之后,你通常可以擺脫大部分人力勞動,讓自動化完成繁重的工作。Docker Swarm 容器編排有一個很酷的功能是,你只需一個命令即可在多個主機上部署應用程序(前提是啟用了 Swarm 模式)。另外,如果 Docker Swarm 中的其中一個節點停止了運行,其他節點將自動接過負載,你的應用程序將繼續運作如常。
如果你通常只使用 docker run 來部署應用程序,那么使用 Docker Compose 或 Docker Swarm 模式或二者兼用將很有可能是你受益不淺。
第二節:配置 Docker Swarm 模式
如前所述,實際應用程序通常部署在多個主機上。這可以提高應用程序性能和可用性,并允許各個組件獨立擴展。Docker 擁有強大的原生工具來幫助你實現這一目標。
手動在單個主機上運行程序的一個例子,是在node1上運行 docker run -dt Ubuntu sleep infinity,來創建一個新的容器。
docker run -dt Ubuntu sleep infinity Unable to find image 'ubuntu:latest' locally latest: Pulling from library/ubuntu d54efb8db41d: Pull complete f8b845f45a87: Pull complete e8db7bf7c39f: Pull complete 9654c40e9079: Pull complete 6d9ef359eaaa: Pull complete Digest: sha256:dd7808d8792c9841d0b460122f1acf0a2dd1f56404f8d1e56298048885e45535 Status: Downloaded newer image for Ubuntu:latest 846af8479944d406843c90a39cba68373c619d1feaa932719260a5f5afddbf71
此命令將基于 ubuntu:latest 鏡像創建一個新容器,并將運行 sleep 命令以使容器在后臺運行。您可以通過在 node1 上運行 docker ps 來驗證我們的示例容器已啟動。
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 044bea1c2277 Ubuntu "sleep infinity" 2 seconds ago Up 1 second distracted_mayer
但是,這只是在一個節點上。如果此節點出現故障會怎樣?好吧,我們的應用程序會被終止,它永遠不會重新啟動。要恢復服務,我們必須手動登錄此計算機,折騰一番才能使其恢復運行。因此,如果我們有某種類型的系統允許我們在許多機器上運行這個“睡眠”應用程序 / 服務,那將會很有幫助。
在本節中,你將練習配置 Swarm 模式。這是一種新的可選模式,其中多個 Docker 主機形成一個稱為群組的自編排引擎。Swarm 模式支持新功能,如服務和捆綁,可幫助你跨多個 Docker 主機部署和管理多容器應用程序。
你需要完成以下幾步:
- 配置 Swarm 模式
- 運行應用程序
- 對應用規模進行伸縮
- 出于維護需要,排空(drain)一個節點,并重新調度節點上的容器
在本練習的余下部分中,我們將 Docker 原生集群管理稱作 Swarm 模式。配置了 Swarm 模式的一組 Docker 機器將被稱為群組。
一個群組包含了一個或多個管理節點,以及一個或多個工作節點。管理節點維護群組狀態并對應用容器進行調度。工作節點則負責應用容器的實際運行。在 Docker 1.12 中,使用群組管理的完整功能不需要任何外部后端或第三方組件,也就是說這完全是內置的!
在這一小節的演示里,實驗中的三個節點你全部都需要用到。node1 將成為群組管理節點,node2 和 node3 將成為工作節點。Swarm 模式支持高可用的冗余管理節點的設置,但如果只是以此次練習為目的,你只需要部署單個管理節點就夠了。
步驟 2.1 創建管理節點
在這一步驟中,你將要初始化一個新的 Swarm 群組,添加一個工作節點,并驗證操作是否生效。
在 node1 上運行 docker swarm INIt
docker swarm INIt --advertise-addr $(hostname -i) Swarm INItialized: current node (6dlewb50pj2y66q4zi3egnwbi) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-1wxyoueqgpcrc4xk2t3ec7n1poy75G4kowmwz64p7ulqx611ih-68pazn0mj8p4p4lnuf4ctp8xy 10.0.0.5:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
你可以運行 docker info 命令來驗證 node1 是否成功被配置成群組管理節點。
docker info Containers: 2 Running: 0 Paused: 0 Stopped: 2 Images: 2 Server Version: 17.03.1-ee-3 Storage Driver: aufs Root Dir: /var/lib/docker/aufs Backing Filesystem: extfs Dirs: 13 Dirperm1 Supported: true Logging Driver: JSON-file Cgroup Driver: cgroupfs Plugins: Volume: local Network: bridge host macvlan null overlay Swarm: active NodeID: rwezvezez3bg1kqg0y0f4ju22 Is Manager: true ClusterID: qccn5eanox0uctyj6xtfvesy2 Managers: 1 Nodes: 1 Orchestration: Task History Retention Limit: 5 Raft: Snapshot Interval: 10000 Number of Old Snapshots to Retain: 0 Heartbeat Tick: 1 Election Tick: 3 Dispatcher: Heartbeat Period: 5 seconds CA Configuration: Expiry Duration: 3 months Node Address: 10.0.0.5 Manager Addresses: 10.0.0.5:2377 <Snip>
至此,群組已經初始化完畢,以 node1 作為管理節點。下一小節中,你將要把 node2 和 node3 添加成為工作節點。
步驟 2.2 向群組中添加工作節點
你需要在 node2 和 node3 上完成下列步驟,在完成后切換回 node1 節點。
現在,從 node1 的終端輸出中復制整個 docker swarm join ... 命令。我們需要將這條命令粘貼到 node2 和 node3 的終端。
順便一提,如果 docker swarm join ... 命令已經滾動出屏幕顯示范圍,可以在管理節點上運行 docker swarm join-token worker 命令,來重新找到它。
記住,這里展示的 tokens 并非你將實際用到的。要從 node1 的輸出中復制命令。在 node2 和 node3 上,應該像下面這樣:
docker swarm join --token SWMTKN-1-1wxyoueqgpcrc4xk2t3ec7n1poy75g4kowmwz64p7ulqx611ih-68pazn0mj8p4p4lnuf4ctp8xy 10.0.0.5:2377 docker swarm join --token SWMTKN-1-1wxyoueqgpcrc4xk2t3ec7n1poy75g4kowmwz64p7ulqx611ih-68pazn0mj8p4p4lnuf4ctp8xy 10.0.0.5:2377
當你在 node2 和 node3 上運行完這一命令之后,切換回 node1,然后運行 docker node ls 來驗證是不是兩個新的節點都加入到群組當中。你應當會看到共有三個節點,node1 是管理節點,node2 和 node3 都是工作節點。
docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 6dlewb50pj2y66q4zi3egnwbi * node1 Ready Active Leader ym6sdzrcm08s6ohqmjx9mk3dv node3 Ready Active yu3hbegvwsdpy9esh9t2lr431 node2 Ready Active
docker node ls 命令展示的是群組中的所有節點以及它們在群組中的角色。* 標志表示你發布指令的節點。
恭喜!你已經成功部署了含有一個管理節點和兩個工作節點的群組了。
第三節:跨多主機部署應用
現在你有了一個運行中的群組,是時候部署我們非常簡單的 sleep 應用了。你需要在 node1上完成以下步驟。
步驟 3.1 將應用組件部署為 Docker 服務
我們的 sleep 應用正在互聯網上躥紅(由于在 Reddit 和 HN 上廣受關注)。人們真的就很喜歡它。所以,你需要為你的應用擴容以滿足峰值需求。你同樣需要在多主機上部署,來獲得高可用性。我們用服務的概念來簡化應用擴容,并將多個容器作為一個單獨的實體來管理。
服務(Services)是在 Docker 1.12 出現的新概念。這一概念與集群聯系緊密,并且是為長時間運行(long-running)的容器設計的。
你需要在 node1 上進行以下操作。
先來將 sleep 部署成我們 Docker 群組上的一個服務吧。
docker service create --name sleep-App Ubuntu sleep infinity of5rxsxsmm3asx53dqcq0o29c
驗證 service create 請求已經被 Swarm 管理節點接收。
docker service ls ID NAME MODE REPLICAS IMAGE of5rxsxsmm3a sleep-app replicated 1/1 Ubuntu:latest
服務的狀態可能會經過多次改變,直到進入運行狀態。鏡像從 Docker Store 下載到群組里其他的機器上。當鏡像下載完畢后,容器將在三個節點中的一個上進入運行狀態。
到這一步為止,我們所做的事情似乎并沒有比運行一條 docker run ... 命令更加復雜。我們同樣還是只在一臺主機上部署了單個的容器。不同之處在于,這個容器是在一個 Swarm 集群中進行調度。
好的,利用了 Docker 服務這一特性,你已經成功在新群組上部署了這個 sleep 應用。
第四節:應用擴容縮容
需求量爆炸!大家都愛上你的 sleep 應用了!是時候進行擴容了。
服務的一大優勢在于,你可以進行擴容、縮容以更好地滿足需求。在本節中,你將首先對服務進行擴容,然后在縮容回去。
你需要在 node1 上進行以下操作。
使用 docker service update --replicas 7 sleep-app 命令對 sleep-app 服務中的容器數量進行調節。其中 replicas 一詞,描述提供同一服務的相同容器。
docker service update --replicas 7 sleep-app
群組管理節點將進行調度,使得集群中共有 7 個 sleep-app 容器。這些容器會被均勻地調度到各個群組成員上。
我們將要使用 docker service ps sleep-app 命令。如果你在上一步設置了 --replicas 之后足夠快地運行這條命令,你將看到這些容器實時啟動的過程。
docker service ps sleep-app ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 7k0flfh2wpt1 sleep-app.1 Ubuntu:latest node1 Running Running 9 minutes ago wol6bzq7xf0v sleep-app.2 Ubuntu:latest node3 Running Running 2 minutes ago id50tzzk1qbm sleep-app.3 Ubuntu:latest node2 Running Running 2 minutes ago ozj2itmio16q sleep-app.4 Ubuntu:latest node3 Running Running 2 minutes ago o4rk5aiely2o sleep-app.5 Ubuntu:latest node2 Running Running 2 minutes ago 35t0eamu0rue sleep-app.6 Ubuntu:latest node2 Running Running 2 minutes ago 44s8d59vr4a8 sleep-app.7 Ubuntu:latest node1 Running Running 2 minutes ago
注意,這里一共列出了 7 個容器。這些新容器從啟動到變成如上面顯示的 RUNNING 狀態,可能需要一些時間。NODE 一列向我們展示容器是跑在哪個節點上面。
要想將服務縮容回 4 個容器,只需要 docker service update --replicas 4 sleep-app 命令。
docker service update --replicas 4 sleep-app
驗證容器的數量是否確實減少到了 4,我們可以用 docker service ps sleep-app 命令。
docker service ps sleep-app ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 7k0flfh2wpt1 sleep-app.1 Ubuntu:latest node1 Running Running 13 minutes ago wol6bzq7xf0v sleep-app.2 Ubuntu:latest node3 Running Running 5 minutes ago 35t0eamu0rue sleep-app.6 Ubuntu:latest node2 Running Running 5 minutes ago 44s8d59vr4a8 sleep-app.7 Ubuntu:latest node1 Running Running 5 minutes ago
你現在已經成功完成群組服務的擴容縮容啦。
第五節:排空節點并重新調度容器
你的 sleep-app 在火爆 Reddit 和 HN 之后一直保持強勁勢頭。現在已經攀升到應用商店的第一位了!你在節假日進行擴容,在淡季進行縮容。現在你要維護其中的一臺服務器,所以你要優雅地將這臺服務器移出群組,而不影響到顧客們使用服務。
首先在 node1 上使用 docker node ls 命令,再查看一下節點的狀態。
docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 6dlewb50pj2y66q4zi3egnwbi * node1 Ready Active Leader ym6sdzrcm08s6ohqmjx9mk3dv node3 Ready Active yu3hbegvwsdpy9esh9t2lr431 node2 Ready Active
你需要將 node2 移出群組進行維護。
讓我們看看在 node2 上有哪些運行中的容器。
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4e7ea1154ea4 Ubuntu@sha256:dd7808d8792c9841d0b460122f1acf0a2dd1f56404f8d1e56298048885e45535 "sleep infinity" 9 minutes ago Up 9 minutes sleep-app.6.35t0eamu0rueeozz0pj2xaesi
你會看到有其中一個 sleep-app 的容器正在這里運行(雖然你的輸出可能會稍有不同)。
現在讓我們回到 node1,把 node2 移出這個服務。要做到這一點,先再運行一次 docker node ls 命令。
docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 6dlewb50pj2y66q4zi3egnwbi * node1 Ready Active Leader ym6sdzrcm08s6ohqmjx9mk3dv node3 Ready Active yu3hbegvwsdpy9esh9t2lr431 node2 Ready Active
我們需要用到 node2 的 ID,運行 docker node update --availability drain yournodeid。我們使用 node2 的主機 ID 作為 drain 命令的輸入。你需要將命令中的 yournodeid 替換成 node2 的實際 ID。
docker node update --availability drain yournodeid
檢查節點狀態
docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 6dlewb50pj2y66q4zi3egnwbi * node1 Ready Active Leader ym6sdzrcm08s6ohqmjx9mk3dv node3 Ready Active yu3hbegvwsdpy9esh9t2lr431 node2 Ready Drain
現在 node2 就進入了 Drain 狀態。
切換到 node2,使用 docker ps 看看運行中的容器。
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
在 node2 上已經沒有容器在運行了。
最后,我們回到 node1,看看容器是否被重新調度了。理論上你將看到所有的四個容器都在剩下的兩個節點上運行。
docker service ps sleep-app ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 7k0flfh2wpt1 sleep-app.1 Ubuntu:latest node1 Running Running 25 minutes ago wol6bzq7xf0v sleep-app.2 Ubuntu:latest node3 Running Running 18 minutes ago s3548wki7rlk sleep-app.6 Ubuntu:latest node3 Running Running 3 minutes ago 35t0eamu0rue _ sleep-app.6 Ubuntu:latest node2 Shutdown Shutdown 3 minutes ago 44s8d59vr4a8 sleep-app.7 Ubuntu:latest node1 Running Running 18 minutes ago
清理工作
在 node1 上執行 docker service rm sleep-app 命令,刪掉名為 sleep-app 的服務。
docker service rm sleep-app
在 node1 上執行 docker ps,獲取運行中的容器列表。
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 044bea1c2277 Ubuntu "sleep infinity" 17 minutes ago 17 minutes ag distracted_mayer
你可以在 node1 上用 docker kill <CONTAINER ID> 命令,清理掉我們最開始啟動的那個 sleep 容器。
docker kill yourcontainerid
最后,讓我們把 node1,node2,node3 從群組中移除。我們可以用 docker swarm leave --force 命令做到這一點。
先在 node1 上運行 docker swarm leave --force。
docker swarm leave --force
然后在 node2 上運行 docker swarm leave --force。
docker swarm leave --force
最后在 node3 上運行 docker swarm leave --force。
docker swarm leave --force
恭喜你,完成本次的練習!你現在應該學會了怎樣創建群組、將應用部署成服務以及對每個服務進行擴容縮容。
via: https://training.play-with-docker.com/orchestration-hol/
作者:Play with Docker classroom[1]譯者:Mockery-Li[2]校對:magichan[3]
本文由 GCTT[4] 原創編譯,Go 中文網[5] 榮譽推出