Loki 生產環境集羣方案
很多新入坑 Loki 的小夥伴當看到 distributor、ingester、querier 以及各種依賴的三方存儲時,往往都比較懵逼,不知道從哪兒入手。此外再加上官方的文檔裏面對於集羣部署的粗淺描述,更是讓新手們大呼部署太難。其實,除了官方的 helm 外,藏在 Loki 倉庫的 production 目錄裏面有一篇生產環境的集羣部署模式。
原文裏面,社區採用的是 docker-compose 的方式來快速拉起一套 Loki 集羣。雖然我們正式在生產環境中實施時,不會傻到用 docker-compose 部署在一個 node 上(顯然這裏我們強行不考慮 docker-swarm)。不過裏面關於 Loki 的架構和配置文件卻值得我們學習。
那麼,與純分佈式的 Loki 集羣相比,這套方案有什麼特別的呢?首先我們先來看看下面這張圖:
可以看到,最明顯的有三大不同點:
-
loki 核心服務 distributor、ingester、querier 沒有分離,而是啓動在一個實例當中;
-
拋棄了 consul 和 etcd 外部的 kv 存儲,而是直接用 memberlist 在內存中維護集羣狀態;
-
使用 boltdb-shipper 替代其他日誌索引方案
這樣看起來,Loki 集羣的整體架構就比較清晰,且更少的依賴外部系統。簡單總結了下,除了用於存儲 chunks 和 index 而繞不開的 S3 存儲外,還需要一個緩存服務用於加速日誌查詢和寫入。
Loki2.0 版本之後,對於使用 boltdb 存儲索引部分做了較大的重構,採用新的 boltdb-shipper 模式,可以讓 Loki 的索引存儲在 S3 上,而徹底擺脫 Cassandra 或者谷歌的 BigTable。此後服務的橫向擴展將變得更加容易。關於 bolt-shipper 的更多細節,可以參考:https://grafana.com/docs/loki/latest/operations/storage/boltdb-shipper/
說得這麼玄乎,那我們來看看這套方案的配置有哪些不一樣呢?
原生部分
memberlist
memberlist:
join_members: ["loki-1", "loki-2", "loki-3"]
dead_node_reclaim_time: 30s
gossip_to_dead_nodes_time: 15s
left_ingesters_timeout: 30s
bind_addr: ['0.0.0.0']
bind_port: 7946
Loki 的 memberlist 使用的是 gossip 協議來讓集羣內的所有節點達到最終一致性的。此部分的配置幾乎都是協議頻率和超時的控制,保持默認的就好
ingester
ingester:
lifecycler:
join_after: 60s
observe_period: 5s
ring:
replication_factor: 2
kvstore:
store: memberlist
final_sleep: 0s
ingester 的狀態通過 gossip 協議同步到集羣的所有 member 當中,同時讓 ingester 的複製因子爲 2。即一個日誌流同時寫入到兩個 ingster 服務當中以保證數據的冗餘。
擴展部分
社區的集羣模式配置原生部分仍然顯得不太夠意思,除了 memberlist 的配置稍顯誠意外,其它部分仍然不夠我們對生產環境的要求。這裏小白簡單改造了一下,分享給大家。
storage
將 index 和 chunks 的存儲統一讓 S3 對象存儲納管,讓 Loki 徹底擺脫三方依賴。
schema_config:
configs:
- from: 2021-04-25
store: boltdb-shipper
object_store: aws
schema: v11
index:
prefix: index_
period: 24h
storage_config:
boltdb_shipper:
shared_store: aws
active_index_directory: /loki/index
cache_location: /loki/boltdb-cache
aws:
s3: s3://<S3_ACCESS_KEY>:<S3_SECRET_KEY>@<S3_URL>/<S3__BUCKET>
s3forcepathstyle: true
insecure: true
這裏值得說明的就是用於存儲日誌流索引的是 bolt_shipper,它是可以通過共享存儲方式寫到 s3 當中的。那麼active_index_directory
就是 S3 上的 Bucket 路徑,cache_location
則爲 Loki 本地 bolt 索引的緩存數據。
事實上 ingester 上傳到 s3 的 index 路徑爲
<S3__BUCKET>/index/
redis
原生的方案裏並不提供緩存,這裏我們引入 redis 來做查詢和寫入的緩存。對於很多小夥伴糾結的是一個 redis 共用還是多個 redis 單獨使用,這個看你集羣規模,不大的情況下,一個 redis 實例足以滿足需求。
query_range:
results_cache:
cache:
redis:
endpoint: redis:6379
expiration: 1h
cache_results: true
index_queries_cache_config:
redis:
endpoint: redis:6379
expiration: 1h
chunk_store_config:
chunk_cache_config:
redis:
endpoint: redis:6379
expiration: 1h
write_dedupe_cache_config:
redis:
endpoint: redis:6379
expiration: 1h
ruler
既然 Loki 以及做了集羣化部署,當然 ruler 這個服務也得跟在切分。難以接受的是,社區這部分的配置竟然是缺失的。所以我們得自己補充完整。我們知道日誌的 ruler 可以寫在 S3 對象存儲上,同時每個 ruler 實例也是通過一致性哈希環來分配自己的 rules。所以這部分配置,我們可以如下參考:
ruler:
storage:
type: s3
s3:
s3: s3://<S3_ACCESS_KEY>:<S3_SECRET_KEY>@<S3_URL>/<S3_RULES_BUCKET>
s3forcepathstyle: true
insecure: true
http_config:
insecure_skip_verify: true
enable_api: true
enable_alertmanager_v2: true
alertmanager_url: "http://<alertmanager>"
ring:
kvstore:
store: memberlist
支持 kubernetes
最後,最最最重要的是要讓官方的 Loki 集羣方案支持在 Kubernetes 中部署,否則一切都是瞎扯。由於篇幅的限制,我將 manifest 提交到 github 上,大家直接 clone 到本地部署。
GitHub 地址:https://github.com/CloudXiaobai/loki-cluster-deploy/tree/master/production/loki-system
這個 manifest 只依賴一個 S3 對象存儲,所以你在部署到生產環境時,請務必預先準備好對象存儲的 AccessKey 和 SecretKey。將他們配置到 installation.sh 當中後,直接執行腳本就可以開始安裝了。
文件中的 ServiceMonitor 是爲 Loki 做的 Prometheus Operator 的 Metrics 服務發現,你可以自己選擇是否部署
總結
本文介紹了官方提供的一種 Loki 生產環境下的集羣部署方案,並在此基礎上加入了一些諸如緩存、S3 對象存儲的擴展配置,並將官方的 docker-compose 部署方式適配到 Kubernetes 當中。官方提供的方案有效的精簡了 Loki 分佈式部署下複雜的結構,值得我們學習。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/qnt7JUzHLUU6Qs_tv5V0Hw