天天看點

使用Docker Swarm來運作服務

本文講的是<b>使用Docker Swarm來運作服務</b>【編者的話】本文介紹了Docker 1.12中的Docker Swarm Mode,包括如何安裝Docker Engine、如何建立Swarm叢集、如何部署服務和建立Global Service。

Docker的最新版本v1.12,包含了很多更新和Docker Swarm提供的功能。在今天的文章中,我們将探讨如何使用Docker Swarm來部署服務。

在我們使用Docker Engine Swarm部署服務之前,我們需要建立一個Swarm叢集。因為我們需要1.12新添加的功能,是以我們也要安裝Docker Engine的最新版本。

我們會使用Ubuntu的标準安裝方式,依賴于Apt包管理器。因為我們需要安裝最新版本的Docker Engine,是以我們需要配置Apt,從Docker官方Apt倉庫來安裝<code>docker-engine</code>,而不是從系統預配置的倉庫。

配置Apt來使用新倉庫的第一步是想Apt緩存中添加該庫的公鑰。使用<code>apt-key</code>指令:

以上的<code>apt-key</code>指令向密鑰伺服器<code>p80.pool.sks-keyservers.net</code>請求一個特定的密鑰(<code>58118E89F3A912897C070ADBF76221572C52609D</code>)。公鑰将會被用來驗證從新倉庫下載下傳的所有包。

引入Docker的公鑰,我們可以配置Apt使用Docker的倉庫伺服器。我們可以在<code>/etc/apt/sources.list.d/</code>目錄中添加一個條目。

當我們重新整理Apt緩存時,Apt将會搜尋<code>sources.list.d/</code>目錄下的所有檔案,來尋找新的包倉庫。上述指令會建立一個新檔案<code>docker.list</code>,其中包含了一個添加了<code>apt.dockerproject.org</code>倉庫的條目。

運作<code>apt-get</code>指令的<code>update</code>選項,來重新整理Apt包緩存。

這會觸發Apt重新讀取配置檔案,重新整理倉庫清單,包含進我們添加的那個倉庫。該指令也會查詢這些倉庫來緩存可用的包清單。

在安裝Docker Engine之前,我們需要安裝一個先決軟體包(prerequisite package)。<code>linux-image-extra</code>包是一個核心相關的包,Ubuntu系統需要它來支援<code>aufs</code>儲存設備驅動。Docker會使用該驅動來加載卷。

為了安裝該包,我們将使用<code>apt-get</code>指令的<code>install</code>選項。

在<code>apt-get</code>指令中,<code>$(uname -r)</code>将傳回正在運作的核心的版本。任何對于該系統的核心更新應當包括安裝<code>linux-image-extra</code>,它的版本需要與新核心版本相一緻。如果該包沒有正确更新的話,Docker加載卷的功能可能受到影響。

在Apt配置好和<code>linux-image-extra</code>安裝好之後,我們可以繼續安裝Docker Engine了。我們可以使用<code>apt-get</code>指令的<code>install</code>選項來安裝<code>docker-engine</code>包。

此時,我們應該已經安裝好了<code>Docker Engine v1.12.0</code>或者更新版本。我們可以執行<code>docker</code>指令的<code>version</code>選項來驗證我們已經安裝了最新版本。

我們可以看到,Server版本和Client版本都是<code>1.12.0</code>。接下來,我們會建立Swarm叢集。

在這一小節中,我們将在多台機器上執行多個任務。為了更清楚地表述,我會在例子中包含主機名。

我們會使用兩個節點來啟動Swarm叢集。此時,兩個節點都按照上述步驟安裝了Docker Engine。

當建立Swarm叢集時,我們需要指定一個manager節點。在這個例子中,我們會使用主機名為<code>swarm-01</code>的主機作為manager節點。為了使<code>swarm-01</code>成為manager節點,我們需要首先在<code>swarm-01</code>執行指令來建立Swarm叢集。這個指令就是<code>docker</code>指令的<code>swarm init</code>選項。

在上述指令中,除了<code>swarm init</code>之外,我們還指定了<code>--advertise-addr</code>為<code>10.0.0.1</code>。Swarmmanager節點會使用該IP位址來廣告Swarm叢集服務。雖然該位址可以是私有位址,重要的是,為了使節點加入該叢集,那些節點需要能通過該IP的<code>2377</code>端口來通路manager節點。

在運作<code>docker swarm init</code>指令之後,我們可以看到<code>swarm-01</code>被賦予了一個節點名字(<code>awwiap1z5vtxponawdqndl0e7</code>),并被選為Swarm叢集的管理器。輸出中也提供了兩個指令:一個指令可以添加worker節點到swarm中,另一個指令可以添加另一個manager節點到該Swarm中。

Docker Swarm Mode可以支援多個manager節點。然而,其中的一個會被選舉為主節點伺服器,它會負責Swarm的編排。

Swarm叢集建立之後,我們需要添加一個新的worker節點。

在本例中,我們将<code>swarm-02</code>添加到了swarm中,作為worker節點。Swarm叢集中的worker節點的角色是用來運作任務(tasks)的;在該例中,任務(tasks)就是容器(containers)。另一方面,manager節點的角色是管理任務(容器)的編排,并維護Swarm叢集本身。

除此之外,manager節點本身也是worker節點,也可以運作任務。

我們現在有了一個最基本的兩節點的Swarm叢集。我們可以執行<code>docker</code>指令的<code>node ls</code>選項來驗證叢集的狀态。

從輸出中可以看到,<code>swarm-01</code>和<code>swarm-02</code>都處于<code>Ready</code>和<code>Active</code>狀态。是以,我們可以繼續在Swarm叢集上部署服務了。

在Docker Swarm Mode中,服務是指一個長期運作(long-running)的Docker容器,它可以被部署到任意一台worker節點上,可以被遠端系統或者Swarm中其他容器連接配接和消費(consume)的。

在本例中,我們會部署一個Redis服務。

一個有副本的服務是一個Docker Swarm服務,運作了特定數目的副本(replicas)。這些副本是由多個Docker容器的執行個體組成的。在本例中,每個副本都是一個獨立的Redis執行個體。

為了建立新服務,我們會使用<code>docker</code>指令的<code>service create</code>選項。以下指令将建立一個名為<code>redis</code>的服務,包含<code>2</code>個副本,并在叢集中釋出<code>6379</code>端口。

除了<code>service create</code>選項之外,我們還指定了<code>--name</code>為<code>redis</code>,<code>--replicas</code>表示該服務需要運作在<code>2</code>個不同的節點上。我們可以運作<code>docker</code>指令的<code>service ls</code>選項來驗證該服務是運作在兩個節點上的。

從輸出中可以看到,<code>2</code>個副本都在運作。如果我們想看到這些任務的更多細節,我們可以運作<code>docker</code>指令的<code>service ps</code>選項。

<code>service ps</code>選項會顯示特定服務的任務(容器)。在本例中,我們可以看到<code>redis</code>服務有一個任務(容器)運作在兩個Swarm節點上。

我們已經驗證了服務正在運作,我們可以嘗試從遠端系統,使用<code>redis-cli</code>用戶端來連接配接該服務。

從上面的連接配接可以看到,我們已經成功地連接配接上了<code>redis</code>服務。這意味着我們的服務已經運作起來了。

當我們建立了<code>redis</code>服務時,我們使用了<code>--publish</code>選項。該選項用來告知Docker将端口<code>6379</code>釋出為<code>redis</code>服務的可用端口。

當Docker釋出了服務端口時,它在Swarm叢集上的所有節點上監聽該端口。當流量到達該端口時,該流量将被路由到運作該服務的容器上。如果所有節點都運作着一個服務的容器,那麼概念是相對标準的;然而,當我們的節點數比副本多時,概念就變得有趣了。

為了添加另一個worker節點,我們隻要簡單地重複第一部分中的安裝步驟。因為我們已經做過這些步驟了,是以我們直接跳到3節點的Swarm叢集。再一次地,我們可以運作<code>docker</code>指令來檢查叢集狀态。

我們可以看到叢集包含三個主機:

swarm-01

swarm-02

swarm-03

當我們建立了兩個副本的服務時,它在<code>swarm-01</code>和<code>swarm-02</code>上分别建立了任務(容器)。即便我們添加了另一個worker節點,我們可以看到情況仍然是這樣的。

Docker Swarm通過replicated服務,可以保證對于每個指定的副本,都運作了一個任務(容器)。當我們建立<code>redis</code>服務時,我們指定了<code>2</code>個副本。這就意味着,即便我們有了第三個節點,Docker也沒有理由在新節點上建立一個新任務。

此時,我們遇到了一個有趣的情形:我們在<code>3</code>個Swarm節點中的<code>2</code>個上運作了服務。在non-swarm的世界中,這就意味着當連接配接第三個Swarm節點時,<code>redis</code>服務将變得不可用。然而,Swarm Mode中,情況卻不是這樣的。

之前,我們提到Docker是如何釋出服務端口的,Swarm在所有節點上都釋出了該端口。有趣的是,當我們連接配接一個并未運作任何容器的worker節點時,會發生什麼呢。

讓我們看一下,當我們連接配接<code>swarm-03</code>的<code>redis</code>端口時,會發生什麼呢。

有趣的是,連接配接竟然成功了。盡管<code>swarm-03</code>上并未運作任何<code>redis</code>容器,但是連接配接成功了。這是因為,在内部,Docker将<code>redis</code>服務流量重路由到運作了<code>redis</code>容器的worker節點。

Docker稱之為入口負載均衡(ingress load balancing)。它的工作方式是,所有worker節點都監聽在釋出的服務端口上。當該服務被外部系統調用時,收到流量的節點會通過Docker提供的内部DNS服務,将流量負載均衡該流量。

是以,即便我們将Swarm叢集擴充至100個worker節點時,<code>redis</code>服務的終端使用者可以連接配接到任意一個worker節點。他們會被重定向到運作了任務(容器)的兩個Docker主控端之一。

這些重路由和負載均衡對于終端使用者是完全透明的。

此時,我們已經建立了<code>redis</code>服務,運作了<code>2</code>個副本,這意味着,<code>3</code>個節點中的<code>2</code>個正在運作容器。

如果我們希望<code>redis</code>服務在每一個worker節點上運作一個執行個體,我們可以簡單地修改服務的副本數目,從<code>2</code>增加到<code>3</code>。這意味着,如果我們增加或者減少worker節點數目,我們需要調整副本數目。

我們可以自動化地做這件事,隻要把我們的服務變成一個Global Service。Docker Swarm Mode中的Global Service使用了建立一個服務,該服務會自動地在每個worker節點上運作任務。這種方法對于像Redis這樣的一般服務都是有效的。

讓我們重新建立<code>redis</code>服務為Global Service。

同樣是<code>docker service create</code>指令,唯一的差別是指定了<code>--mode</code>參數為<code>global</code>。

服務建立好之後,運作<code>docker</code>指令的<code>service ps</code>選項,我們可以看到,Docker是如何分發該服務的。

我們可以看到,一旦該服務被建立為Global Service,那麼每個worker節點上都會運作一個任務。

在本文中,我們不僅安裝了Docker Engine,也建立了一個Swarm叢集,部署了一個有副本的服務,然後建立了Global Service。

<b>原文釋出時間為:</b>2016-10-08

<b>本文作者:</b>夏彬

<b>本文來自雲栖社群合作夥伴Dockerone.io,了解相關資訊可以關注Dockerone.io。</b>

<b></b>

<b>原文标題:</b><b>使用Docker Swarm來運作服務</b>

繼續閱讀