---
# System prepended metadata

title: Telegraf+Prometheus+Grafana學習筆記
tags: [監控系統, BruceYang]

---

# Telegraf+Prometheus+Grafana學習筆記
> [TOC]

---

# 一、學習資料來源
### 1. [Hiskio線上課程](https://hiskio.com/)
### 2. [Github教材資源](https://github.com/udemy-course/telegraf-prometheus-grafana)（共24個Branch）
### 3. [延伸學習－正規表達式（Regular Expression, Regex）](https://hackmd.io/@aaronlife/regular-expression)

---

# 二、事前準備
### 1. [安裝 Docker Engine](https://docs.docker.com/engine/install/)
### 2. [安裝 Docker Compose](https://docs.docker.com/compose/install/)

---

# 三、Telegraf![telegraf](https://hackmd.io/_uploads/H1hidgt0C.png)

### 1. Telegraf是什麼
  ![Telegraf架構圖](https://hackmd.io/_uploads/BJabsX44Je.png)

  Telegraf使用GO語言撰寫，支援Linux和Windows作業系統。主要用於收集系統和服務的數據資料並進行數據處理、聚合，後續可以針對數據設置告警、可視化的操作。大致架構可以分為4個套件：

  ![telegraf架構圖2](https://hackmd.io/_uploads/r1Zz_lKAA.jpg)

  - **Input Plugins數據收集：**
    收集系統、資料庫、網路、服務、第三方套件的數據。

  - **Processor Plugins數據處理：**
    轉換、處理、過濾等資料處理。

  - **Aggregator Plugins數據聚合：**
    針對數據的特徵，進行數據聚合。

  - **Output Plugins數據輸出：**
    撰寫Metric數據，可以發送至儲存空間、其他採集數據的應用程式，如Prometheus。

---

### 2. Telegraf官方文檔資源
  - [官方文檔連結](https://docs.influxdata.com/telegraf/v1/)
  - [官方Github資源](https://github.com/influxdata/telegraf)

---

### 3. 實作範例
  :::info
  :::spoiler **啟動Telegraf容器**
  </br>

  **1. 創建Telegraf目錄**
  ```
  mkdir -p telegraf && cd telegraf
  ```
  ```
  mkdir -p app && cd app
  ```
  </br>

  **2. Telegraf容器啟動文件**
  - **docker-compose.yml文件(運行Telegraf容器)**
    ```
    version: "3.0"
  
    services:
      telegraf:
        image: telegraf:latest
        restart: always
        container_name: telegraf
        hostname: telegraf
        ports:
          - 9273:9273
        volumes:
          - /本地config路徑/telegraf.conf:/etc/telegraf/telegraf.conf
          #本地telegraf.config文件路徑:容器的telegraf.conf文件路徑
        command: telegraf --config /etc/telegraf/telegraf.conf
    ```

  - **telegraf.conf文件(設定Telegraf要監控的數據)**
    ```
    [agent]
    # https://docs.influxdata.com/telegraf/v1/configuration/
    interval = "30s"
    ## 每次執行input套件的時間
    flush_interval = "10s"
    ## 每次執行output套件的時間
  
    [[inputs.ping]]
    # https://github.com/influxdata/telegraf/tree/master/plugins/inputs/ping/README.md
    urls = ["google.com"]
    method = "exec"
    ## 執行ping的方式
    count = 3
    ## 執行ping的次數
  
    [[inputs.cpu]]
    # https://github.com/influxdata/telegraf/blob/master/plugins/inputs/cpu/README.md
    ## 本地主機的CPU
    percpu = true
    totalcpu = true
    collect_cpu_time = false
    report_active = false
  
    [[inputs.mem]]
    # https://github.com/influxdata/telegraf/blob/master/plugins/inputs/mem/README.md
    ## 本地主機的MEM
  
    [[outputs.prometheus_client]]
    # https://github.com/influxdata/telegraf/tree/master/plugins/outputs/prometheus_client/README.md
    listen = ":9273"
    ## 監聽的Port號
    metric_version = 2
    ```

  - **.env文件(避免與其它專案容器搞混)**
    ```
    COMPOSE_PROJECT_NAME=telegraf
    ```
  </br>

  **3. 運行Telegraf容器**
  ```
  docker compose up -d
  ```
  ```
  docker compose ps
  ```
  ![telegraf容器](https://hackmd.io/_uploads/BJ1Zbft0R.jpg)
  </br>

  **4. 訪問瀏覽器查看監控數據**
  ```
  主機IP:9273/metrics
  domain:9273/metrics
  ```
  ![telegraf容器2](https://hackmd.io/_uploads/rkPc-zYRC.jpg)
  可以看到標籤都有『host="telegraf"』
  ![telegraf容器3](https://hackmd.io/_uploads/ByhddMYC0.jpg)
  </br>
  :::

  :::info
  :::spoiler **為全局的監控數據添加靜態標籤**
  </br>

  **1. 編輯telegraf.conf文件**
  ```
  [global_tags]
  environment = "testing"
  ```
  ![telegraf容器4](https://hackmd.io/_uploads/rkHKhMKCA.jpg)
  </br>

  **2. 重新啟動Telegraf容器**
  ```
  docker compose restart
  ```
  </br>

  **3. 重新整理瀏覽器查看監控數據**
  ![telegraf容器5](https://hackmd.io/_uploads/ryhqYzF0C.jpg)
  </br>
  :::

  :::info
  :::spoiler **針對輸入套件添加靜態標籤**
  </br>

  **1. 針對Ping套件添加標籤**
  ```
  [inputs.ping.tags]
  version = 'PingV2'
  ```
  ![telegraf容器6](https://hackmd.io/_uploads/BknanGtRC.jpg)
  </br>

  **2. 針對CPU套件添加標籤**
  ```
  [inputs.cpu.tags]
  type = 'CPU'
  ```
  ![telegraf容器7](https://hackmd.io/_uploads/HyY91XF00.jpg)
  </br>

  **3. 針對MEM套件添加標籤**
  ```
  [inputs.mem.tags]
  type = 'MEM'
  ```
  ![telegraf容器8](https://hackmd.io/_uploads/Sk7i1XtAA.jpg)
  </br>

  **4. 重新啟動Telegraf容器**
  ```
  docker compose restart
  ```
  </br>

  **5. 重新整理瀏覽器查看監控數據**
  ![telegraf容器9](https://hackmd.io/_uploads/B17PgXKCA.jpg)
  ![telegraf容器10](https://hackmd.io/_uploads/B1PwgmY0A.jpg)
  ![telegraf容器11](https://hackmd.io/_uploads/SyoPe7tR0.jpg)
  </br>
  :::

  :::info
  :::spoiler **為Ping輸入套件添加動態標籤**
  </br>

  **1. 使用Regex處理套件為Ping輸入套件添加**
  ```
  [[processors.regex]]
  # https://github.com/influxdata/telegraf/blob/master/plugins/processors/regex/README.md
    namepass = ["ping"]
    ## 處理包含ping字串的數據資料
    [[processors.regex.tags]]
    ## 選擇regex的tags套件
      key = "url"
      ## 要處理url的標籤內容
      pattern = "^([^.]+).*$"
      ## 表達式，表達要抓取的內容(domain不抓取頂級域名)
      replacement = "${1}"
      ## 如何替換pattern抓取的內容
      result_key = "service_name"
      ## 新的標籤，同時保留url標籤
  ```
  ![telegraf容器12](https://hackmd.io/_uploads/SJUh6faRA.jpg)
  </br>

  **2. 重新啟動Telegraf容器**
  ```
  docker compose restart
  ```
  </br>

  **3. 重新整理瀏覽器查看監控數據**
  ![telegraf容器13](https://hackmd.io/_uploads/r14gympR0.jpg)
  </br>
  :::

  :::info
  :::spoiler **透過telegraf.d以組織的方式管理監控數據**
  </br>

  **1. 建立telegraf.d資料夾**
  ```
  mkdir -p telegraf.d && cd telegraf.d
  ```
  </br>

  **2. 添加組織的監控config**
  ```
  vim 組織名稱.conf
  ```
  </br>

  **3. 編輯該組織的監控config內容**
  本文新增amazon.config、google.config的Ping套件為範例，如下：
  - amazon.config：
    ```
    [[inputs.ping]]
    # https://github.com/influxdata/telegraf/tree/master/plugins/inputs/ping/README.md
    urls = ["amazon.com", "amazon.jp", "amazon.cn", "amazon.uk"]
    method = "exec"
    ## 執行ping的方式
    count = 3
    ## 執行ping的次數

      [[processors.regex]]
        namepass= ["ping"]

        [[processors.regex.tags]]
          key = "url"
          pattern = "^([^.]+).*$"
          replacement = "${1}"
          result_key = "service_name"

      [inputs.ping.tags]
      version = 'PING-Amazon'
    ```

  - google.config：
    ```
    [[inputs.ping]]
    # https://github.com/influxdata/telegraf/tree/master/plugins/inputs/ping/README.md
    urls = ["www.google.com"], ["www.google.co.jp"], ["www.google.cn"], ["www.google.de"]
    method = "exec"
    ## 執行ping的方式
    count = 3
    ## 執行ping的次數

      [[processors.regex]]
        namepass= ["ping"]

        [[processors.regex.tags]]
          key = "url"
          pattern = "^([^.]+).*$"
          replacement = "${1}"
          result_key = "service_name"

      [inputs.ping.tags]
      version = 'PING-Google'
    ```
    備註：可以刪除原本在telegraf.conf中的群組PING套件內容。
  </br>

  **4. 修改docker-compose.yml內容**
  ```
  vim docker-compose.yml
  ```
  為Telegraf容器添加telegraf.d掛載目錄，docker-compose.yml內容修正如下：
  ```
  volumes:
    - "本地telegraf.d目錄路徑/:/etc/telegraf/telegraf.d/
    #本地telegraf.d目錄路徑:容器telegraf.d目錄路徑
    command: telegraf --config /etc/telegraf/telegraf.conf --config-directory "容器telegraf.d目錄路徑"
  ```
  ![telegraf.d修改config檔](https://hackmd.io/_uploads/r1KTDQgE1g.jpg)
  </br>

  **5. 暫停telegraf docker容器**
  ```
  docker compose stop
  ```
  </br>

  **6. 刪除telegraf docker容器**
  因為有修改docker-compose.yml內容，因此必須重新啟動一個docker容器。
  ```
  docker compose rm
  ```
  </br>

  **7. 重新運行Telegraf容器**
  ```
  docker compose up -d
  ```
  ![telegraf.d修改config檔2](https://hackmd.io/_uploads/S1z0BSl4yg.jpg)
  </br>
  :::

---

# 四、Prometheus ![prometheus](https://hackmd.io/_uploads/ryXyurxN1g.jpg =80%x)

### 1. Prometheus是什麼
  - **功能概述：**
    監控+告警的開源應用程式工具集。
  - **特點：**
    - 基於時間序列的數據儲存。
    - 提供並使用 `PromQL` 語言來查詢數據。
    - 與其他監控工具不同，是在固定時間從目標對象拉取監控數據 Metric。

---

### 2. Prometheus架構元件、流程圖
  ![Prometheus架構圖](https://hackmd.io/_uploads/rJEFbENVke.png)
  - **Prometheus Server：**
    從指定的 `Jobs／Exporter` 抓取數據並將數據按時間序列排序。

  - **Client Libraries：**
    提供不同程式語言的客戶端套件。

  - **Push Gateway：**
    若Prometheus Server無法從 `Jobs／Exporter` 抓取某些數據，則可以透過撰寫腳本／程式碼的方式將數據推送到 Push Gateway（使 Push Gateway 擔任 Exporter 的角色）。

  - **Exporters：**
    負責向外部提供抓取Metrics的通道。

  - **Alertmanager：**
    根據告警規則，處理告警通知。

---

### 3. 數據指標（Metrics）類型
  |**名稱**|**說明**|**範例場景**|
  | -- | -- | -- |
  |**Counters**|單調遞增計數器，適合累計的事件。|HTTP請求總數、消息處理總數|
  |**Gauges**|可以增減，反映實時的數值。|記憶體使用空間、磁碟可用空間|
  |**Histogram**|1.追蹤事件並定義事件的不同統計分組(chunk_range_bucket)。</br></br>2.最終提供SUM加總平均、Count次數。|回應時間chunk1:小於10=5次</br>chunk2:小於20=1次</br>chunk3:小於30=2次</br></br>統計：</br>SUM=平均16.25</br>COUNT=8次|
  |**Summary**|與Histogram分組統計相似，但以PR數值(quantiles)來分組數據。|quantile1(0.5=PR50):10</br>quantile2(0.9=PR90):20</br>quantile3(0.99=PR99):30</br></br>統計:</br>SUM=平均16.25</br>COUNT=8次|

---

### 4. Prometheus官方文檔資源
  - [官方文檔連結](https://prometheus.io/docs/introduction/overview/)
  - [官方Github資源](https://github.com/prometheus)

---

### 5. 實作範例：運行Prometheus應用程式
:::info
:::spoiler **啟動Prometheus容器**
</br>

**1. 抓取Prometheus docker image**
```
docker pull prom/prometheus
```
</br>

**2. 建立Prometheus目錄**
```
mkdir -p prometheus && cd prometheus
```
```
mkdir -p prometheus && mkdir -p telegraf
```
```
cp /root/telegraf/app/telegraf.conf /root/prometheus/telegraf/telegraf.conf
```
```
cp /root/telegraf/app/docker-compose.yml /root/prometheus/docker-compose.yml
```
```
cp -r /root/telegraf/app/telegraf.d/ /root/prometheus/telegraf/telegraf.d/
```
```
cd prometheus && vim prometheus.yml
```
- 最終目錄、文件會如下圖所示：
  ```mermaid
  graph TD;
  Prometheus --> docker-compose.yml;
  Prometheus --> prometheus;
  Prometheus --> telegraf;
  prometheus --> prometheus.yml;
  telegraf --> telegraf.conf;
  telegraf --> telegraf.d;
  ```
</br>

**3. 撰寫 Prometheus.yml 文件**
```
global:
  scrape_interval: 15s
  #全局設定每15秒去抓取一次metrics。
  
scrape_configs:
  - job_name: "telegraf"
    static_configs:
      - targets: ["telegraf:9273"]
      # 指定 docker-compose.yml 裡面的telegraf容器(hostname)。
```
![prometheus.yml](https://hackmd.io/_uploads/S1t6RxdEkl.jpg)
- 其它 Prometheus configuration 內容請參考 [Prometheus官方文檔](https://prometheus.io/docs/prometheus/latest/configuration/configuration/)
</br>

**4. 修改 docker-compose.yml 文件**
```
version: "3.0"

services:
  telegraf:
    image: telegraf:latest
    restart: always
    container_name: telegraf
    hostname: telegraf
    ports:
      - 9273:9273
    volumes:
      - 本地telegraf.conf路徑:/etc/telegraf/telegraf.conf
      - 本地telegraf.d路徑:/etc/telegraf/telegraf.d/
      #本地telegraf.config文件路徑:容器的telegraf.conf文件路徑
    command: telegraf --config /etc/telegraf/telegraf.conf --config-directory /etc/telegraf/telegraf.d

  prometheus:
    image: prom/prometheus:latest
    restart: always
    container_name: prometheus
    hostname: prometheus
    ports:
      - 9090:9090
    volumes:
      - 本地prometheus.yml路徑:/etc/prometheus/prometheus.yml
    command: --config.file=/etc/prometheus/prometheus.yml
```
![prometheus.docker-compose.yml](https://hackmd.io/_uploads/BydATlOV1l.jpg)
</br>

**5. 停止並刪除舊有的Telegraf容器**
```
docker compose stop
```
```
docker compose rm
```
```
y
```
![prometheus.docker-compose rm](https://hackmd.io/_uploads/SJIXv1_Nyg.jpg)
</br>

**6. 用docker-compose啟動Telegraf+Prometheus容器**
```
docker compose up -d
```
![prometheus.docker-compose up](https://hackmd.io/_uploads/BkUFoeON1e.jpg)
</br>

**7. 確認Telegraf+Prometheus容器運行狀態**
```
docker compose ps
```
![prometheus.docker-compose up](https://hackmd.io/_uploads/S1xx7ieOE1e.jpg)
```
主機IP:9273/metrics
```
![telegraf啟動](https://hackmd.io/_uploads/Hkn73ZuEyx.jpg)
```
主機IP:9090
```
![prometheus啟動](https://hackmd.io/_uploads/ryuN2WO4Je.jpg)
![prometheus啟動2](https://hackmd.io/_uploads/rywrnb_Vkx.jpg)
![prometheus啟動3](https://hackmd.io/_uploads/r1wH3-OVkx.jpg)
![prometheus啟動4](https://hackmd.io/_uploads/Hk6H6W_Vke.jpg)
</br>
:::

---
### 6. 使用PromQL查看Metric數據
- **說明**
使用Prometheus Web UI搜尋Metric數據，例如：`ping_average_response_ms`，搜尋後若希望針對Metric數據中Label標籤值或Metric值進行數據篩選，篩選一共可以分為2種類型：

  |  |**Instant Vector Selector**|**Range Vector Selector**|
  |--|--|--|
  |**Metric數據範圍**|單個時間點上的數據值|一段時間內的數據值集合|
  |**返回數據類型**|單個值（標量數據）|值的集合（向量數據）|
  |**聚合函數應用**|不需要時間範圍|需要時間範圍（如：avg_over_time）|
  |**語法範例**|`metric_name{label_selector}`|`metric_name{label_selector}[time_range]`|
  |**適用場景**|僅查看數據內容|數據分析、趨勢分析|
</br>

- **標籤篩選（Label Selector）說明**
  用於篩選Metric數據中的標籤，大致格式如下：
  {`label_name標籤名稱` `運算符` `label_value標籤值`}`比較運算符` `Metric_value值`
  {`label_name標籤名稱` `運算符` `Regex正規表達式label_value標籤值`}`比較運算符` `Metric_value值`

  - **運算符**
    `=`：等於
    `!=`：不等於
    `=~`：符合正規表達式
    `!~`：不符合正規表達式

  - **比較運算符**
    `>`：大於
    `<`：小於
    `>=`：大於等於
    `<=`：小於等於
    `==`：等於
    `!=`：不等於

  - **什麼是正規表達式**
    [正規表達式（Regular Expression, Regex）](https://hackmd.io/lrXV3iXPT52ggzHZ87Zr_w?both#3-%E5%BB%B6%E4%BC%B8%E5%AD%B8%E7%BF%92%EF%BC%8D%E6%AD%A3%E8%A6%8F%E8%A1%A8%E9%81%94%E5%BC%8F%EF%BC%88Regular-Expression-Regex%EF%BC%89)
</br>

- **時間範圍（time_range）說明**
  指定時間範圍，支持的時間格式如下：
  `S`：秒
  `m`：分鐘
  `h`：小時
  `d`：天
  `w`：周
  `y`：年
</br>

:::info
:::spoiler **Instant vector selector(單點時間)**
</br>

  **1. Metric數據**
  ```
  metric_name
  ```
  ![prometheus query1](https://hackmd.io/_uploads/ryANyvpNJx.jpg)
  </br>

  **2. Metric數據+指定Label標籤值**
  - 篩選條件：`version`等於`PING-HIGHERCLOUD`
    ```
    metric_name{version="version值"}
    ```
    ![prometheus query2](https://hackmd.io/_uploads/BJJPHsDSkl.jpg)

  - 篩選條件：`version`不等於`PING-HIGHERCLOUD`
    ```
    metric_name{version!="version值"}
    ```
    ![prometheus query4](https://hackmd.io/_uploads/BkrYrjPr1l.jpg)

  - 篩選條件：`version`等於`PING-Boyu`+`service_name`等於`circlecreative`
    ```
    metric_name{version="version值", service_name="service_name值"}
    ```
    ![prometheus query3](https://hackmd.io/_uploads/B1ODrjwH1e.jpg)
  </br>

  **3. Metric數據+正規表達式篩選Label標籤值**
  - 篩選條件：`url`以`.com`結尾的二級域名
    ```
    metric_name{url=~"^[^.]+\\.com$"}
    ```
    ![prometheus query5](https://hackmd.io/_uploads/HJrU4lYSkg.jpg)


  - 篩選條件：`url`以`.com`結尾的二級域名+`service_name`以`s`作為開頭
    ```
    metric_name{url=~"^[^.]+\\.com$", service_name=~"^s.*"}
    ```
    ![prometheus query6](https://hackmd.io/_uploads/H1gsVxFrke.jpg)


  - 篩選條件：`url`以`.com`結尾的二級域名+`service_name`以`s`作為開頭+Metric值大於30
    ```
    metric_name{url=~"^[^.]+\\.com$", service_name=~"^s.*"}>30
    ```
    ![prometheus query7](https://hackmd.io/_uploads/H1c0NxtBJx.jpg)
  </br>
  :::

  :::info
  :::spoiler **Range vector selector(時間範圍)**
  </br>

  篩選條件：`url`以`.com`結尾的二級域名
  ```
  metric名稱{Label運算符+值（正規表達式可選）}<比較運算符>metric值
  ```
  ![prometheus query8](https://hackmd.io/_uploads/HJahvU08Jl.jpg)
  </br>
  :::

---

### 7. 配置Prometheus Alerting and Rules
