Fluent Bitを使ってKubernetesのPodのログをSyslogサーバー(rsyslog)へ転送してみた。
Fluent Bitとは
高いパフォーマンスと低リソースでの動作を考慮して設計されC言語で実装された、ログのコレクター・アグリゲータ。
ライセンスはApache License v2.0で、CNCFではgraduatedのプロジェクト。
Fluentdとの違いは以下
KubernetesへのFluent Bitインストール
Kubernetesへのインストール自体はHelmチャートが用意されている。
リポジトリを追加し、
helm repo add fluent https://fluent.github.io/helm-charts
インストールするのが基本。
helm upgrade --install fluent-bit fluent/fluent-bit -n logging --create-namespace
なお、デフォルト設定では以下の構成でデプロイされる。
- DaemonSetでデプロイ
- ノードOS上に生成されるpodのログの保存先をhostPathでボリュームマウント
- 上記のpodのログをTail inputプラグインで取得
- 取得したログをKubernetesフィルタでメタデータ含めてオブジェクト化
- "elasticsearch-master"でアクセスできるElasticsearchサーバーへ転送
本記事では、レガシーなシステムも含んだ構成であれば割とありがちのような気がする、リモートのSyslogサーバーへの転送についてのまとめ。
Syslog転送設定
やることは、デフォルトではElasticsearch outputプラグインが指定されている箇所を、Syslog outputプラグインを使うように置き換える。
Syslog outputプラグインは以下。
kubernetesフィルタ使用時のデータ構造
ドキュメントのどこかに載ってるかもしれないけどよくわからなかったのでfile
やstdout
で確認。サンプルとしてApache HTTP ServerのログであればJSON形式に整形すると以下の通り。
Apacheのログ自体はlog
キー以下にある。Pod名、コンテナ名、イメージ名、ネームスペース名などのKubernetesの情報はkubernetes
キー以下で確認できる。
[ 1680840043.426684408, { "time": "2023-04-07T04:00:43.426684408Z", "stream": "stdout", "_p": "F", "log": "192.168.0.131 - - [07/Apr/2023:04:00:43 +0000] \"GET / HTTP/1.1\" 200 45", "kubernetes": { "pod_name": "sample-http-6bf6795c4-shn9t", "namespace_name": "sample-web", "pod_id": "136e2e0b-0a71-4a0c-9a18-13f335c03e83", "labels": { "app": "sample-http", "pod-template-hash": "6bf6795c4" }, "annotations": { "cni.projectcalico.org/containerID": "8f6ece5e3158043f9b9243b8a8a7979662151f1c4c603e7f087fabc7105d76a5", "cni.projectcalico.org/podIP": "10.244.56.6/32", "cni.projectcalico.org/podIPs": "10.244.56.6/32" }, "host": "k8su-worker02", "container_name": "httpd", "docker_id": "94b43c48d5f2861fbaf4ade9a8e3263fa50579a066dc275b6e066b5856d7eb24", "container_hash": "docker.io/library/httpd@sha256:83e99e7c437898cb564bbd3ceba7f1ea3f2d86e1cbd7a5324940086e59082f2b", "container_image": "docker.io/library/httpd:latest" } } ]
Syslog outputプラグイン設定
結論から言うと以下の内容で最低限「Pod内のアプリケーションのログ」を基本的な設定のSyslogサーバーへ転送できる。
キー | 設定内容 |
---|---|
name | syslog |
match | kube.* |
host | Syslogサーバーのアドレス |
port | Syslogサーバーのポート(default:514) |
mode | プロトコル(default:udp) |
syslog_message_key | log |
設定例は以下。
outputs: | [OUTPUT] name syslog match kube.* host 192.168.0.16 syslog_message_key log
ホスト名やアプリ名などを指定
ログの構造データのkubernetes
キーの配下にあるhost
やcontainer_name
をSyslogのホスト名やアプリ名に指定したい場合、kubernetes.host
などのように指定しても残念ながら認識しない。(少なくともSyslog outputプラグインはネストを解釈しないっぽい)
どうすれば良いかと言うと、まさにネストを処理するnest filterプラグインがあり、operation lift
の指定でフラットな構造に展開できる。
[FILTER] name nest match kube.* operation lift nest_under kubernetes add_prefix kubernetes_
これでkubernetes
キー配下の辞書になっていたPodのメタデータがkubernetes_host
やkubernetes_container_name
で参照できるようになる。
config
のfilters
およびoutputs
全体は以下のような感じ。
filters: | [FILTER] Name kubernetes Match kube.* Merge_Log On Keep_Log Off K8S-Logging.Parser On K8S-Logging.Exclude On [FILTER] name nest match kube.* operation lift nest_under kubernetes add_prefix kubernetes_ outputs: | [OUTPUT] name syslog match kube.* host 192.168.0.16 syslog_message_key log syslog_hostname_key kubernetes_namespace_name syslog_appname_key kubernetes_pod_name syslog_procid_key kubernetes_container_name
Appendix
Syslogサーバー側設定
以下参照 (若干古い)
ログ構造の確認
host
、port
、mode
などはSyslogサーバーの設定に合わせれば良いが、key
関連はFluent Bitが取り込んだログデータの構造がわからないと指定のしようがない。
ということで、Syslog転送設定の前にまずはデータ形式を確認してみた。
手っ取り早く、Standard Output
プラグインを使用。
outputs: | [OUTPUT] Name stdout Match kube.*
確認できるPodのログは例えばApache HTTP ServerのPodであればこんな感じ。
[0] kube.var.log.containers.sample-http-6bf6795c4-dcn9s_sample-web_httpd-c02fe813a7bfdc5206951a53c87f59e85df124cbc47bf97edfd2edcfb00c8b3e.log: [1680839704.357093483, {"time"=>"2023-04-07T03:55:04.357093483Z", "stream"=>"stdout", "_p"=>"F", "log"=>"192.168.0.131 - - [07/Apr/2023:03:55:04 +0000] "GET / HTTP/1.1" 200 45", "kubernetes"=>{"pod_name"=>"sample-http-6bf6795c4-dcn9s", "namespace_name"=>"sample-web", "pod_id"=>"15d48c8a-36b2-4faf-b5fc-f0550b7aa923", "labels"=>{"app"=>"sample-http", "pod-template-hash"=>"6bf6795c4"}, "annotations"=>{"cni.projectcalico.org/containerID"=>"80881d377d4b50307d972991fcb7ec2a7e9cb3419bd5547b640f6a7c5f74a1af", "cni.projectcalico.org/podIP"=>"10.244.165.70/32", "cni.projectcalico.org/podIPs"=>"10.244.165.70/32"}, "host"=>"k8su-worker01", "container_name"=>"httpd", "docker_id"=>"c02fe813a7bfdc5206951a53c87f59e85df124cbc47bf97edfd2edcfb00c8b3e", "container_hash"=>"docker.io/library/httpd@sha256:83e99e7c437898cb564bbd3ceba7f1ea3f2d86e1cbd7a5324940086e59082f2b", "container_image"=>"docker.io/library/httpd:latest"}}]
Fluent Bit自体のログは以下
[2023/04/07 03:54:34] [ info] [input:tail:tail.0] inotify_fs_add(): inode=541802 watch_fd=9 name=/var/log/containers/fluent-bit-clj5h_logging_fluent-bit-1f073e12bfef2f617e7a973953eaac518b4564253f550eb3735b8b101251bf2f.log
ホスト上のファイルシステムにアクセスできるなら、/var/log/pods/*/*/*.log
にあるはずのログファイルを直接見れば良い。
root@k8su-master:~# ls -F /var/log/pods/*/*/*.log /var/log/pods/calico-system_calico-kube-controllers-6b7b9c649d-6h9l7_34ddcac2-7f99-46fb-9824-e09915c6b6e2/calico-kube-controllers/0.log /var/log/pods/calico-system_calico-kube-controllers-6b7b9c649d-6h9l7_34ddcac2-7f99-46fb-9824-e09915c6b6e2/calico-kube-controllers/1.log /var/log/pods/calico-system_calico-node-x2zzv_47bd0f4f-7b6f-4007-966a-213bb9e95b8e/calico-node/0.log /var/log/pods/calico-system_calico-node-x2zzv_47bd0f4f-7b6f-4007-966a-213bb9e95b8e/flexvol-driver/0.log /var/log/pods/calico-system_calico-node-x2zzv_47bd0f4f-7b6f-4007-966a-213bb9e95b8e/install-cni/0.log /var/log/pods/calico-system_calico-typha-78cf4b6dfb-k9pp7_af899e10-6897-42ad-ae11-1f6ad80de873/calico-typha/0.log /var/log/pods/calico-system_csi-node-driver-d84sz_870ea5e3-9885-4f68-aa7a-3f4fa6b26ddd/calico-csi/0.log /var/log/pods/calico-system_csi-node-driver-d84sz_870ea5e3-9885-4f68-aa7a-3f4fa6b26ddd/csi-node-driver-registrar/0.log /var/log/pods/kube-system_coredns-787d4945fb-7jbpp_53643398-8d8f-4514-8aa3-5fa169f4e802/coredns/0.log /var/log/pods/kube-system_coredns-787d4945fb-w56qw_8fd2147a-7abc-4855-863e-5f250b1cc843/coredns/0.log /var/log/pods/kube-system_etcd-k8su-master_699fd81b5c8ec8c4dbc4338395262e53/etcd/0.log /var/log/pods/kube-system_kube-apiserver-k8su-master_de088f05e01138ec1dbc93cd4c84e2f2/kube-apiserver/0.log /var/log/pods/kube-system_kube-controller-manager-k8su-master_c41031e429b4a5f760fcbc35a86855b3/kube-controller-manager/14.log /var/log/pods/kube-system_kube-controller-manager-k8su-master_c41031e429b4a5f760fcbc35a86855b3/kube-controller-manager/15.log /var/log/pods/kube-system_kube-proxy-v8brj_8c1fa81b-af68-4bfd-bca3-18d55ee44f15/kube-proxy/0.log /var/log/pods/kube-system_kube-scheduler-k8su-master_258e9658795a8f3c8547485c6cfc7d9c/kube-scheduler/14.log /var/log/pods/kube-system_kube-scheduler-k8su-master_258e9658795a8f3c8547485c6cfc7d9c/kube-scheduler/15.log /var/log/pods/tigera-operator_tigera-operator-54b47459dd-kmxhr_4c57047a-7302-4170-bcc5-5a1e2f9df382/tigera-operator/12.log /var/log/pods/tigera-operator_tigera-operator-54b47459dd-kmxhr_4c57047a-7302-4170-bcc5-5a1e2f9df382/tigera-operator/13.log
除外条件
例えばFluent Bit自体のログを除外するために、Fluent Bitをデプロイするネームスペースを処理対象外とするなら以下のようにgrep
フィルタを指定する。
[FILTER] Name grep Match * Exclude $kubernetes['namespace_name'] logging
stdoutを使う場合は、Fluent Bitを含む各podが出力するログをFluent Bitが収集しFluent Bitのpodのログとしても出力するため、この除外設定が無いとFluent Bitのログが大量に出力されるので注意。
環境
- Kubernetes: v1.26.1 (kubeadmで構築)
- Fluent Bit Helmチャート: 0.24.0
- Fluent Bit: 2.0.9
- rsyslog: 8.2204.0-2.fc35 (Fedora 35)