問題
某天,突然發現 k8s 集群有大量的 evicted 記錄,排查發現某節點 Fluentd 的 Buffer 占用超過 13G 存儲,導致 K8s 節點 DiskPressure.
排查
K8s 默認在 Node 的可用存儲空間低於 85% 時觸發 DiskPressure,嘗試清理空間,驅逐 Pod。
查找 Fluentd 官方文檔:Fluentd - Config: Buffering parameters 發現,File 模式下 Buffer 的 total_limit_size 默認值為 64GB,而我的 Node 節點總存儲才 30G。
很可能是因為做為存儲的 ElasticSearch 出問題下線了,導致日志堆積在 Buffer 中,存儲被 Buffer 侵占。
因此需要根據機器存儲的大小修改 total_limit_size,查看 fluentd-kubernetes-daemonset 的 fluent.conf 發現它有將各參數以環境變量的方式暴露出容器。
但是沒有 total_limit_size 這個參數,只有舊的 queue_limit_length,對應的環境變量為 FLUENT_ELASTICSEARCH_BUFFER_QUEUE_LIMIT_LENGTH,可以通過設置這個環境變量來修改 buffer 上限。
fluentd 的官方 k8s 配置文件:fluentd-daemonset-elasticsearch.yaml,按照前面給的 fluent.conf 中的配置設置環境變量, 就可以修改 fluentd 的各項參數,比如 es 索引的前綴 FLUENT_ELASTICSEARCH_LOGSTASH_PREFIX.
畫外:Fluentd 的日志抓取策略
我們開發集群的日志被抓取到 ElasticSearch 后,每晚會執行一次數據清理(通過 ES API 刪除索引),只保留最近三天的日志,以保證日志服務器(ES)一直可用。
但是有一個現象,日志清理腳本剛剛跑完,這時只剩三個 ES 索引(以日期為索引),可剛過一會兒,往期的日志立馬又被 Fluentd 抓了進來。前面七八天的日志索引又回來了。
這讓我們有點摸不清 Fluentd 的抓取策略和 Kubernetes Pod 的日志輸出策略。
幾個問題:
1. Kubernetes 的容器日志有沒有 rotate 上限?這個上限是多少?
查詢發現 Kubernetes 目前沒有任何容器日志大小限制,相關 issue 包括 Docker daemon logs filled node disk space 和 docker container log does not get rotate on k8s master node causes host to run out of space quickly
目前的建議是修改 /etc/docker/daemon.json,設置節點層級的 log size limit。
2. Fluentd 的日志抓取策略是怎樣的?它會監控后端 ES 索引的內容么?還是說它每次都在全量掃描所有容器日志?
查看 fluentd-kubernetes-daemonset 的 kubernetes.conf 發現,它使用 type: tail 進行日志的抓取。
這種抓取方式只抓取最新的行,並且會記錄下當前的位置(記錄在文件 /fluentd/log/xxx.pos 中)。如果日志被 rotated 了,fluentd 會從頭開始讀取日志。
至於為何手動刪除掉所有已經同步好的 ES 數據后,Fluend 新同步的數據里,為何還存在舊數據(七八天前的日志都可能被同步過來)?這個我也還沒搞清楚。。。待研究。
設置 Fluend 的 ES 索引名稱
查看 fluentd+elasticsearch 的官方 k8s 配置文件:fluentd-daemonset-elasticsearch.yaml,發現它默認啟用 logstash_format
,以方便地和 ES+Kibana 協作。
Fluentd 默認使用 logstash
為 ES 索引的前綴,可以通過設定環境變量 FLUENT_ELASTICSEARCH_LOGSTASH_PREFIX
修改這個前綴。