关于云计算:Fluent-Operator云原生日志管理的一把瑞士军刀

5次阅读

共计 19035 个字符,预计需要花费 48 分钟才能阅读完成。

作者:程德昊,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 地址:https://github.com/fluent/flu…)。在 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 Bit 或者 Fluentd,并不会强制要求应用 Fluent Bit 或 Fluentd,同时还反对应用 Fluentd 接管 Fluent Bit 转发的日志流进行多租户日志隔离,这极大地减少了部署的灵活性和多样性。为了更全面的理解 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 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 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 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。

应用 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 公布!

正文完
 0