help request: Multiple Buffers in "cluster-wide and namespaced FluentdConfig multi-tenant scenarios"
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 32/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- kubernetes, yaml
- Lĩnh vực
- devops, infrastructure
Hướng nghiên cứu
Bắt đầu với các manifest ClusterFluentdConfig, FluentdConfig, ClusterOutput và Filter, sau đó so sánh các section được tạo trong /fluentd/etc/fluent.conf cho các route phát triển và trên toàn cluster. Tái hiện deployment và kiểm tra lỗi duplicate buffer-path đã được báo cáo. Hoàn thành khi developer filter có thể được deploy mà Fluentd không bị lỗi, đồng thời cấu hình được tạo vẫn giữ các route dự kiến và hành vi của buffer.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Describe the issue
Hi everyone.
does somebody get fluent-operator fully working with kubernetes with mixed clusterinput, -filter, and -output written by cloudops and Filter written by Devops?
I want in fluentd something like this:
- Source is defined as ClusterInput by CloudOp
- ClusterFilter adds company related metainformation to the incoming Logs. In my example, i want to append the opensearch indexname (zzz-namespace-index).
- CloudOp setup a Opensearch ClusterOutput, with a Buffer Section for log persistency
- Developer creates his own Filter, which referes to the ClusterOutput.
This are my manifests i managed to get running so far:
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterFluentdConfig
metadata:
labels:
fluentd.default.config: "true"
name: fluentd-config
namespace: fluent
spec:
clusterInputSelector:
matchLabels:
fluentd.default.input: "true"
clusterFilterSelector:
matchLabels:
fluentd.default.filter: "true"
clusterOutputSelector:
matchLabels:
fluentd.default.output: "true"
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: Fluentd
metadata:
labels:
app.kubernetes.io/name: fluentd
name: fluentd
namespace: fluent
spec:
envVars:
- name: FLUENTD_OUTPUT_LOGLEVEL
value: debug
- name: OPENSEARCH_USERNAME
valueFrom:
secretKeyRef:
name: fluentbit-credentials
key: username
- name: OPENSEARCH_PASSWORD
valueFrom:
secretKeyRef:
name: fluentbit-credentials
key: password
- name: OPENSEARCH_HOST
value: opensearch-ingest.my-domain.org
fluentdCfgSelector:
matchLabels:
fluentd.default.config: "true"
buffer:
pvc:
apiVersion: v1
kind: PersistentVolumeClaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 16Gi
storageClassName: default
defaultFilterSelector:
matchLabels:
fluentd.default.filter: "true"
defaultOutputSelector:
matchLabels:
fluentd.default.output: "true"
globalInputs:
- forward:
bind: 0.0.0.0
port: 24224
image: ghcr.io/fluent/fluent-operator/fluentd:v1.17.0
logLevel: info
mode: collector
positionDB: {}
replicas: 3
resources:
limits:
cpu: 1000m
memory: 2Gi
requests:
cpu: 500m
memory: 1Gi
service: {}
livenessProbe:
exec:
command:
- /bin/sh
- -c
- "[ $(du -sb /buffers/opensearch-buffer | cut -f1) -gt 94371840 ] && exit 1 || true"
volumeMounts:
- name: cm-opensearch-client-certs
mountPath: /etc/opensearch-tls
volumes:
- name: cm-opensearch-client-certs
secret:
defaultMode: 420
secretName: cm-opensearch-client-certs
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterFilter
metadata:
name: 001-istio-proxy-0-parsing
namespace: fluent
labels:
fluentd.default.filter: "true"
spec:
filters:
- parser:
keyName: log
parse:
type: json
reserveData: true
removeKeyNameField: false
hashValueField: "istio-access-log"
emitInvalidRecordToError: false
tag: "istio-proxy.**"
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterFilter
metadata:
name: 001-istio-proxy-1-transforming
namespace: fluent
labels:
fluentd.default.filter: "true"
spec:
filters:
- recordTransformer:
enableRuby: true
records:
- key: log
value: "${record['kubernetes'] && record['kubernetes']['container_name'] == 'istio-proxy' && record['istio-access-log'] && !record['istio-access-log'].empty? ? nil : record['log']}"
tag: "istio-proxy.**"
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterFilter
metadata:
name: zzz-namespace-index
namespace: fluent
labels:
fluentd.default.filter: "true"
spec:
filters:
- recordTransformer:
enableRuby: true
records:
- key: logstash_prefix
value: "${record['namespaceindex'] or 'adm-unknown'}"
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterOutput
metadata:
labels:
fluentd.default.output: "true"
name: fluentd-output-opensearch
namespace: fluent
spec:
outputs:
- customPlugin:
config: |
<match **>
@type opensearch
enable_ruby true
host "#{ENV['OPENSEARCH_HOST']}"
port 9200
scheme http
user "#{ENV['OPENSEARCH_USERNAME']}"
password "#{ENV['OPENSEARCH_PASSWORD']}"
logstash_format true
logstash_prefix ${$.logstash_prefix}
#connection settings
request_timeout 15s
reload_connections true
reload_on_failure true
resurrect_after 5s
log_os_400_reason true
<buffer tag, $.logstash_prefix>
@type file
path /buffers/opensearch-buffer
flush_thread_count 16
flush_interval 1s
chunk_limit_size 90M
overflow_action block
queue_limit_length 16
flush_mode interval
retry_max_interval 30
retry_forever true
</buffer>
</match>
It results to this config:
<source>
@type forward
bind 0.0.0.0
port 24224
</source>
<match **>
@id main
@type label_router
<route>
@label @db681e4cb763ca5b7cdbf9ab76f67bbe
<match>
</match>
</route>
</match>
<label @db681e4cb763ca5b7cdbf9ab76f67bbe>
<filter istio-proxy.**>
@id ClusterFluentdConfig-cluster-fluentd-config::cluster::clusterfilter::001-istio-proxy-0-parsing-0
@type parser
emit_invalid_record_to_error false
hash_value_field istio-access-log
key_name log
remove_key_name_field false
reserve_data true
<parse>
@type json
</parse>
</filter>
<filter istio-proxy.**>
@id ClusterFluentdConfig-cluster-fluentd-config::cluster::clusterfilter::001-istio-proxy-1-transforming-0
@type record_transformer
enable_ruby true
<record>
log ${record['kubernetes'] && record['kubernetes']['container_name'] == 'istio-proxy' && record['istio-access-log'] && !record['istio-access-log'].empty? ? nil : record['log']}
</record>
</filter>
<filter **>
@id ClusterFluentdConfig-cluster-fluentd-config::cluster::clusterfilter::zzz-namespace-index-0
@type record_transformer
enable_ruby true
<record>
logstash_prefix ${record['namespaceindex'] or 'adm-unknown'}
</record>
</filter>
<match **>
@type opensearch
enable_ruby true
host "#{ENV['OPENSEARCH_HOST']}"
port 9200
scheme http
user "#{ENV['OPENSEARCH_USERNAME']}"
password "#{ENV['OPENSEARCH_PASSWORD']}"
logstash_format true
logstash_prefix ${$.logstash_prefix}
#connection settings
request_timeout 15s
reload_connections true
reload_on_failure true
resurrect_after 5s
log_os_400_reason true
<buffer tag, $.logstash_prefix>
@type file
path /buffers/opensearch-buffer
flush_thread_count 16
flush_interval 1s
chunk_limit_size 90M
overflow_action block
queue_limit_length 16
flush_mode interval
retry_max_interval 30
retry_forever true
</buffer>
</match>
</label>
So far, so good. Now i am struggling with the Developer Part. The developer should able to get his own filter running, before our clusterfilter adds the "zzz-namespace-clusterfilter". This are my test manifests for the developer part in his namespace:
apiVersion: fluentd.fluent.io/v1alpha1
kind: FluentdConfig
metadata:
name: fluentd-clusterconfig-referrer
namespace: development
labels:
fluentd.default.config: "true"
spec:
clusterOutputSelector:
matchLabels:
fluentd.default.output: "true"
filterSelector:
matchLabels:
my-own-namespaced-filter: "true"
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: Filter
metadata:
labels:
my-own-namespaced-filter: "true"
name: development-fulllog-parsing
namespace: development
spec:
filters:
- grep:
regexp:
- key: "log"
pattern: '\[fulllog\]'
- parser:
keyName: log
reserveData: true
removeKeyNameField: false
injectKeyPrefix: "processed."
emitInvalidRecordToError: false
parse:
type: regexp
expression: '^(?<date>\S+)\s+(?<time>\S+)\s+(?<pid>\S+)\s+(?<logger>\S+)\s+\[(?<level>\S+)\]:\s+\[fulllog\]\s+(?<logmessage>.*)$'
- parser:
keyName: processed.logmessage
parse:
type: json
reserveData: true
removeKeyNameField: false
injectKeyPrefix: "fulllog."
emitInvalidRecordToError: false
As soon as I deploy the manifesto, fluentd stops working. As an error, i get
2025-02-03 20:58:42 +0000 [error]: config error file="/fluentd/etc/fluent.conf" error_class=Fluent::ConfigError error="Other 'opensearch' plugin already use same buffer path: type = opensearch, buffer path = /buffers/opensearch-buffer"
level=error msg="Fluentd exited" error="exit status 1"
The created config looks like this:
<source>
@type forward
bind 0.0.0.0
port 24224
</source>
<source>
@type prometheus
@id in_prometheus
bind "0.0.0.0"
port 2021
metrics_path "/metrics"
</source>
<source>
@type prometheus_output_monitor
interval 10
<labels>
hostname ${hostname}
</labels>
</source>
<match **>
@id main
@type label_router
<route>
@label @b7d2982af63a444d6468354108b8c5f1
<match>
namespaces development
</match>
</route>
<route>
@label @db681e4cb763ca5b7cdbf9ab76f67bbe
<match>
</match>
</route>
</match>
<label @b7d2982af63a444d6468354108b8c5f1>
<filter **>
@id FluentdConfig-development-fluentd-clusterconfig-referrer::development::filter::development-fulllog-parsing-0
@type grep
<regexp>
key log
pattern \[fulllog\]
</regexp>
</filter>
<filter **>
@id FluentdConfig-development-fluentd-clusterconfig-referrer::development::filter::development-fulllog-parsing-1
@type parser
emit_invalid_record_to_error false
inject_key_prefix processed.
key_name log
remove_key_name_field false
reserve_data true
<parse>
@type regexp
expression ^(?<date>\S+)\s+(?<time>\S+)\s+(?<pid>\S+)\s+(?<logger>\S+)\s+\[(?<level>\S+)\]:\s+\[fulllog\]\s+(?<logmessage>.*)$
</parse>
</filter>
<filter **>
@id FluentdConfig-development-fluentd-clusterconfig-referrer::development::filter::development-fulllog-parsing-2
@type parser
emit_invalid_record_to_error false
inject_key_prefix fulllog.
key_name processed.logmessage
remove_key_name_field false
reserve_data true
<parse>
@type json
</parse>
</filter>
<match **>
@type opensearch
enable_ruby true
host "#{ENV['OPENSEARCH_HOST']}"
port 9200
scheme http
user "#{ENV['OPENSEARCH_USERNAME']}"
password "#{ENV['OPENSEARCH_PASSWORD']}"
logstash_format true
logstash_prefix ${$.logstash_prefix}
#connection settings
request_timeout 15s
reload_connections true
reload_on_failure true
resurrect_after 5s
log_os_400_reason true
<buffer tag, $.logstash_prefix>
@type file
path /buffers/opensearch-buffer
flush_thread_count 16
flush_interval 1s
chunk_limit_size 90M
overflow_action block
queue_limit_length 16
flush_mode interval
retry_max_interval 30
retry_forever true
</buffer>
</match>
</label>
<label @db681e4cb763ca5b7cdbf9ab76f67bbe>
<filter istio-proxy.**>
@id ClusterFluentdConfig-cluster-fluentd-config::cluster::clusterfilter::001-istio-proxy-0-parsing-0
@type parser
emit_invalid_record_to_error false
hash_value_field istio-access-log
key_name log
remove_key_name_field false
reserve_data true
<parse>
@type json
</parse>
</filter>
<filter istio-proxy.**>
@id ClusterFluentdConfig-cluster-fluentd-config::cluster::clusterfilter::001-istio-proxy-1-transforming-0
@type record_transformer
enable_ruby true
<record>
log ${record['kubernetes'] && record['kubernetes']['container_name'] == 'istio-proxy' && record['istio-access-log'] && !record['istio-access-log'].empty? ? nil : record['log']}
</record>
</filter>
<filter **>
@id ClusterFluentdConfig-cluster-fluentd-config::cluster::clusterfilter::zzz-namespace-index-0
@type record_transformer
enable_ruby true
<record>
logstash_prefix ${record['namespaceindex'] or 'adm-unknown'}
</record>
</filter>
<match **>
@type opensearch
enable_ruby true
host "#{ENV['OPENSEARCH_HOST']}"
port 9200
scheme http
user "#{ENV['OPENSEARCH_USERNAME']}"
password "#{ENV['OPENSEARCH_PASSWORD']}"
logstash_format true
logstash_prefix ${$.logstash_prefix}
#connection settings
request_timeout 15s
reload_connections true
reload_on_failure true
resurrect_after 5s
log_os_400_reason true
<buffer tag, $.logstash_prefix>
@type file
path /buffers/opensearch-buffer
flush_thread_count 16
flush_interval 1s
chunk_limit_size 90M
overflow_action block
queue_limit_length 16
flush_mode interval
retry_max_interval 30
retry_forever true
</buffer>
</match>
</label>
Contrary to what I thought, it does not use the route that I had created as cloudop at the end, instead it creates a copy in its own namespace. This leads to the buffer collision.
The Question are
-
is my approach correct? If not, whats the best practice here? -
How does i manage the file buffer per namespace? -
How can i setup ONE global clusteroutput for logs?
How did you install fluent operator?
No response
Additional context
No response
- Ngôn ngữ chính
- Go
- Star
- 689
- Fork
- 333
- Merge trung bình
- 2 ngày 6 giờ
- Pull request đã merge (30 ngày)
- 43
Chuẩn bị môi trường
Khởi chạy dev container của dự án ngay trên trình duyệt, bằng tài khoản GitHub của bạn.
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của fluent/fluent-operator
-
feat: support the Fluent Bit type_converter filterCó thể đã có người làm @NopeCharon đã nhận hôm nay. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 65/100
fluent/fluent-operator#2131 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug: fluent-bit image still ships vulnerable libbrotli1 (CVE-2026-111497)Có thể đã có người làm @joshuabaird đã nhận 9 ngày trước. Đang mởfluent-bit security
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 55/100
fluent/fluent-operator#2082 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug: fluent operator is consuming lot of cpu cores (~27 of the 32 available cores on a Node)Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
fluent/fluent-operator#1990 · 9 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement fluent-bit good first issue
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
fluent/fluent-operator#1854 · 2 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Remove tag consideration from Fluentd ClusterFilter / Filter orderCó thể đã có người làm @cvas22 đã nhận 1 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 45/100
fluent/fluent-operator#1832 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của fluent/fluent-operator
Issue tương tự
-
automated-triage type/bug type/ci
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 75/100
hashicorp/terraform-provider-google#30678 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 83/100
ethereum-optimism/optimism#24120 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area/docs
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 86/100
meshery/meshery#23375 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
ApplicationSet: BitBucket Cloud SCM provider returns corrupted error (%!w(<nil>)) when a branch has no commit hashCó thể đã có người làm @AP24110011695 đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 1 ngày