Logstash: 如何創建可維護和可重用的Logstash管道

Logstash是一種開源數據處理管道,它從一個或多個輸入中提取事件,對其進行轉換,然後將每個事件發送至一個或多個輸出。 一些Logstash實現可能具有多行代碼,並且可能處理來自多個輸入源的事件。 爲了使此類實現更具可維護性,我將展示如何通過從模塊化組件創建管道來提高代碼的可重用性。

 

寫這篇文章的動機

Logstash通常有必要將通用的處理邏輯子集應用於來自多個輸入源的事件。通常通過以下兩種方式之一來實現:

  • 在單個管道中處理來自多個不同輸入源的事件,以便可以將通用邏輯輕鬆應用於來自所有源的所有事件。在這樣的實現中,除了通用邏輯之外,通常還有大量的條件邏輯。因此,此方法可能會導致Logstash實現複雜且難以理解。

  • 執行一個唯一的管道來處理來自每個唯一輸入源的事件。這種方法需要將通用功能複製和複製到每個管道中,這使得難以維護代碼的通用部分。

本博客中介紹的技術通過將模塊化管道組件存儲在不同的文件中,然後通過組合這些組件來構造管道,從而解決了上述方法的缺點。此技術可以減少流水線複雜性並可以消除代碼重複。

 

模塊化管道建設

Logstash配置文件由Logstash管道執行的輸入,過濾器和輸出組成:
 

在更高級的設置中,通常有一個Logstash實例執行多個管道。 默認情況下,當啓動不帶參數的Logstash時,它將讀取一個名爲pipelines.yml的文件,並將實例化指定的管道。

Logstash輸入,過濾器和輸出可以存儲在多個文件中,可以通過指定glob表達式來選擇這些文件以將其包含在管道中。 匹配全局表達式的文件將按字母順序組合。 由於過濾器的執行順序通常很重要,因此在文件名中包括數字標識符以確保文件按所需順序組合可能會有所幫助。

在下面,我們將定義兩個獨特的管道,這些管道是幾個模塊化Logstash組件的組合。 我們將Logstash組件存儲在以下文件中:

  • 輸入聲明:01_in.cfg,02_in.cfg
  • 過濾器聲明:01_filter.cfg,02_filter.cfg,03_filter.cfg
  • 輸出聲明:01_out.cfg

然後使用glob表達式,在pipelines.yml中定義管道,使其由所需組件組成,如下所示:

- pipeline.id: my-pipeline_1
  path.config: "<path>/{01_in,01_filter,02_filter,01_out}.cfg"
- pipeline.id: my-pipeline_2
  path.config: "<path>/{02_in,02_filter,03_filter,01_out}.cfg"

在上述管道配置中,兩個管道中都存在文件02_filter.cfg,該文件演示瞭如何在兩個文件中定義和維護兩個管道共有的代碼,以及如何由多個管道執行這些代碼。

 

測試管道

在本節中,我們提供文件的具體示例,這些文件將被合併到上述pipelines.yml中定義的唯一管道中。 然後,我們使用這些文件運行Logstash,並顯示生成的輸出。

配置文件

input file:01_in.cfg

該文件定義了作爲生成器的輸入。 生成器輸入旨在測試Logstash,在這種情況下,它將生成一個事件。

input { 
  generator { 
    lines => ["Generated line"] 
    count => 1 
  } 
}

Input file: 02_in.cfg

該文件定義了一個偵聽stdin的Logstash輸入。

input { 
  stdin {} 
}

Filter file: 01_filter.cfg

filter { 
  mutate { 
    add_field => { "filter_name" => "Filter 01" } 
  } 
}

Filter file: 02_filter.cfg

filter { 
  mutate { 
    add_field => { "filter_name" => "Filter 02" } 
  } 
}

Filter file: 03_filter.cfg

filter { 
  mutate { 
    add_field => { "filter_name" => "Filter 03" } 
  } 
}

Output file: 01_out.cfg

output { 
  stdout { codec =>  "rubydebug" } 
}

 

執行管道

不帶任何選項啓動Logstash將執行我們先前定義的pipelines.yml文件。 運行Logstash,如下所示:

./bin/logstash

由於管道my-pipeline_1正在執行生成器以模擬輸入事件,因此Logstash完成初始化後,我們應該看到以下輸出。 這表明01_filter.cfg02_filter.cfg的內容已按預期由該管道執行。

{
     "@timestamp" => 2020-02-29T02:44:40.024Z,
           "host" => "liuxg-2.local",
       "sequence" => 0,
        "message" => "Generated line",
       "@version" => "1",
    "filter_name" => [
        [0] "Filter 01",
        [1] "Filter 02"
    ]
}

當另一個名爲my-pipeline_2的管道正在等待stdin上的輸入時,我們尚未看到該管道處理的任何事件。 在運行Logstash的終端中鍵入內容,然後按Return鍵爲此管道創建一個事件。 完成此操作後,您應該會看到類似以下的內容:

hello, the world!
{
        "message" => "hello, the world!",
       "@version" => "1",
     "@timestamp" => 2020-02-29T02:48:26.142Z,
           "host" => "liuxg-2.local",
    "filter_name" => [
        [0] "Filter 02",
        [1] "Filter 03"
    ]
}

從上面我們可以看到,按預期應用了02_filter.cfg03_filter.cfg的邏輯。

 

執行順序

請注意,Logstash不會注意glob表達式中文件的順序。 它僅使用glob表達式確定要包含的文件,然後按字母順序對其進行排序。 這就是說,即使我們要更改my-pipeline_2的定義,以使03_filter.cfg出現在02_filter.cfg之前的glob表達式中,每個事件也會在03_filter.cfg中定義的過濾器之前通過02_filter.cfg中的過濾器。

 

結論

使用全局表達式可以使Logstash管道由模塊化組件組成,這些組件存儲爲單獨的文件。 這樣可以提高代碼的可維護性,可重用性和可讀性。

附帶說明,除了本博客中記錄的技術之外,還應考慮管道到管道的通信,以查看它是否可以改善Logstash實現模塊。

參考:

【1】https://www.elastic.co/blog/how-to-create-maintainable-and-reusable-logstash-pipelines

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章