日志和成本咱們運(yùn)維人該如何平衡?
今天聊聊日志的事,都知道日志采集不是越多越好,也不是越少越省心這個(gè)道理,那么如何平衡日志和成本的關(guān)系呢?
什么叫價(jià)值大于成本?簡(jiǎn)單說(shuō)就是,這些日志在關(guān)鍵時(shí)刻能救你命的,那就得全量保存;那些只是看起來(lái)有用,實(shí)際上99%的時(shí)間都在吃灰的,該省就省。

我踩過(guò)的那些坑
先說(shuō)說(shuō)我犯過(guò)的蠢事兒吧。
剛開始做運(yùn)維那會(huì)兒,老楊特別"勤奮",恨不得把服務(wù)器上每個(gè)進(jìn)程放的每個(gè)屁都記錄下來(lái)。結(jié)果呢?
存儲(chǔ)成本直接爆表不說(shuō),光是在茫茫日志海里找一條有用的信息,就能讓人頭禿。我記得有次凌晨三點(diǎn)接到告警,系統(tǒng)出故障了,我花了兩個(gè)小時(shí)才從幾十GB的debug日志里找到真正的錯(cuò)誤信息。那感覺(jué),就像在垃圾堆里找鉆戒。
后來(lái)我又矯枉過(guò)正,想著既然全量不行,那就只保存ERROR級(jí)別的日志吧。結(jié)果呢?遇到一些詭異的問(wèn)題,錯(cuò)誤日志看起來(lái)很正常,但就是定位不到根因。最后發(fā)現(xiàn),關(guān)鍵信息都在被我丟棄的INFO級(jí)別里。
這么折騰了幾年,我才摸索出一套相對(duì)靠譜的策略。
我的分級(jí)采集心得
經(jīng)過(guò)這么多年的試錯(cuò),我把日志分成了四個(gè)等級(jí):
(1) A級(jí):生死攸關(guān)的日志
這類日志包括審計(jì)記錄、交易流水、合規(guī)相關(guān)的。這些東西必須全量保存,而且保留期要長(zhǎng)。為什么?因?yàn)槌隽耸聝?,這些就是你的救命稻草。法務(wù)找你要證據(jù),審計(jì)來(lái)檢查,你拿不出來(lái)就死定了。
(2) B級(jí):排障必備的日志
主要是錯(cuò)誤和異常堆棧。這些也得優(yōu)先保留,畢竟出故障的時(shí)候,這些是最直接的線索。
(3) C級(jí):業(yè)務(wù)監(jiān)控類日志
這些通常是結(jié)構(gòu)化的指標(biāo)信息,比如接口響應(yīng)時(shí)間、用戶行為統(tǒng)計(jì)等。這類數(shù)據(jù)有一定價(jià)值,但不是每條都重要,可以按需保留。
(4) D級(jí):調(diào)試追蹤日志
這就是那些debug、trace級(jí)別的詳細(xì)信息了。平時(shí)基本用不上,但調(diào)試的時(shí)候又離不開。我的策略是默認(rèn)采樣保存,需要的時(shí)候再開全量。
技術(shù)實(shí)現(xiàn)的一些門道
說(shuō)完理論,來(lái)點(diǎn)實(shí)際的。我這些年用過(guò)不少工具,也寫過(guò)不少腳本。
(1) 動(dòng)態(tài)采樣這招真好用
我現(xiàn)在用的是Fluent Bit配合自己寫的Lua腳本做采樣。比如這個(gè)概率采樣的腳本:
function sample(tag, timestamp, record)
-- 正常情況下采樣1%
local p = 0.01
-- 如果是錯(cuò)誤日志,100%保留
if record['level'] == 'ERROR' or record['level'] == 'FATAL' then
return 1, timestamp, record
end
-- 其他按概率采樣
math.randomseed(os.time() + tonumber(tostring(record['request_id']):sub(-4), 10))
if math.random() < p then
return 1, timestamp, record
end
return 0, 0, 0
end對(duì)應(yīng)的Fluent Bit配置:
[FILTER]
Name lua
Match *
script sample.lua
call sample運(yùn)行起來(lái)大概是這個(gè)效果:
[info] Lua filter: sampled 12 of 1200 events
[info] Lua filter: kept 45 ERROR events(2) 故障時(shí)一鍵切換全量
這個(gè)功能救過(guò)我好幾次命。平時(shí)采樣運(yùn)行,出故障了立馬切換到全量模式。
在Kubernetes環(huán)境里,我用這個(gè)命令快速切換:
$ kubectl -n logging set env daemonset/fluent-bit LOG_SAMPLE_RATE=1.0控制臺(tái)會(huì)顯示:
daemonset.apps/fluent-bit updated
...問(wèn)題解決后,再切回來(lái):
$ kubectl -n logging set env daemonset/fluent-bit LOG_SAMPLE_RATE=0.01(3) 成本控制要算清楚賬
老楊給你算筆賬。假設(shè)你們公司有200臺(tái)服務(wù)器,每臺(tái)每天產(chǎn)生0.5GB日志。
- 日總量:200臺(tái) × 0.5GB = 100GB/天
- 月總量:100GB × 30天 = 3TB/月
如果存儲(chǔ)價(jià)格按0.2元/GB·月算(這還只是存儲(chǔ),不包括索引和查詢費(fèi)用):3000GB × 0.2元 = 600元/月
這還沒(méi)算索引費(fèi)用呢,實(shí)際成本可能要翻倍。所以你得想想,這些日志到底值不值這個(gè)錢。
我現(xiàn)在的保留策略
經(jīng)過(guò)這么多年的摸索,我現(xiàn)在的策略是這樣的:
- 審計(jì)和交易日志:全量保存90天以上,有些甚至要保存幾年
- 錯(cuò)誤異常日志:全量保存30天,這個(gè)時(shí)間基本夠排查大部分問(wèn)題了
- 業(yè)務(wù)info日志:結(jié)構(gòu)化后保留7-30天,看具體業(yè)務(wù)重要程度
- 調(diào)試trace日志:采樣1%-10%,保留1-3天就夠了
對(duì)于歷史數(shù)據(jù),我會(huì)壓縮后放到對(duì)象存儲(chǔ)里,需要的時(shí)候再取出來(lái)分析。
監(jiān)控聯(lián)動(dòng)讓采集更智能
現(xiàn)在我還加了個(gè)智能的東西——用監(jiān)控指標(biāo)來(lái)觸發(fā)采集策略。
比如當(dāng)某個(gè)服務(wù)的錯(cuò)誤率超過(guò)閾值時(shí),自動(dòng)把這個(gè)服務(wù)的日志采樣率調(diào)到100%:
# 這是我寫的一個(gè)簡(jiǎn)單監(jiān)控腳本的片段
if [ $(curl -s "http://prometheus:9090/api/v1/query?query=error_rate{service=\"$service\"}" | jq -r '.data.result[0].value[1]') -gt 0.01 ]; then
kubectl -n logging set env daemonset/fluent-bit LOG_SAMPLE_RATE_${service^^}=1.0
echo "Service $service error rate elevated, switched to full logging"
fi這樣平時(shí)保持低成本運(yùn)行,有問(wèn)題的時(shí)候自動(dòng)切換到全量模式,既省錢又不會(huì)漏掉關(guān)鍵信息。























