Cheng Dehao, Fluent Member, KubeSphere Member

Fluent Operator is introduced

With the rapid development of cloud native technology and continuous iteration of technology, higher requirements are put forward for log collection, processing and forwarding. There is a big difference between the logging architecture design based on physical machines or virtual airport landscape and the logging architecture design based on cloud native architecture. As a graduate project of CNCF, Fluent Bit is undoubtedly one of the preferred solutions for logging problems in cloud environments. However, the installation, deployment and configuration of Fluent Bit in Kubernetes has a certain threshold, which increases the cost of users.

On January 21, 2019, the KubeSphere community developed the Fluentbit Operator to meet the requirement of managing Fluent Bit in a cloud-native manner, and released v0.1.0 on February 17, 2020. Iterations followed, and the Fluentbit Operator was officially donated to the Fluent community on August 4, 2021.

The Fluentbit Operator reduces the threshold of using the Fluent Bit and can process log information efficiently and quickly. However, the Fluent Bit is weak in log processing. We have not integrated log processing tools, such as Fluentd, which has more plug-ins available. Based on the above requirements, the Fluentbit Operator integrates with Fluentd, aiming to integrate Fluentd into an optional log aggregation and forwarding layer, and renamed as the **Fluent Operator (GitHub address: Github.com/fluent/flue… Fluent Operator released v1.0.0 on March 25, 2022, and will continue to iterate on The Fluentd Operator, with v1.1.0 expected in q2 2022, adding more features and highlights.

The Fluent Operator provides flexibility and ease in deploying, configuring, and uninstalling the Fluent Bit and Fluentd. At the same time, the community also provides a large number of plug-ins supporting Fluentd and Fluent Bit, users can customize the configuration according to the actual situation. The official documentation provides detailed examples that are easy to use and reduce the barriers to using the Fluent Bit and Fluentd.

The stages of the logging pipeline

The Fluent Operator can deploy the Fluent Bit or Fluentd separately and is not required to use the Fluent Bit or Fluentd. It also supports multi-tenant log isolation using Fluentd to receive log flows forwarded by Fluent Bit, which greatly increases the flexibility and diversity of deployment. To understand the Fluent Operator more fully, the following figure takes the complete log pipeline as an example and divides the pipeline into three parts: collection and forwarding, filtering, and output.

Collection and forwarding

Both Fluent Bit and Fluentd can collect logs.

When deployed independently, the intPUT plug-in of Fluent Bit, Forward plug-in of Fluentd, and HTTP plug-in can be used to meet log collection requirements. When combined, Fluentd can use forward to accept the log flow of Fluent Bit.

In terms of performance, the Fluent Bit is lighter and consumes less memory (about 650KB) than Fluentd, so the Fluent Bit is mainly responsible for collecting and forwarding logs. The Fluent Bit installed as DaemonSet is used to collect and forward logs on each node.

filter

The data collected by logs is often too messy and redundant, which requires the log processing middleware to provide the ability to filter and process the log information. The Fluent Bit and Fluentd both support the Filter plug-in. Users can integrate and customize log data based on their own requirements.

The output

The Fluent Bit Output or Fluentd Output plug-in outputs the processed log information to multiple destinations, such as third-party components such as Kafka and Elasticsearch.

Introduction of CRD

The Fluent Operator defines two groups for the Fluent Bit and Fluentd: Fluentbit.fluent. IO and fluentD.fluent. IO.

fluentbit.fluent.io

Fluentbit.fluent. IO contains the following 6 CRDs:

  • Fluentbit CRD defines the Fluent Bit properties, such as mirroring version, stain, affinity, and other parameters.
  • The ClusterFluentbitConfig CRD defines the Fluent Bit configuration file.
  • ClusterInput CRD defines the Input plug-in of Fluent Bit, that is, the input plug-in. The plug-in allows you to customize the type of logs to be collected.
  • ClusterFilter CRD defines the Filter plug-in of Fluent Bit, which is mainly responsible for filtering and processing the information collected by Fluentbit.
  • ClusterParser CRD defines Fluent Bit’s Parser plug-in, which parses log information into other formats.
  • ClusterOutput CRD defines the Output plug-in of Fluent Bit, which is mainly responsible for forwarding processed log information to the destination.
fluentd.fluent.io

Fluentd.fluent. IO contains the following seven CRDs:

  • Fluentd CRD defines Fluentd attributes, such as mirroring version, stains, and affinity.
  • ClusterFluentdConfig CRD defines Fluentd cluster-level configuration files.
  • FluentdConfig CRD defines the namespace configuration file of Fluentd.
  • ClusterFilter CRD defines the Fluentd cluster-wide Filter plug-in, which filters and processes the information collected by Fluentd. If Fluent Bit is installed, you can further process the log information.
  • Filter CRD This CRD defines the Filter plug-in of Fluentd Namespace, which filters and processes the information collected by Fluentd. If Fluent Bit is installed, you can further process the log information.
  • ClusterOutput CRD This CRD defines the Cluster-wide Output plug-in of Fluentd, which forwards processed log information to the destination.
  • Output CRD This CRD defines the Namespace Output plug-in of Fluentd, which forwards processed log information to the destination.

Instance + Mounted Secret + CRD

Although Fluent Bit and Fluentd both have the ability to collect, process (parse and filter), and output logs, they have different advantages. The Fluent Bit is lighter and more efficient than Fluentd, and Fluentd has more plug-ins.

To accommodate these benefits, the Fluent Operator allows users the flexibility to use the Fluent Bit and Fluentd in a variety of ways:

  • Fluent Bit Only mode: If you only need to collect logs and send them to their final destination after simple processing, you only need the Fluent Bit.
  • Fluentd only mode: If you need to receive logs over the network in HTTP or Syslog mode, process logs and send them to the final destination, only Fluentd is required.
  • Fluent Bit + Fluentd mode: If you need to do some advanced processing on the collected logs or send them to more sinks, you can use Fluent Bit and Fluentd together.

The Fluent Operator allows you to configure the logging pipeline in each of the three modes as required. Fluentd and Fluent Bit have rich plug-ins to meet various customization requirements of users. Because Fluentd and Fluent Bit have similar configuration mount modes, the mount mode of Fluent Bit configuration file is briefly introduced.

Bit in Fluent CRD in each ClusterInput ClusterParser, ClusterFilter, Bit ClusterOutput represents a Fluent configuration section, Selected by the ClusterFluentBitConfig label selector. The Fluent Operator monitors these objects, builds the final configuration, and finally creates a Secret to store the configuration installed into the Fluent Bit DaemonSet. The entire workflow is as follows:

Because the Fluent Bit itself does not reload the interface (see this known issue for details), a wrapper called Fluentbit Watcher was added to enable the Fluent Bit to get and use the latest configuration when the Fluent Bit configuration changes. To restart the Fluent Bit process as soon as a configuration change is detected. This allows you to reload the new configuration without restarting Fluent Bit Pod.

To facilitate user configuration, we extract application and configuration parameters based on CRD’s powerful abstraction capability. You can configure the Fluent Bit and Fluentd using the defined CRD. The Fluent Operator monitors these objects to change the state and configuration of the Fluent Bit and Fluentd. Especially for the definition of the plug-in, in order to make the transition smoother for the user, we basically keep the same naming with the original fields of Fluent Bit to reduce the threshold of use.

How do I implement multi-tenant log isolation

The Fluent Bit can efficiently collect logs, but if complex log information processing is needed, the Fluent Bit is a little powerless, while Fluentd can complete advanced log information processing with the help of its rich plug-ins. Fluent-operator abstracts various plug-ins of Fluentd so that it can process log information to meet user customization requirements.

As can be seen from the above CRD definition, Fluentd config and plug-in CRD are divided into cluster level and namespace level CRD. Multi-tenant isolation can be achieved by defining CRDS into two scopes with the help of Fluentd’s Label Router plug-in.

We added the watchNamespace field in ClusterFluentConfig. Users can select which namespaces to listen to according to their own requirements. If it is empty, it means that all namespaces are monitored. Fluentconfig at the Namesapce level can only listen for CR and global configurations in the namespace where it resides. Therefore, namespace-level logs can be output to both the outputs of the namespace and the outputs of the CLsuter level to achieve multi-tenant isolation.

Fluent Operator vs logging-operator

The difference

  • Fluent Bit and Fluentd are automatically deployed for both. Logging-operator requires the Fluent Bit and Fluentd to be deployed simultaneously. The Fluent operator supports pluggable deployment of the Fluent Bit and Fluentd, which is not strongly coupled. Users can deploy Fluentd or Fluent Bit according to their own needs, which is more flexible.
  • Logs collected by the Fluent Bit in logging-operator must pass through Fluentd before being output to the final destination, and Fluentd may have a single point of failure if the amount of data is too large. The Fluent Bit in the Fluent Operator can directly send log information to the destination, avoiding the potential single point of failure.
  • Logging-operator defines loggings, Outputs, Flows, ClusterFlows, and Fluent Operator defines 13 CRDS. Compared to logging-operator, the Fluent operator has a more diverse CRD definition, allowing users to configure Fluentd and Fluent Bit more flexibly as needed. At the same time, when defining CRD, we choose a name similar to Fluentd and Fluent Bit configuration to make naming clearer and conform to the native component definition.
  • Both use the Label Router plug-in of Fluentd for reference to realize multi-tenant log isolation.

Outlook:

  • Support HPA automatic scaling;
  • Improve Helm Chart, such as collecting metrics information;
  • .

Usage,

The Fluent Operator allows for complex log processing, The fluent operator can export logs to ElasticSearch and Kafka by using fluent-operator-walkThrough. To get some hands-on experience with the Fluent Operator, you need a Kind cluster. You also need to set up a Kafka cluster and an Elasticsearch cluster in this type of cluster.

#Create a cluster of KIND and name it Fluent
./create-kind-cluster.sh

#Create a Kafka cluster under Kafka namespace
./deploy-kafka.sh

#Create an Elasticsearch cluster under elastic Namespace
./deploy-es.sh
Copy the code

The Fluent Operator controls the Fluent Bit and Fluentd life cycles. You can start the Fluent Operator in the Fluent namespace using the following script:

./deploy-fluent-operator.sh
Copy the code

Both Fluent Bit and Fluentd have been defined as CRDS in Fluent Operator, You can create FluentBit DaemonSet or Fluentd StatefulSet by declaring FluentBit or Fluentd’s CR.

Fluent Bit Only mode

Fluent Bit Only enables Only the lightweight Fluent Bit to collect, process, and forward logs.

Use Fluent Bit to collect kubelet logs and export them to Elasticsearch

cat <<EOF | kubectl apply -f -
apiVersion: fluentbit.fluent.io/v1alpha2
kind: FluentBit
metadata:
  name: fluent-bit
  namespace: fluent
  labels:
    app.kubernetes.io/name: fluent-bit
spec:
  image: - bit: kubesphere/fluent v1.8.11
  positionDB:
    hostPath:
      path: /var/lib/fluent-bit/
  resources:
    requests:
      cpu: 10m
      memory: 25Mi
    limits:
      cpu: 500m
      memory: 200Mi
  fluentBitConfigName: fluent-bit-only-config
  tolerations:
    - operator: Exists
---
apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterFluentBitConfig
metadata:
  name: fluent-bit-only-config
  labels:
    app.kubernetes.io/name: fluent-bit
spec:
  service:
    parsersFile: parsers.conf
  inputSelector:
    matchLabels:
      fluentbit.fluent.io/enabled: "true"
      fluentbit.fluent.io/mode: "fluentbit-only"
  filterSelector:
    matchLabels:
      fluentbit.fluent.io/enabled: "true"
      fluentbit.fluent.io/mode: "fluentbit-only"
  outputSelector:
    matchLabels:
      fluentbit.fluent.io/enabled: "true"
      fluentbit.fluent.io/mode: "fluentbit-only"
---
apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterInput
metadata:
  name: kubelet
  labels:
    fluentbit.fluent.io/enabled: "true"
    fluentbit.fluent.io/mode: "fluentbit-only"
spec:
  systemd:
    tag: service.kubelet
    path: /var/log/journal
    db: /fluent-bit/tail/kubelet.db
    dbSync: Normal
    systemdFilter:
      - _SYSTEMD_UNIT=kubelet.service
---
apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterFilter
metadata:
  name: systemd
  labels:
    fluentbit.fluent.io/enabled: "true"
    fluentbit.fluent.io/mode: "fluentbit-only"
spec:
  match: service.*
  filters:
  - lua:
      script:
        key: systemd.lua
        name: fluent-bit-lua
      call: add_time
      timeAsTable: true
---
apiVersion: v1
data:
  systemd.lua: | function add_time(tag, timestamp, record) new_record = {} timeStr = os.date("! *t", timestamp["sec"]) t = string.format("%4d-%02d-%02dT%02d:%02d:%02d.%sZ", timeStr["year"], timeStr["month"], timeStr["day"], timeStr["hour"], timeStr["min"], timeStr["sec"], timestamp["nsec"]) kubernetes = {} kubernetes["pod_name"] = record["_HOSTNAME"] kubernetes["container_name"] = record["SYSLOG_IDENTIFIER"] kubernetes["namespace_name"] = "kube-system" new_record["time"] = t new_record["log"] = record["MESSAGE"] new_record["kubernetes"] = kubernetes return 1, timestamp, new_record endkind: ConfigMap
metadata:
  labels:
    app.kubernetes.io/component: operator
    app.kubernetes.io/name: fluent-bit-lua
  name: fluent-bit-lua
  namespace: fluent
---
apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterOutput
metadata:
  name: es
  labels:
    fluentbit.fluent.io/enabled: "true"
    fluentbit.fluent.io/mode: "fluentbit-only"
spec:
  matchRegex: (? :kube|service)\.(.*)
  es:
    host: elasticsearch-master.elastic.svc
    port: 9200
    generateID: true
    logstashPrefix: fluent-log-fb-only
    logstashFormat: true
    timeKey: "@timestamp"
EOF
Copy the code

Use Fluent Bit to collect kubernetes application logs and output them to Kafka

cat <<EOF | kubectl apply -f -
apiVersion: fluentbit.fluent.io/v1alpha2
kind: FluentBit
metadata:
  name: fluent-bit
  namespace: fluent
  labels:
    app.kubernetes.io/name: fluent-bit
spec:
  image: - bit: kubesphere/fluent v1.8.11
  positionDB:
    hostPath:
      path: /var/lib/fluent-bit/
  resources:
    requests:
      cpu: 10m
      memory: 25Mi
    limits:
      cpu: 500m
      memory: 200Mi
  fluentBitConfigName: fluent-bit-config
  tolerations:
    - operator: Exists
---
apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterFluentBitConfig
metadata:
  name: fluent-bit-config
  labels:
    app.kubernetes.io/name: fluent-bit
spec:
  service:
    parsersFile: parsers.conf
  inputSelector:
    matchLabels:
      fluentbit.fluent.io/enabled: "true"
      fluentbit.fluent.io/mode: "k8s"
  filterSelector:
    matchLabels:
      fluentbit.fluent.io/enabled: "true"
      fluentbit.fluent.io/mode: "k8s"
  outputSelector:
    matchLabels:
      fluentbit.fluent.io/enabled: "true"
      fluentbit.fluent.io/mode: "k8s"
---
apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterInput
metadata:
  name: tail
  labels:
    fluentbit.fluent.io/enabled: "true"
    fluentbit.fluent.io/mode: "k8s"
spec:
  tail:
    tag: kube.*
    path: /var/log/containers/*.log
    parser: docker
    refreshIntervalSeconds: 10
    memBufLimit: 5MB
    skipLongLines: true
    db: /fluent-bit/tail/pos.db
    dbSync: Normal
---
apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterFilter
metadata:
  name: kubernetes
  labels:
    fluentbit.fluent.io/enabled: "true"
    fluentbit.fluent.io/mode: "k8s"
spec:
  match: kube.*
  filters:
  - kubernetes:
      kubeURL: https://kubernetes.default.svc:443
      kubeCAFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      kubeTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
      labels: false
      annotations: false
  - nest:
      operation: lift
      nestedUnder: kubernetes
      addPrefix: kubernetes_
  - modify:
      rules:
      - remove: stream
      - remove: kubernetes_pod_id
      - remove: kubernetes_host
      - remove: kubernetes_container_hash
  - nest:
      operation: nest
      wildcard:
      - kubernetes_*
      nestUnder: kubernetes
      removePrefix: kubernetes_
---
apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterOutput
metadata:
  name: kafka
  labels:
    fluentbit.fluent.io/enabled: "false"
    fluentbit.fluent.io/mode: "k8s"
spec:
  matchRegex: (? :kube|service)\.(.*)
  kafka:
    brokers: my-cluster-kafka-bootstrap.kafka.svc:9091,my-cluster-kafka-bootstrap.kafka.svc:9092,my-cluster-kafka-bootstrap.kafka.svc : 9093
    topics: fluent-log
EOF
Copy the code

Fluent Bit + Fluentd mode

With Fluentd’s rich plug-ins, Fluentd can act as a log aggregation layer to perform more advanced log processing. You can easily forward logs from the Fluent Bit to Fluentd using the Fluent Operator.

Forward logs from Fluent Bit to Fluentd

To forward logs from Fluent Bit to Fluentd, you need to enable the Forward plug-in of Fluent Bit, as shown below:

cat <<EOF | kubectl apply -f -
apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterOutput
metadata:
  name: fluentd
  labels:
    fluentbit.fluent.io/enabled: "true"
    fluentbit.fluent.io/component: logging
spec:
  matchRegex: (? :kube|service)\.(.*)
  forward:
    host: fluentd.fluent.svc
    port: 24224
EOF
Copy the code

Deploy Fluentd

The Fluentd Forward Input plugin is enabled by default when Fluentd is deployed, so you only need to deploy yamL to deploy Fluentd:

apiVersion: fluentd.fluent.io/v1alpha1
kind: Fluentd
metadata:
  name: fluentd
  namespace: fluent
  labels:
    app.kubernetes.io/name: fluentd
spec:
  globalInputs:
  - forward:
      bind: 0.0. 0. 0
      port: 24224
  replicas: 1
  image: Kubesphere/fluentd: v1.14.4
  fluentdCfgSelector:
    matchLabels:
      config.fluentd.fluent.io/enabled: "true"
Copy the code

ClusterFluentdConfig: Fluentd cluster-wide configuration

If you define ClusterFluentdConfig, you can collect logs under any or all namespaces. You can use the watchedNamespaces field to select a namespace to collect logs. The following configuration collects logs from kube-system and the default namespace:

cat <<EOF | kubectl apply -f -
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterFluentdConfig
metadata:
  name: cluster-fluentd-config
  labels:
    config.fluentd.fluent.io/enabled: "true"
spec:
  watchedNamespaces:
  - kube-system
  - default
  clusterOutputSelector:
    matchLabels:
      output.fluentd.fluent.io/scope: "cluster"
      output.fluentd.fluent.io/enabled: "true"
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterOutput
metadata:
  name: cluster-fluentd-output-es
  labels:
    output.fluentd.fluent.io/scope: "cluster"
    output.fluentd.fluent.io/enabled: "true"
spec:
  outputs:
  - elasticsearch:
      host: elasticsearch-master.elastic.svc
      port: 9200
      logstashFormat: true
      logstashPrefix: fluent-log-cluster-fd
EOF

Copy the code

FluentdConfig: Fluentd Namespace configuration

If you define FluentdConfig, you can only send logs from the same namespace as FluentdConfig to Output. This way you can isolate logs from different namespaces.

cat <<EOF | kubectl apply -f -
apiVersion: fluentd.fluent.io/v1alpha1
kind: FluentdConfig
metadata:
  name: namespace-fluentd-config
  namespace: fluent
  labels:
    config.fluentd.fluent.io/enabled: "true"
spec:
  outputSelector:
    matchLabels:
      output.fluentd.fluent.io/scope: "namespace"
      output.fluentd.fluent.io/enabled: "true"
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: Output
metadata:
  name: namespace-fluentd-output-es
  namespace: fluent
  labels:
    output.fluentd.fluent.io/scope: "namespace"
    output.fluentd.fluent.io/enabled: "true"
spec:
  outputs:
  - elasticsearch:
      host: elasticsearch-master.elastic.svc
      port: 9200
      logstashFormat: true
      logstashPrefix: fluent-log-namespace-fd
EOF
Copy the code

Route logs to different Kafka topics based on namespace

Also, you can use Fluentd’s Filter plug-in to distribute logs to different topics based on different namespaces. Here we include recordTransformer plug-in in the Fluentd kernel, which can add, delete, change and check events.

cat <<EOF | kubectl apply -f -
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterFluentdConfig
metadata:
  name: cluster-fluentd-config-kafka
  labels:
    config.fluentd.fluent.io/enabled: "true"
spec:
  watchedNamespaces:
  - kube-system
  - default
  clusterFilterSelector:
    matchLabels:
      filter.fluentd.fluent.io/type: "k8s"
      filter.fluentd.fluent.io/enabled: "true"
  clusterOutputSelector:
    matchLabels:
      output.fluentd.fluent.io/type: "kafka"
      output.fluentd.fluent.io/enabled: "true"
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterFilter
metadata:
  name: cluster-fluentd-filter-k8s
  labels:
    filter.fluentd.fluent.io/type: "k8s"
    filter.fluentd.fluent.io/enabled: "true"
spec:
  filters:
  - recordTransformer:
      enableRuby: true
      records:
      - key: kubernetes_ns
        value: ${record["kubernetes"]["namespace_name"]}
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterOutput
metadata:
  name: cluster-fluentd-output-kafka
  labels:
    output.fluentd.fluent.io/type: "kafka"
    output.fluentd.fluent.io/enabled: "true"
spec:
  outputs:
  - kafka:
      brokers: my-cluster-kafka-bootstrap.default.svc:9091,my-cluster-kafka-bootstrap.default.svc:9092,my-cluster-kafka-bootstrap.defau lt.svc:9093
      useEventTime: true
      topicKey: kubernetes_ns
EOF

Copy the code

Use both cluster-scoped and namespace scoped FluentdConfig

Of course, you can use ClusterFluentdConfig and FluentdConfig together as shown below. FluentdConfig will send the logs under the Fluent namespace to ClusterOutput. ClusterFluentdConfig also sends namespaces (kube-System and default) under watchedNamespaces to ClusterOutput.

cat <<EOF | kubectl apply -f -
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterFluentdConfig
metadata:
  name: cluster-fluentd-config-hybrid
  labels:
    config.fluentd.fluent.io/enabled: "true"
spec:
  watchedNamespaces:
  - kube-system
  - default
  clusterOutputSelector:
    matchLabels:
      output.fluentd.fluent.io/scope: "hybrid"
      output.fluentd.fluent.io/enabled: "true"
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: FluentdConfig
metadata:
  name: namespace-fluentd-config-hybrid
  namespace: fluent
  labels:
    config.fluentd.fluent.io/enabled: "true"
spec:
  clusterOutputSelector:
    matchLabels:
      output.fluentd.fluent.io/scope: "hybrid"
      output.fluentd.fluent.io/enabled: "true"
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterOutput
metadata:
  name: cluster-fluentd-output-es-hybrid
  labels:
    output.fluentd.fluent.io/scope: "hybrid"
    output.fluentd.fluent.io/enabled: "true"
spec:
  outputs:
  - elasticsearch:
      host: elasticsearch-master.elastic.svc
      port: 9200
      logstashFormat: true
      logstashPrefix: fluent-log-hybrid-fd
EOF

Copy the code

In multi-tenant scenarios, FluentdConfig in both the cluster scope and namespace scope is used

In multi-tenant scenarios, we can use both cluster-scoped and namespace-scoped FluentdConfig to isolate logs.

cat <<EOF | kubectl apply -f -
apiVersion: fluentd.fluent.io/v1alpha1
kind: FluentdConfig
metadata:
  name: namespace-fluentd-config-user1
  namespace: fluent
  labels:
    config.fluentd.fluent.io/enabled: "true"
spec:
  outputSelector:
    matchLabels:
      output.fluentd.fluent.io/enabled: "true"
      output.fluentd.fluent.io/user: "user1"
  clusterOutputSelector:
    matchLabels:
      output.fluentd.fluent.io/enabled: "true"
      output.fluentd.fluent.io/user: "user1"
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterFluentdConfig
metadata:
  name: cluster-fluentd-config-cluster-only
  labels:
    config.fluentd.fluent.io/enabled: "true"
spec:
  watchedNamespaces:
  - kube-system
  - kubesphere-system
  clusterOutputSelector:
    matchLabels:
      output.fluentd.fluent.io/enabled: "true"
      output.fluentd.fluent.io/scope: "cluster-only"
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: Output
metadata:
  name: namespace-fluentd-output-user1
  namespace: fluent
  labels:
    output.fluentd.fluent.io/enabled: "true"
    output.fluentd.fluent.io/user: "user1"
spec:
  outputs:
  - elasticsearch:
      host: elasticsearch-master.elastic.svc
      port: 9200
      logstashFormat: true
      logstashPrefix: fluent-log-user1-fd
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterOutput
metadata:
  name: cluster-fluentd-output-user1
  labels:
    output.fluentd.fluent.io/enabled: "true"
    output.fluentd.fluent.io/user: "user1"
spec:
  outputs:
  - elasticsearch:
      host: elasticsearch-master.elastic.svc
      port: 9200
      logstashFormat: true
      logstashPrefix: fluent-log-cluster-user1-fd
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterOutput
metadata:
  name: cluster-fluentd-output-cluster-only
  labels:
    output.fluentd.fluent.io/enabled: "true"
    output.fluentd.fluent.io/scope: "cluster-only"
spec:
  outputs:
  - elasticsearch:
      host: elasticsearch-master.elastic.svc
      port: 9200
      logstashFormat: true
      logstashPrefix: fluent-log-cluster-only-fd
EOF

Copy the code

Use buffers for Fluentd output

You can add a buffer to cache the output plug-in’s logs.

cat <<EOF | kubectl apply -f -
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterFluentdConfig
metadata:
  name: cluster-fluentd-config-buffer
  labels:
    config.fluentd.fluent.io/enabled: "true"
spec:
  watchedNamespaces:
  - kube-system
  - default
  clusterFilterSelector:
    matchLabels:
      filter.fluentd.fluent.io/type: "buffer"
      filter.fluentd.fluent.io/enabled: "true"
  clusterOutputSelector:
    matchLabels:
      output.fluentd.fluent.io/type: "buffer"
      output.fluentd.fluent.io/enabled: "true"
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterFilter
metadata:
  name: cluster-fluentd-filter-buffer
  labels:
    filter.fluentd.fluent.io/type: "buffer"
    filter.fluentd.fluent.io/enabled: "true"
spec:
  filters:
  - recordTransformer:
      enableRuby: true
      records:
      - key: kubernetes_ns
        value: ${record["kubernetes"]["namespace_name"]}
---
apiVersion: fluentd.fluent.io/v1alpha1
kind: ClusterOutput
metadata:
  name: cluster-fluentd-output-buffer
  labels:
    output.fluentd.fluent.io/type: "buffer"
    output.fluentd.fluent.io/enabled: "true"
spec:
  outputs:
  - stdout: {}
    buffer:
      type: file
      path: /buffers/stdout.log
  - elasticsearch:
      host: elasticsearch-master.elastic.svc
      port: 9200
      logstashFormat: true
      logstashPrefix: fluent-log-buffer-fd
    buffer:
      type: file
      path: /buffers/es.log
EOF
Copy the code

Fluentd Only mode

You can also turn on Fluentd Only mode, which deploys Only Fluentd StatefulSet.

Use Fluentd to receive logs from HTTP and output them to standard output

If you want to enable the Fluentd plugin separately, you can receive logs over HTTP.

cat <<EOF | kubectl apply -f -
apiVersion: fluentd.fluent.io/v1alpha1
kind: Fluentd
metadata:
  name: fluentd-http
  namespace: fluent
  labels:
    app.kubernetes.io/name: fluentd
spec:
  globalInputs:
    - http:
        bind: 0.0. 0. 0
        port: 9880
  replicas: 1
  image: Kubesphere/fluentd: v1.14.4
  fluentdCfgSelector:
    matchLabels:
      config.fluentd.fluent.io/enabled: "true"

---
apiVersion: fluentd.fluent.io/v1alpha1
kind: FluentdConfig
metadata:
  name: fluentd-only-config
  namespace: fluent
  labels:
    config.fluentd.fluent.io/enabled: "true"
spec:
  filterSelector:
    matchLabels:
      filter.fluentd.fluent.io/mode: "fluentd-only"
      filter.fluentd.fluent.io/enabled: "true"
  outputSelector:
    matchLabels:
      output.fluentd.fluent.io/mode: "true"
      output.fluentd.fluent.io/enabled: "true"

---
apiVersion: fluentd.fluent.io/v1alpha1
kind: Filter
metadata:
  name: fluentd-only-filter
  namespace: fluent
  labels:
    filter.fluentd.fluent.io/mode: "fluentd-only"
    filter.fluentd.fluent.io/enabled: "true"
spec:
  filters:
    - stdout: {}

---
apiVersion: fluentd.fluent.io/v1alpha1
kind: Output
metadata:
  name: fluentd-only-stdout
  namespace: fluent
  labels:
    output.fluentd.fluent.io/enabled: "true"
    output.fluentd.fluent.io/enabled: "true"
spec:
  outputs:
    - stdout: {}
EOF

Copy the code

This article is published by OpenWrite!