Elasticsearch 动态字段映射和 JSON 点表示法

rpf*_*pf3 5 elasticsearch logstash kubernetes kubernetes-helm fluent-bit

我正在尝试将日志从 Kubernetes 集群写入 Elasticsearch 索引。Fluent-bit 用于读取标准输出,并使用包括 Pod 标签在内的元数据来丰富日志。一个简化的日志对象示例是

{
  "log": "This is a log message.",
  "kubernetes": {
    "labels": {
      "app": "application-1"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

问题是部署到集群的一些其他应用程序具有以下格式的标签:

{
  "log": "This is another log message.",
  "kubernetes": {
    "labels": {
      "app.kubernetes.io/name": "application-2"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这些应用程序是通过 Helm 图表安装的,较新的应用程序遵循此处列出的标签和选择器约定。标签和选择器的命名约定于 2018 年 12 月更新,请参见此处,但并非所有图表都已更新以反映这一点。

最终结果是,根据哪种类型的标签格式首先将其纳入弹性索引,尝试发送其他类型将引发映射异常。如果我创建一个新的空索引并首先发送命名空间标签,则尝试记录简单app标签将引发此异常:

object mapping for [kubernetes.labels.app] tried to parse field [kubernetes.labels.app] as object, but found a concrete value
Run Code Online (Sandbox Code Playgroud)

相反的情况,第二个发布命名空​​间标签,会导致此异常:

Could not dynamically add mapping for field [kubernetes.labels.app.kubernetes.io/name]. Existing mapping for [kubernetes.labels.app] must be of type object but found [text].
Run Code Online (Sandbox Code Playgroud)

我怀疑正在发生的事情是 Elasticsearch 将字段名称中的句点视为 JSON 点表示法,并试图将其充实为一个对象。我在 2015 年找到了这个 PR ,它明确禁止在字段名称中使用句点,但在 2016 年这个 PR似乎已经逆转了这一情况。还有一个 2015-2017 年的多年线程讨论这个问题,但我找不到任何涉及最新版本的内容。

我目前的想法是标准化我们正在使用的 Helm 图表,让所有标签都使用相同的约定。这似乎是解决根本问题的创可贴,但我觉得我在 Elasticsearch 和动态字段映射的配置中遗漏了一些明显的东西。

任何帮助将不胜感激。

rpf*_*pf3 4

我选择使用 Logstash mutate 过滤器以及rename此处描述的选项:

https://www.elastic.co/guide/en/logstash/current/plugins-filters-mutate.html#plugins-filters-mutate-rename

最终结果看起来像这样:

filter {
  mutate {
    '[kubernetes][labels][app]'   => '[kubernetes][labels][app.kubernetes.io/name]'
    '[kubernetes][labels][chart]' => '[kubernetes][labels][helm.sh/chart]'
  }
}
Run Code Online (Sandbox Code Playgroud)