使用 Elastic 和 OpenTelemetry 在 Kubernetes 上打造现代的可观测性和安全性

azure-kubernetes-720x420-2.png

Kubernetes 的结构化特性使我们能够通过一种可重复且可扩展的方法来部署和管理服务及应用程序。这使得其在各个垂直市场领域都得到了广泛采用,其中既有本地部署模式,也不乏云端部署模式。然而,Kubernetes 运维的自治特性则要求实现全面且完全聚合式的可观测性和安全性。目前,唯有使用 Elastic 平台才有可能实现这一点。

在本文中,我们将会围绕如何使用 Elasticsearch 和 OpenTelemetry 观测 Kubernetes 上的应用程序和服务工作流并确保其安全,讨论一些最佳实践。你将会学习下列内容:

  • 如何在您的 Kubernetes 集群中部署和配置 Elastic Agent
  • 如何使用 Elastic Agent 采集 OpenTelemetry 应用程序跟踪记录、指标和事件
  • 如何使用 Elastic Agent 采集 Kubernetes 容器日志、集群指标以及网络流量模式
  • 如何使用 Elastic Defend 为您的 Kubernetes 集群添加以安全为中心的监测和威胁保护
  • 熟悉如何使用 Elastic 的开箱即用型仪表板来观测运维问题、找出问题之间的关联性并开展根本原因分析

数据孤岛为对 Kubernetes 部署进行故障排查带来了挑战

传统上,业界把应用程序可观测性、基础架构可观测性和基础架构安全性看作截然不同的领域,每个领域都需要使用由不同团队管理的不同工具进行处理。这一模式虽然在组织层面通常非常便捷,但也很快暴露出了一个常见的痛点和处理限制:

分析师(真人或机器)需要使用通过应用程序可观测性、基础架构可观测性和基础架构安全性收集的所有数据,才能确定某个特定运维问题是基础架构问题、应用程序缺陷,还是安全漏洞。此外,专员还需要访问来自全部这三个来源的全保真数据,才能找出特定问题的根本原因。

作为权宜之计,客户经常会跨多个数据平台复制某些可观测性数据。最好的情况就是,这会使数据存储、支持和培训的费用增加一倍或两倍。最坏的情况则是,分析师缺少必要的关键数据来正确地找出问题的根本原因。鉴于 Kubernetes 的动态和可扩展特性,这一问题进一步恶化。我们认为,对于 Kubernetes 所提供的集成式服务部署模型而言,将可观测性和安全性平台分开是反面模式。 

实现可观测性的恰当时机

最终,开发人员、运维人员和安全分析师等都需要一个统一端到端视图,用于洞悉自身系统的应用程序和基础架构。基础架构部署团队需要一个统一的 Kubernetes 原生部署模式来提供这一可见性并确保其集群的安全。

这需要三个推动因素:

  1. 所有可观测性和安全性数据,包括应用程序、服务和基础架构的日志、跟踪记录、事件和指标,都必须存储在一个统一的数据平台中,而且存储方式要在搜索(关联性和延迟)和存储(成本)两方面都进行优化。
  2. 该统一的数据平台还必须能够确认数据关联性并以基于角色的方式将关联性展示出来:例如,如果分析师正在尝试确定问题的根本原因,则平台应引导分析师找出可能的问题,并让分析师与数据进行无缝交互,而无须关注数据的底层形式或来源。
  3. 应用程序和基础架构的插桩必须与 Kubernetes 的下列准则相符:可重复、可扩展的部署,且没有定制配置。

Elastic:如您所知,适用于 Kubernetes

现在,由 Elastic、OpenTelemetry、Kubernetes 以及现代计算硬件驱动的技术核心推动出现了全规模的 Kubernetes 原生可观测性和安全性:

  • OpenTelemetry 对开发人员(既包括自有团队也包括第三方)而言就像催化剂,它通过将 APM 供应商遴选流程与 APM 实施分离开来,可用来对开发人员的全部应用程序和服务进行插桩
  • 拥有足量 CPU 和 RAM 的现代计算硬件使得在不影响性能的前提下“随时在线”跟踪成为可能,甚至对于实时应用程序而言也是如此
  • 最新的 Elastic 架构,包括可搜索快照和新的时序数据流,再配上 Elastic APM 智能尾部采样,使得在线存储多年的全面可观测性和安全性数据变得可行且价格合理
  • 由于可在每个 Kubernetes 节点上的 DaemonSet 中部署 Elastic Agent,所以能够以可重复且可扩展的方式部署远程控制的统一数据收集器。部署完毕后,Elastic Agent 可作为一个 Fleet 进行管理,这样您便能无比轻松地添加、配置或移除数据集成
  • Elastic 平台提供了一套全集成式 Kubernetes 安全解决方案,涵盖保护、可观测性和态势管理
  • Elasticsearch 支持使用开箱即用型仪表板、异常检测和告警,跨所有已收集数据源确定关联性并提供指导

数据收集模型

如下图所示,我们建议对于可观测性和安全性数据收集采用混合模型,依靠 Elastic Agent 获取 Kubernetes 基础架构指标和应用程序容器日志,同时使用 OpenTelemetry APM 代理来获取应用程序跟踪记录、事件及指标。此种方法的原理在下方进行了比较详细的描述。

应用程序跟踪记录、事件和指标数据

要想生成应用程序跟踪记录和指标,通常需要向应用程序代码内直接注入一个 APM 库。然而,通过利用 OpenTelemetry APM 代理,我们可以移除 APM 采用过程中的供应商锁定这一障碍。截至目前,OpenTelemetry 的工作重心是实现稳健且标准化的代理部署,以便捕获应用程序跟踪记录和跟踪记录事件,同时也开始对应用程序指标提供支持。当今,对于几乎每一门热门编程语言都有已达到合理成熟程度的代理。很多情况下,您仅需进行少量编码,甚至完全无须编码,便可通过自动插桩对您的应用程序进行插桩。如果您的应用程序是用 .NET、Java、NodeJS 或 Python 写成的,而且使用典型框架,您甚至可以在运行时使用 OpenTelemetry Kubernetes 运算符注入 APM 库!

要进行根本原因分析,需要确定 APM 数据与应用程序日志及基础架构指标之间的关联性。为了能够获得这一关联性,我们在应用程序跟踪和日志以及基础架构指标中都需要有共同的特定识别元数据(或称资源属性)。Elastic 平台使用 service.name、pod.uidcontainer.id 将来自 Kubernetes 中所运行应用程序的可观测性数据关联起来。传统上,APM 库需要到墙外“窥看”以获得这一元数据。部分 OpenTelemetry APM 库现在支持这一功能(例如 Java),但是其他的则不支持 (Rust)。尽管能够简化部署,但是这一方法普遍被认为远不够理想:APM 代理(在应用程序的背景下运行)不仅需要确定其运行时环境(Docker、Kubernetes 等),还需要足够的许可来访问这些标识符(例如 /proc/self/cgroup 或 Kubernetes API 的访问权)。后者显然是一个潜在的安全问题。有鉴于此,理想情况下,我们想要在跟踪记录数据生成之后,依赖外部实体来向内传送此类元数据(作为环境变量)或者添加此类元数据。为了能够无论使用什么 OpenTelemetry APM 库都能够可靠地向跟踪记录数据添加 container.id,我们部署了一个 OpenTelemetry 收集器,该收集器配置了在节点的 DaemonSet 中运行的 k8sattribute 处理器

向 APM 数据添加了关联的 Kubernetes 元数据后,APM 数据会从 OpenTelemetry 收集器被转发至也在节点的 DaemonSet 中运行的 Elastic Agent。Elastic Agent 已使用 APM 集成通过 Fleet 配置完毕。将 APM 集成分配至每个节点 DaemonSet 有助于分配 APM 采集负载,并更紧密地将其可用性与它支持的应用程序关联起来。不仅如此,它将 GRPC/HTTP2 流量保持在本地的 DaemonSet 自身,从而避开 GRPC/HTTP2 负载平衡的复杂问题。最后,安全性得以简化:在节点和 Elasticsearch 集群之间使用 Fleet 管理型 Elastic Agent TLS 安全性后,OTLP 在节点上可能会不安全。Elastic APM 集成会将 OpenTelemetry 跟踪记录、指标和事件数据转换为 Elasticsearch Common Schema (ECS)。然后最终生成的文档会被发送到 Elasticsearch,以对其进行采集和索引。

容器日志和 Kubernetes 基础架构指标

尽管 OpenTelemetry 标准支持日志,但实施仍在起草阶段。因此,很多可用的代理尚不支持挂钩日志框架的功能。在实际应用中,采集容器日志文件是捕获应用程序日志数据的唯一可行方法。虽然使用 OpenTelemetry 收集器 filelogreceiver 有可能实现这一点,但它目前仍处于 alpha 质量阶段,尚不推荐用于生产用例。同样的道理适用于旨在捕获 Kubernetes 基础架构指标的 k8sclusterreceiver

通过对比,Elastic Kubernetes 集成不仅稳健且得到验证,而且能够实现应用程序日志和 Kubernetes 基础架构指标的全保真收集。不仅如此,我们的 Kubernetes 集成可以从 Kibana 中在 Fleet 层级上进行远程控制,大大简化了配置工作。与应用程序跟踪记录和指标不同,Elastic Kubernetes 集成在您的应用程序代码之外运行,因此能够减少供应商锁定的顾虑。

此外,在每个节点的 DaemonSet 中部署 Elastic Agent 的价值远不止于 Kubernetes 集成。如您稍后会在本文中看到的,我们将会利用同一个 Elastic Agent 实例来部署 Elastic Defend,以监测我们的 Kubernetes 节点并确保其安全。

安全事件和主机数据

现代 Kubernetes 可观测性和安全性工作流必须同步运行,以便让分析师能够找出给定问题的根本原因。Elastic 的安全解决方案提供全集成、全功能且可识别 Kubernetes 的 SIEMSOARXDR 解决方案,包括终端保护

需注意的是,Elastic 的 Defend 集成能够从内在大幅提高 Kubernetes 可观测性。我们的 Kubernetes 安全态势管理集成能够在您的安全团队发现应用程序的潜在配置问题之前,便向您的开发、DevOps 以及 DevSecOps 团队发送有关这些问题的告警。我们的 Kubernetes 安全仪表板可让分析师准确了解在您的 Kubernetes 节点上执行了哪些进程,什么时候执行的,使用的是哪些运行时参数,以及是在哪个账户下面!借助这一前所未有级别的运行时可见性,您能够检测作为您容器化应用程序内的依赖关系引入到容器层的未预见安全威胁。

与 Elastic 的 APM 集成类似,这些安全集成可通过 Fleet 添加、配置和移除,并且会在您 Kubernetes 集群每个节点上的 DaemonSet 中的 Elastic Agent 内运行。

开始工作吧!

要求

您需要一个 Kubernetes 集群,以便在上面部署您的应用、Elastic Agent,以及 OpenTelemetry 收集器。我喜欢使用 kOps 来在超大规模云服务商平台中轻松地创建、管理和删除测试集群。仅供参考,单个 AWS EC2 t3.xlarge 便足以部署 OpenTelemetry 演示和我们的 Elastic Agent。这里的示例应该适用于在任何超大规模云服务商平台或本地(例如 OpenShift)部署的任何自管型或托管型(例如 EKS、GKE)Kubernetes 集群。它们理论上还应适用于桌面 Kubernetes 集群(例如 MicroK8s 或 Docker 的内置 Kubernetes 引擎),前提是您赋予这些环境足够的 RAM 和 CPU(例如 4 个 vCPU 和 16GB RAM)。您还需要基础的 Kubernetes 管理员知识(例如部署 yaml,检查 pod 状态,以及查看 pod 日志文件)。开始前,确保您的 Kubernetes 上下文指向正确的集群。

您当然还要有应用程序和服务,以便使用 OpenTelemetry 对其插桩。要开始,您可以使用我们的 OpenTelemetry 演示分叉。在那里,您可以遵照我们的自有应用程序和服务插桩最佳实践

最后,您要能够访问一个您可随意操作的现代(8.5 或更高版本)Elasticsearch 部署(您可以在我们的云中免费创建一个!),且该部署应能从您的 Kubernetes 应用程序集群访问。

工具

本教程假设您正在使用 Linux 或 MacOS 主机来配置您的 Kubernetes 集群。您需要确保已安装下列工具:

创建您的 Elasticsearch 集群

如果已经拥有一个您可随意操作的的现代 Elasticsearch 部署,当然很好!如果没有,我们可以设置一个,只需在 cloud.elastic.co 上创建一个免费试用集群即可!

  1. 导航至 cloud.elastic.co,注册一个免费试用账户(无需提供信用卡)
  2. 将您的 Elasticsearch 集群命名为 "o11y"(示例),其他设置保持默认值即可
  3. 单击 [ 创建部署 ]
  4. 等待 Elasticsearch Cloud 报告“您的部署已就绪!”
  5. 点击 [ 继续 ] 登录 Kibana

将 Elastic Agent 部署到 DaemonSet

我们将会使用安装到您 Kubernetes 集群每个节点上 DaemonSet 中的 Elastic Agent(带集成)来将数据采集到 Elasticsearch 中。

1. 将下列 YAML(此处曾提及)下载到您的本地机器上。我们将会使用此 YAML 将 Elastic Agent(带 Elastic Defend) 部署到您 Kubernetes 节点的 DaemonSet 中。

curl -L -O https://raw.githubusercontent.com/elastic/endpoint/main/releases/8.5.0/kubernetes/deploy/elastic-defend.yaml 

2. 将下列补丁下载到您的本地机器上。该补丁可提升分配给 Elastic Agent 容器的默认 RAM 和 CPU,从而轻松地支持我们将安装的所有集成。在生产环境中,您可以决定仅部署下列集成的一个子集,这可能会使此修改变得无关紧要。

curl -L -O https://raw.githubusercontent.com/ty-elastic/elastic-otel-k8s/main/agent/8.5.0/elastic-defend.yaml.patch 

3. 就地应用补丁

patch elastic-defend.yaml elastic-defend.yaml.patch 

4. 确保您已登录进入您 Elasticsearch 集群上的 Kibana

5. 导航至 [ 管理 / Fleet ]

6. 点击 [ 添加代理 ]

7. 将新策略命名为 "k8s-apps"(示例) 

  • 这里 "k8s-apps" 策略将会用于向您应用程序 Kubernetes 集群节点的 DaemonSet 部署集成

8. 在 [ 高级选项 ] 下,将 [ 取消注册超时 ] 设置为 "3600" 秒 

  • Kubernetes 可以动态创建和删除节点;该设置将确保在已删除节点上部署的 Elastic Agent 会被自动修剪掉

9. 点击 [ 创建策略 ]

10. 在 [ 在您的主机上安装 Elastic Agent ] 下,选择 "Kubernetes"

11. 查找 "FLEET_URL" 变量的值,并将其复制到您之前下载并打补丁的 "elastic-defend.yaml" 文件中的 "FLEET_URL" 值处

12. 查找 "FLEET_ENROLLMENT_TOKEN" 变量的值,并将其复制到您之前下载并打补丁的 "elastic-defend.yaml" 文件中的 "FLEET_ENROLLMENT_TOKEN" 值处

13. 通过下列代码将 elastic-defend.yaml 应用到您的集群:

kubectl apply -f elastic-defend.yaml 

14. 等待 [ 确认代理注册情况 ] 显示“1 个代理已完成注册”

15. 等待 [ 输入消息已确认 ] 显示“已从 1 个(共 1 个)近期注册的代理处接收到输入数据”

16. 点击“关闭”

您可能已经发现,当您选择 Kubernetes 主机选项时,Elastic 提供预配置的 Elastic Agent 部署 YAML。该部署 YAML 尚不包含 Elastic Defend 镜像。

设置 Elastic Agent 集成

现在到了简单的部分了!向您的 DaemonSet 中部署了 Fleet 托管型 Elastic Agent 后,通过 Kibana 集成界面远程添加/配置/删除集成就是小事一桩了。

APM

Elastic APM 集成用于将 OpenTelemetry APM 数据导入到 Elastic 中。

  1. 在 Kibana 中导航至 [ 管理 / 集成 ]
  2. 搜索 "APM"
  3. 点击 [ APM ]
  4. 点击 [ 在 Fleet 中管理 APM 集成 ]
  5. 点击 [ 添加 Elastic APM ]
  6. 将 [ 通用 / 服务器配置 / 主机 ] 设置为 "0.0.0.0:8200"(这会将 APM 集成采集暴露给节点上的其他 pod(包括也在 DaemonSet 中运行的 OpenTelemetry 收集器)。)
  7. 禁用 [ 代理授权 / 匿名代理访问 ](经过这一简化,能够让 OpenTelemetry 收集器无需使用授权令牌便能将 OTEL 数据发送至 Elastic APM 集成(需注意的是,APM 集成不会暴露到节点外面)。)
  8. (可选)启用 [ 基于 Tail 的采样 ](这能够启用针对跟踪记录数据的智能次级采样,从而在降低存储要求的前提下捕获异常和整体性能。)
  9. 将 [ 向何处添加此集成 ] 设置为“既有主机”,并将 [ 代理策略 ] 设置为 "k8s-apps"
  10. 点击 [ 保存并继续 ]
  11. 点击 [ 保存并部署变更 ]

Kubernetes

部署 Kube State Metrics

Kubernetes 集成要求您的 Kubernetes 集群内有 kube-state-metrics,从而启用开箱即用型 Kubernetes 仪表板。

1. 添加 kube-state-metrics Helm 存储库

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts 

helm repo update 

2. 将 kube-state-metrics 安装到您 Kubernetes 集群上与 Elastic Agent 相同的命名空间中(如果使用所提供的 Elastic Agent 部署 yaml,则默认为 "kube-system")

helm install --set namespaceOverride=kube-system kube-state-metrics prometheus-community/kube-state-metrics 

安装 Kubernetes 集成

Elastic Kubernetes 集成用于将 Kubernetes 指标和日志导入到 Elasticsearch 中。

  1. 在 Kibana 中导航至 [ 管理 / 集成 ]
  2. 搜索 "Kubernetes"
  3. 选择 [ Kubernetes ]
  4. 点击 [ 添加 Kubernetes ]
  5. 如果还未设置的话,启用 [ 从 kube-state-metrics 收集 Kubernetes 指标 ]
  6. 将 [ 向何处添加此集成 ] 设置为“既有主机”,并将 [ 代理策略 ] 设置为 "k8s-apps"
  7. 点击 [ 保存并继续 ]
  8. 点击 [ 保存并部署变更 ]

Elastic Defend

Elastic Defend 集成用于保护您的节点并收集更多以安全为中心的可观测性数据。

  1. 在 Kibana 中导航至 [ 管理 / 集成 ]
  2. 搜索 "Elastic Defend"
  3. 选择 [ Elastic Defend ]
  4. 点击 [ 添加 Elastic Defend ]
  5. 将 [ 集成名称 ] 设置为 "defend-1"
  6. 导航至 [ 选择配置设置 ],将 [ 选择您想保护的环境类型 ] 设置为“云端负载(Linux 服务器或 Kubernetes 环境)”,并将 [ 要降低数据采集量,仅选择交互 ] 设置为“所有事件”
  7. 将 [ 向何处添加此集成 ] 设置为“既有主机”,并将 [ 代理策略 ] 设置为 "k8s-apps"
  8. 如果您的 Kubernetes 集群并非在 GKE 或 EKS 上运行,则在 [ 高级选项 ] 下,将 [ 命名空间 ] 设置为 "k8sapps"(示例),其中 "k8sapps" 能够识别您的应用程序 Kubernetes 集群(这一步很有必要,能够为 Elastic Defend 遥测数据添加标签,而且标签中含有其所应用到的 Kubernetes 集群的名称。)
  9. 点击 [ 保存并继续 ]
  10. 选择 [ 设置 ]
  11. 导航至 [ Elastic Defend 版本 ],并启用“自动确保集成策略为最新状态”
  12. 选择 [ 集成策略 ],然后点击 [ defend-1 ]
  13. 导航至 [ 类型:操作系统 / 事件收集:Linux ],然后启用 [ 捕获终端输出 ]
  14. 点击 [ 保存并继续 ]
  15. 点击 [ 保存并部署变更 ]

某些 Elasticsearch Kubernetes 仪表板要求您知道您 Kubernetes 集群的名称和 ID。如果您的集群在 GKE 或 EKS 上运行,Elastic Agent 会自动获取这一元数据。如果您运行的是自管型 Kubernetes 集群,则您可以创建一个采集管道来为安全事件自动添加 orchestrator.cluster.nameorchestrator.cluster.id 字段(从您之前定义的策略命名空间自动设置)。

  1. 导航至 [ 管理 / 开发工具 ]
  2. 执行下列代码:
PUT _ingest/pipeline/logs-endpoint.events.process@custom
{
  "processors": [
    {
      "set": {
        "field": "orchestrator.cluster.name",
        "copy_from": "data_stream.namespace",
        "ignore_empty_value": true,
        "ignore_failure": true
      }
    },
    {
      "set": {
        "field": "orchestrator.cluster.id",  		
        "copy_from": "data_stream.namespace",
        "ignore_empty_value": true,
        "ignore_failure": true
      }
    }
  ]
}

Kubernetes 安全态势管理

Elastic Kubernetes 安全态势管理集成用于验证您的 Kubernetes 集群和应用程序是否符合有关安全 Kubernetes 配置的最佳实践(基于互联网安全中心 (CIS) 的定义)。这能够允许您的开发和部署团队在错误配置造成安全漏洞之前发现这些错误配置。

  1. 在 Kibana 中导航至 [ 管理 / 集成 ]
  2. 搜索“Kubernetes 安全态势管理”
  3. 选择 [ Kubernetes 安全态势管理 ]
  4. 点击 [ 添加 Kubernetes 安全态势管理 ]
  5. 将 [ Kubernetes 部署 ] 设置为“未托管型 Kubernetes”(适用于自管型 Kubernetes)或 "EKS (Elastic Kubernetes Service)"(如果您的 Kubernetes 应用程序集群具体是在 AWS EKS 上运行的)
  6. 将 [ 向何处添加此集成 ] 设置为“既有主机”,并将 [ 代理策略 ] 设置为 "k8s-apps"
  7. 点击 [ 保存并继续 ]
  8. 点击 [ 保存并部署变更 ]

网络数据包捕获

Elastic 网络数据包捕获集成用于获取进出您 Kubernetes 节点的网络流量的相关洞察。

  1. 在 Kibana 中导航至 [ 管理 / 集成 ]
  2. 搜索“网络数据包捕获”
  3. 选择 [ 网络数据包捕获 ]
  4. 点击 [ 添加网络数据包捕获 ]
  5. 将 [ 向何处添加此集成 ] 设置为“既有主机”,并将 [ 代理策略 ] 设置为 "k8s-apps"
  6. 点击 [ 保存并继续 ]
  7. 点击 [ 保存并部署变更 ]

使用 OpenTelemetry 插桩

我已经针对 Elastic 可观测性优化了 OpenTelemetry 演示OpenTelemetry Helm 图表(参见对自有应用程序插桩以了解做了哪些改变以及改变的原因)。如果您只是使用 OpenTelemetry 演示中的应用程序来理解 Elastic 给 Kubernetes 可观测性和安全性带来的价值,请从创建 OpenTelemetry 演示开始。否则,如果您想对自己的应用程序和服务进行监测,请从对自有应用程序插桩中列出的指南开始。

创建 OpenTelemetry 演示

本部分假定您想部署并观测在 OpenTelemetry 演示中已插桩的应用程序。我们将会使用一个修改版 OpenTelemetry Helm 图表,该图表会同时部署演示应用程序和一个 OpenTelemetry 收集器实例。

1. 添加我们的 helm 存储库

helm repo add elastic-open-telemetry https://ty-elastic.github.io/opentelemetry-helm-charts 
helm repo update 

2. 将演示应用和收集器安装到您的 Kubernetes 集群中

helm install elastic-otel elastic-open-telemetry/opentelemetry-demo 

3. 通过列出运行中的 pod 来对安装进行验证

kubectl get pods 

除了一个 OpenTelemetry 收集器实例外,您应该还会看到所有的 OpenTelemetry 演示 pod:

> kubectl get pods
NAME                                                  READY   STATUS    RESTARTS   AGE
elastic-otel-adservice-86b5b4f779-8lsgf               1/1     Running   0          3h28m
elastic-otel-cartservice-55659bd5f4-lvtjx             1/1     Running   0          3h28m
elastic-otel-checkoutservice-88bfcf745-42nvt          1/1     Running   0          3h28m
elastic-otel-currencyservice-659dd55fc8-pcrrx         1/1     Running   0          3h28m
elastic-otel-emailservice-64df788455-mkb56            1/1     Running   0          3h28m
elastic-otel-featureflagservice-6dcf49d84c-n5jtk      1/1     Running   0          3h28m
elastic-otel-ffspostgres-67dcd7596d-htbpm             1/1     Running   0          3h28m
elastic-otel-frontend-674c8fdc74-zmv8r                1/1     Running   0          3h28m
elastic-otel-frontendproxy-5bd757dc89-r2728           1/1     Running   0          3h28m
elastic-otel-loadgenerator-5b98bd9656-8z8hz           1/1     Running   0          3h28m
elastic-otel-otelcol-agent-kbb54                      1/1     Running   0          3h28m
elastic-otel-paymentservice-5c4b5c57bd-wkbqj          1/1     Running   0          3h28m
elastic-otel-productcatalogservice-6995496975-7wm46   1/1     Running   0          3h28m
elastic-otel-quoteservice-849797dfdd-bkj29            1/1     Running   0          3h28m
elastic-otel-recommendationservice-6cb4476f-zpqqv     1/1     Running   0          3h28m
elastic-otel-redis-5698bf675b-dl2xv                   1/1     Running   0          3h28m
elastic-otel-shippingservice-6b9fdcc467-knlxb         1/1     Running   0          3h28m

4. 跳至验证和观测以验证您的应用程序跟踪记录、指标和事件正在流入 Elasticsearch

使用 OpenTelemetry 对自己的应用程序插桩

本部分假定您将使用 OpenTelemetry 对自己的应用程序进行插桩。为了让您的应用程序适用于本文中所展示的部署模型,您的应用程序需要:

  1. 使用稳定的 OpenTelemetry APM 代理版本插桩
  2. 使用特定的 OpenTelemetry 环境变量完成实例化
  3. 如果使用手动插桩,某些跨度属性已正确设置
  4. (选做)向日志行添加特定元数据
  5. 将日志数据发射至 stdout 和 stderr ,以便被 Elastic Kubernetes 集成捕获到

容器环境变量

为了启用 Elastic 的开箱即用型仪 APM 表板,我们需要确保应用程序跟踪记录、指标和事件携带正确的上下文元数据。我们可以从 Kubernetes Downward API 获取此元数据,并通过 OTEL_RESOURCE_ATTRIBUTES 环境变量将其传送到应用程序内。

我们还需要设置 OTEL_EXPORTER_OTLP_ENDPOINT,以指示应用程序通过 OTLP 将其 OpenTelemetry 数据发送至 OpenTelemetry 收集器实例(我们稍后将会部署到节点的 DaemonSet 中)。

下面的 Kubernetes 容器配置片段能够在您应用程序的部署 YAML 中设置您需要应用到该应用程序的环境变量。

---
apiVersion: apps/v1
kind: Deployment
...
spec:
  ...
  template:
    ...
    spec:
      containers:
        ...
        env:
          - name: OTEL_K8S_CONTAINER_NAME
            valueFrom:
              fieldRef:
                apiVersion: v1
                fieldPath: "metadata.labels['app.kubernetes.io/component']"
          - name: OTEL_K8S_NODE_IP
            valueFrom:
              fieldRef:
                fieldPath: status.hostIP
          - name: OTEL_K8S_POD_UID
            valueFrom:
              fieldRef:
                apiVersion: v1
                fieldPath: metadata.uid
          - name: OTEL_K8S_POD_IP
            valueFrom:
              fieldRef:
                apiVersion: v1
                fieldPath: status.podIP
          - name: OTEL_SERVICE_NAME
            valueFrom:
              fieldRef:
                apiVersion: v1
                fieldPath: "metadata.labels['app.kubernetes.io/component']"
          - name: OTEL_K8S_NAMESPACE
            valueFrom:
              fieldRef:
                apiVersion: v1
                fieldPath: metadata.namespace
          - name: OTEL_K8S_NODE_NAME
            valueFrom:
              fieldRef:
                apiVersion: v1
                fieldPath: spec.nodeName
          - name: OTEL_K8S_POD_NAME
            valueFrom:
              fieldRef:
                apiVersion: v1
                fieldPath: metadata.name
          - name: OTEL_EXPORTER_OTLP_ENDPOINT
            value: '$(OTEL_K8S_NODE_IP):4317'
          - name: OTEL_RESOURCE_ATTRIBUTES
            value: service.name=$(OTEL_SERVICE_NAME),k8s.namespace.name=$(OTEL_K8S_NAMESPACE),k8s.node.name=$(OTEL_K8S_NODE_NAME),k8s.pod.name=$(OTEL_K8S_POD_NAME),k8s.pod.uid=$(OTEL_K8S_POD_UID),k8s.pod.ip=$(OTEL_K8S_POD_IP),k8s.container.name=$(OTEL_K8S_CONTAINER_NAME),k8s.container.restart_count=0

您可能会纳闷我们为什么将 k8s.container.restart_count=0 设置为一个资源属性。对当前的 OpenTelemetry 收集器 k8sattrribute 处理器而言,必须有此提示,才能(通过 k8s.container.name)将容器匹配至容器运行实例,从而获取 container.id。设置 k8s.container.restart_count=0 是一项简化:跟踪在一个 pod 中特定容器被 Kubernetes 重新启动了多少次,并通过某种方式将该信息纳入到环境变量中,是一个很复杂的过程。在典型情景下,容器通常在给定 pod 生命周期内仅会启动一次。然而,如果容器被 pod 重新启动,则此简化将会失效。

跨度属性

Elastic APM 需要显式设置特定跨度参数,以正确地对跨度数据进行特征化、分类和可视化。大部分 OpenTelemetry APM 自动插桩库会为您设置这些字段。但是,如果手动对自己的应用程序插桩,则您需要显式设定下列属性:SpanKind:为了让 Elastic APM 能够正确地对跨度进行分类,它需要知道 SpanKind(例如 INTERNAL、SERVER、CLIENT)。大部分 OpenTelemetry APM 自动插桩库会为您设置该字段。然而,如果您对您的应用程序手动插桩,则对于接受 RPC 或 REST 调用的跨度,您必须将 SpanKind 设置为 SERVER;对于启动 RPC 或 REST 或数据库调用的跨度,必须将 SpanKind 设置为 CLIENT;对于服务内部的函数调用,必须将 SpanKind 设置为 INTERNAL(默认)。例如,在 JAVA 中,对于接收 gRPC 调用的跨度,您需要使用类似下面的代码将 SpanKind 设置为 SERVER:

Span span = tracer.spanBuilder("testsystem.TestService/TestFunction").setSpanKind(SpanKind.SERVER).startSpan();

RpcSystem / DbSystem:为了让 Elastic APM 正确地对跨度进行分类,它需要知道该跨度代表的是 RPC 事务还是数据库事务,此外还需要知道使用的是什么类型的 RPC 或 DB 系统。大部分 OpenTelemetry APM 自动插桩库会为您设置该字段。如果对自己的应用程序手动插桩,您应该设置 RpcSystem 或 DbSystem 跨度属性。例如,在 Rust 中,对于接收 gRPC 调用的跨度,您需要使用类似下面的代码将 RpcSystem 设置为 'grpc':

span.set_attribute(semcov::trace::RPC_SYSTEM.string("grpc"));

NetPeerHost & NetPeerPort:为了让 Elastic APM 能够正确地对服务之间的依赖关系进行映射,当 SpanKind 被设置为 CLIENT(即输出 gRPC 或数据库调用)时,必须设置 NetPeerName 和 NetPeerPort 跨度属性以指示调用的预期接收者。部分 OpenTelemetry APM 自动插桩库会为您设置该字段。如果手动对自己的应用程序插桩,则您必须显式设置这些属性。例如,在 JavaScript 中,对于发送 gRPC 调用的跨度,您需要使用类似下面的代码对 NetPeerName 和 NetPeerPort 进行设置:

// this => grpcJs.Client, this.getChannel().getTarget() => "dns:elastic-otel-productcatalogservice:8080"
const URI_REGEX = /(?:([A-Za-z0-9+.-]+):(?:\/\/)?)?(?<name>[A-Za-z0-9+.-]+):(?<port>[0-9+.-]+)$/;
const parsedUri = URI_REGEX.exec(this.getChannel().getTarget());        
if (parsedUri != null && parsedUri.groups != null) {
    span.setAttribute(SemanticAttributes.NET_PEER_NAME, parsedUri.groups['name']);
    span.setAttribute(SemanticAttributes.NET_PEER_PORT, parseInt(parsedUri.groups['port']));
}

日志属性

Elastic APM 能够将特定日志行关联至具体跟踪记录。为了启用这一功能,从您的应用程序发出的日志行需要加上 span.id 和 trace.id 键值对标签(如适用)。部分 Elastic APM 代理(例如 Java 代理)会自动修改您的日志模板来添加这一上下文元数据。

将 OpenTelemetry 收集器部署到 DaemonSet

如果您使用的是 OpenTelemetry 演示和我们的修改版 OpenTelemetry Helm 图表,则已经为您在每个节点上的 DaemonSet 中安装了经过优化的 OpenTelemetry 收集器。

如果您在对自己的应用程序插桩,则可以基于下列 YAML 来配置 OpenTelemetry 收集器并将其部署到您集群内节点上的 DaemonSet 中。示例配置(使用 ConfigMap 进行部署)会在 TCP 端口 4317 (grpc) 和 4318 (http) 上,从应用程序采集 OTLP 跟踪记录、指标和事件数据。由于收集器是在 DaemonSet 中运行,所以对于在同一节点上运行的其他 pod ,该端口通过该节点的 IP 是可以访问的。输入 OTLP 数据会通过 k8sattributes 处理器运行以添加 container.id。我们会丢弃任何输入日志数据(回想一下,我们通过 Elastic Kubernetes 集成获取此数据),并将跟踪记录、事件和指标传送至也在 DaemonSet 中运行的 Elastic APM 集成。Elastic APM 集成会聆听端口 8200,该端口也可通过节点的 IP 访问(作为从 Kubernetes Downward API 获取的环境变量传送至此处)。

1. 下载该示例 OpenTelemetry 收集器部署 YAML

curl -L -O https://raw.githubusercontent.com/ty-elastic/elastic-otel-k8s/main/collector/otel-collector.yaml 

2. 针对您的部署进行相应编辑

3. 将其应用至您的 Kubernetes 集群

kubectl apply -f otel-collector.yaml 

验证和可观测性

在这一部分,我们将会验证上面所配置的可观测性和安全性数据正按照预期进入我们的 Elasticsearch 集群。本练习还会为您简要概述一下 Elasticsearch 中可用的一些开箱即用型可观测性和安全仪表板。我们鼓励您将此练习作为一个跳板来探索我们丰富的可视化和分析产品。

APM 服务地图

APM 服务地图会提供有关您的服务以及服务之间彼此关系的可视化。某些类型的服务错误和告警会在此地图中突出显示(如适用)。从这一地图中,您可以进行透视,前往使用 OpenTelemetry(或 Elastic 的自有 APM 代理)插桩的任何服务的详细视图。

  1. 在 Kibana 的导航侧边栏中,选择 [ 可观测性 ] 下的 [ APM ]
  2. 选择 [ APM ] 下的 [ 服务地图 ]
Video thumbnail

APM 服务

APM 服务视图提供了特定服务的概览。从该仪表板中,您可以轻松向下钻取到跟踪记录、日志和相关基础架构指标。传统上,要确定这些数据源之间的原始关联性,需要跨多个孤立的可观测性平台对时间戳和服务标识符进行翻译。通过 Elastic 和 OpenTelemetry,这一关联性会自动建立,让分析师、运维人员以及开发人员专注于根本原因分析,而不再是可观测性工具之间的细微差异。

  1. 在 Kibana 的导航侧边栏中,选择 [ 可观测性 ] 下的 [ APM ]
  2. 选择 [ APM ] 下的 [ 服务地图 ]
  3. 在地图上右键点击任何服务
  4. 选择 [ 服务详情 ]
Video thumbnail

从同一视图中,您可以轻松进行透视,检查将您的用户连接至您的服务以及将服务彼此相连的事务和跨度。

  1. 从标头中选择 [ 事务 ]
  2. 从 [ 事务 ] 子版块中选择感兴趣的事务
Video thumbnail

Kubernetes 集群指标

Elastic Kubernetes 仪表板能够提供有关您 Kubernetes 集群运维状况的概览和详细视图。从这里,您可以跨集群、节点、pod、DaemonSet、服务等监测指标。

  1. 在 Kibana 的导航侧边栏中,选择 [ 分析 ] 下的 [ 仪表板 ]
  2. 从 [ 标签 ] 菜单中选择 [ Kubernetes ]
  3. 选择 [ 集群概览 ] 仪表板
Video thumbnail

Kubernetes 进程监测

Elastic Defend 集成能够跨您的 Kubernetes 资源提供以安全为中心的可观测性。我们的 Kubernetes 安全仪表板可让分析师准确了解在您的 Kubernetes 节点上执行了哪些进程,什么时候执行的,使用的是哪些运行时参数,以及是在哪个账户下面。

  1. 在 Kibana 的导航侧边栏中,选择 [ 安全 ] 下的 [ 仪表板 ]
  2. 选择 [ Kubernetes ]

Video thumbnail

Kubernetes 安全态势管理

Kubernetes 安全态势管理 (KSPM) 仪表板会提供自动化分析和补救建议,涵盖有关安全部署的全部 Kubernetes 最佳实践。对于开发人员和 DevOps 人员而言,该仪表板可以在潜在配置问题成为影响生产的问题之前,提供有关这些问题的宝贵通知。

  1. 在 Kibana 的导航侧边栏中,选择 [ 安全 ] 下的 [ 仪表板 ]
  2. 选择 [ 云态势 ]
Video thumbnail

网络流量分析

网络数据包捕获集成能够让您深入挖掘进出您的 Kubernetes 节点的 IP 流量,查找表现异常的服务或者安全漏洞。

  1. 在 Kibana 的导航侧边栏中,选择 [ 安全 ] 下的 [ 探索 ]
  2. 选择 [ 网络 ]

Video thumbnail

Elastic:为 Kubernetes 构建的可观测性和安全性!

Kubernetes 对很多企业而言代表了绿地应用程序部署模型。绿地部署模型要求针对可观测性和安全性采用同样眼界开阔、现代且整体性的方法。如此处所示,Elastic 在业内具有独特优势,能够为 Kubernetes 提供全集成、全功能、全保真的可观测性和安全性。

感兴趣?联系我们的售前团队,即可开始使用 Elastic 进行构建!