×

解析JSON日志

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

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

示例结构化JSON日志条目
{"level":"info","name":"fred","home":"bedrock"}

要启用解析JSON日志,请在ClusterLogForwarder CR中的管道中添加parse: json,如下例所示

显示parse: json的示例代码片段
pipelines:
- inputRefs: [ application ]
  outputRefs: myFluentd
  parse: json

启用使用parse: json解析JSON日志后,CR会将JSON结构化日志条目复制到structured字段中,如下例所示

包含结构化JSON日志条目的示例structured输出
{"structured": { "level": "info", "name": "fred", "home": "bedrock" },
 "more fields..."}

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

为Elasticsearch配置JSON日志数据

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

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

结构类型

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

  • structuredTypeKey是消息字段的名称。该字段的值用于构建索引名称。

    • kubernetes.labels.<key>是Kubernetes Pod标签,其值用于构建索引名称。

    • openshift.labels.<key>ClusterLogForwarder CR中的pipeline.label.<key>元素,其值用于构建索引名称。

    • kubernetes.container_name使用容器名称来构建索引名称。

  • structuredTypeName:如果未设置structuredTypeKey字段或其键不存在,则使用structuredTypeName值作为结构化类型。当同时使用structuredTypeKey字段和structuredTypeName字段时,如果structuredTypeKey字段中的键在JSON日志数据中缺失,则structuredTypeName值提供备用索引名称。

尽管您可以将structuredTypeKey的值设置为“日志记录字段”主题中显示的任何字段,但最有用的字段在上文列出的结构类型中。

structuredTypeKey: kubernetes.labels.<key>示例

假设以下情况:

  • 您的集群正在运行产生两种不同格式的JSON日志(“apache”和“google”)的应用程序Pod。

  • 用户使用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字段的*非结构化*记录。

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

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

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

因为将不同的模式转发到同一个索引可能会导致类型冲突和基数问题,所以在将数据转发到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 日志操作符会重新部署收集器 Pod。但是,如果它们没有重新部署,请删除收集器 Pod 以强制它们重新部署。

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

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

您可以将同一 Pod 内不同容器的结构化日志转发到不同的索引。要使用此功能,必须使用多容器支持配置管道并对 Pod 添加注释。日志将写入以app-为前缀的索引。建议将 Elasticsearch 配置为使用别名以适应此情况。

JSON 日志格式因应用程序而异。由于创建过多索引会影响性能,因此请将此功能的使用限制为仅为 JSON 格式不兼容的日志创建索引。使用查询来分离来自不同命名空间的日志,或具有兼容 JSON 格式的应用程序的日志。

先决条件
  • {logging-title-uc}: 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/<容器名称>: <索引>
    2 注释名称必须与容器名称匹配

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

其他资源
其他资源