在建構生產級 Docker 叢集時,穩定且高效的組態至關重要。本文建議採用 Ubuntu Server 16.04.3 LTS 與 Linux Kernel 4.4 LTS 的組合,搭配 Docker CE 17.06.2 或 17.09.1 版本,並使用 Overlay2 作為儲存驅動程式,以確保基礎環境的穩定性及與 Docker 的高度相容性。網路層面,建議捨棄 Docker 預設的 overlay 網路,改用 WeaveWorks 等效能更佳的網路外掛,搭配 Træfik 負載平衡器,實作服務請求的有效路由與管理。此外,整合 Envoy 作為 Sidecar Proxy,可實作分散式追蹤,提升服務監控與問題排查效率。文章也探討了在 AWS Spot 例項上佈署 Docker Swarm 叢集的策略,以及如何透過使用者資料指令碼自動化節點組態,有效降低營運成本。最後,文章以 Python 程式碼示例說明如何實作帶有指數退避的重試機制,提升服務的容錯能力與穩定性。

穩定化叢集組態

在建立Docker叢集時,首先需要謹慎地穩定化叢集組態。目前,Docker叢集的最佳組態如下:

作業系統與核心版本

  • Ubuntu Server 16.04.3 LTS:雖然Red Hat Linux或CentOS可能更適合某些使用場景,但Ubuntu Server因其易用性和與Docker的良好相容性而被廣泛採用。Docker在Ubuntu Server上的測試最為充分。
  • Linux Kernel 4.4 LTS:4.4核心是一個長期支援版本(LTS),非常適合Docker環境。雖然4.9核心也是一個不錯的選擇,但過於新的核心(如4.13)可能與Docker的相容性尚待驗證。

Docker儲存驅動程式

  • Overlay2:對於執行在4.4+核心上的Docker,overlay2應該成為預設的儲存驅動程式。AUFS曾經是Docker的常用儲存驅動,但在新版本中,overlay2提供了更好的效能和穩定性。在CentOS或RHEL 7.4上,overlay2也是一個很好的選擇。

Docker版本

  • Docker CE 17.06.2 或 17.09.1:這兩個版本都是穩定且適合生產環境的選擇。如果你有企業支援,Docker EE 17.06也是一個很好的選擇。

穩定的Docker Swarm堆積疊組態

  graph LR
    A[Ubuntu Server 16.04.3 LTS] --> B[Linux Kernel 4.4 LTS]
    B --> C[Docker CE 17.06.2 或 17.09.1]
    C --> D[Overlay2 儲存驅動]
    D --> E[WeaveWorks 網路外掛]
    E --> F[Træfik 負載平衡]
    F --> G[Envoy 分散式追蹤]

圖表翻譯: 上圖展示了一個穩定的Docker Swarm叢集組態,包括作業系統、核心版本、Docker版本、儲存驅動程式、網路外掛以及負載平衡和分散式追蹤元件。

選擇適當的網路外掛

長久以來,Docker預設的overlay網路被認為不適合生產環境。儘管其品質不斷提升,但我們仍然可以考慮其他網路外掛以獲得最佳效能。例如,可以使用WeaveWorks或Contiv來替換預設的overlay驅動程式。本章節中,我們使用WeaveWorks網路外掛版本2。

為什麼選擇WeaveWorks?

WeaveWorks網路外掛使用了與Kubernetes CNI相同的底層網路實作,並且經過了開發團隊的嚴格測試,在生產叢集中的表現非常出色。為了避免當前overlay網路驅動程式中的斷線問題,建議完全移除根據預設overlay網路驅動程式的ingress網路。

新的Ingress和路由機制

由於我們將移除預設的Docker ingress網路,因此需要建立自己的路由機制。如圖7.2所示,我們將使用根據L7負載平衡器Træfik構建新的ingress層,以實作對叢集中服務的請求路由。

Træfik的優勢

  • 自動解析服務為IP位址列表。
  • 可以選擇使用Docker Swarm提供的根據IPVS的負載平衡器,或是Træfik內建的負載平衡機制。
  • 支援根據主機名稱匹配服務,並將請求轉發到特定的服務任務。
  • 可以在不影響執行中的服務的前提下,靈活地重新啟動或重新組態ingress層。

分散式追蹤元件

在本文提出的架構中,我們為每個佈署的函式使用Envoy作為Sidecar Proxy。Envoy允許函式之間的分散式追蹤呼叫,即使這些函式是由不同的FaaS平台準備或佈署的。這是避免供應商鎖定的重要一步。

Envoy作為Sidecar Proxy的兩種組態

  1. 直接嵌入EnvoyProxy到Docker映像檔中:這種方式效能最佳,因為EnvoyProxy透過容器內的迴環介面與函式程式通訊。但是,當需要更改Envoy的組態時,需要重新啟動EnvoyProxy和函式例項。

  2. 將EnvoyProxy作為Edge Proxy分離出來:這種方式在管理和靈活性方面更具優勢,但會引入EnvoyProxy和函式容器之間的網路開銷。

  graph LR
    A[函式例項] -->|迴環介面|> B[EnvoyProxy Sidecar]
    A -->|HTTP請求|> C[外部服務]
    subgraph 容器內部
        A
        B
    end

    subgraph 組態1
        D[函式容器] -->|包含|> B
    end

    subgraph 組態2
        E[EnvoyProxy Edge Proxy] -->|請求轉發|> F[函式容器]
    end

圖表翻譯: 上圖展示了兩種使用Envoy作為Sidecar Proxy的組態,第一種是將EnvoyProxy直接嵌入函式容器,第二種是將EnvoyProxy作為Edge Proxy獨立出來。

重試和斷路器模式

在本文中,我們將討論重試和斷路器模式,這些模式對於解決服務鏈中的級聯故障至關重要。

重試機制

當服務鏈中的某個服務或函式不可用時,會導致整體可用性下降。例如,如果五個不同的函式或服務各有99%的可用性,那麼客戶端體驗到的整體可用性將降低到95.09%。為瞭解決這個問題,我們需要在發生錯誤(如HTTP 500)時重試呼叫另一個服務或函式例項。

然而,簡單的重試機制可能會增加對已經故障的服務的不必要負載,因此需要更為智慧的重試策略。

import random
import time

def retry_with_backoff(func, max_retries=3, backoff_factor=0.5):
    retries = 0
    while retries < max_retries:
        try:
            return func()
        except Exception as e:
            print(f"嘗試失敗:{e}")
            retries += 1
            time.sleep(backoff_factor * (2 ** retries))
    raise Exception("達到最大重試次數")

# 示例用法:
def example_function():
    if random.random() < 0.5:  # 模擬50%失敗率
        raise Exception("模擬錯誤")
    return "成功"

result = retry_with_backoff(example_function)
print(result)

內容解密:

這段程式碼實作了一個帶有指數退避的重試機制。retry_with_backoff函式接受一個需要執行的函式func,並設定最大重試次數max_retries和退避因子backoff_factor。每次重試失敗後,等待時間會指數增加,以避免對故障服務造成額外負載。這種機制在分散式系統中非常有用,可以提高整體的可靠性和彈性。

本篇文章詳細討論瞭如何穩定化Docker叢集組態,包括選擇適當的作業系統、核心版本、Docker版本和儲存驅動程式。同時,我們還探討了使用WeaveWorks網路外掛和Træfik負載平衡器來最佳化叢集網路,以及如何使用Envoy實作分散式追蹤。此外,我們還深入討論了重試和斷路器模式對於提高系統可靠性的重要性,並提供了一個Python範例來說明如何實作帶有指數退避的重試機制。這些技術對於建立一個高效、可靠的生產級Docker叢集至關重要。

在AWS Spot例項上準備生產級Docker Swarm叢集以執行FaaS平台

使用Spot例項節省成本

當我們談論雲端運算時,其按需例項的價格其實已經相當便宜。然而,從長遠來看,使用雲端例項的成本最終會與購買實體機器相差無幾。為瞭解決這個定價問題,主要的雲端供應商,如Amazon EC2和Google Cloud Platform,提供了一種新的例項型別,在本文中統稱為Spot例項。

Spot例項的特點

Spot例項比按需例項便宜得多,但其缺點是生命週期短且可能被意外終止。也就是說,Spot例項可能在任何時候被終止。當它被終止時,我們可以選擇是否保留或完全丟棄其儲存卷。在AWS上,例項會在終止前約120秒透過遠端後設資料接收通知,而在Google Cloud上,則會在機器停止前30秒透過ACPI訊號傳送通知。兩者的比較如前圖所示。

在AWS上使用EC2 Spot例項

在Amazon EC2上,存取https://aws.amazon.com/ec2/spot/,我們會看到如下所示的頁面。登入AWS控制檯以設定Spot例項:

請求Spot例項的三種模式

  1. 一次性請求:這是一次性的請求,當例項被終止後,我們需要再次發起請求。
  2. 請求一組例項並讓AWS維護目標例項數量:當某些例項被終止時,AWS會盡力根據我們的最大競價分配例項,以滿足每個佇列的目標數量。本章中我們選擇了這種請求模式。
  3. 請求固定時間段的例項:固定時間段稱為Spot區塊,可以設定在1到6小時之間。設定較長時間段將需要支付更多費用。

準備Docker Swarm叢集

假設我們已經有三台機器被組態為管理節點。為了獲得最便宜的費率,建議使用三台按需EC2節點作為Docker管理節點,並使用N-3台Spot例項作為Docker工作節點。我們從三台Spot工作節點開始。

叢集初始化

首先,透過SSH登入我們希望作為第一個管理節點的機器,安裝Docker,並在其上執行docker swarm init命令。eth0是由雲端供應商提供的私有網路介面。在繼續之前,請使用ip addr命令檢查您的介面。如果您知道哪個介面是私有的,請使用以下命令初始化叢集:

$ docker swarm init --advertise-addr=eth0

接下來,透過SSH登入其他兩台節點,安裝Docker,並使用docker swarm join命令加入叢集。不要忘記使用管理節點的加入令牌,而不是工作節點的令牌。下面的例子中的令牌是管理節點令牌。請注意,在此設定過程中,我的第一個管理節點的IP是172.31.4.52,請將其替換為您的IP位址:

$ docker swarm join --token SWMTKN-1-5rvucdwofoam27qownciovd0sngpm31825r2wbdz1jdneiyfyt-b5bdh4i2jzev4aq4oid1pubi6 172.31.4.52:2377

對於這前三台節點,不要忘記將它們標記為管理節點,以便您記住。


#### 內容解密:
此步驟用於初始化Docker Swarm叢集並將節點加入叢集。
1. `docker swarm init --advertise-addr=eth0` 命令用於初始化Swarm叢集,並指定通告地址為eth0介面。
2. `docker swarm join` 命令用於將其他節點加入Swarm叢集,需要指定加入令牌和管理節點的地址。
3. 將節點標記為管理節點,以方便管理和識別。

驗證叢集狀態

請確保docker info命令顯示管理節點列表,包含所有私有的IP地址。我們使用grep -A3來檢視目標後的下三行:

$ docker info | grep -A3 "Manager Addresses:"
Manager Addresses:
172.31.0.153:2377
172.31.1.223:2377
172.31.4.52:2377

或者,如果您熟悉jq命令,可以嘗試以下操作:

$ docker info --format="{{json .Swarm.RemoteManagers}}" | jq -r .[].Addr
172.31.4.52:2377
172.31.1.223:2377
172.31.0.153:2377

docker info命令也接受--format引數,讓我們自定義輸出。在前面的例子中,我們使用了範本提供的JSON方法生成JSON輸出。然後,我們使用jq查詢所有Swarm管理節點的IP地址。JSON範本和jq的組合將成為建立我們自己的根據Docker的叢集操作指令碼的強大工具。

在Spot例項上組態工作節點

然後,我們將組態另外三台節點作為一組Spot例項。如以下截圖所示,它顯示了請求一組三台Spot例項的設定。選擇“請求並維護”選項,然後將目標容量設定為3台例項:

組態啟動指令碼

我們組態啟動指令碼以在例項建立時安裝Docker,將節點加入叢集,並設定網路驅動程式。啟動指令碼必須放在佇列設定的“使用者資料”部分,如以下截圖所示:


#### 內容解密:
此步驟用於在Spot例項上組態Docker工作節點。
1. 透過AWS控制檯請求一組Spot例項,並設定目標容量。
2. 在“使用者資料”部分組態啟動指令碼,以安裝Docker並將節點加入Swarm叢集。
3. 啟動指令碼還負責設定網路驅動程式,以確保叢集內的網路連線正常。

隨著雲端運算技術的不斷發展,使用Spot例項佈署FaaS平台將變得越來越普遍。透過結合Docker Swarm和Spot例項,我們可以實作既經濟又高效的FaaS解決方案。未來,我們可以期待更多的創新和最佳化,使這一領域繼續發展和成熟。

程式碼示例:自動化佈署指令碼

#!/bin/bash

# 安裝Docker
sudo apt-get update
sudo apt-get install -y docker.io

# 將節點加入Swarm叢集
sudo docker swarm join --token SWMTKN-1-5rvucdwofoam27qownciovd0sngpm31825r2wbdz1jdneiyfyt-b5bdh4i2jzev4aq4oid1pubi6 172.31.4.52:2377

# 組態網路驅動程式
sudo docker network create -d overlay my-network

#### 內容解密:
此指令碼用於自動化佈署Docker Swarm工作節點。
1. 首先,更新軟體包列表並安裝Docker。
2. 然後,將節點加入Swarm叢集,使用指定的加入令牌和管理節點地址。
3. 最後,建立一個overlay型別的網路,用於跨多個Docker主機的容器間通訊。

透過這種自動化佈署指令碼,我們可以簡化工作節點的組態過程,提高佈署效率。這對於大規模佈署FaaS平台尤其重要,因為它可以減少手動操作的錯誤和時間消耗。

總之,使用AWS Spot例項和Docker Swarm可以幫助我們以較低的成本佈署高效的FaaS平台。透過自動化佈署指令碼和仔細的規劃,我們可以進一步簡化佈署過程,提高系統的可靠性和可擴充套件性。這使得根據FaaS的應用開發和佈署變得更加靈活和經濟。

使用WeaveWorks網路外掛建立Docker Swarm網路

在建立Docker Swarm叢集時,網路組態是一個重要的環節。WeaveWorks提供了一個強大的網路外掛,能夠幫助我們建立一個跨主機的容器網路。本篇文章將介紹如何在Docker Swarm中使用WeaveWorks網路外掛。

安裝WeaveWorks網路外掛

在建立Docker Swarm叢集時,我們需要在每個節點上安裝WeaveWorks網路外掛。可以使用以下命令安裝:

docker plugin install --grant-all-permissions weaveworks/net-plugin:2.1.3

內容解密:

此命令會安裝WeaveWorks網路外掛的2.1.3版本。--grant-all-permissions引數用於自動授權外掛所需的許可權。

驗證WeaveWorks網路外掛安裝

安裝完成後,可以使用以下命令驗證外掛是否正確安裝:

docker plugin ls

輸出結果應該包含WeaveWorks網路外掛的資訊,例如:

ID                  NAME                              DESCRIPTION           ENABLED
f85f0fca2af9        weaveworks/net-plugin:2.1.3       Weave Net plugin for Docker   true

內容解密:

此命令會列出已安裝的Docker外掛。ENABLED欄位顯示外掛是否已啟用。

檢查WeaveWorks網路狀態

可以使用以下命令檢查WeaveWorks網路外掛的狀態:

curl localhost:6782/status

輸出結果應該包含WeaveWorks網路外掛的狀態資訊,例如:

Version: 2.1.3
Service: router
Protocol: weave 1..2
Name: e6:cc:59:df:57:72(ip-172-31-11-209)
Encryption: disabled
PeerDiscovery: enabled
Targets: 3
Connections: 5 (5 established)
Peers: 6 (with 30 established connections)
TrustedSubnets: none
Service: ipam
Status: idle
Range: 10.32.0.0/12
DefaultSubnet: 10.32.0.0/12
Service: plugin (v2)

內容解密:

此輸出結果顯示了WeaveWorks網路外掛的狀態,包括連線數、節點數和IP範圍等資訊。

建立WeaveWorks網路

可以使用以下命令建立一個WeaveWorks網路:

docker network create -d weaveworks/net-plugin:2.1.3 \
--subnet=10.32.0.0/24 \
--gateway=10.32.0.1 \
--attachable my_net

內容解密:

此命令會建立一個名為my_net的WeaveWorks網路,子網為10.32.0.0/24,閘道器為10.32.0.1--attachable引數允許容器使用docker run命令附加到此網路。

WeaveWorks網路拓撲

下圖顯示了WeaveWorks網路的拓撲結構:

  graph LR;
    A[ip-172-31-11-209] --> B[ip-172-31-8-157];
    A --> C[ip-172-31-4-52];
    A --> D[ip-172-31-1-223];
    A --> E[ip-172-31-15-229];
    A --> F[ip-172-31-0-153];
    B --> A;
    C --> A;
    D --> A;
    E --> A;
    F --> A;

圖表翻譯: 此圖表顯示了WeaveWorks網路中各個節點之間的連線關係。每個節點都與其他五個節點建立連線,形成了一個全網狀網路。