はじめに
Logging Operator (https://kube-logging.dev/) はCNCFの1プロジェクトでfluentd, fluentbit, syslog-ng等を一元管理するためのOperatorです。
環境
- Logging Operator v4.11.0
公式ガイドの記述はLogigng, Flutentbit, Fluentdに関するリソース設定を分割しようとしているようですが、まだLoggingの定義に含まれる記述が残っているようです。
Logging Operatorの利点
Fluentdを既に利用している人にとっては新しくOperatorの書式で書き直す利点は少ないでしょう。
動作自体は次のようにFluentbitとFluentdを組み合わせて動作します。
- Flutentbitを各ノードで実行して/var/log/container/以下から全Podのメッセージを収集する
- Flow, Outputの設定に従って必要なログをFluentdクラスターに送信する
- FluentdはOutputの設定に従って最終到達先に届ける
試した構成
apiVersion: logging.banzaicloud.io/v1beta1
kind: Logging
metadata:
name: default-logging-namespaced
namespace: logging
spec:
controlNamespace: logging
errorOutputRef: default
apiVersion: logging.banzaicloud.io/v1beta1
kind: ClusterOutput
metadata:
name: default
spec:
http:
endpoint: http://logging-operator-test-receiver.logging:8080
content_type: application/json
buffer:
type: memory
tags: time
timekey: 1s
timekey_wait: 0s
apiVersion: logging.banzaicloud.io/v1beta1
kind: FluentbitAgent
metadata:
# Use the name of the logging resource
name: default-logging-resource
spec:
inputTail:
storage.type: filesystem
bufferStorage:
storage.path: /buffers
customParsers: |
[PARSER]
Name harbor-nginx
Format regex
Regex ^\[(?<time>.*)\]:(?<remote>[^ ]+) (?<user>[^ ]*) "(?<method>[^ ]*) (?<path>[^ ]*) (?<scheme>[^ ]*)" (?<status>[^ ]*) (?<size>[^ ]*) "(?<referer>[^ ]*)" "(?<agent>[^ ]*)".*$
Time_Key time
Time_Format %d/%b/%Y:%H:%M:%S %z
apiVersion: logging.banzaicloud.io/v1beta1
kind: FluentdConfig
metadata:
# Use the name of the logging resource
name: example-logging-resource
# Use the control namespace of the logging resource
namespace: logging
spec:
scaling:
replicas: 2
単純にdocker.io/library/nginx:latestを動作させたnamespace: logging-testで、ログファイルをOpenSearchとtest-receiverに収集するための設定を行います。
apiVersion: logging.banzaicloud.io/v1beta1
kind: Output
metadata:
name: opensearch
spec:
opensearch:
host: my-first-cluster.opensearch-operator
port: 9200
scheme: https
ssl_verify: false
ssl_version: TLSv1_2
user: admin
password:
valueFrom:
secretKeyRef:
name: logging-password
key: password
buffer:
timekey: 1m
timekey_wait: 30s
timekey_use_utc: true
test-receiverはHelmを導入した際にOperatorと一緒にインストールされています。
namespace:loggingで動作しているので、他のnamespaceで動作しているnginxなどから接続するためにホスト名(Service名)の後ろにnamespace名を入れて次のように設定しました。
apiVersion: logging.banzaicloud.io/v1beta1
kind: Output
metadata:
name: test-receiver
spec:
http:
endpoint: http://logging-operator-test-receiver.logging:8080
content_type: application/json
buffer:
type: memory
tags: time
timekey: 1s
timekey_wait: 0s
準備した2つのoutputを指定して、Flowを設定します。
apiVersion: logging.banzaicloud.io/v1beta1
kind: Flow
metadata:
name: nginx
spec:
match:
- select:
labels:
app: my-nginx
localOutputRefs:
- opensearch
- test-receiver
filters:
- tag_normaliser: {}
- parser:
remove_key_name_field: true
reserve_data: true
parse:
type: nginx
OpenSearchに接続する時のユーザー名はadminにしていますが、ここは適宜変更してください。
またパスワードを登録するsecret/logging-passwordは次のように定義しています。
apiVersion: v1
kind: Secret
metadata:
name: logging-password
type: Opaque
data:
# username: admin
# password: a1341a57063b07e7
password: YTEzNDFhNTcwNjNiMDdlNw==
こんな方法でOpenSearchにログファイルを集めることができるようになりました。
デフォルトのパーサーが対応できないログファイルの収集
バルクで出力をMinioなどのオブジェクトストアや、fruentedで構成されたtest-reveicerに送信するには問題ありませんが、OpenSearchなどに転送しようとすると問題が発生します。
解析を前提としている以上、フォーマットをある程度解析してあげないとうまくいかないようです。
以下のようなnginxのデフォルト出力はうまく処理できています。
10.233.113.0 - - [16/Dec/2024:06:25:29 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.81.0" "-"
この要素はデフォルトの設定だとOpenSearchに渡されて次のように分類されます。
Harborのfrontendもnginxですが、出力されるログの形式が少し違います。
## $ sudo kubectl -n harbor logs -l app=harbor,app.kubernetes.io/component=nginx
[17/Dec/2024:00:27:12 +0000]:192.168.100.52 - "GET / HTTP/1.1" 200 785 "-" "kube-probe/1.30" 0.002 0.001 .
[17/Dec/2024:00:27:12 +0000]:192.168.100.52 - "GET / HTTP/1.1" 200 785 "-" "kube-probe/1.30" 0.001 0.002 .
Harborのnginxの設定を確認すると、次のようにlog_formatが変更されています。
log_format timed_combined '[$time_local]:$remote_addr - '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time $pipe';
nginxのガイドに記載されているデフォルトのcombined形式は次のように定義されています。
c
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
この違いを吸収するため、fluentbitにカスタムフォーマットを追加します。
このfluentbitのドキュメントにはOnigmoのRubyモードでregexが動くので、Rubularで正規表現をチェックするように書かれています。
Rubularを使ってregexを決めていきました。
またTime_Formatはstrptimeのフォーマットなので一般的なドキュメントを確認するようガイドされています。
最終的に冒頭で導入したような03.fluentbitagent.yamlを設定しています。
全体の感想
複数のnamespaceに設定を入れていくと、1つの設定ミスが全体のパフォーマンスやログ送信に影響するような印象を受けました。
きちんとテストしきれていませんが、不安定になった時の挙動や設定の反映までの時間には課題がありそうです。
Outputリソースを再定義した場合にはfluentdは自動的に再起動されているようですが、試行錯誤していた初期の頃はちぐはぐな設定がそこら中に散乱している状態で、なぜ設定を反映したのにうまく反映できないのかよく分からない状態になることが多かったです。

