9.3. 启用 JSON 日志转发

您可以配置 Log Forwarding API,将 JSON 字符串解析为结构化对象。

9.3.1. 解析 JSON 日志

您可以使用 ClusterLogForwarder 对象将 JSON 日志解析到结构化对象,并将它们转发到受支持的输出。

为了说明其工作原理,假定您有以下结构化 JSON 日志条目:

结构化 JSON 日志条目示例

{"level":"info","name":"fred","home":"bedrock"}

要启用解析 JSON 日志,您需要将 parse: json 添加到 ClusterLogForwarder CR 的管道中,如下例所示。

显示 parse: json 的片段示例

pipelines:
- inputRefs: [ application ]
  outputRefs: myFluentd
  parse: json

当使用 parse: json 来启用 JSON 日志解析时,CR 会复制 structured 项中的 JSON 结构化日志条目,如下例所示。

包含结构化 JSON 日志条目的 structured 输出示例

{"structured": { "level": "info", "name": "fred", "home": "bedrock" },
 "more fields..."}

重要

如果日志条目不包含有效的结构化 JSON,则将缺少 structured 字段。

9.3.2. 为 Elasticsearch 配置 JSON 日志数据

如果您的 JSON 日志遵循多个模式,在单个索引中存储它们可能会导致类型冲突和卡性问题。要避免这种情况,您必须配置 ClusterLogForwarder 自定义资源 (CR),将每个 schema 分组到单个输出定义中。这样,每个架构被转发到单独的索引。

重要

如果您将 JSON 日志转发到 OpenShift Logging 管理的默认 Elasticsearch 实例,它会根据您的配置生成新的索引。为避免与索引数量过多相关的性能问题,请考虑通过标准化到常见模式来保持可能的模式数量较低。

结构类型

您可以使用 ClusterLogForwarder CR 中的以下结构类型来为 Elasticsearch 日志存储构建索引名称:

  • structuredTypeKey 是 message 字段的名称。该字段的值用于构造索引名称。

    • kubernetes.labels.<key> 是 Kubernetes pod 标签,其值用于构造索引名称。
    • openshift.labels.<key>ClusterLogForwarder CR 中的 pipeline.label.<key> 元素,其值用于构造索引名称。
    • kubernetes.container_name 使用容器名称来构造索引名称。
  • structuredTypeName: 如果没有设置 structuredTypeKey 字段,或者其键不存在,则 structuredTypeName 值将用作结构化类型。当您将 structuredTypeKey 字段和 structuredTypeName 字段一起使用时,如果 JSON 日志数据中缺少 structuredTypeKey 字段中的密钥,则 structuredTypeName 值将提供一个回退索引名称。
注意

虽然您可以将 structuredTypeKey 的值设置为 "Log Record Fields" 主题中显示的任何字段,但最有用的字段将显示在前面的结构类型列表中。

structuredTypeKey: kubernetes.labels.<key> 示例

假设如下:

  • 集群正在运行以两种不同格式生成 JSON 日志的应用 pod,即 "apache" 和 "google"。
  • 用户使用 logFormat=apachelogFormat=google 标记这些应用 pod。
  • 您可以在 ClusterLogForwarder CR YAML 文件中使用以下代码片段。
apiVersion: logging.openshift.io/v1
kind: ClusterLogForwarder
metadata:
# ...
spec:
# ...
  outputDefaults:
    elasticsearch:
      structuredTypeKey: kubernetes.labels.logFormat 1
      structuredTypeName: nologformat
  pipelines:
  - inputRefs:
    - application
    outputRefs:
    - default
    parse: json 2
1
使用 Kubernetes logFormat 标签形成的键值对值。
2
启用解析 JSON 日志。

在这种情况下,以下结构化日志记录进入 app-apache-write 索引:

{
  "structured":{"name":"fred","home":"bedrock"},
  "kubernetes":{"labels":{"logFormat": "apache", ...}}
}

以下结构化日志记录进入 app-google-write 索引中:

{
  "structured":{"name":"wilma","home":"bedrock"},
  "kubernetes":{"labels":{"logFormat": "google", ...}}
}

structuredTypeKey: openshift.labels.<key> 示例

假设您在 ClusterLogForwarder CR YAML 文件中使用了以下代码片段:

outputDefaults:
 elasticsearch:
    structuredTypeKey: openshift.labels.myLabel 1
    structuredTypeName: nologformat
pipelines:
 - name: application-logs
   inputRefs:
   - application
   - audit
   outputRefs:
   - elasticsearch-secure
   - default
   parse: json
   labels:
     myLabel: myValue 2
1
使用由 OpenShift myLabel 标签组成的键值对的值。
2
myLabel 元素将字符串值 myValue 提供给结构化日志消息。

在这种情况下,以下结构化日志记录进入 app-myValue-write 索引中:

{
  "structured":{"name":"fred","home":"bedrock"},
  "openshift":{"labels":{"myLabel": "myValue", ...}}
}

其他注意事项

  • 结构化记录的 Elasticsearch 索引通过将"app-"添加到结构化类型并附加 "-write" 来形成。
  • 非结构化记录不会发送到结构化索引。在应用、基础架构或审计索引中,它们按照常态进行索引。
  • 如果没有非空的结构化类型,则转发一个没有 structured 项的 unstructured 记录。

不要过载有太多索引的 Elasticsearch。仅对不同的日志格式使用不同的结构化类型,而不用为每个应用程序或命名空间都使用不同的结构化类型。例如,大多数 Apache 应用使用相同的 JSON 日志格式和结构化类型,如 LogApache

9.3.3. 将 JSON 日志转发到 Elasticsearch 日志存储

对于 Elasticsearch 日志存储,如果您的 JSON 日志条目遵循不同的模式,请将 ClusterLogForwarder 自定义资源 (CR) 配置为将每个 JSON 模式分组到单个输出定义中。这样,Elasticsearch 会为每个 schema 使用一个单独的索引。

重要

因为将不同的模式转发到同一索引可能会导致类型冲突和卡化问题,所以您必须在将数据转发到 Elasticsearch 存储前执行此配置。

为避免与索引数量过多相关的性能问题,请考虑通过标准化到常见模式来保持可能的模式数量较低。

流程

  1. 将以下代码片段添加到 ClusterLogForwarder CR YAML 文件中。

    outputDefaults:
     elasticsearch:
        structuredTypeKey: <log record field>
        structuredTypeName: <name>
    pipelines:
    - inputRefs:
      - application
      outputRefs: default
      parse: json
  2. 使用 structuredTypeKey 字段指定其中一个日志记录字段。
  3. 使用 structuredTypeName 字段指定名称。

    重要

    要解析 JSON 日志,您必须同时设置 structuredTypeKeystructuredTypeName 字段。

  4. 对于 inputRefs,指定要使用该管道转发哪些日志类型,如 applicationinfrastructureaudit
  5. parse: json 元素添加到管道。
  6. 创建 CR 对象:

    $ oc create -f <filename>.yaml

    Red Hat OpenShift Logging Operator 会重新部署收集器 Pod。但是,如果没有重新部署,请删除收集器 Pod 以强制重新部署。

    $ oc delete pod --selector logging-infra=collector

9.3.4. 将同一 pod 中的容器的 JSON 日志转发到单独的索引

您可以将来自同一 pod 的不同容器的结构化日志转发到不同的索引。要使用此功能,您必须使用多容器支持配置管道并注解 pod。日志被写入带有 app- 前缀的索引。建议将 Elasticsearch 配置为使用别名来容纳此目的。

重要

日志的 JSON 格式化因应用程序而异。因为创建太多索引会影响性能,所以请限制使用此功能,仅对与 JSON 格式不兼容的日志创建索引。使用查询将日志与不同命名空间分离,或使用兼容 JSON 格式的应用程序进行隔离。

先决条件

  • Red Hat OpenShift 的日志记录: 5.5

步骤

  1. 创建或编辑定义 ClusterLogForwarder CR 对象的 YAML 文件:

    apiVersion: logging.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: instance
      namespace: openshift-logging
    spec:
      outputDefaults:
        elasticsearch:
          structuredTypeKey: kubernetes.labels.logFormat 1
          structuredTypeName: nologformat
          enableStructuredContainerLogs: true 2
      pipelines:
      - inputRefs:
        - application
        name: application-logs
        outputRefs:
        - default
        parse: json
    1
    使用 Kubernetes logFormat 标签形成的键值对值。
    2
    启用多容器输出。
  2. 创建或编辑定义 Pod CR 对象的 YAML 文件:

    apiVersion: v1
    kind: Pod
    metadata:
      annotations:
        containerType.logging.openshift.io/heavy: heavy 1
        containerType.logging.openshift.io/low: low
    spec:
      containers:
      - name: heavy 2
        image: heavyimage
      - name: low
        image: lowimage
    1
    格式:containerType.logging.openshift.io/<container-name>: <index>
    2
    注解名称必须与容器名称匹配
警告

此配置可能会显著增加集群中的分片数量。

其它资源

其他资源