作者:程德昊,Fluent Member,KubeSphere Member

Fluent Operator​ 介绍

跟着云原生技能的快速发展,技能的不断迭代,关于日志的搜集、处理及转发提出了更高的要求。云原生架构下的日志计划相比依据物理机或许是虚拟机场景的日志架构设计存在很大不同。作为 CNCF 的结业项目,Fluent Bit 无疑为解决云环境中的日志记录问题的首选解决计划之一。可是在 Kubernetes 中装置布置以及装备 Fluent Bit 都具有一定的门槛,加大了用户的运用成本。

2019 年 1 月 21 日,KubeSphere 社区为了满足以云原生的方法管理 Fluent Bit 的需求开发了 Fluentbit Operator,并在 2020 年 2 月 17 日发布了 v0.1.0 版别。此后产品不断迭代,在 2021 年 8 月 4 日 正式将 Fluentbit Operator 捐献给 Fluent 社区。

Fluentbit Operator 降低了 Fluent Bit 的运用门槛,能高效、快捷的处理日志信息,可是 Fluent Bit 处理日志的才干稍弱,咱们还没有集成日志处理工具,比方 Fluentd,它有更多的插件可供运用。依据以上需求,Fluentbit Operator 集成了 Fluentd,旨在将 Fluentd 集成为一个可选的日志聚合和转发层,并从头命名为 **Fluent Operator(GitHub 地址:github.com/fluent/flue… 2022 年 3 月 25 日 Fluent Operator 发布了 v1.0.0 版别,并将继续迭代 Fluentd Operator,预计在 2022 年第 2 季度发布 v1.1.0 版别,增加更多的功能与亮点。

运用 Fluent Operator 能够灵敏且便利地布置、装备及卸载 Fluent Bit 以及 Fluentd。一起, 社区还供给支撑 Fluentd 以及 Fluent Bit 的海量插件,用户能够依据实践情况进行定制化装备。官方文档供给了详细的示例,极易上手,大大降低了 Fluent Bit 以及 Fluentd 的运用门槛。

Fluent Operator:云原生日志管理的一把瑞士军刀

日志流水线的各个阶段

Fluent Operator 能够独自布置 Fluent Bit 或许 Fluentd,并不会强制要求运用 Fluent Bit 或 Fluentd,一起还支撑运用 Fluentd 接纳 Fluent Bit 转发的日志流进行多租户日志阻隔,这极大地增加了布置的灵敏性和多样性。 为了更全面的了解 Fluent Operator,下图以完整的日志流水线为例,将流水线分为三部分:搜集和转发、过滤以及输出。

Fluent Operator:云原生日志管理的一把瑞士军刀

搜集和转发

Fluent Bit 与 Fluentd 均能够搜集日志。

独自布置时,能够经过 Fluent Bit 的 intput 插件或许 Fluentd 的 forward 以及 http 等插件来满足对日志搜集的需求。两者结合时,Fluentd 可运用 forward 接受 Fluent Bit 的日志流转发。

在功能方面,Fluent Bit 相比 Fluentd 更轻量,内存耗费更小(约为 650KB),所以首要由 Fluent Bit 担任搜集与转发日志。在各个节点上经过以 DaemonSet 方法装置的 Fluent Bit 来搜集和转发日志。

过滤

日志搜集的数据往往过于凌乱与冗余,这要求日志处理中间件供给对日志信息进行过滤和处理的才干。Fluent Bit 或 Fluentd 均支撑 filter 插件,用户能够依据自身需求,整合和定制日志数据。

输出

Fluent Bit output 或 Fluentd output 插件将处理后的日志信息输出到多个意图地,意图地能够是 Kafka、Elasticsearch 等第三方组件。

CRD 简介

Fluent Operator 为 Fluent Bit 和 Fluentd 别离界说了两个 Group:fluentbit.fluent.io 和 fluentd.fluent.io。

fluentbit.fluent.io

fluentbit.fluent.io​ 分组下包括以下 6 个 CRDs:

  • Fluentbit CRD 界说了 Fluent Bit 的特点,比方镜像版别、污点、亲和性等参数。
  • ClusterFluentbitConfig CRD 界说了 Fluent Bit 的装备文件。
  • ClusterInput CRD 界说了 Fluent Bit 的 input 插件,即输入插件。经过该插件,用户能够自界说搜集何种日志。
  • ClusterFilter CRD 界说了 Fluent Bit 的 filter 插件,该插件首要担任过滤以及处理 fluentbit 搜集到的信息。
  • ClusterParser CRD 界说了 Fluent Bit 的 parser 插件,该插件首要担任解析日志信息,能够将日志信息解析为其他格局。
  • ClusterOutput CRD 界说了 Fluent Bit 的 output 插件,该插件首要担任将处理后的日志信息转发到意图地。
fluentd.fluent.io

fluentd.fluent.io​ 分组下包括以下 7 个 CRDs:

  • Fluentd CRD 界说了 Fluentd 的特点,比方镜像版别、污点、亲和性等参数。
  • ClusterFluentdConfig CRD 界说了 Fluentd 集群等级的装备文件。
  • FluentdConfig CRD 界说了 Fluentd 的 namespace 规模的装备文件。
  • ClusterFilter CRD 界说了 Fluentd 集群规模的 filter 插件,该插件首要担任过滤以及处理 Fluentd 搜集到的信息。假如装置了 Fluent Bit,则能够更进一步的处理日志信息。
  • Filter CRD 该 CRD 界说了 Fluentd namespace 的 filter 插件,该插件首要担任过滤以及处理 Fluentd 搜集到的信息。假如装置了 Fluent Bit,则能够更进一步的处理日志信息。
  • ClusterOutput CRD 该 CRD 界说了 Fluentd 的集群规模的 output 插件,该插件首要担任将处理后的日志信息转发到意图地。
  • Output CRD 该 CRD 界说了 Fluentd 的 namespace 规模的 output 插件,该插件首要担任将处理后的日志信息转发到意图地。

编列原理简介 (instance + mounted secret + CRD 的笼统才干)

尽管 Fluent Bit 与 Fluentd 都有搜集、处理(解析和过滤)以及输出日志的才干,但它们有着不同的优点。Fluent Bit 相对 Fluentd 更为轻量与高效,而 Fluentd 插件更为丰厚。

为了统筹这些优点,Fluent Operator 答运用户以多种方法灵敏地运用 Fluent Bit 和 Fluentd:

  • Fluent Bit only 形式:假如您只需求在搜集日志并在简略处理后将日志发送到终究意图地,您只需求 Fluent Bit。
  • Fluentd only 形式:假如需求经过网络以 HTTP 或 Syslog 等方法接纳日志,然后将日志处理并发送到终究的意图地,则只需求 Fluentd。
  • Fluent Bit + Fluentd 形式:假如你还需求对搜集到的日志进行一些高级处理或许发送到更多的 sink,那么你能够组合运用 Fluent Bit 和 Fluentd。

Fluent Operator 答应您依据需求在上述 3 种形式下装备日志处理管道。Fluentd 与 Fluent Bit 具有丰厚的插件以满足用户的各种自界说化需求,由于 Fluentd 与 Fluent Bit 的装备挂载方法相似,所以以 Fluent Bit 装备文件的挂载方法来进行简略介绍。

在 Fluent Bit CRD 中每个 ClusterInput, ClusterParser, ClusterFilter,ClusterOutput 代表一个 Fluent Bit 装备部分,由 ClusterFluentBitConfig 标签挑选器挑选。Fluent Operator 监视这些对象,构建终究装备,最后创立一个 Secret 来存储装置到 Fluent Bit DaemonSet 中的装备。整个工作流程如下所示:

Fluent Operator:云原生日志管理的一把瑞士军刀

由于 Fluent Bit 本身没有从头加载接口(详细信息请参阅此已知问题),为了使 Fluent Bit 能够在 Fluent Bit 装备更改时获取并运用最新装备,添加了一个名为 fluentbit watcher 的包装器,以便在检测到 Fluent Bit 装备更改时立即从头发动 Fluent Bit 进程。这样,无需从头发动 Fluent Bit pod 即可从头加载新装备。

为了运用户装备更为便利,咱们依据 CRD 强壮的笼统才干将运用以及装备的参数提取出来。用户能够经过界说的 CRD 来对 Fluent Bit 以及 Fluentd 进行装备。Fluent Operator 监控这些对象的变化然后更改 Fluent Bit 以及 Fluentd 的状况及装备。特别是插件的界说,为了运用户更为滑润地过渡,咱们在命名上根本与 Fluent Bit 原有的字段保持一致,降低运用的门槛。

如何实现多租户日志阻隔

Fluent Bit 能够高效的搜集日志,可是假如需求对日志信息进行复杂处理,Fluent Bit 则稍显无能为力,而 Fluentd 则能够凭仗其丰厚的插件完结对日志信息的高级处理。fluent-operator 为此笼统了 Fluentd 的各种插件,以便能够对日志信息进行处理来满足用户的自界说需求。

从上面 CRD 的界说能够看出,咱们将 Fluentd 的 config 及插件的 CRD 分成了 cluster 等级与 namespace 等级的 CRD。经过将 CRD 界说为两种规模,凭仗 Fluentd 的 label router 插件,就能够到达多租户阻隔的作用。

咱们在 clusterfluentconfig 添加了 watchNamespace 字段,用户能够依据自己的需求挑选监听哪些 namespace,假如为空,则表明监控一切的 namespace。而 namesapce 等级的 fluentconfig 只能监听自己所坐落的 namespace 中的 CR 及大局等级的装备。所以 namespace 等级的日志既能够输出到该 namespace 中的 output,也能够输出到 clsuter 等级的 output,然后到达多租户阻隔的意图。

Fluent Operator vs logging-operator

不同

  • 两者皆可自动布置 Fluent Bit 与 Fluentd。logging-operator 需求一起布置 Fluent Bit 和 Fluentd,而 Fluent Operator 支撑可插拔布置 Fluent Bit 与 Fluentd,非强耦合,用户能够依据自己的需求自行挑选布置 Fluentd 或许是 Fluent Bit,更为灵敏。
  • 在 logging-operator 中 Fluent Bit 搜集的日志都必须经过 Fluentd 才干输出到终究的意图地,并且假如数据量过大,那么 Fluentd 存在单点故障隐患。Fluent Operator 中 Fluent Bit 能够直接将日志信息发送到意图地,然后规避单点故障的隐患。
  • logging-operator 界说了 loggings,outputs,flows,clusteroutputs 以及 clusterflows 四种 CRD,而 Fluent Operator 界说了 13 种 CRD。相较于 logging-operator,Fluent Operator 在 CRD 界说上更加多样,用户能够依据需求更灵敏的对 Fluentd 以及 Fluent Bit 进行装备。一起在界说 CRD 时,选取与 Fluentd 以及 Fluent Bit 装备类似的命名,力求命名更加明晰,以符合原生的组件界说。
  • 两者均借鉴了 Fluentd 的 label router 插件实现多租户日志阻隔。

展望:

  • 支撑 HPA 自动伸缩;
  • 完善 Helm Chart,如搜集 metrics 信息;

用法详解

凭仗 Fluent Operator 能够对日志进行复杂处理,在这里咱们能够经过 fluent-operator-walkthrough 中将日志输出到 elasticsearch 与 kafka 的例子对 Fluent Operator 的实践功能进行介绍。要取得 Fluent Operator 的一些实践操作经验,您需求一个 Kind 集群。一起你还需求在这种类型的集群中设置一个 Kafka 集群和一个 Elasticsearch 集群。

# 创立一个 kind 的集群并命名为 fluent
./create-kind-cluster.sh

# 在 Kafka namespace 下创立一个 Kafka 集群
./deploy-kafka.sh

# 在 elastic namespace 下创立一个 Elasticsearch 集群
./deploy-es.sh

Fluent Operator 控制 Fluent Bit 和 Fluentd 的生命周期。您能够运用以下脚本在 fluent 命名空间中发动 Fluent Operator:

./deploy-fluent-operator.sh

Fluent Bit 和 Fluentd 都已被界说为 Fluent Operator 中的 CRD,您能够经过声明 FluentBit 或 Fluentd 的 CR 来创立 Fluent Bit DaemonSet 或 Fluentd StatefulSet。

Fluent Bit Only 形式

Fluent Bit Only 将只启用轻量级的 Fluent Bit 对日志进行搜集、处理以及转发。

Fluent Operator:云原生日志管理的一把瑞士军刀

运用 Fluent Bit 搜集 kubelet 的日志并输出到 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: kubesphere/fluent-bit: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
    end
kind: 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

运用 Fluent Bit 搜集 kubernetes 的运用日志并输出到 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: kubesphere/fluent-bit: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

Fluent Bit + Fluentd 形式

凭仗 Fluentd 丰厚的插件,Fluentd 能够充任日志聚合层,履行更高级的日志处理。您能够运用 Fluent Operator 轻松地将日志从 Fluent Bit 转发到 Fluentd。

Fluent Operator:云原生日志管理的一把瑞士军刀

将日志从 Fluent Bit 转发到 Fluentd

要将日志从 Fluent Bit 转发到 Fluentd,您需求启用 Fluent Bit 的 forward 插件,如下所示:

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

布置 Fluentd

Fluentd forward Input 插件会在布置 Fluentd 时默许启用,因而你只需求布置下列 yaml 来布置 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"

ClusterFluentdConfig: Fluentd 集群规模的装备

假如你界说了 ClusterFluentdConfig,那么你能够搜集恣意或许一切 namespace 下的日志。我么能够经过 watchedNamespaces 字段来挑选所需求搜集日志的 namespace。以下装备是搜集 kube-system 以及 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

FluentdConfig: Fluentd namespace 规模的装备

假如你界说了 FluentdConfig,那么你只能将与该 FluentdConfig 同一 namespace 下的日志发送到 Output,经过这种方法实现了不同 namespace 下的日志阻隔。

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

依据 namespace 将日志路由到不同的 Kafka topic

相同您能够运用 Fluentd 的 filter 插件依据不同的 namespace 将日志分发到不同的 topic。在这里咱们包括在 Fluentd 内核中的插件 recordTransformer,该插件能够对事情进行增修改查。

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.default.svc:9093
      useEventTime: true
      topicKey: kubernetes_ns
EOF

一起运用集群规模与 namespace 规模的 FluentdConfig

当然,你能够像下面相同一起运用 ClusterFluentdConfig 与 FluentdConfig。FluentdConfig 会将 fluent namespace 下的日志发送到 ClusterOutput,而 ClusterFluentdConfig 一起也会将 watchedNamespaces 字段下的 namespace(即 kube-system 以及 default 两个 namespace)发送到 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

在多租户场景下一起运用集群规模与 namespace 规模的 FluentdConfig

在多租户场景下,咱们能够一起运用集群规模与 namespace 规模的 FluentdConfig 到达日志阻隔的作用。

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

为 Fluentd 输出运用缓冲区

您能够添加一个缓冲区来缓存 output 插件的日志。

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

Fluentd Only 形式

你相同能够敞开 Fluentd Only 形式,该形式只会布置 Fluentd statefulset。

Fluent Operator:云原生日志管理的一把瑞士军刀

运用 Fluentd 从 HTTP 接纳日志并输出到规范输出

假如你想独自敞开 Fluentd 插件,你能够经过 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

本文由博客一文多发渠道 OpenWrite 发布!