使用Docker Swarm來運行服務

2021-02-15 分布式實驗室


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

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

以下步驟將指導你在Ubuntu 16.04上安裝Docker Engine。對於其他平臺和版本,你可以參考Docker的官方安裝文檔(https://docs.docker.com/engine/installation/#installation)。

設置Docker Apt倉庫

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

添加Docker公鑰

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

# apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D

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

指定Docker倉庫的位置

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

# echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" >> /etc/apt/sources.list.d/docker.list

當我們刷新Apt緩存時,Apt將會搜索sources.list.d/目錄下的所有文件,來尋找新的包倉庫。上述命令會創建一個新文件docker.list,其中包含了一個添加了apt.dockerproject.org倉庫的條目。

更新Apt包緩存

運行apt-get命令的update選項,來刷新Apt包緩存。

# apt-get update

這會觸發Apt重新讀取配置文件,刷新倉庫列表,包含進我們添加的那個倉庫。該命令也會查詢這些倉庫來緩存可用的包列表。

安裝linux-image-extra

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

為了安裝該包,我們將使用apt-get命令的install選項。

# apt-get install linux-image-extra-$(uname -r)

在apt-get命令中,$(uname -r)將返回正在運行的內核的版本。任何對於該系統的內核更新應當包括安裝linux-image-extra,它的版本需要與新內核版本相一致。如果該包沒有正確更新的話,Docker加載卷的功能可能受到影響。

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

# apt-get install docker-engine

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

# docker versionClient:Version:      1.12.0API version:  1.24Go version:   go1.6.3Git commit:   8eab29eBuilt:        Thu Jul 28 22:11:10 2016OS/Arch:      linux/amd64Server:Version:      1.12.0API version:  1.24Go version:   go1.6.3Git commit:   8eab29eBuilt:        Thu Jul 28 22:11:10 2016OS/Arch:      linux/amd64

我們可以看到,Server版本和Client版本都是1.12.0。接下來,我們會創建Swarm集群。

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

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

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

root@swarm-01:~# docker swarm init --advertise-addr 10.0.0.1Swarm initialized: current node (awwiap1z5vtxponawdqndl0e7) is now a manager.To add a worker to this swarm, run the following command:docker swarm join \--token SWMTKN-1-51pzs5ax8dmp3h0ic72m9wq9vtagevp1ncrgik115qwo058ie6-3fokbd3onl2i8r7dowtlwh7kb \10.0.0.1:2377To add a manager to this swarm, run the following command:docker swarm join \--token SWMTKN-1-51pzs5ax8dmp3h0ic72m9wq9vtagevp1ncrgik115qwo058ie6-bwex7fd4u5aov4naa5trcxs34 \10.0.0.1:2377

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

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

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

添加worker節點到Swarm集群中

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

root@swarm-02:~# docker swarm join \> --token SWMTKN-1-51pzs5ax8dmp3h0ic72m9wq9vtagevp1ncrgik115qwo058ie6-3fokbd3onl2i8r7dowtlwh7kb \> 10.0.0.1:2377This node joined a swarm as a worker.

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

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

查看當前的Swarm節點

我們現在有了一個最基本的兩節點的Swarm集群。我們可以執行docker命令的node ls選項來驗證集群的狀態。

root@swarm-01:~# docker node lsID                           HOSTNAME              STATUS  AVAILABILITY  MANAGER STATUS13evr7hmiujjanbnu3n92dphk    swarm-02.example.com  Ready   Active        awwiap1z5vtxponawdqndl0e7 *  swarm-01.example.com  Ready   Active        Leader

從輸出中可以看到,swarm-01和swarm-02都處於Ready和Active狀態。因此,我們可以繼續在Swarm集群上部署服務了。

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

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

部署一個有副本的服務

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

為了創建新服務,我們會使用docker命令的service create選項。以下命令將創建一個名為redis的服務,包含2個副本,並在集群中發布6379埠。

root@swarm-01:~# docker service create --name redis --replicas 2 --publish 6379:6379 rediser238pvukeqdev10nfmh9q1kr

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

root@swarm-01:~# docker service lsID            NAME   REPLICAS  IMAGE  COMMANDer238pvukeqd  redis  2/2       redis

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

root@swarm-01:~# docker service ps redisID                         NAME     IMAGE  NODE                  DESIRED STATE  CURRENT STATE           ERROR5lr10nbpy91csmc91cew5cul1  redis.1  redis  swarm-02.example.com  Running        Running 40 minutes ago  1t77jsgo1qajxxdekbenl4pgk  redis.2  redis  swarm-01.example.com  Running        Running 40 minutes ago

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

連接Redis服務

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

vagrant@vagrant:~$ redis-cli -h swarm-01.example.com -p 6379swarm-01.example.com:6379>

從上面的連接可以看到,我們已經成功地連接上了redis服務。這意味著我們的服務已經運行起來了。

Docker Swarm是如何發布服務的

當我們創建了redis服務時,我們使用了--publish選項。該選項用來告知Docker將埠6379發布為redis服務的可用埠。

當Docker發布了服務埠時,它在Swarm集群上的所有節點上監聽該埠。當流量到達該埠時,該流量將被路由到運行該服務的容器上。如果所有節點都運行著一個服務的容器,那麼概念是相對標準的;然而,當我們的節點數比副本多時,概念就變得有趣了。

添加第三個worker節點

為了添加另一個worker節點,我們只要簡單地重複第一部分中的安裝步驟。因為我們已經做過這些步驟了,所以我們直接跳到3節點的Swarm集群。再一次地,我們可以運行docker命令來檢查集群狀態。

root@swarm-01:~# docker node lsID                           HOSTNAME              STATUS  AVAILABILITY  MANAGER STATUS13evr7hmiujjanbnu3n92dphk    swarm-02.example.com  Ready   Active        awwiap1z5vtxponawdqndl0e7 *  swarm-01.example.com  Ready   Active        Leadere4ymm89082ooms0gs3iyn8vtl    swarm-03.example.com  Ready   Active

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

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

root@swarm-01:~# docker service ps redisID                         NAME     IMAGE  NODE                  DESIRED STATE  CURRENT STATE           ERROR5lr10nbpy91csmc91cew5cul1  redis.1  redis  swarm-02.example.com  Running        Running 55 minutes ago  1t77jsgo1qajxxdekbenl4pgk  redis.2  redis  swarm-01.example.com  Running        Running 55 minutes ago

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

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

在一個無任務運行的worker節點上連接服務

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

讓我們看一下,當我們連接swarm-03的redis埠時,會發生什麼呢。

vagrant@vagrant:~$ redis-cli -h swarm-03.example.com -p 6379swarm-03.example.com:6379>

有趣的是,連接竟然成功了。儘管swarm-03上並未運行任何redis容器,但是連接成功了。這是因為,在內部,Docker將redis服務流量重路由到運行了redis容器的worker節點。

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

因此,即便我們將Swarm集群擴展至100個worker節點時,redis服務的終端用戶可以連接到任意一個worker節點。他們會被重定向到運行了任務(容器)的兩個Docker宿主機之一。

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

讓服務global化

此時,我們已經建立了redis服務,運行了2個副本,這意味著,3個節點中的2個正在運行容器。

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

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

讓我們重新創建redis服務為Global Service。

root@swarm-01:~# docker service create --name redis --mode global --publish 6379:6379 redis5o8m338zmsped0cmqe0guh2to

同樣是docker service create命令,唯一的區別是指定了--mode參數為global。

服務建立好之後,運行docker命令的service ps選項,我們可以看到,Docker是如何分發該服務的。

root@swarm-01:~# docker service ps redisID                         NAME       IMAGE  NODE                  DESIRED STATE  CURRENT STATE           ERROR27s6q5yvmyjvty8jvp5k067ul  redis      redis  swarm-03.example.com  Running        Running 26 seconds ago  2xohhkqvlw7969qj6j0ca70xx   \_ redis  redis  swarm-02.example.com  Running        Running 38 seconds ago  22wrdkun5f5t9lku6sbprqi1k   \_ redis  redis  swarm-01.example.com  Running        Running 38 seconds ago

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

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

在最近的一篇文章(https://blog.codeship.com/getting-started-with-kubernetes/)中,我不僅安裝了Kubernetes,也創建了Kubernetes服務。通過比較Docker Swarm Mode服務和Kubernetes服務,我發現Swarm Mode服務更容易創建。如果只想使用Kubernetes的服務特性,而不需要Kubernetes的其他功能,那麼Docker Swarm Mode可能是一個更容易的選擇。

本文為翻譯文章,點擊閱讀原文連結可查看原文。




相關焦點

  • 使用docker swarm 搭建docker集群
    Swarm 關鍵概念1)Swarm集群的管理和編排是使用嵌入到 docker 引擎的 SwarmKit,可以在 docker 初始化時啟動 swarm 模式或者加入已存在的 swarm(docker swarm –help 查看幫助)docker service:服務創建,子命令有 create, inspect, update, remove, tasks。
  • 代碼級操作指南 如何在Docker Swarm中運行服務
    在本示例中,我們將使用名稱為swarm-01的主機作為節點管理器。要讓swarm-01成為節點管理器,我們需要首先在swarm-01之上執行一條命令以創建Swarm集群。這裡我們使用docker命令配合swarm init選項。
  • Docker Swarm集群管理
    1、Swarm原理Swarm集群由多個運行在swarm mode的docker主機組成,這些docker主機分為管理節點(manager)和工作節點(work node)。Swarm mananger節點負責整個集群的管理工作包括集群配置、服務管理等;Work node節點主要負責運行相應的服務來執行任務(task)。
  • 如何使用Docker Machine創建Swarm集群
    通過本篇文章,讓我們來了解一下Docker Machine,以及如何使用Docker Machine創建Swarm集群。與Docker Compose一樣,Docker Machine 也是旨在幫助開發人員快速使用Docker的工具。
  • 在Docker Swarm模式下,Docker應用如何實現服務發現
    如果你已經安裝了Vagrant和Virtualbox,可用以下方式來啟動一個Docker Swarm集群:$ git clone https://github.com/jlk/docker-swarm-mode-vagrant.gitCloning into 'docker-swarm-mode-vagrant'...
  • 使用Docker Swarm創建Overlay Network
    後來我們使用Machine直接進入高級的主題,使用Docker Swarm來創建一個Docker主機集群。生產級別的分布式應用需在在Docker主機集群上部署。這篇文章中,我們使用Docker Swarm設置允許主機之間的容器互相訪問的網絡。實際上,Swarm集群允許我們使用本地Docker單一的主機網絡,也允許我們創建依賴VXLAN的Overlay Network。
  • 聊聊代碼 Docker Swarm模式下,Docker應用如何實現服務發現
    vagrant@node-1:~$ git clone http://github.com/jlk/wordpress-swarm.gitCloning into 'wordpress-swarm'...remote: Counting objects: 7, done.
  • Kubernetes vs Docker Swarm:有什麼區別?
    在Docker swarm集群的幫助下,管理員以及開發人員可以隨著計算需求的變化而增加或減少容器的迭代次數。對於想要獲得更多支持的公司,還有Docker的Docker企業即服務(EaaS)。EaaS執行所有必要的升級和配置,從客戶身上去除這一負擔。使用AWS或微軟Azure的公司可以 "消費Docker企業3.0"。集群管理和編排也被稱為swarm。
  • 搭建 Docker Swarm GPU 集群 並 部署 OpenFaas 深度學習模型算法服務
    本周狗哥嘗試在 OpenFaas 框架中加入需要使用 GPU 計算的深度學習模型算法服務,因此需要攻克 Docker 中使用 GPU 資源的問題,經過一周的研究實踐,終於找到了 Docker 使用 Nvidia 顯卡資源的方案,此外還編寫了一個基於 Centos 7 的 OpenFaas Python3-Flask 的 Dockerfile
  • Docker 集群工具對比:Kubernetes vs Docker Swarm
    通過 Kubernetes,你可以在容器中使用實際的物理存儲單元,從而可以很方便地把容器移動到其他機器上,從而不丟失任何數據;Kubernetes 使用 flannel 來創建容器之間的網絡;Kubernetes 集成了負載均衡;Kubernetes 使用 etcd 來實現服務發現,諸如此類的東西還有很多。
  • 使用Docker部署Redis集群
    重新本地consul,docker daemon, swarm manager和swarm join$ sudo ./boot_local_docker_services.sh3.指向Docker Swarm請修改終端的環境變量,以便使用已經運行的Docker Swarm$ export DOCKER_HOST=localhost:4000$ env | grep DOCKERDOCKER_HOST=localhost:4000$4.
  • 使用 Elasticsearch 和 cAdvisor 監控 Docker 容器
    Elastic Stack 就一個工具集,包括以下工具:ElasticsearchKibanaLogstashBeats我們會使用其中一部分工具,比如使用 Elasticsearch 來分析基於 JSON 格式的文本,以及使用 Kibana 來可視化數據並產生報表。
  • Docker的安裝與使用
    容器是完全使用沙箱機制,相互之間不會有任何接口,更重要的是容器性能開銷極低。為什麼要用docker?在沒有用docker之前,我們需要在本地,測試,線上部署相同的環境,相同的軟體每個環境都要安裝一次,並且每來一個新同事,相同的環境有要重新安裝一遍,很麻煩且過於重複。
  • Docker 實戰總結(非常全面)
    a)  啟動swarm集群只需要執行初始化命令即可:docker swarm init \       # 默認初始化節點為管理節點--advertise-addr xx.xx.xx.xx \   #指定使用的ip
  • Docker 實戰總結(非常全面),收藏了!
    Docker改變了雲服務,使雲服務的共融共通的理想逐步成為了可能。並且Docker 已經是雲策略的一部分,許多開發者正在計劃使用 Docker 將業務遷移到雲端。另外,為了避免被雲服務供應商綁定,Docker成為很多開發者的首選。Docker改變了產品交付,為產品的整個生命周期提供了一整套的解決方案和流程。
  • 用portainer管理docker服務
    portainer 是一個輕量級的 docker 圖形化管理方案,可以用來管理 docker 宿主機和 docker swarm 集群。提供狀態顯示面板、應用模板快速部署、容器鏡像網絡數據卷的基本操作(包括上傳下載鏡像,創建容器等操作)、事件日誌顯示、容器控制臺操作、Swarm集群和服務等集中管理和操作、登錄用戶管理和控制等功能。
  • docker入門
    卸載本機上舊的dockersudo apt-get update更新aptsudo apt-get install docker-ce安裝doccker ce免費版本,另外還有收費版本doccker eedocker鏡像加速器默認的拉去官方鏡像比較慢,所以使用國內鏡像服務來加速
  • 來了來了!Docker安裝及運行原理
    社區版是免費提供給個人開發者和小型團體使用的,企業版會提供額外的收費服務,比如經過官方測試認證過的基礎設施、容器、插件等。我們平時用社區版就足夠了。所以我們安裝社區版;2,工具準備;首先我們可以按照官方文檔來安裝:https://docs.docker.com/engine/install/centos/虛擬機VMware,系統CentOS7以及連接工具FinalShell
  • 免費學習 Docker 的最佳方法:Play-with-docker(PWD)
    幾天後,Play-with-docker[3](PWD)就誕生了。PWD 像是一個 Docker 遊樂場,用戶在幾秒鐘內就可以運行 Docker 命令。 還可以在瀏覽器中安裝免費的 Alpine Linux 虛擬機,然後在虛擬機裡面構建和運行 Docker 容器,甚至可以使用 Docker 集群模式[4]創建集群。
  • 使用Docker運行SQL Server
    跟.net經常配套使用的SQL SERVER以前一直是windows only,但是從SQL Server 2017開始已經支持運行在docker上,也就說現在SQL Serer已經可以運行在linux下了。