返回文章列表

Fluentd 扇出與高用性組態實踐

本文探討 Fluentd 的扇出和高用性組態,涵蓋負載平衡、TLS 加密以及在 Kubernetes 環境中的佈署策略。文章提供詳細的組態範例和程式碼解析,幫助讀者理解如何在不同場景下組態 Fluentd 以實作最佳效能和安全性。

DevOps 系統管理

Fluentd 作為一款開源的日誌收集器,在現代系統架構中扮演著重要的角色。本文探討 Fluentd 的扇出和高用性組態,以確保日誌資料的可靠收集和處理。扇出組態允許將日誌資料分發到多個節點,提高系統的吞吐量,而高用性組態則透過備用節點的設定,保障系統在單點故障下的持續執行。在 Kubernetes 環境中,Fluentd 可以作為 DaemonSet 佈署,有效地收集容器日誌。此外,文章還探討了使用 TLS 加密保護 Fluentd 節點間通訊安全的重要性,以及憑證管理的最佳實踐。

擴充套件與工作負載遷移:Fluentd 組態實作扇出(Fan-out)與高用性

在實作扇出(fan-out)和高用性佈署時,我們需要能夠將工作負載傳送到多個節點。在高用性的上下文中,向不同節點傳送流量的觸發條件是通訊丟失,而在扇出中,這種連線性是由工作負載分享驅動的。讓我們來檢查這兩種需求,因為在組態上有一些共同點。如圖7.7所示,這次我們只佈署一個節點作為假資料來源生成器,但將日誌事件路由到多個消費節點,這些節點將輸出到控制檯。

圖示:Fluentd 扇出組態範例

此圖示展示了一個節點將日誌事件傳遞給多個節點進行處理的組態。

與前面的源節點組態的主要區別在於,forward 外掛的組態現在需要指定多個伺服器。在高用性組態中,需要確定哪個節點應被視為主節點,哪個應被視為備用節點。對於扇出,我們可能希望根據某種比例將工作負載分配給不同的節點。所有這些都可以在組態中透過屬性來實作。對於多個伺服器,如列表7.4所示,我們可以簡單地為伺服器輔助外掛<server>宣告多個連續的屬性塊。

Fluentd 組態範例:使用 forward 外掛實作扇出

<source>
  @type dummy
  tag dummy-fanout-source
  auto_increment_key counter
  dummy {"hello":"world"}
</source>

<filter *>
  @type stdout
  <inject>
    tag_key fluentd_tag
  </inject>
</filter>

<match *>
  @type forward
  buffer_type memory
  flush_interval 2s
  <server>
    host 127.0.0.1
    port 28080
    weight 10
  </server>
  <server>
    host 127.0.0.1
    port 38080
    weight 1
  </server>
  <secondary>
    @type stdout
  </secondary>
</match>

程式碼解析:

此組態定義了一個使用 dummy 外掛生成假資料的日誌源,並透過 forward 外掛將日誌事件轉發到兩個不同的伺服器。

  • @type dummy 指定了資料來源的型別為 dummy,用於生成假資料。
  • <filter *> 部分使用 stdout 外掛輸出過濾後的日誌事件,並注入標籤鍵 fluentd_tag
  • <match *> 部分定義了日誌事件的匹配規則,將匹配的日誌事件透過 forward 外掛轉發到指定的伺服器。
  • <server> 部分定義了目標伺服器的地址和埠,以及權重(weight),用於控制工作負載的分佈比例。

由於我們在同一台機器上執行所有 Fluentd 例項,因此形成扇出(fan-out)的 Fluentd 例項需要組態為在不同的網路埠上執行,以避免衝突。在生產環境中,Fluentd 例項通常組態為在不同的伺服器上執行,但使用相同的網路埠。利用列表7.2中所示的命名技巧,我們可以使組態值動態化,避免需要多個具有不同值的組態檔案。因此,每個節點都需要一個名為 NodePort 的環境變數,用於定義節點組態源端使用的埠之一,如下所示。

環境變數設定範例:

export NodePort=28080 # for Linux/macOS
set NodePort=28080 # for Windows

Roundrobin 外掛實作負載平衡

另一種分佈工作負載的方法是利用 roundrobin 外掛。該外掛是 Fluentd 的核心輸出外掛,與 store 輔助外掛一起工作。如下所示,透過 roundrobin 輪詢各個伺服器來分佈輸出。

Roundrobin 組態範例:

<source>
  @type dummy
  tag dummy-fanout-source
  auto_increment_key counter
  dummy {"hello":"world"}
</source>

<filter *>
  @type stdout
  <inject>
    tag_key fluentd_tag_roundrobin
  </inject>
</filter>

<match *>
  @type roundrobin
  <store>
    @type forward
    buffer_type memory
    flush_interval 1s
    <server>
      host 127.0.0.1
      port 28080
    </server>
  </store>
  <store>
    @type forward
    buffer_type memory
    flush_interval 1s
    <server>
      host 127.0.0.1
      port 38080
    </server>
  </store>
</match>

程式碼解析:

此組態使用 roundrobin 外掛將日誌事件輪詢分佈到多個伺服器。

  • @type roundrobin 指定了輸出外掛的型別為 roundrobin,實作輪詢輸出。
  • <store> 部分定義了具體的輸出目標,使用 forward 外掛將日誌事件轉發到指定的伺服器。
  • 每個 <store> 部分可以包含一個或多個 <server> 定義,用於指定目標伺服器的地址和埠。

7.2.3 高用性組態

在高用性組態中,Fluentd 的設定與扇出(fan-out)組態並無太大差異。不同之處在於,高用性組態使用 standby 屬性來決定是否將某個伺服器設為備用伺服器,而非使用 weight 屬性來分配工作負載。以下是一個範例組態:

<server>
  name myserver1
  host 127.0.0.1
  port 28080
  standby false
</server>
<server>
  name myserver2
  host 127.0.0.1
  port 38080
  standby true
</server>

內容解密:

  1. name 屬性:用於標識不同的伺服器,方便日誌記錄和憑證驗證。
  2. standby 屬性:決定伺服器是否為備用狀態。設為 false 表示該伺服器為主伺服器,而設為 true 表示該伺服器為備用伺服器。
  3. 工作原理:當 Fluentd 例項啟動時,它會嘗試將日誌事件傳送到標記為 standby false 的主伺服器(此例中為 myserver1)。如果與主伺服器的通訊出現問題,Fluentd 將自動切換到備用伺服器(此例中為 myserver2)。

7.2.4 高用性組態實作比較

客戶希望瞭解高用性組態與其他組態在設定和行為上的差異。團隊決定修改 Chapter7/Fluentd/dummy-forward2.confChapter7/Fluentd/forward-stdout2.conf 組態檔案以進行比較。

實作步驟:

  1. 重構上述兩個組態檔案以實作高用性組態。
  2. 執行重構後的組態,並關閉個別 Fluentd 例項以觀察結果。

結果:

修改後的組態檔案位於 Chapter7/ExerciseResults/dummy-forward2-Answer.confChapter7/ExerciseResults/forward-stdout2-Answer.conf。主要變更是移除了 weight 屬性,並引入了 standby 屬性。

<server>
  name myserver1
  host 127.0.0.1
  port 28080
  standby false
</server>
<server>
  name myserver2
  host 127.0.0.1
  port 38080
  standby true
</server>

行為觀察:

  • 當 Fluentd 例項啟動時,日誌事件將只會輸出到監聽埠 28080 的節點。
  • 當該節點關閉後,日誌事件將被轉發到監聽埠 38080 的 Fluentd 例項。

7.3 Fluentd 在容器與原生環境中的擴充套件性比較

7.3.1 Kubernetes 工作節點組態

在 Kubernetes 環境中,Fluentd 可以作為 DaemonSet 佈署在每個工作節點上,以收集所有容器的日誌。如下圖所示,所有容器的標準輸出(stdout)和標準錯誤輸出(stderr)都會被 Fluentd 捕捉。

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title 7.3.1 Kubernetes 工作節點組態

rectangle "stdout/stderr" as node1
rectangle "日誌" as node2

node1 --> node2

@enduml

此圖示說明瞭在 Kubernetes 環境中,Fluentd 如何作為 DaemonSet 佈署並收集容器日誌。

7.3.2 每叢集組態

在每叢集組態模型中,容器會將日誌寫入一個集中的檔案系統位置。這種方式使得日誌的收集和處理更加結構化,並且可以根據日誌型別進行區分。Fluentd 可以透過 tail 外掛程式來捕捉這些日誌檔案。

主要優點:

  1. 結構化日誌管理:透過將日誌寫入檔案系統,使得日誌管理更加有條理。
  2. 靈活性:可以根據需要掛載不同的儲存卷,以實作持久化儲存。

總之,Fluentd 在容器化環境(如 Kubernetes)中的擴充套件性和靈活性使其成為日誌收集和管理的理想選擇。

在容器化環境中擴充套件 Fluentd:佈署策略比較

在現代化的容器化環境中,如何有效地收集、處理和傳輸日誌資料是一個重要的挑戰。Fluentd 和 Fluent Bit 是兩個流行的日誌收集和處理工具,它們提供了多種佈署模式以適應不同的需求。本文將探討在容器化環境中佈署 Fluentd 的不同策略,並比較它們的優缺點。

容器化環境中的日誌收集挑戰

在 Kubernetes 等容器協調平台上,日誌收集面臨著多個挑戰。首先,日誌資料分散在不同的 Pod 和容器中,需要一個統一的日誌收集機制。其次,日誌格式多樣,需要進行解析和轉換。最後,日誌資料需要被傳輸到後端儲存或分析平台進行進一步處理。

Fluentd 佈署模式

1. 將 Fluentd 佈署在工作節點上

將 Fluentd 佈署在 Kubernetes 的工作節點上是一種簡單直接的方法。這種方法只需要組態工作節點上的 Fluentd 例項,無需修改 Pod 或容器的組態。然而,這種方法需要額外的工作來解析日誌資料,並且 Fluentd 的組態更改會影響整個工作節點。

2. 在應用容器中執行 Fluentd

在每個應用容器中執行一個 Fluentd 例項可以實作日誌收集的隔離。這種方法使得組態更改可以精確到每個應用容器。然而,這種方法會增加計算資源的佔用,因為每個容器都需要執行一個 Fluentd 例項。

3. 使用 Sidecar 模式佈署 Fluentd

Sidecar 模式是一種在 Pod 中執行額外容器的設計模式,可以用來執行 Fluentd 或 Fluent Bit。這種方法可以最小化 Fluentd 例項的數量,並且可以實作服務感知日誌收集。然而,這種方法需要更複雜的 Pod 組態。

Fluentd 與 Fluent Bit 的比較

佈署模式優點缺點
在工作節點上佈署 Fluentd簡單直接,無需修改 Pod 或容器組態需要額外工作來解析日誌資料,組態更改影響整個工作節點
在應用容器中執行 Fluentd日誌收集隔離,組態更改精確到每個容器增加計算資源佔用
在應用容器中執行 Fluent Bit比 Fluentd 佔用更少的資源功能和外掛支援有限
使用 Sidecar 模式佈署 Fluentd最小化 Fluentd 例項數量,實作服務感知日誌收集需要更複雜的 Pod 組態
使用 Sidecar 模式佈署 Fluent Bit比 Fluentd 佔用更少的資源,實作服務感知日誌收集需要更複雜的 Pod 組態
程式碼示例:使用 Fluent Bit 作為 Sidecar 容器
apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
  - name: app-container
    image: example-app:latest
    volumeMounts:
    - name: logs
      mountPath: /var/log
  - name: fluent-bit-sidecar
    image: fluent/fluent-bit:latest
    volumeMounts:
    - name: logs
      mountPath: /var/log
    - name: fluent-bit-config
      mountPath: /fluent-bit/etc/fluent-bit.conf
      subPath: fluent-bit.conf
  volumes:
  - name: logs
    emptyDir: {}
  - name: fluent-bit-config
    configMap:
      name: fluent-bit-config

程式碼解密:

此 YAML 組態檔案定義了一個 Pod,其中包含一個應用容器和一個 Fluent Bit Sidecar 容器。應用容器將日誌寫入 /var/log 目錄,Fluent Bit Sidecar 容器則負責收集這些日誌並將其傳輸到後端儲存或分析平台。fluent-bit-config ConfigMap 中定義了 Fluent Bit 的組態檔案,用於指定日誌收集和傳輸的詳細組態。

7.4 在Fluentd節點之間保護流量安全

當Fluentd節點之間進行通訊時,提供一定的安全保障是非常重要的。使用未經加密的網路流量可能會導致憑證被暴露,不僅是在Fluentd節點之間進行身份驗證時,還包括在Fluentd與來源或目標(如Elasticsearch)之間。使用HTTPS加密與TLS(傳輸層安全性協定,SSL的後繼者)可以有效解決這些問題。

如果日誌事件包含個人識別資訊(PII),則需要在應用程式和日誌事件傳輸及儲存過程中採取積極的安全措施。除了考慮日誌事件可能在雲端和資料中心之間透過不安全的網路(如網際網路)傳輸外,還需要考慮憑證暴露和日誌資訊被利用的風險。但安全措施並不僅僅是採用TLS或更好的雙向TLS(mTLS)。

7.4.1 TLS組態

在組態網路傳輸時,可以提供一系列傳輸組態。有些介面卡直接利用輔助外掛,因此有時會提供稍微不同的屬性名稱。例如,secure_forward在伺服器部分的組態中使用tls_version。相比之下,當直接使用傳輸輔助程式時(可以在來源、過濾器和匹配指令中提供),屬性被稱為version。傳輸結構在XML括號內的組態中表示,並包括指示傳輸型別(udp、tcp、tls)的元素。例如:

<transport tls>
  <!-- 組態內容 -->
</transport>

雖然我們一直專注於TLS和抽象了更多網路的外掛,但我們仍然可以處理TCP(傳輸控制協定)或UDP(使用者資料報協定)流量。不過,這些需要更多的組態工作。

TLS版本和演算法

可以透過Fluentd組態來控制支援的TLS版本。TLS 1.3(於2018年8月發布為RFC 8446)是目前最新的標準版本。目前,TLS 1.2是Fluentd預設使用的版本,反映了TLS 1.2是最廣泛採用的版本。業界最佳實踐建議盡可能使用最新版本的TLS(因為它最安全),並且僅在必要時才相容較低版本。

TLS相容性和加密選項可以透過versionciphers屬性進行管理。

專用轉發外掛用於SSL/TLS

正如之前所提到的,有一個安全的版本的前向外掛,用於輸入和輸出操作。這個外掛可以像所有外掛一樣使用gem安裝。例如:

gem install fluent-plugin-secure-forward

這個版本的外掛仍然需要憑證,但簡化了組態並掩蓋了傳輸層組態部分。

7.4.2 TLS不僅僅用於加密

使用TLS不僅僅是為了提供加密金鑰,還應該驗證來自憑證授權單位(CA)的真實憑證。通常,在客戶端和伺服器連線時,這是握手的一部分。如果與憑證授權單位確認憑證真實性的過程影響了延遲,那麼在完全受信任的網路環境中(例如,實體私人資料中心網路,但不是雲端託管網路),您可以考慮停用檢查。但關閉這種檢查違背了縱深防禦的安全理念,因此需要考慮可能帶來的風險。如果使用自簽名憑證,則需要額外的屬性——tls_insure_modetls_allow_self_signed_cert——來防止Fluentd與CA檢查憑證。

7.4.3 憑證和私鑰儲存

要使用憑證,我們顯然需要能夠儲存它和私鑰。這些資訊被定義為多個屬性,包括適應Windows儲存選項(更多資訊請參見http://mng.bz/vo6M)。

更多關於TCP和UDP的資訊

有關如何使用這些協定的更多資訊,請參閱以下資源:

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title 更多關於TCP和UDP的資訊

rectangle "TLS加密" as node1
rectangle "憑證驗證" as node2
rectangle "額外屬性組態" as node3

node1 --> node2
node2 --> node3

@enduml

此圖示展示了Fluentd節點之間使用TLS加密進行安全通訊,並透過CA進行憑證驗證,以及自簽名憑證的額外組態需求。

內容解密:

此圖示說明瞭Fluentd節點之間的通訊過程,包括使用TLS加密、憑證驗證以及自簽名憑證的處理。Fluentd節點之間透過TLS加密進行安全通訊,同時與CA憑證授權單位進行憑證驗證。如果使用自簽名憑證,則需要進行額外的屬性組態,以確保Fluentd能夠正確處理這些憑證。