官方文档地址:
Kubernetes
Fluent Bit Kubernetes 过滤器允许使用 Kubernetes 元数据丰富您的日志文件。
当 Fluent Bit 作为 DaemonSet 部署在 Kubernetes 中并配置为从容器读取日志文件(使用tail 或systemd 输入插件)时,该过滤器旨在执行以下操作:
- 分析 Tag 并提取以下元数据:
- Pod Name
- Namespace
- Container Name
- Container ID
- 查询 Kubernetes API 服务器以获取 POD 的额外元数据:
数据缓存在内存中,并附加到每条记录中。
1. 配置参数
插件支持以下配置参数:
参数 | 描述 | 默认值 |
---|
Buffer_Size | 当从 Kubernetes API 服务器读取响应时,设置 HTTP 客户端的缓冲区大小。该值必须符合 Unit Size 规格。值为0 的结果是没有限制,缓冲区将根据需要展开。注意,如果响应的 pod 元数据信息超出了缓冲区限制,则在检索元数据时将丢弃 API 响应,一些 kubernetes 元数据将无法注入到日志中。 | 32k | Kube_URL | API 服务器端点 | https://kubernetes.default.svc:443 | Kube_CA_File | CA 证书文件 | /var/run/secrets/kubernetes.io/serviceaccount/ca.crt | Kube_CA_Path | 扫描证书文件的绝对路径 | | Kube_Token_File | Token 文件 | /var/run/secrets/kubernetes.io/serviceaccount/token | Kube_Tag_Prefix | 当源记录来自 Tail 输入插件时,这个选项允许指定 Tail 配置中使用的前缀。 | kube.var.log.containers. | Merge_Log | 当启用时,它检查 log 字段内容是否是一个 JSON 字符串映射,如果是,它将作为日志结构的一部分追加 map 字段。 | Off | Merge_Log_Key | 当启用 Merge_Log 时,过滤器尝试假设传入消息中的 log 字段是一个 JSON 字符串消息,并在映射中的 log 字段的同一级别上对其进行结构化表示。现在如果设置了 Merge_Log_Key(字符串名),从原始 log 内容中获取的所有新的结构化字段都插入到新的 key 下。 | | Merge_Log_Trim | 当启用 Merge_Log 时,修剪(删除可能的 \n 或 \r)字段值。 | On | Merge_Parser | 可选解析器名称,用于指定如何解析 log 键中包含的数据。建议仅供开发人员或测试人员使用。 | | Keep_Log | 当禁用 Keep_Log 时,一旦成功合并传入消息,log 字段将从传入消息中删除(Merge_Log 也必须启用)。 | On | tls.debug | 调试级别介于 0(无)和 4(每个细节)之间。 | -1 | tls.verify | 当启用时,将在连接到 Kubernetes API 服务器时启用证书验证。 | On | Use_Journal | 当启用时,过滤器读取以 Journald 格式传入的日志。 | Off | Cache_Use_Docker_Id | 启用时,当 docker_id 被更改时,元数据将从 k8s 中获取。 | Off | Regex_Parser | 设置一个替代的解析器来处理记录标记并提取 pod_name, namespace_name,container_name 和 docker_id。解析器必须在解析器文件中注册(参考解析器 filter-kube-test 的示例)。 | | K8S-Logging.Parser | 允许 Kubernetes Pods 建议一个预定义的解析器(在 Kubernetes Annotations 部分阅读更多相关内容)。 | Off | K8S-Logging.Exclude | 允许 Kubernetes Pods 从日志处理器中排除它们的日志(在 Kubernetes Annotations 部分阅读更多相关内容)。 | Off | Labels | 在额外的元数据中包含 Kubernetes 资源标签。 | On | Annotations | 在额外的元数据中包含 Kubernetes 资源注释。 | On | Kube_meta_preload_cache_dir | 如果设置了,Kubernetes 元数据可以从该目录中的 JSON 格式文件中缓存 / 预加载,该目录命名为 namespace-pod.meta。 | | Dummy_Meta | 如果设置了,则使用虚拟元数据(用于 test/dev 目的)。 | Off | DNS_Retries | DNS 查找重试 N 次,直到网络开始工作。 | 6 | DNS_Wait_Time | 网络状态检查之间的 DNS 查找时间间隔。 | 30 | Use_Kubelet | 这是一个可选的特性标志,用于从 kubelet 获取元数据信息,而不是调用Kube Server API 来增强日志。这可以缓解大型集群的 Kube API 繁忙的流量问题。 | Off | Kubelet_Port | kubelet 端口用于 HTTP 请求,只有当 Use_Kubelet 设置为 On 时才有效。 | 10250 | Kube_Meta_Cache_TTL | 为 K8s 缓存的元数据配置 TTL。默认情况下,该值设置为 0,这意味着缓存项的 TTL 被禁用,当达到容量时,缓存项将被随机逐出。为了启用这个选项,您应该将这个数字设置为一个时间间隔。例如,将该值设置为 60 或 60s,则创建的缓存项超过60s 将被逐出。 | 0 | Kube_Token_Command | 命令获取 Kubernetes 授权令牌。默认情况下,它是 NULL,我们将使用令牌文件来获取令牌。如果你想手动选择一个命令来获取它,你可以在这里设置命令。例如,运行aws-iam-authenticator -i your-cluster-name token --token-only 来设置 token。这个选项目前仅适用于 Linux。 | |
2. 处理 ‘log’ 值
Kubernetes 过滤器旨在提供几种方法来处理 log 键中包含的数据。下面对工作流的解释假设在 parser.conf 中定义的 Docker 解析器如下所示:
[PARSER]
Name docker
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L
Time_Keep On
由于 Fluent Bit v1.2,如果您在输出中使用 Elasticsearch 数据库以避免数据类型冲突,我们不建议使用解码器(Decode_Field_As)。
要执行 log 键的处理,必须在此过滤器中启用 Merge_Log 配置属性,然后执行以下处理顺序:
- 如果 Pod 建议使用解析器,过滤器将使用该解析器处理 log 的内容。
- 如果设置了 Merge_Parser 选项,Pod 没有建议使用解析器,则使用配置中建议的解析器处理 log 的内容。
- 如果没有建议 Pod,也没有设置 Merge_Parser,那么尝试将内容作为 JSON 处理。
如果 log 值处理失败,则该值不变。上面的顺序不是链式的,这意味着它是排他的,过滤器将只尝试上面的一个选项,而不是所有选项。
3. Kubernetes Annotations
Fluent Bit Kubernetes 过滤器的一个灵活特性是允许 Kubernetes Pods 在处理记录时为日志处理器管道建议某些行为。目前它支持:
以下 annotations 是有效的:
Annotation | 描述 | 默认值 |
---|
fluentbit.io/parser[_stream][-container] | 建议使用预定义的解析器。解析器必须已经由 Fluent Bit 注册。只有当 Fluent Bit 配置(Kubernetes Filter)启用了选项K8S-Logging.Parser 时,才会处理此选项。如果存在,流(stdout或stderr)将限制特定的流。如果存在,容器可以覆盖 Pod 中的特定容器。 | | fluentbit.io/exclude[_stream][-container] | 请求 Fluent Bit 排除或不排除 Pod 生成的日志。只有当 Fluent Bit 配置(Kubernetes Filter)启用了选项K8S-Logging.Exclude 时,此选项才会被处理。 | False |
3.1. Pod 定义中的 annotations 示例
3.1.1. 建议一个解析器
下面的 Pod 定义运行一个 Pod,该 Pod 将 Apache 日志发送到标准输出,在 annotations 中,它建议使用预定义的解析器 apache 处理数据:
apiVersion: v1
kind: Pod
metadata:
name: apache-logs
labels:
app: apache-logs
annotations:
fluentbit.io/parser: apache
spec:
containers:
- name: apache
image: edsiper/apache_logs
3.1.2. 请求排除日志
在某些情况下,用户希望日志处理器简单地跳过相关 Pod 的日志:
apiVersion: v1
kind: Pod
metadata:
name: apache-logs
labels:
app: apache-logs
annotations:
fluentbit.io/exclude: "true"
spec:
containers:
- name: apache
image: edsiper/apache_logs
注意,annotation 值是布尔值,可以接受 true 或 false,必须加引号。
4. Tail + Kubernetes 过滤器的工作流程
Kubernetes 过滤器依赖 Tail 或 Systemd 输入插件来为记录处理和丰富 Kubernetes 元数据。在这里我们将解释 Tail 的工作流程,以及它的配置是如何与 Kubernetes 过滤器相关联的。考虑以下配置示例(仅用于演示,不用于生产):
[INPUT]
Name tail
Tag kube.*
Path /var/log/containers/*.log
Parser docker
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
Kube_Tag_Prefix kube.var.log.containers.
Merge_Log On
Merge_Log_Key log_processed
在输入部分,Tail 插件将监控路径/var/log/containers/ 中以.log 结尾的所有文件。对于每个文件,它将读取每一行并应用 docker 解析器。然后,这些记录将通过扩展 tag 发送到下一个步骤。
Tail 支持标签扩展,这意味着如果一个标签有星号字符(*),它将用监控文件的绝对路径替换星号,所以如果你的文件名和路径是:
/var/log/container/apache-logs-annotated_default_apache-aeeccc7a9f00f6e4e066aeff0434cf80621215071f1b20a51e8340aa7c35eac6.log
那么该文件的每条记录的 Tag 将变为:
kube.var.log.containers.apache-logs-annotated_default_apache-aeeccc7a9f00f6e4e066aeff0434cf80621215071f1b20a51e8340aa7c35eac6.log
注意,斜线被圆点代替了。
当 Kubernetes 过滤器运行时,它将尝试匹配所有以kube. 开头的记录(注意结束的点),因此上面提到的文件中的记录将符合匹配规则,过滤器将尝试丰富记录。
Kubernetes 过滤器不关心日志来自哪里,但它关心被监视文件的绝对名称,因为该信息包含 pod 名称和命名空间名称,用于从 Kubernetes Master/API Server 检索与运行 pod 相关的元数据。
如果您有较大的 pod 规格(元数据信息,可能是由大量的环境变量等造成的),一定要增加 kubernetes 过滤器的Buffer_Size 参数。如果对象的大小超过这个缓冲区,一些元数据将无法注入到日志中。
如果配置参数 Kube_Tag_Prefix 已配置(在 Fluent Bit >= 1.x 可用),它将使用该值来删除前面 Input 部分中附加到 Tag 的前缀。注意,配置属性默认为_kube._var.logs.containers. ,因此之前的 Tag 内容将从:
kube.var.log.containers.apache-logs-annotated_default_apache-aeeccc7a9f00f6e4e066aeff0434cf80621215071f1b20a51e8340aa7c35eac6.log
变为
apache-logs-annotated_default_apache-aeeccc7a9f00f6e4e066aeff0434cf80621215071f1b20a51e8340aa7c35eac6.log
上面的转换不会修改原始的 Tag,只是为过滤器创建一个新的表示来执行元数据查找。
这个新值被过滤器用来查找 pod 名称和命名空间,为此它使用一个内部正则表达式:
(?<pod_name>[a-z0-9](?:[-a-z0-9]*[a-z0-9])?(?:\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?<namespace_name>[^_]+)_(?<container_name>.+)-(?<docker_id>[a-z0-9]{64})\.log$
如果您想了解更多细节,请在这里查看该定义的源代码。
你可以在 Rublar.com 网站上看到这个操作是如何执行的,检查下面的演示链接:https://rubular.com/r/HZz3tYAahj6JCd
自定义正则表达式 在某些不常见的条件下,用户可能想要更改硬编码的正则表达式,为此可以使用选项 Regex_Parser(在最上面有文档说明)。
最后建议 此时过滤器能够收集 pod_name 和 namespace 的值,将检查本地缓存(内部哈希表)中是否存在该键值对的元数据,如果存在,它将用该元数据值填充记录,否则它将连接到 Kubernetes Master/API Server 并检索该信息。
5. 可选特性:使用 Kubelet 获取元数据
报告了一个问题,当集群太大,有太多的请求发送给它时,kube-apiserver 会崩溃并失去响应。对于此特性,fluent bit Kubernetes 过滤器将向 kubelet / pods 端点而不是 kube-apiserver 发送请求,以检索 pods 信息并使用它来丰富日志。由于 Kubelet 是在本地节点中运行的,因此请求的响应速度会更快,每个节点一次只能得到一个请求。这可以节省 kube-apiserver 的性能来处理其他请求。当启用该特性时,您应该不会看到添加到日志中的 kubernetes 元数据有什么不同,但是当集群很大时,应该可以避免 Kube-apiserver 瓶颈。
5.1. 配置设置
这个特性需要一些配置设置。
luent Bit DaemonSet 角色配置示例:
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: fluentbitds
namespace: fluentbit-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: fluentbit
rules:
- apiGroups: [""]
resources:
- namespaces
- pods
- nodes
- nodes/proxy
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: fluentbit
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: fluentbit
subjects:
- kind: ServiceAccount
name: fluentbitds
namespace: fluentbit-system
不同之处在于 kubelet 需要为资源nodes/proxy 获得 HTTP 请求的特殊权限。在创建role 或clusterRole 时,需要在resources 规则中添加nodes/proxy 。
Fluent Bit 配置示例:
[INPUT]
Name tail
Tag kube.*
Path /var/log/containers/*.log
DB /var/log/flb_kube.db
Parser docker
Docker_Mode On
Mem_Buf_Limit 50MB
Skip_Long_Lines On
Refresh_Interval 10
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc.cluster.local:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
Merge_Log On
Buffer_Size 0
Use_Kubelet true
Kubelet_Port 10250
因此,对于 Fluent Bit 配置,需要将Use_Kubelet 设置为true 以启用该特性。
DaemonSet 配置示例:
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentbit
namespace: fluentbit-system
labels:
app.kubernetes.io/name: fluentbit
spec:
selector:
matchLabels:
name: fluentbit
template:
metadata:
labels:
name: fluentbit
spec:
serviceAccountName: fluentbitds
containers:
- name: fluent-bit
imagePullPolicy: Always
image: fluent/fluent-bit:latest
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: fluentbit-config
mountPath: /fluent-bit/etc/
resources:
limits:
memory: 1500Mi
requests:
cpu: 500m
memory: 500Mi
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: fluentbit-config
configMap:
name: fluentbit-config
关键是将hostNetwork 设置为true ,将dnpolicy 设置为ClusterFirstWithHostNet ,fluent bit DaemonSet 可以在本地调用 Kubelet。否则它不能为 kubelet 解析dns。
现在您可以使用这个新特性了!
5.2. 验证 Use_Kubelet 选项是否正常工作
基本上,和使用 Kubernetes 元数据丰富日志文件的体验没有什么不同。
要检查 Fluent Bit 是否在使用 kubelet,可以检查 Fluent Bit 日志,应该有如下日志:
[ info] [filter:kubernetes:kubernetes.0] testing connectivity with Kubelet...
如果你在 debug 模式,你可以看到更多:
[debug] [filter:kubernetes:kubernetes.0] Send out request to Kubelet for pods information.
[debug] [filter:kubernetes:kubernetes.0] Request (ns=<namespace>, pod=node name) http_do=0, HTTP Status: 200
[ info] [filter:kubernetes:kubernetes.0] connectivity OK
[2021/02/05 10:33:35] [debug] [filter:kubernetes:kubernetes.0] Request (ns=<Namespace>, pod=<podName>) http_do=0, HTTP Status: 200
[2021/02/05 10:33:35] [debug] [filter:kubernetes:kubernetes.0] kubelet find pod: <podName> and ns: <Namespace> match
6. 故障排除
以下部分将介绍您可能遇到的特定日志消息,以及如何解决这些消息,以确保 Fluent Bit 的 Kubernetes 过滤器正常运行。
(1)我无法看到附加到我的 pod 或其他 Kubernetes 对象的元数据
如果您没有看到添加到 kubernetes 日志中的元数据,并且在日志消息中看到以下内容,那么您可能面临与 kubernetes API 服务器的连接问题。
[2020/10/15 03:48:57] [ info] [filter_kube] testing connectivity with API server...
[2020/10/15 03:48:57] [error] [filter_kube] upstream connection error
[2020/10/15 03:48:57] [ warn] [filter_kube] could not get meta for POD
可能的解决方案1:检查 Kubernetes 的角色
当 Fluent Bit 被部署为 DaemonSet 时,它通常以特定的角色运行,允许应用程序与 Kubernetes API 服务器对话。如果您部署在一个较多限制的环境中,请检查所有 Kubernetes 角色是否设置正确。
可能的解决方案2:检查 Kubernetes 的 IPv6
在某些情况下,您可能在环境中启用了 IPv6,而您需要在 Fluent Bit 中启用该功能。在 service 标签下,请将选项ipv6 设置为on 。
可能的解决方案3:检查到 Kube_URL 的连接
默认情况下,Kube_URL 设置为https://kubernetes.default.svc:443 。确保您从集群内连接到这个端点,并且没有特殊权限干扰连接。
(2)我看不到新对象获得元数据
在某些情况下,您可能只看到一些对象被附加了元数据,而其他对象没有被附加元数据。当本地数据被缓存且不包含需要充实的 kubernetes 对象的正确 id 时,有时会发生这种情况。对于大多数 Kubernetes 对象,Kubernetes API 服务器会被更新,然后会在 Fluent Bit 日志中反映出来,但在某些情况下,Pod 对象的 Kubernetes API 服务器的刷新可能会被跳过,从而导致跳过元数据。
|