Docker 引擎的 Swarm 模式:入門教程
Swarm,聽起來像是一個朋克搖滾樂隊。但它確實是個新的編排機制,抑或者是,一個 Docker 現有編排體制的改進。簡單來講,如果你在用一個舊版本的 Docker,你必須手動配置 Swarm 來創建 Docker 集群。從 1.12 版開始,Docker 引擎集成了一個原生的實現(LCTT 譯註:見下文)來支持無縫的集群設置。也就是為什麼會有這篇文章。
在這篇教程中,我將帶你體驗一下編排後的 Docker 將能做的事情。這篇文章並不是包含所有細節(如 BnB 一般)或是讓你對其全知全能,但它能帶你踏上你的集群之路。在我的帶領下開始吧。
技術概要
如果把 Docker 詳細而又好用的文檔照搬到這裡那將太丟人了,所以我將簡要概括下這個技術的概要。我們已經有了 Docker,對吧。現在,你想要更多的伺服器作為 Docker 主機,但同時你希望它們屬於同一個邏輯上的實體。也就是說,你想建立一個集群。
我們先從一個主機組成的集群開始。當你在一個主機上初始化一個 Swarm 集群,這台主機將成為這個集群的 管理者 。從技術角度來講,它成為了 共識組 中的一個 節點 。其背後的數學邏輯建立在 Raft 演算法之上。 管理者 負責調度任務。而具體的任務則會委任給各個加入了 Swarm 集群的 工作者 節點。這些操作將由 Node API 所管理。雖說我討厭 API 這個辭彙,但我必須在這裡用到它。
Service API 是這個實現中的第二個組件。它允許 管理者 節點在所有的 Swarm 集群節點上創建一個分散式的服務。這個服務可以 被複制 ,也就是說它們(LCTT 譯註:指這些服務)會由平衡機制被分配到集群中(LCTT 譯註:指 replicated 模式,多個容器實例將會自動調度任務到集群中的一些滿足條件的節點),或者可以分配給全局(LCTT 譯註:指 global 模式),也就是說每個節點都會運行一個容器實例。
此外還有更多的功課需要做,但這些信息已經足夠你上路了。現在,我們開始整些實際的。我們的目標平台是 CentOS 7.2,有趣的是在我寫這篇教程的時候,它的軟體倉庫中只有 1.10 版的 Docker,也就是說我必須手動更新以使用 Swarm。我們將在另一篇教程中討論這個問題。接下來我們還有一個跟進的指南,其中涵蓋了如何將新的節點加入我們現有的集群(LCTT 譯註:指剛剛建立的單節點集群),並且我們將使用 Fedora 進行一個非對稱的配置。至此,請確保正確的配置已經就位,並有一個工作的集群啟動並正在運行(LCTT 譯註:指第一個節點的 Docker 已經安裝並已進入 Swarm 模式,但到這裡筆者並沒有介紹如何初始化 Swarm 集群,不過別擔心下章會講)。
配置鏡像和服務
我將嘗試配置一個負載均衡的 Apache 服務,並使用多個容器實例通過唯一的 IP 地址提供頁面內容。挺標準的吧(LCTT 譯註:指這個負載均衡的網頁伺服器)。這個例子同時也突出了你想要使用集群的大多數原因:可用性、冗餘、橫向擴展以及性能。當然,你同時需要考慮網路和儲存這兩塊,但它們超出了這篇指南所涉及的範圍了。
這個 Dockerfile 模板其實可以在官方鏡像倉庫里的 httpd 下找到。你只需一個最簡單的設置來起步。至於如何下載或創建自己的鏡像,請參考我的入門指南,鏈接可以在這篇教程的頂部可以找到。
docker build -t my-apache2 .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM httpd:2.4
Trying to pull repository docker.io/library/httpd ...
2.4: Pulling from docker.io/library/httpd
8ad8b3f87b37: Pull complete
c95e1f92326d: Pull complete
96e8046a7a4e: Pull complete
00a0d292c371: Pull complete
3f7586acab34: Pull complete
Digest: sha256:3ad4d7c4f1815bd1c16788a57f81b413...a915e50a0d3a4
Status: Downloaded newer image for docker.io/httpd:2.4
---> fe3336dd034d
Step 2 : COPY ../public-html/ /usr/local/apache2/htdocs/
...
在你繼續下面的步驟之前,你應該確保你能無錯誤的啟動一個容器實例並能鏈接到這個網頁伺服器上(LCTT 譯註:使用下面的命令)。一旦你確保你能連上,我們就可以開始著手創建一個分散式的服務。
docker run -dit --name my-running-app my-apache2
將這個 IP 地址輸入瀏覽器,看看會出現什麼。
Swarm 初始化和配置
下一步就是啟動 Swarm 集群了。你將需要這些最基礎的命令來開始,它們與 Docker 博客中的例子非常相似:
docker service create --name frontend --replicas 5 -p 80:80/tcp my-apache2:latest
這裡我們做了什麼?我們創建了一個叫做 frontent
的服務,它有五個容器實例。同時我們還將主機的 80 埠和這些容器的 80 埠相綁定。我們將使用剛剛新創建的 Apache 鏡像來做這個測試。然而,當你在自己的電腦上直接鍵入上面的指令時,你將看到下面的錯誤:
docker service create --name frontend --replicas 5 -p 80:80/tcp my-apache2:latest
Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again.
這意味著你沒有將你的主機(節點)配置成一個 Swarm 管理者 。你可以在這台主機上初始化 Swarm 集群或是讓它加入一個現有的集群。由於我們目前還沒有一個現成的集群,我們將初始化它(LCTT 譯註:指初始化 Swarm 集群並使當前節點成為 manager):
docker swarm init
Swarm initialized: current node (dm58mmsczqemiikazbfyfwqpd) is now a manager.
為了向這個 Swarm 集群添加一個 工作者 ,請執行下面的指令:
docker swarm join
--token SWMTKN-1-4ofd46a2nfyvrqwu8w5oeetukrbylyznxla
9srf9vxkxysj4p8-eu5d68pu5f1ci66s7w4wjps1u
10.0.2.15:2377
為了向這個 Swarm 集群添加一個 管理者 ,請執行 docker swarm join-token manager
並按照指示操作。
操作後的輸出不用解釋已經很清楚明了。我們成功的創建了一個 Swarm 集群。新的節點們將需要正確的 令牌 來加入這個 Swarm 集群。如果你需要配置防火牆,你還需找到它的 IP 地址和埠(LCTT 譯註:指 Docker 的 Swarm 模式通訊所需的埠,默認 2377)。此外,你還可以向 Swarm 集群中添加管理者節點。現在,重新執行剛剛的服務創建指令:
docker service create --name frontend --replicas 5 -p 80:80/tcp my-apache2:latest
6lrx1vhxsar2i50is8arh4ud1
測試連通性
現在,我們來驗證下我們的服務是否真的工作了。從某些方面講,這很像我們在 Vagrant 和 coreOS 中做的事情那樣。畢竟它們的原理幾乎相同。相同指導思想的不同實現罷了(LCTT 譯註:筆者觀點,無法苟同)。首先需要確保 docker ps
能夠給出正確的輸出。你應該能看到所創建服務的多個容器副本。
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
cda532f67d55 my-apache2:latest "httpd-foreground"
2 minutes ago Up 2 minutes 80/tcp frontend.1.2sobjfchdyucschtu2xw6ms9a
75fe6e0aa77b my-apache2:latest "httpd-foreground"
2 minutes ago Up 2 minutes 80/tcp frontend.4.ag77qtdeby9fyvif5v6c4zcpc
3ce824d3151f my-apache2:latest "httpd-foreground"
2 minutes ago Up 2 minutes 80/tcp frontend.2.b6fqg6sf4hkeqs86ps4zjyq65
eda01569181d my-apache2:latest "httpd-foreground"
2 minutes ago Up 2 minutes 80/tcp frontend.5.0rmei3zeeh8usagg7fn3olsp4
497ef904e381 my-apache2:latest "httpd-foreground"
2 minutes ago Up 2 minutes 80/tcp frontend.3.7m83qsilli5dk8rncw3u10g5a
我也測試了不同的、非常規的埠,它們都能正常工作。對於你如何連接伺服器和收取請求你將會有很多可配置的餘地。你可以使用 localhost 或者 Docker 網路介面(筆者註:應該是指 Docker 的默認網橋 docker0,其網關為 172.17.0.1) 的 IP 地址的正確埠去訪問。下面的例子使用了埠 1080:
至此,這是一個非常粗略、簡單的開始。真正的挑戰是創建一個優化過的、可擴展的服務,但是它們需要一個準確的技術用例。此外,你還會用到 docker info
和 docker service
(還有 inspect
和 ps
)命令來詳細了解你的集群是如何工作的。
可能會遇到的問題
你可能會在把玩 Docker 和 Swarm 時遇到一些小的問題(也許沒那麼小)。比如 SELinux 也許會抱怨你正在執行一些非法的操作(LCTT 譯註:指在強制訪問控制策略中沒有許可權的操作)。然而,這些錯誤和警告應該不會對你造成太多阻礙。
docker service
不是一條命令(docker service is not a docker command
)
當你嘗試執行必須的命令去創建一個 複製模式 的服務時,你可能會遇到一條錯誤說 docker: 'service' is not a docker command
(LCTT 譯註:見下面的例子)。這表示你的 Docker 版本不對(使用 -v
選項來檢查)。我們將在將來的教程討論如何修復這個問題。
docker service create --name frontend --replicas 5 -p 80:80/tcp my-apache2:latest
docker: 'service' is not a docker command.
docker tag
無法識別(docker tag not recognized
)
你也許會看到下面的錯誤:
docker service create -name frontend -replicas 5 -p 80:80/tcp my-apache2:latest
Error response from daemon: rpc error: code = 3 desc = ContainerSpec: "-name" is not a valid repository/tag
關於這個錯誤已經有多個相關的討論和帖子了。其實這個錯誤也許相當無辜。你也許是從瀏覽器粘貼的命令,在瀏覽器中的橫線也許沒被正確解析(筆者註:應該用 --name
而不是 -name
)。就是這麼簡單的原因所導致的。
擴展閱讀
關於這個話題還有很多可談的,包含 1.12 版之前的 Swarm 集群實現(筆者註:舊的 Swarm 集群實現,下文亦作獨立版本
,需要 Consul 等應用提供服務發現),以及當前的 Docker 版本提供的(筆者註:新的 Swarm 集群實現,亦被稱為 Docker 引擎的 Swarm 模式)。也就是說,請別偷懶花些時間閱讀以下內容:
- Docker Swarm 概述(獨立版本的 Swarm 集群安裝)
- 構建一個生產環境的 Swarm 集群(獨立版本安裝)
- 安裝並創建一個 Docker Swarm 集群(獨立版本安裝)
- Docker 引擎 Swarm 概述(對於 1.12 版)
- Swarm 模式入門(對於 1.12 版)
總結
你總算看到這裡了。到這裡仍然無法保證你學到了什麼,但我相信你還是會覺得這篇文章有些用的。它涵蓋了一些基礎的概念,以及一個 Swarm 集群模式是如何工作的以及它能做什麼的概述,與此同時我們也成功的下載了並創建了我們的網頁伺服器的鏡像,並且在之後基於它運行了多個集群式的容器實例。雖然我們目前只在單一節點做了以上實驗,但是我們會在將來解釋清楚(LCTT 譯註:以便解釋清楚多節點的 Swarm 集群操作)。並且我們解決了一些常見的問題。
我希望你能認為這篇指南足夠有趣。結合著我過去所寫的關於 Docker 的文章,這些文章應該能給你一個像樣的解釋,包括:怎麼樣操作鏡像、網路棧、儲存、以及現在的集群。就當熱身吧。的確,請享受並期待在新的 Docker 教程中與你見面。我控幾不住我記幾啊。
祝你愉快。
via: http://www.dedoimedo.com/computers/docker-swarm-intro.html
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive