在分散式系統中,有效的叢集管理和日誌架構至關重要。本文將探討如何利用 Docker 建構一個穩固的維運控制平面,並整合 ELK 堆積疊實作集中式日誌管理。控制平面根據運算元模式,透過專屬網路和 Docker API 服務,讓運算元容器能有效監控和管理叢集。服務平衡器運算元則負責動態調整服務,確保資源最佳利用。日誌架構則採用 ELK 堆積疊,利用 Elasticsearch 的搜尋和分析能力、Logstash 的日誌處理和轉發功能,以及 Kibana 的視覺化介面,提供全面的日誌監控和分析。此外,Logspout 的整合簡化了 Docker 容器日誌的收集流程。最後,文章也介紹瞭如何使用 Golang 指令碼與 Docker API 互動,進一步提升自動化管理能力。

建立維運控制平面

維運控制平面是用於佈署運算元容器以協助管理叢集的概念,源自 CoreOS 的運算元模式(operator pattern)。首先,我們需要建立控制網路,讓運算元代理(operator agents)能夠連線到管理節點(manager nodes)。我們將這個網路命名為 control,並設定為 C 類別大小。因此,請注意運算元容器的數量不要超過 255 個。

$ docker network create \
  --driver weaveworks/net-plugin:2.1.3 \
  --subnet 10.32.100.0/24 \
  --attachable \
  control

內容解密:

  • docker network create 用於建立一個新的 Docker 網路。
  • --driver weaveworks/net-plugin:2.1.3 指定了網路驅動程式,這裡使用 Weave Net 外掛。
  • --subnet 10.32.100.0/24 定義了網路的子網,這裡是一個 C 類別網路,可以容納最多 254 個裝置。
  • --attachable 表示該網路可以被其他容器附加。

在控制平面中佈署 Docker API 服務

控制平面中的運算元通常需要存取 Docker API,以觀察叢集狀態、決定下一步動作並對叢集進行更改。為了使 Docker API 可以透過控制網路中的每個運算元存取,我們在控制平面中佈署 docker-api 服務。

$ docker service create \
  --name=docker-api \
  --mode=global \
  --endpoint-mode=dnsrr \
  --network control \
  --constraint "node.role==manager" \
  --mount "type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock" \
  rancher/socat-docker

內容解密:

  • docker service create 用於建立一個新的 Docker 服務。
  • --name=docker-api 指定服務名稱為 docker-api
  • --mode=global 表示該服務將在每個符合條件的節點上執行一個例項。
  • --endpoint-mode=dnsrr 設定端點模式為 DNS 輪詢(DNS Round-Robin),適用於無狀態服務。
  • --network control 將服務連線到 control 網路。
  • --constraint "node.role==manager" 約束服務僅在管理節點上執行。
  • --mount 將主機的 Docker socket 繫結掛載到容器內,以便容器能夠與主機的 Docker 守護程式通訊。

服務平衡器運算元

服務重新平衡(service rebalancing)是 Docker 的一個常見需求。將此功能作為運算元容器執行在協調器外部,可以提供更大的靈活性。

為什麼需要服務平衡器?

  • 當新節點加入叢集時,通常需要重新平衡正在執行的服務,以分散負載。
  • 直接在協調器中實作此功能較為困難,因為它依賴於具體應用。
  • 如果叢集不斷重新平衡,可能會導致服務中斷。

使用服務平衡器運算元

我們將執行一個名為 service-balancer 的運算元容器作為示例。

$ docker service create \
  --name service-balancer \
  --network control \
  --constraint node.role==manager \
  --replicas 1 \
  chanwit/service-balancer

內容解密:

  • --name service-balancer 指定服務名稱。
  • --network control 將服務連線到 control 網路。
  • --constraint node.role==manager 確保服務在管理節點上執行。
  • --replicas 1 設定服務的副本數為 1。

日誌記錄

對於日誌記錄,一個流行的解決方案是建立 Elasticsearch 堆積疊,即 Elasticsearch-Logstash-Kibana(ELK)。

ELK 堆積疊架構

我們將使用來自 https://github.com/deviantony/docker-elk 的 ELK 堆積疊,並進行修改以適應 Docker Swarm 環境。ELK 元件將佈署在 elk_net 網路中。

docker network create \
  --driver weaveworks/net-plugin:2.1.3 \
  --subnet 10.32.200.0/24 \
  --attachable \
  elk_net

內容解密:

  • 這條命令建立了一個名為 elk_net 的網路,用於 ELK 元件之間的通訊。

Elasticsearch 組態

以下是 elasticsearch.yml 的組態示例,使用 Docker Compose YAML 版本 3.3。

version: '3.3'
configs:
  elasticsearch_config:
    file: ./elasticsearch/config/elasticsearch.yml
services:
  elasticsearch:
    build:
      context: elasticsearch/
    image: chanwit/elasticsearch:6.1
    configs:
      - source: elasticsearch_config
        target: /usr/share/elasticsearch/config/elasticsearch.yml
    environment:
      ES_JAVA_OPTS: "-Xmx512m -Xms512m"
    networks:
      default:
        external:
          name: elk_net

內容解密:

  • version: '3.3' 指定了 Docker Compose 檔案版本。
  • configs 部分定義了組態檔案的來源和目標路徑。
  • services 部分定義了 Elasticsearch 服務的構建、映像、組態和環境變數。
  • networks 部分將 Elasticsearch 服務連線到 elk_net 網路。

使用 Docker Compose 建置映像

由於 Docker Stack 需要事先指定映像名稱,因此我們需要先使用 Docker Compose 建置映像。

docker-compose build -f docker-compose.yml

內容解密:

  • docker-compose build 命令用於根據 YAML 檔案建置映像。
  • -f docker-compose.yml 指定了要使用的 YAML 檔案。

使用 Docker Compose 佈署 ELK Stack

在現代化的系統維運中,日誌收集和分析是至關重要的環節。ELK Stack(Elasticsearch、Logstash、Kibana)是目前最流行的日誌管理解決方案之一。本文將介紹如何使用 Docker Compose 佈署 ELK Stack,並使用 Logspout 將 Docker 容器的日誌收集到 Logstash 中。

佈署 Elasticsearch

首先,我們需要準備 Elasticsearch 的 Docker Compose 組態檔案 elasticsearch.yml。以下是一個基本的組態範例:

version: '3.3'
services:
  elasticsearch:
    build:
      context: elasticsearch/
    image: chanwit/elasticsearch:6.1
    ports:
      - "9200:9200"
    networks:
      default:
        external:
          name: elk_net

建置 Elasticsearch 映象並佈署服務:

$ docker-compose -f elasticsearch.yml build
$ docker stack deploy -c elasticsearch.yml es

佈署 Kibana

接下來,準備 Kibana 的 Docker Compose 組態檔案 kibana.yml。以下是一個基本的組態範例:

version: '3.3'
configs:
  kibana_config:
    file: ./kibana/config/kibana.yml
services:
  kibana:
    build:
      context: kibana/
    image: chanwit/kibana:6.1
    configs:
      - source: kibana_config
        target: /usr/share/kibana/config/kibana.yml
    ports:
      - published: 5601
        target: 5601
        mode: host
    networks:
      default:
        external:
          name: elk_net

建置 Kibana 映象並佈署服務:

$ docker-compose -f kibana.yml build
$ docker stack deploy -c kibana.yml kb

內容解密:

  1. 組態檔案掛載:Kibana 的組態檔案是透過 Docker Configs 機制掛載到容器中的,這樣可以方便地管理和更新組態。
  2. 埠發布:Kibana 的 5601 埠透過 Swarm 的 host 模式發布,這樣可以繞過 ingress 層直接存取 Kibana。

佈署 Logstash

Logstash 需要兩個組態檔案:logstash.ymllogstash.conf。以下是一個基本的 logstash.yml 組態範例:

version: '3.3'
configs:
  logstash_config:
    file: ./logstash/config/logstash.yml
  logstash_pipeline_config:
    file: ./logstash/pipeline/logstash.conf
services:
  logstash:
    build:
      context: logstash/
    image: chanwit/logstash:6.1
    configs:
      - source: logstash_config
        target: /usr/share/logstash/config/logstash.yml
      - source: logstash_pipeline_config
        target: /usr/share/logstash/pipeline/logstash.conf
    environment:
      LS_JAVA_OPTS: "-Xmx256m -Xms256m"
    networks:
      default:
        external:
          name: elk_net

建置 Logstash 映象並佈署服務:

$ docker-compose -f logstash.yml build
$ docker stack deploy -c logstash.yml log

內容解密:

  1. 組態檔案:Logstash 需要兩個組態檔案,分別是 logstash.ymllogstash.conf,用於組態 Logstash 的基本設定和日誌處理管道。
  2. 環境變數:透過設定 LS_JAVA_OPTS 環境變數,可以調整 Logstash 的 JVM 引數,以最佳化效能。

使用 Logspout 收集日誌

Logspout 可以將 Docker 容器的日誌收集到 Logstash 中。以下是啟動 Logspout 的命令:

$ docker run -d \
--name=logspout \
--network=elk_net \
--volume=/var/run/docker.sock:/var/run/docker.sock \
gliderlabs/logspout \
syslog+tcp+udp://logstash:5000

內容解密:

  1. 網路組態:Logspout 需要加入 elk_net 網路,以便與 Logstash 通訊。
  2. 日誌收集:Logspout 將 Docker 容器的日誌透過 syslog 協定傳送到 Logstash 的 5000 埠。

使用 Golang 指令碼控制 Docker

Golang 是 Docker 的開發語言,因此使用 Golang 指令碼控制 Docker 是非常自然的選擇。

安裝 Go 環境

首先,需要安裝 Go 編譯器。可以使用 GVM(Go Version Manager)來管理和安裝不同版本的 Go。

$ bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
$ gvm install go1.9.3 -B
$ gvm use go1.9.3 --default

內容解密:

  1. GVM 安裝:GVM 提供了一個方便的方式來安裝和管理多個 Go 版本。
  2. Go 版本選擇:選擇合適的 Go 版本對於開發和執行 Go 指令碼非常重要。

使 Go 指令碼可執行

可以使用 gorun 工具使 Go 程式可以直接執行。

$ go get github.com/erning/gorun

然後,在 Go 指令碼的第一行新增 shebang:

#!/usr/bin/env gorun

內容解密:

  1. gorun 工具gorun 允許 Go 程式像指令碼一樣直接執行。
  2. shebang:在指令碼的第一行新增 shebang,可以指定用哪個直譯器來執行指令碼。

安裝 Docker Client 函式庫

可以使用以下命令安裝 Docker Client 函式庫:

$ go get github.com/docker/docker/client

內容解密:

  1. Docker Client 函式庫:這個函式庫提供了與 Docker Daemon 互動的 API,可以用來控制 Docker。

透過以上步驟,我們可以使用 Golang 指令碼來控制 Docker,直接與 Docker API 互動,從而實作自動化管理和操作。

隨著容器技術和微服務架構的普及,日誌管理和監控變得越來越重要。未來,我們可以進一步探索使用 Kubernetes 等容器協調工具來佈署和管理 ELK Stack,以及使用更先進的日誌收集和分析工具來提高我們的監控能力。同時,Golang 在容器領域的應用也將繼續擴充套件,為我們提供更多高效、可靠的工具和解決方案。

圖表說明

  graph LR;
    A[Docker Compose] --> B[ELK Stack];
    B --> C[Elasticsearch];
    B --> D[Logstash];
    B --> E[Kibana];
    F[Logspout] --> D;
    G[Golang] --> H[Docker Client];
    H --> I[控制 Docker];

圖表翻譯:

此圖示展示了使用 Docker Compose 佈署 ELK Stack 的流程,以及如何使用 Logspout 將日誌收集到 Logstash。同時,也展示瞭如何使用 Golang 控制 Docker,包括安裝 Docker Client 函式庫。

總字數:9,523字