---
title: Tanzu Kubernetes Grid ExtensionsのFluent Bitにyttを使ってLua Filterでscriptを設定するメモ
tags: ["Kubernetes", "TKG", "Tanzu", "TKG Extensions", "Fluent Bit", "ytt"]
categories: ["Dev", "CaaS", "Kubernetes", "TKG", "Extensions", "FluentBit"]
date: 2021-01-19T05:39:39Z
updated: 2021-01-19T13:22:23Z
---

[TKG ExtensionsのFluent Bit](https://docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/1.2/vmware-tanzu-kubernetes-grid-12/GUID-extensions-logging-fluentbit.html)をyttでカスタマイズする例です。

ここでは[Lua Filter](https://docs.fluentbit.io/manual/pipeline/filters/lua)を使ってLua Scriptによるrecordの加工を行います。
ログメッセージ中の`@n@`を`\n`に変換する処理を書きます。

以下ではTKG Extensionは1.2を使用しています。マニフェストは[こちら](https://my.vmware.com/en/group/vmware/downloads/details?downloadGroup=TKG-121&productId=988&rPId=56777)からダウンロードできます。
`tkg-extensions`ディレクトリに展開してある前提です。


次のディレクトリ及びファイルを作成します。

`tkg-extensions/overlays/logging/fluent-bit/filter-transform.yaml`

```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-config` ConfigMapの`filter-record.conf`にLua用の`[Filter]`の設定を追記
* Lua Scriptを含む`fluent-bit-scripts` Config Mapを追加
* `fluent-bit` DaemonSetに`fluent-bit-scripts` ConfigMapをマウント

です。

`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@`に置換できます。

```yaml
        - 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上で複数行ログを見ることができます。

![image](https://user-images.githubusercontent.com/106908/104992726-f6df7080-5a64-11eb-84f6-7850a217aa0a.png)


尚、複数行対応はFluent Bitの[Multiline Configuration](https://docs.fluentbit.io/manual/v/1.5/pipeline/inputs/tail#multiline)を設定した方がスマートだと思います。
また、既存のログフォーマット自体を変えて良いなら[ecs-logging](https://github.com/elastic/ecs-logging)を使って構造化ログを送った方が良いでしょう。


**追記**

Elasticsearchの表示改行させるだけなら次のように`\n`を`\r`するだけで良かったです。

```yaml
        - 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スクリプトを使いたいことがあると思うので、この記事は残しておきます。
