管理和維護 Docker Engine 的 swarm
當您執行 Docker 引擎的 swarm 時,管理器節點是管理 swarm 和儲存 swarm 狀態的關鍵元件。瞭解管理器節點的一些關鍵特性對於正確部署和維護 swarm 非常重要。
有關 Docker Swarm 模式的簡要概述以及管理器和工作節點之間的區別,請參閱節點如何工作。
在 swarm 中操作管理器節點
Swarm 管理器節點使用 Raft 共識演算法來管理 swarm 狀態。您只需要瞭解 Raft 的一些一般概念即可管理 swarm。
管理器節點的數量沒有限制。實施多少個管理器節點的決定是效能和容錯之間的權衡。向 swarm 新增管理器節點可以使 swarm 更具容錯性。但是,額外的管理器節點會降低寫入效能,因為更多節點必須確認更新 swarm 狀態的提案。這意味著更多的網路往返流量。
Raft 需要大多數管理器(也稱為法定人數)同意對 swarm 的提議更新,例如節點的新增或刪除。成員資格操作受到與狀態複製相同的約束。
維護管理器的法定人數
如果 swarm 失去了管理器的法定人數,swarm 就無法執行管理任務。如果您的 swarm 有多個管理器,請始終保持兩個以上。為了維持法定人數,大多數管理器必須可用。建議使用奇數個管理器,因為下一個偶數並不會使法定人數更容易維持。例如,無論您有 3 個還是 4 個管理器,您仍然只能失去 1 個管理器並維持法定人數。如果您有 5 個或 6 個管理器,您仍然只能失去兩個。
即使一個 swarm 失去了管理器的法定人數,現有工作節點上的 swarm 任務仍會繼續執行。但是,swarm 節點不能被新增、更新或刪除,新的或現有的任務不能被啟動、停止、移動或更新。
如果您確實失去了管理器的法定人數,請參閱從失去法定人數中恢復以獲取故障排除步驟。
配置管理器以在靜態 IP 地址上進行廣播
在初始化一個 swarm 時,您必須指定 --advertise-addr
標誌,以便向 swarm 中的其他管理器節點廣播您的地址。有關更多資訊,請參閱在 swarm 模式下執行 Docker 引擎。因為管理器節點旨在成為基礎設施的穩定元件,您應該為廣播地址使用一個固定的 IP 地址,以防止 swarm 在機器重啟時變得不穩定。
如果整個 swarm 重啟,並且每個管理器節點隨後都獲得了一個新的 IP 地址,那麼任何節點都無法聯絡到現有的管理器。因此,當節點嘗試用舊的 IP 地址相互聯絡時,swarm 會掛起。
動態 IP 地址對於工作節點來說是可以的。
新增管理器節點以實現容錯
您應該在 swarm 中維護奇數個管理器,以支援管理器節點故障。擁有奇數個管理器可確保在網路分割槽期間,如果網路被分成兩組,法定人數有更高的機會保持可用以處理請求。如果您遇到兩個以上的網路分割槽,則無法保證維持法定人數。
Swarm 大小 | 多數 | 容錯能力 |
---|---|---|
1 | 1 | 0 |
2 | 2 | 0 |
3 | 2 | 1 |
4 | 3 | 1 |
5 | 3 | 2 |
6 | 4 | 2 |
7 | 4 | 3 |
8 | 5 | 3 |
9 | 5 | 4 |
例如,在一個有 5 個節點的 swarm 中,如果您失去了 3 個節點,您就沒有法定人數。因此,您不能新增或刪除節點,直到您恢復一個不可用的管理器節點或使用災難恢復命令恢復 swarm。請參閱從災難中恢復。
雖然可以將 swarm 縮減到單個管理器節點,但不可能降級最後一個管理器節點。這可以確保您保持對 swarm 的訪問,並且 swarm 仍然可以處理請求。縮減到單個管理器是一個不安全的操作,不推薦使用。如果在降級操作期間最後一個節點意外離開 swarm,swarm 將變得不可用,直到您重新啟動該節點或使用 --force-new-cluster
重新啟動。
您可以使用 docker swarm
和 docker node
子系統管理 swarm 成員資格。有關如何新增工作節點和將工作節點提升為管理器的更多資訊,請參閱向 swarm 新增節點。
分發管理器節點
除了維護奇數個管理器節點外,在放置管理器時還要注意資料中心拓撲。為了獲得最佳的容錯性,請將管理器節點分佈在至少 3 個可用區,以支援整套機器的故障或常見的維護場景。如果您在任何一個區域遇到故障,swarm 應該保持管理器節點的法定人數可用,以處理請求和重新平衡工作負載。
Swarm 管理器節點 | 重新分割槽(在 3 個可用區) |
---|---|
3 | 1-1-1 |
5 | 2-2-1 |
7 | 3-2-2 |
9 | 3-3-3 |
執行僅管理器的節點
預設情況下,管理器節點也充當工作節點。這意味著排程程式可以將任務分配給管理器節點。對於小型和非關鍵的 swarm,只要您使用 CPU 和記憶體的資源約束來排程服務,將任務分配給管理器相對風險較低。
然而,由於管理器節點使用 Raft 共識演算法以一致的方式複製資料,它們對資源匱乏很敏感。您應該將 swarm 中的管理器與可能阻塞 swarm 操作(如 swarm 心跳或領導者選舉)的程序隔離開來。
為避免干擾管理器節點操作,您可以排空管理器節點,使其作為工作節點不可用
$ docker node update --availability drain <NODE>
當您排空一個節點時,排程程式會將該節點上執行的任何任務重新分配給 swarm 中其他可用的工作節點。它還會阻止排程程式向該節點分配任務。
新增工作節點以實現負載均衡
向 swarm 新增節點以平衡您的 swarm 的負載。只要工作節點符合服務的要求,複製的服務任務就會隨著時間的推移儘可能均勻地分佈在整個 swarm 中。當將服務限制為僅在特定型別的節點上執行時,例如具有特定數量 CPU 或記憶體量的節點,請記住不滿足這些要求的工作節點無法執行這些任務。
監控 swarm 健康狀況
您可以透過 HTTP /nodes
端點以 JSON 格式查詢 docker nodes
API 來監控管理器節點的健康狀況。有關更多資訊,請參閱nodes API 文件。
在命令列中,執行 docker node inspect <id-node>
來查詢節點。例如,查詢節點作為管理器的可達性
$ docker node inspect manager1 --format "{{ .ManagerStatus.Reachability }}"
reachable
查詢節點作為接受任務的工作節點的狀態
$ docker node inspect manager1 --format "{{ .Status.State }}"
ready
從這些命令中,我們可以看到 manager1
作為管理器處於 reachable
狀態,作為工作節點處於 ready
狀態。
一個 unreachable
的健康狀態意味著這個特定的管理器節點無法從其他管理器節點訪問。在這種情況下,您需要採取措施來恢復無法訪問的管理器
- 重新啟動守護程序,看看管理器是否恢復為可達狀態。
- 重啟機器。
- 如果重啟或重啟都不起作用,您應該新增另一個管理器節點或將一個工作節點提升為管理器節點。您還需要使用
docker node demote <NODE>
和docker node rm <id-node>
從管理器集中乾淨地刪除失敗的節點條目。
或者,您也可以從管理器節點使用 docker node ls
獲取 swarm 健康狀況的概覽
$ docker node ls
ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS
1mhtdwhvsgr3c26xxbnzdc3yp node05 Accepted Ready Active
516pacagkqp2xc3fk9t1dhjor node02 Accepted Ready Active Reachable
9ifojw8of78kkusuc4a6c23fx * node01 Accepted Ready Active Leader
ax11wdpwrrb6db3mfjydscgk7 node04 Accepted Ready Active
bb1nrq2cswhtbg4mrsqnlx1ck node03 Accepted Ready Active Reachable
di9wxgz8dtuh9d2hn089ecqkf node06 Accepted Ready Active
對管理器節點進行故障排除
您永遠不應該透過從另一個節點複製 raft
目錄來重新啟動管理器節點。資料目錄對於一個節點 ID 是唯一的。一個節點只能使用一個節點 ID 一次加入 swarm。節點 ID 空間應該是全域性唯一的。
要乾淨地將管理器節點重新加入叢集
- 使用
docker node demote <NODE>
將節點降級為工作節點。 - 使用
docker node rm <NODE>
從 swarm 中刪除節點。 - 使用
docker swarm join
以全新狀態將節點重新加入 swarm。
有關將管理器節點加入 swarm 的更多資訊,請參閱將節點加入 swarm。
強制刪除節點
在大多數情況下,您應該在用 docker node rm
命令從 swarm 中刪除節點之前先關閉它。如果一個節點變得無法訪問、無響應或被入侵,您可以透過傳遞 --force
標誌強制刪除該節點而不關閉它。例如,如果 node9
被入侵
$ docker node rm node9
Error response from daemon: rpc error: code = 9 desc = node node9 is not down and can't be removed
$ docker node rm --force node9
Node node9 removed from swarm
在強制刪除管理器節點之前,必須先將其降級為工作節點角色。如果您降級或刪除管理器,請確保始終有奇數個管理器節點。
備份 swarm
Docker 管理器節點將 swarm 狀態和管理器日誌儲存在 /var/lib/docker/swarm/
目錄中。此資料包括用於加密 Raft 日誌的金鑰。沒有這些金鑰,您無法恢復 swarm。
您可以使用任何管理器來備份 swarm。請使用以下步驟。
如果 swarm 啟用了自動鎖定,您需要解鎖金鑰才能從備份中恢復 swarm。如有必要,請檢索解鎖金鑰並將其存放在安全的位置。如果您不確定,請閱讀鎖定您的 swarm以保護其加密金鑰。
在備份資料之前,請在管理器上停止 Docker,以便在備份期間沒有資料被更改。可以在管理器執行時進行備份(“熱”備份),但不推薦這樣做,恢復時的結果可預測性較差。當管理器關閉時,其他節點會繼續生成不屬於此備份的 swarm 資料。
注意確保維護 swarm 管理器的法定人數。在管理器關閉期間,如果更多節點丟失,您的 swarm 將更容易失去法定人數。您執行的管理器數量是一種權衡。如果您定期關閉管理器進行備份,請考慮執行一個五管理器的 swarm,這樣在備份執行時您可以再失去一個管理器,而不會中斷您的服務。
備份整個
/var/lib/docker/swarm
目錄。重新啟動管理器。
要恢復,請參閱從備份中恢復。
從災難中恢復
從備份中恢復
在按照備份 swarm 中所述備份 swarm 後,使用以下步驟將資料恢復到一個新的 swarm。
在用於恢復 swarm 的目標主機上關閉 Docker。
移除新 swarm 上
/var/lib/docker/swarm
目錄的內容。用備份的內容恢復
/var/lib/docker/swarm
目錄。注意新節點使用與舊節點相同的磁碟儲存加密金鑰。目前無法更改磁碟儲存加密金鑰。
在啟用了自動鎖定的 swarm 中,解鎖金鑰也與舊 swarm 上的相同,並且需要解鎖金鑰來恢復 swarm。
在新節點上啟動 Docker。如有必要,解鎖 swarm。使用以下命令重新初始化 swarm,以便此節點不會嘗試連線到屬於舊 swarm 且可能已不存在的節點。
$ docker swarm init --force-new-cluster
驗證 swarm 的狀態是否符合預期。這可能包括特定於應用程式的測試,或者簡單地檢查
docker service ls
的輸出以確保所有預期的服務都存在。如果您使用自動鎖定,請輪換解鎖金鑰。
新增管理器和工作節點,使您的新 swarm 達到執行能力。
在新 swarm 上恢復您以前的備份方案。
從失去法定人數中恢復
Swarm 對故障具有彈性,可以從任何數量的臨時節點故障(機器重啟或崩潰後重啟)或其他瞬時錯誤中恢復。但是,如果 swarm 失去法定人數,則無法自動恢復。現有工作節點上的任務會繼續執行,但管理任務(包括擴充套件或更新服務以及從 swarm 加入或移除節點)將無法進行。最好的恢復方法是讓丟失的管理器節點重新上線。如果無法做到這一點,請繼續閱讀以瞭解一些恢復 swarm 的選項。
在擁有 N
個管理器的 swarm 中,必須始終有法定人數(多數)的管理器節點可用。例如,在一個有五個管理器的 swarm 中,至少必須有三個管理器處於執行狀態並相互通訊。換句話說,swarm 可以容忍最多 (N-1)/2
個永久性故障,超出這個數量,涉及 swarm 管理的請求就無法處理。這些型別的故障包括資料損壞或硬體故障。
如果您失去了管理器的法定人數,您就無法管理 swarm。如果您失去了法定人數並試圖對 swarm 執行任何管理操作,將會出現錯誤
Error response from daemon: rpc error: code = 4 desc = context deadline exceeded
從失去法定人數中恢復的最佳方法是讓發生故障的節點重新上線。如果您無法做到這一點,從這種狀態恢復的唯一方法是從一個管理器節點使用 --force-new-cluster
操作。這將移除除執行該命令的管理器之外的所有管理器。由於現在只有一個管理器,因此達到了法定人數。將節點提升為管理器,直到您擁有所需數量的管理器。
從要恢復的節點執行
$ docker swarm init --force-new-cluster --advertise-addr node01:2377
當您使用 --force-new-cluster
標誌執行 docker swarm init
命令時,您執行該命令的 Docker 引擎將成為一個單節點 swarm 的管理器節點,該 swarm 能夠管理和執行服務。該管理器擁有所有關於服務和任務的先前資訊,工作節點仍然是 swarm 的一部分,服務也仍在執行。您需要新增或重新新增管理器節點,以實現您之前的任務分發,並確保您有足夠的管理器來維持高可用性並防止失去法定人數。
強制 swarm 重新平衡
通常,您不需要強制 swarm 重新平衡其任務。當您向 swarm 新增一個新節點,或者一個節點在一段時間不可用後重新連線到 swarm 時,swarm 不會自動將工作負載分配給空閒節點。這是一個設計決策。如果 swarm 為了平衡而定期將任務轉移到不同的節點,那麼使用這些任務的客戶端將會中斷。目標是避免為了 swarm 的平衡而中斷正在執行的服務。當新任務啟動時,或者當執行任務的節點變得不可用時,這些任務會被分配給較不繁忙的節點。目標是最終的平衡,對終端使用者的干擾最小。
您可以使用 docker service update
命令的 --force
或 -f
標誌來強制服務在可用的工作節點之間重新分配其任務。這將導致服務任務重啟。客戶端應用程式可能會中斷。如果您已配置,您的服務將使用滾動更新。
如果您使用的是早期版本,並且希望在工作節點之間實現負載的均勻平衡,且不介意中斷正在執行的任務,您可以透過臨時向上擴充套件服務來強制您的 swarm 重新平衡。使用 docker service inspect --pretty <servicename>
來檢視服務的配置規模。當您使用 docker service scale
時,任務數量最少的節點將被目標接收新的工作負載。您的 swarm 中可能存在多個負載不足的節點。您可能需要多次以適度的增量向上擴充套件服務,以在所有節點上實現您想要的平衡。
當負載平衡到您滿意的程度時,您可以將服務縮減回原始規模。您可以使用 docker service ps
來評估您服務在各節點間的當前平衡狀況。