Tanzu Kubernetes Grid ExtensionsのFluent Bitにyttを使ってLua Filterでscriptを設定するメモ
TKG ExtensionsのFluent Bitをyttでカスタマイズする例です。
ここではLua Filterを使ってLua Scriptによるrecordの加工を行います。
ログメッセージ中の@n@を\nに変換する処理を書きます。
以下ではTKG Extensionは1.2を使用しています。マニフェストはこちらからダウンロードできます。
tkg-extensionsディレクトリに展開してある前提です。
次のディレクトリ及びファイルを作成します。
tkg-extensions/overlays/logging/fluent-bit/filter-transform.yaml
#@ load("@ytt:overlay", "overlay")
#@overlay/match by=overlay.subset({"kind":"ConfigMap", "metadata": {"name": "fluent-bit-config"}})
---
data:
#@overlay/replace via=lambda a, b: a + b
filter-record.conf: |
[FILTER]
Name lua
Match *
script /fluent-bit/scripts/transform.lua
call cb_transform
---
apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-scripts
namespace: tanzu-system-logging
labels:
k8s-app: fluent-bit
data:
transform.lua: |
function cb_transform(tag, timestamp, record)
if record['message'] ~= nil then
record['message'] = record['message']:gsub('@n@', '\n')
end
return 2, timestamp, record
end
#@overlay/match by=overlay.subset({"kind":"DaemonSet", "metadata": {"name": "fluent-bit"}})
---
spec:
template:
spec:
containers:
#@overlay/match by="name"
- name: fluent-bit
volumeMounts:
#@overlay/match by="name", missing_ok=True
- name: fluent-bit-scripts
mountPath: /fluent-bit/scripts/
volumes:
#@overlay/match by="name", missing_ok=True
- name: fluent-bit-scripts
configMap:
name: fluent-bit-scripts
やっていることは
fluent-bit-configConfigMapのfilter-record.confにLua用の[Filter]の設定を追記- Lua Scriptを含む
fluent-bit-scriptsConfig Mapを追加 fluent-bitDaemonSetにfluent-bit-scriptsConfigMapをマウント
です。
yttで結合するの例は以下の通りです。
ytt \
-f tkg-extensions/common \
-f tkg-extensions/logging/fluent-bit \
-f tkg-extensions/overlays/logging/fluent-bit/filter-transform.yaml \
-v tkg.instance_name=my-instance \
-v tkg.cluster_name=my-cluster \
-v fluent_bit.output_plugin=elasticsearch \
-v fluent_bit.elasticsearch.host=elasticsearch.elasticsearch-kibana.svc.cluster.local \
-v fluent_bit.elasticsearch.port=9200
これをkubectlやkappでデプロイすれば良いです。
今回の例は、アプリのログが複数行に跨がる場合に、Fluent Bitが各行をそれぞれ別レコードとしてElasticsearchなどに送信し、検索しづらくなるのを防ぐため、
アプリ側で\nを@n@に置換し、複数行のログを1行にまとめ、Fluent Bit側で送信する前に再度@n@を\nに戻す処理を行いたくて実装しました。
Spring BootでSLF4Jを使う場合は次の環境変数を設定することでログの\nを@n@に置換できます。
- name: LOGGING_EXCEPTIONCONVERSIONWORD
value: "\t%replace(%replace(%xEx){'\n','@n@'}){'\t',' '}%nopex"
- name: LOGGING_PATTERN_CONSOLE
value: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${logging.pattern.level:%5p}) %clr(${PID: }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %replace(%m){'\n','@n@'}${logging.exception-conversion-word:%wEx}%n"
例えば次のようにElasticsearch上で複数行ログを見ることができます。

尚、複数行対応はFluent BitのMultiline Configurationを設定した方がスマートだと思います。 また、既存のログフォーマット自体を変えて良いならecs-loggingを使って構造化ログを送った方が良いでしょう。
追記
Elasticsearchの表示改行させるだけなら次のように\nを\rするだけで良かったです。
- name: LOGGING_EXCEPTIONCONVERSIONWORD
value: "\t%replace(%replace(%xEx){'\n','\r'}){'\t',' '}%nopex"
- name: LOGGING_PATTERN_CONSOLE
value: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${logging.pattern.level:%5p}) %clr(${PID: }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %replace(%m){'\n','\r'}${logging.exception-conversion-word:%wEx}%n"
わざわざLuaで@n@を\nに置換する必要はありませんでした。他の用途でLuaスクリプトを使いたいことがあると思うので、この記事は残しておきます。