Docker Swarm 模式提供原生容器協調能力,簡化了分散式 Docker 容器叢集的管理。本文從獨立 Docker Engine 的限制出發,逐步介紹 Swarm 模式的核心概念,包含節點管理、服務佈署、資源排程、滾動更新等,並結合 AWS 平台與 Docker Cloud 等服務,提供更全面的實戰。此外,本文也涵蓋網路組態、日誌監控、負載平衡以及高用性網站架設等進階議題,協助讀者建構穩健且可擴充套件的容器化應用。
Docker Swarm 模式設計模式與容器協調
Docker 自2013年3月開放原始碼以來,已成為事實上的容器化平台。單獨的 Docker Engine 無法提供建立分散式 Docker 容器叢集的功能,亦無法擴充套件容器叢集、在特定節點上排程容器或掛載磁碟區。本文主要討論使用 Docker 原生的 Swarm 模式來協調 Docker 容器,該模式於2016年7月隨 Docker 1.12 版本推出。Docker Swarm 模式與舊版獨立的 Docker Swarm 不同,後者不在本文討論範圍內。本文涵蓋了 Docker 協調/管理的各個方面,包括建立 Swarm、使用掛載、排程、擴充套件、資源管理、滾動更新、負載平衡、高用性、日誌記錄和監控、使用多個區域以及網路組態。
為何選擇 Docker Swarm 模式?
在有多種容器叢集管理器可用的情況下,為何選擇 Docker Swarm 模式?Docker Swarm 模式是 Docker 原生的,不需要像其他協調框架那樣進行複雜的安裝。Docker 為 AWS 提供了一個託管服務,使得在生產就緒的 AWS EC2 節點上組態 Swarm 成為可能。Docker Cloud 可以連結到 Docker for AWS,以組態新的 Swarm 或連線到現有的 Swarm。Docker 1.13 版本支援使用 Docker Compose 在 Docker Swarm 上佈署 Docker Stack(一組服務)。
本文內容
第一章:介紹在 CoreOS Linux 上執行獨立的 Docker 容器
本章為本文奠定了基礎,後續章節將討論 Swarm 模式提供的管理設計模式如何解決獨立 Docker Engine 的固有問題。
第二章:介紹 Swarm 模式
包括初始化 Swarm 和將工作節點加入 Swarm。討論了提升/降級節點、使節點(管理員或工作節點)離開 Swarm、重新初始化 Swarm 和修改節點可用性。
第三章:Docker for AWS
討論了託管服務 Docker for AWS,它透過提供 Swarm 引數(包括管理員和工作節點數量以及要使用的 EC2 例項型別)來組態 Docker Swarm。AWS 使用 AWS CloudFormation 建立 Swarm 的資源。Docker for AWS 使跨多個 AWS 區域建立 Swarm 成為可能。
第四章:Docker 服務
定義了兩種型別的服務:複製和全域。討論了建立服務(複製和全域)、擴充套件複製服務、列出服務任務和更新服務。
第五章:擴充套件複製服務
詳細討論了擴充套件複製服務,包括同時擴充套件多個服務。全域服務不可擴充套件。
第六章:掛載
定義了兩種型別的掛載:繫結掛載和磁碟區掛載。討論了建立和使用每種型別的掛載。
第七章:資源管理
討論了在 Swarm 中組態和使用資源。支援兩種型別的資源:記憶體和 CPU。定義了兩種型別的資源組態:保留和限制。討論了建立帶或不帶資源規格的服務。
第八章:排程服務任務
討論了使用預設和自定義排程。還討論了排程約束。
第九章:滾動更新
討論了設定滾動更新策略。提供了不同型別的滾動更新,包括更新到不同的 Docker 映像標籤、新增/刪除環境變數、更新資源限制/保留和更新到不同的 Docker 映像。
第十章:Swarm 模式下的網路組態
討論了內建的疊加網路(ingress)和支援建立自定義疊加網路。
第十一章:日誌記錄和監控
Swarm 本身不提供內建的日誌記錄和監控支援。使用 Sematext Docker 代理程式提供日誌記錄和監控,將指標傳送到 SPM 控制台,將日誌傳送到 Logsene 使用者介面和 Kibana。
第十二章:負載平衡
討論了使用 ingress 負載平衡在服務任務之間進行負載平衡。也可新增外部 AWS 彈性負載平衡器,以將客戶端請求分發到執行 Swarm 的 EC2 例項。
第十三章:高用性網站開發
討論了使用 Amazon Route 53 建立託管區域,並以主/次容錯移轉模式組態資源記錄集。
第十四章:Docker Cloud
另一個託管服務,可用於組態 Docker Swarm 或連線到現有的 Swarm。
第十五章:Docker 服務堆積疊
堆積疊是一組具有依賴關係的服務,在單一組態檔案中定義以進行佈署。
本文讀者物件
本文的主要讀者包括 Docker 管理員、Docker 應用開發人員和容器即服務(CaaS)管理員及開發人員。需要具備 Linux 的基本知識和 Docker 的入門知識,例如使用 Docker 映像執行 Docker 容器、使用 bash shell 連線到容器以及停止和移除 Docker 容器。
內容解密:
本文針對具備一定 Linux 和 Docker 基礎知識的技術人員,旨在深入介紹 Docker Swarm 模式及其在容器協調中的應用。透過閱讀本文,讀者可以全面瞭解 Docker Swarm 的各個方面,從基礎的 Swarm 建立到進階的資源管理、滾動更新和負載平衡等功能。
開始使用 Docker
Docker 已成為容器化的事實標準平台。相較於虛擬機器,Docker 的主要優勢在於其輕量級特性。虛擬機器除了應用程式二進位制檔案外還封裝了完整的作業系統,而 Docker 容器則是應用層的輕量級抽象,只封裝執行應用程式所需的程式碼和依賴項。多個 Docker 容器作為隔離的程式在相同的底層作業系統核心上執行。Docker 支援大多數常用的作業系統,包括多種 Linux 發行版、Windows 和 MacOS。在任何這些平台上安裝 Docker 都需要執行多個命令並設定一些引數。CoreOS Linux 預設安裝了 Docker。本章將介紹如何在 CoreOS 上使用 Docker Engine。本章為後續章節奠定了基礎,後續章節將討論使用 Swarm 模式管理 Docker Engine 的設計模式。本章不使用 Swarm 模式,並與使用 Swarm 模式進行對比。
設定環境
我們將在 Amazon Web Services (AWS) EC2 上使用 CoreOS,您可以在 https://console.aws.amazon.com/ec2/v2/home?region=us-east-1# 存取。點選 Launch Instance 以啟動 EC2 例項。接下來,選擇 CoreOS 的 Amazon Machine Image (AMI)。點選 AWS Marketplace 以尋找 CoreOS AMI。在搜尋欄中輸入 CoreOS 以找到 CoreOS AMI。選擇 Container Linux by CoreOS (Stable),如 EC2 精靈中的圖 1-1 所示,以啟動例項。
步驟詳解:
- 選擇例項型別:選擇 t2.micro 型別並點選 Next。
- 組態例項詳細資訊:指定例項數量為 1。選擇網路或點選 Create New VPC 以建立新的 VPC。選擇子網路或點選 Create New Subnet 以建立新的子網路。選擇 Enable 以自動分配公有 IP。點選 Next。
- 新增儲存:選擇預設設定並點選 Next。
- 新增標籤:無需新增標籤。點選 Next。
- 組態安全群組:新增安全群組以允許所有流量透過任何協定在所有埠範圍內從任何來源 (0.0.0.0/0) 存取。點選 Review and Launch,隨後點選 Launch。
- 選擇金鑰對:選擇金鑰對並點選 Launch Instances,如圖 1-2 所示。
登入 EC2 例項
啟動具有 CoreOS 的 EC2 例項後,從 EC2 控制檯取得例項的公有 DNS 或 IPv4 公有 IP 位址,如圖 1-3 所示,以使用 SSH 登入例項。
ssh -i "coreos.pem" core@<public ip>
執行 Docker 應用程式
如前所述,Docker 預先安裝在 CoreOS 上。執行 docker 命令以列出其用法,如下所示:
core@ip-172-30-4-75 ~ $ docker
Usage: docker [OPTIONS] COMMAND [arg...]
docker [ --help | -v | --version ]
...
Docker 版本驗證
使用 docker version 命令輸出 Docker 版本。對於原生 Docker Swarm 支援,Docker 版本必須為 1.12 或更高版本,如下所示:
core@ip-172-30-4-75 ~ $ docker version
Client:
Version: 1.12.6
API version: 1.24
Go version: go1.7.5
Git commit: a82d35e
Built: Mon Jun 19 23:04:34 2017
OS/Arch: linux/amd64
Server:
Version: 1.12.6
API version: 1.24
Go version: go1.7.5
Git commit: a82d35e
Built: Mon Jun 19 23:04:34 2017
OS/Arch: linux/amd64
執行 Hello World 應用程式
使用 tutum/hello-world Docker 映象執行 Hello World 應用程式。
docker run -d -p 8080:80 --name helloapp tutum/hello-world
#### 內容解密:
此命令的作用是從 tutum/hello-world 映象建立並執行一個名為 helloapp 的容器,將容器的 80 埠對映到主機的 8080 埠。-d 表示以分離模式執行容器。
core@ip-172-30-4-75 ~ $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1b7a85df6006 tutum/hello-world "/bin/sh -c 'php-fpm " 19 minutes ago Up 19 minutes 0.0.0.0:8080->80/tcp helloapp
#### 內容解密:
docker ps 命令用於列出正在執行的容器。此輸出顯示了容器的 ID、使用的映象、執行的命令、建立時間、狀態、埠對映和容器名稱。
使用 curl 命令存取 Hello World 應用程式。
curl localhost:8080
#### 內容解密:
此命令向本地主機的 8080 埠傳送 HTTP 請求,取得 Hello World 應用程式的輸出。
<html>
<head>
<title>Hello world!</title>
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
<style>
body {
background-color: white;
text-align: center;
padding: 50px;
font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
}
#logo {
margin-bottom: 40px;
}
</style>
</head>
<body>
<img id="logo" src="logo.png" />
<h1>Hello world!</h1>
<h3>My hostname is 1b7a85df6006</h3>
</body>
</html>
#### 內容解密:
這是 Hello World 網頁的 HTML 原始碼。它顯示了一個簡單的網頁,包含一張圖片和一段文字,其中包含容器的主機名。
此外,也可以使用 EC2 例項的公有 DNS 在瀏覽器中存取 Hello World 應用程式,如圖 1-4 所示。
使用 Docker 在 Swarm 模式下
Docker Engine 是一種容器化平台,用於執行 Docker 容器。多個 Docker 容器在相同的底層作業系統核心上隔離執行,每個容器都有自己的網路和檔案系統。每個 Docker 容器都是應用程式及其依賴項的封裝,不會產生封裝完整作業系統的額外負擔。Docker 應用程式從 Docker 映像檔在 Docker 容器中執行,每個 Docker 映像檔都特定於特定的應用程式或軟體。Docker 映像檔是從 Dockerfile 構建的,Dockerfile 定義了下載和安裝軟體、設定環境變數和執行命令的指令集。
問題
雖然 Docker Engine 在 1.12 版本之前(無原生 Swarm 模式)非常適合在輕量級容器中執行應用程式,但它缺乏一些功能,主要包括:
- 無分散式運算:Docker Engine 安裝並執行在單一節點或作業系統例項上,因此不提供分散式運算。
- 無故障容忍:如果單一節點上的 Docker Engine 失敗,則在其上執行的 Docker 應用程式也會失敗。
解決方案
從 Docker Engine 1.12 版本開始,Docker 容器協調被整合到 Docker Engine 的 Swarm 模式中,並且是 Docker Engine 的原生功能。使用 Swarm 模式,可以在多台機器(作業系統例項)上執行一個由多個節點組成的叢集(swarm)。Docker Swarm 模式預設不會在 Docker Engine 中啟用,需要使用 docker 命令進行初始化。
Docker Swarm 模式
Docker Swarm 是由多個 Docker 主機透過覆寫網路(overlay networking)連線而成的叢集,用於服務發現。一個 Docker Swarm 包括一個或多個管理節點(manager nodes)和一個或多個工作節點(worker nodes)。在 Swarm 模式下,Docker 服務是 Docker 容器化的單位。從管理節點建立的服務的 Docker 容器會被佈署或排程到叢集中的各個節點上,並且 Swarm 內建了負載平衡功能,以擴充套件服務。
節點
Docker 主機(Docker Engine)的例項稱為節點。有兩種型別的節點角色:管理節點和工作節點。
服務
服務是分散在 Swarm 中的一組任務(也稱為副本或副本任務)的抽象。例如,一個服務可以執行三個 Nginx 伺服器的副本。預設的排程策略使用“spread”排程策略,根據計算出的節點排名將任務分散到叢集中的各個節點。一個服務由一個或多個獨立執行的任務組成,這意味著停止一個任務或啟動一個新任務不會影響其他正在執行的任務。
期望狀態
服務的“期望狀態”是指在建立服務時在服務定義中定義的服務狀態。例如,服務定義可以定義一個由三個 Nginx 伺服器副本組成的服務。
管理節點和 Raft 共識
當 Swarm 第一次建立時,當前的節點成為第一個管理節點。預設情況下,所有管理節點也是工作節點。管理節點執行叢集協調和管理 Swarm,包括初始排程服務任務和隨後在期望狀態和實際狀態之間進行協調。例如,對於一個由三個 Nginx 伺服器副本組成的服務定義,管理節點將建立三個任務,並將這些任務排程到 Swarm 中的工作節點上。隨後,如果執行任務的節點失敗,Swarm 管理員將在仍然在 Swarm 中的工作節點上啟動新的替換任務。
Raft 共識演算法
Swarm 使用 Raft 共識演算法在管理節點之間達成關於全域叢集狀態引數(如資料函式庫中儲存的資料值的狀態)的共識。Raft 共識是一種協定,用於在 Swarm 中的所有可達管理節點之間實作分散式共識。Raft 共識演算法具有分散式系統中常見的屬性,例如:
- 為了容錯而達成值的共識
- 叢整合員管理
- 使用互斥進行長官者選舉
只有一個管理節點,稱為長官者,執行所有叢集協調和管理。只有長官者節點執行服務排程、擴充套件和重新啟動服務任務。其他管理節點用於 Swarm 管理員的容錯,這意味著如果長官者節點失敗,其中一個其他管理節點將被選舉為新的長官者並接管叢集管理。長官者選舉是由大多數管理節點的共識完成的。
程式碼範例與說明
以下是一個簡單的使用 Docker Swarm 的範例:
# 初始化Swarm
docker swarm init
# 建立一個服務
docker service create --name mynginx --replicas 3 nginx
# 檢視服務狀態
docker service ls
# 檢視服務詳細資訊
docker service inspect mynginx
# 縮放服務
docker service scale mynginx=5
# 更新服務
docker service update --image nginx:latest mynginx
# 刪除服務
docker service rm mynginx
程式碼解密:
docker swarm init: 初始化一個新的Swarm叢集,並將當前節點設定為管理節點。docker service create --name mynginx --replicas 3 nginx: 建立一個名為mynginx的服務,使用nginx映像檔,並指定啟動3個副本。docker service ls: 列出所有正在執行的服務。docker service inspect mynginx: 檢視mynginx服務的詳細組態和狀態資訊。docker service scale mynginx=5: 將mynginx服務擴充套件到5個副本。docker service update --image nginx:latest mynginx: 更新mynginx服務的映像檔為最新的nginx版本。docker service rm mynginx: 刪除mynginx服務。
這個範例展示瞭如何使用 Docker Swarm 建立、管理和更新一個簡單的 Nginx 服務。透過這些命令,可以輕鬆實作容器的協調和擴充套件,提升應用的可用性和彈性。