Jack ShiraziSylvain JugeAlexander Wert

如何在 Kubernetes Pod 中轻松添加应用程序监控

Elastic APM K8s Attacher 允许 Elastic APM 代理通过在部署中仅添加一个注解来自动附加到 Pod 中的应用程序

How to easily add application monitoring in Kubernetes pods

Elastic® APM K8s Attacher 允许将 Elastic APM 应用程序代理(例如,Elastic APM Java 代理)自动安装到 Kubernetes 集群中运行的应用程序。 该机制使用一个 mutating webhook,这是一个标准的 Kubernetes 组件,但您无需了解所有详细信息即可使用 Attacher。 本质上,您可以安装 Attacher,在任何要监控应用程序的 Kubernetes 部署中添加一个注解,就这么简单!

在本博客中,我们将从头开始,使用 Java 应用程序完整地演示一个示例。 除了 Java 代码和使用 JVM 来运行应用程序之外,其他所有步骤对于 Attacher 支持的其他语言都是相同的。

前提条件

本演练假设系统上已安装以下组件:JDK 17、Docker、Kubernetes 和 Helm。

示例应用程序

虽然下面显示的应用程序是一个 Java 应用程序,但它很容易用任何语言实现,因为它只是一个简单的循环,每 2 秒调用一次方法链 methodA->methodB->methodC->methodD,其中 methodC 休眠 10 毫秒,methodD 休眠 200 毫秒。选择此应用程序只是为了能够在 Elastic APM UI 中清晰地显示正在监控该应用程序。

Java 应用程序的完整代码如下所示

package test;

public class Testing implements Runnable {

  public static void main(String[] args) {
    new Thread(new Testing()).start();
  }

  public void run()
  {
    while(true) {
      try {Thread.sleep(2000);} catch (InterruptedException e) {}
      methodA();
    }
  }

  public void methodA() {methodB();}

  public void methodB() {methodC();}

  public void methodC() {
    System.out.println("methodC executed");
    try {Thread.sleep(10);} catch (InterruptedException e) {}
    methodD();
  }

  public void methodD() {
    System.out.println("methodD executed");
    try {Thread.sleep(200);} catch (InterruptedException e) {}
  }
}

我们为您创建了一个包含该简单 Java 应用程序的 Docker 镜像,可以从以下 Docker 仓库拉取

docker.elastic.co/demos/apm/k8s-webhook-test

部署 Pod

首先,我们需要一个部署配置。我们将配置文件命名为 webhook-test.yaml,其内容非常简单,只需拉取镜像并在默认命名空间中将其作为名为 webhook-test 的 Pod 和容器运行

apiVersion: v1
kind: Pod
metadata:
  name: webhook-test
  labels:
    app: webhook-test
spec:
  containers:
    - image: docker.elastic.co/demos/apm/k8s-webhook-test
      imagePullPolicy: Always
      name: webhook-test

可以使用 kubectl 正常部署

kubectl apply -f webhook-test.yaml

结果正如预期的那样

$ kubectl get pods
NAME           READY   STATUS    RESTARTS   AGE
webhook-test   1/1     Running   0          10s

$ kubectl logs webhook-test
methodC executed
methodD executed
methodC executed
methodD executed

到目前为止,这只是设置一个标准的 Kubernetes 应用程序,没有 APM 监控。现在我们来做有趣的部分:添加自动检测。

安装 Elastic APM K8s Attacher

第一步是安装 Elastic APM K8s Attacher。这只需要对集群执行一次,安装后它始终可用。安装之前,我们将定义监控数据发送到的位置。稍后您会看到,我们可以随时决定或更改此设置。现在,我们将指定我们自己的 Elastic APM 服务器,其地址为 https://myserver.somecloud:443 — 我们还有一个用于授权到该 Elastic APM 服务器的密钥令牌,其值为 MY_SECRET_TOKEN。(如果要设置快速测试 Elastic APM 服务器,可以在 https://cloud.elastic.co/ 上进行)。

为应用程序设置了两个额外的环境变量,通常不需要,但在稍后演练结束时查看生成的 UI 内容时会有帮助(当自动安装代理时,这两个变量会告诉代理在 UI 中为该应用程序提供什么名称以及要跟踪的方法)。现在,我们只需定义自定义 yaml 文件来保存这些变量。安装时,自定义 yaml 将合并到 Attacher 的 yaml 中

apm:
  secret_token: MY_SECRET_TOKEN
  namespaces:
    - default
webhookConfig:
  agents:
    java:
      environment:
        ELASTIC_APM_SERVER_URL: "https://myserver.somecloud:443"
        ELASTIC_APM_TRACE_METHODS: "test.Testing#methodB"
        ELASTIC_APM_SERVICE_NAME: "webhook-test"

该 custom.yaml 文件是我们安装 attacher 所需的全部内容(请注意,我们目前仅为代理自动安装指定了默认命名空间 — 稍后您会看到,可以轻松更改此设置)。接下来,我们将 Elastic 图表添加到 helm 中 — 这只需要执行一次,然后所有 Elastic 图表都可用于 helm。这是常用的 helm add repo 命令,具体为

helm repo add elastic https://helm.elastic.co

现在,Elastic 图表可用于安装(helm search repo 会向您显示所有可用的图表)。我们将使用 “elastic-webhook” 作为安装名称,从而生成以下安装命令

helm install elastic-webhook elastic/apm-attacher --namespace=elastic-apm --create-namespace --values custom.yaml

就这样,我们现在已经安装了 Elastic APM K8s Attacher,并将其设置为将数据发送到 custom.yaml 文件中定义的 APM 服务器!(如果需要,可以使用 helm list -A 确认安装情况。)

自动安装 Java 代理

Elastic APM K8s Attacher 已安装,但它不会将 APM 应用程序代理自动安装到每个 Pod 中 — 这可能会导致问题!相反,Attacher 特意限制为仅将代理自动安装到 a) custom.yaml 中列出的命名空间,以及 b) 这些命名空间中具有特定注解 “co.elastic.apm/attach” 的部署中。

所以现在,重启我们上面创建的 webhook-test pod 对 pod 不会有任何不同的影响,因为它尚未设置为被监控。我们需要做的是添加注解。具体来说,我们需要使用随 Attacher 安装的默认代理配置“java”来添加注解,该配置用于 Java 代理(稍后我们将看到如何更改该代理配置——默认配置安装最新的代理版本,并且对该版本保留其他所有默认设置)。因此,将该注解添加到 webhook-test yaml 中,我们就得到了新的 yaml 文件内容(额外的配置标记为 (1))

apiVersion: v1
kind: Pod
metadata:
  name: webhook-test
  annotations: #(1)
    co.elastic.apm/attach: java #(1)
  labels:
    app: webhook-test
spec:
  containers:
    - image: docker.elastic.co/demos/apm/k8s-webhook-test
      imagePullPolicy: Always
      name: webhook-test

应用此更改后,我们的应用程序现在受到监控

$ kubectl delete -f webhook-test.yaml
pod "webhook-test" deleted
$ kubectl apply -f webhook-test.yaml
pod/webhook-test created
$ kubectl logs webhook-test
… StartupInfo - Starting Elastic APM 1.45.0 …

由于代理现在正在向我们的 APM 服务器提供数据,我们现在可以在 UI 中看到它

请注意,由于 custom.yaml 中 ELASTIC_APM_TRACE_METHODS 环境变量设置为 test.Testing#methodB,代理将 Testing.methodB 方法识别为跟踪根——这告诉代理专门跟踪该方法。该方法所花费的时间将在 UI 中显示每次调用的时间,但我们目前看不到子方法...。在下一节中,我们将看到自定义 Attacher 是多么容易,并且在这样做时,我们将看到有关应用程序中执行的方法链的更多详细信息。

自定义代理

在您的系统中,您可能会有开发、测试和生产环境。您需要指定要使用的代理版本,而不是仅仅拉取最新的版本,您可能希望为某些应用程序或实例启用调试,并且您可能希望将特定选项设置为特定值。这听起来像是一项艰巨的任务,但 attacher 可以让您以一种非常简单的方式启用这些类型的更改。在本节中,我们将添加一个指定所有这些更改的配置,我们可以看到配置和启用它是多么容易。

我们从上面定义的 custom.yaml 文件开始。该文件将被合并到 Attacher 中。添加一个包含上一段中列出的所有项的新配置很简单——尽管首先我们需要为我们的新配置决定一个名称。我们这里称之为“java-interesting”。完整的新的 custom.yaml 如下(第一部分与之前相同,新配置只是简单地附加在后面)

apm:
  secret_token: MY_SECRET_TOKEN
  namespaces:
    - default
webhookConfig:
  agents:
    java:
      environment:
        ELASTIC_APM_SERVER_URL: "https://myserver.somecloud:443"
        ELASTIC_APM_TRACE_METHODS: "test.Testing#methodB"
        ELASTIC_APM_SERVICE_NAME: "webhook-test"
    java-interesting:
      image: docker.elastic.co/observability/apm-agent-java:1.52.1
      artifact: "/usr/agent/elastic-apm-agent.jar"
      environment:
        ELASTIC_APM_SERVER_URL: "https://myserver.somecloud:443"
        ELASTIC_APM_TRACE_METHODS: "test.Testing#methodB"
        ELASTIC_APM_SERVICE_NAME: "webhook-test"
        ELASTIC_APM_ENVIRONMENT: "testing"
        ELASTIC_APM_LOG_LEVEL: "debug"
        ELASTIC_APM_PROFILING_INFERRED_SPANS_ENABLED: "true"
        JAVA_TOOL_OPTIONS: "-javaagent:/elastic/apm/agent/elastic-apm-agent.jar"

分解额外的配置,我们有

  • 新配置的名称 java-interesting

  • APM Java 代理镜像 docker.elastic.co/observability/apm-agent-java

    • 使用特定的 1.43.0 版本而不是 latest
  • 我们需要指定代理 jar 的位置(attacher 将其放在这里)

    • artifact: "/usr/agent/elastic-apm-agent.jar"
  • 然后是环境变量

  • 与之前相同的 ELASTIC_APM_SERVER_URL

  • ELASTIC_APM_ENVIRONMENT 设置为 testing,在 UI 中查看时很有用

  • ELASTIC_APM_LOG_LEVEL 设置为 debug,以获得更详细的代理输出

  • ELASTIC_APM_PROFILING_INFERRED_SPANS_ENABLED 启用此设置(设置为 true)将为我们提供有关应用程序中执行的方法链的更多有趣信息

  • 最后,我们需要将 JAVA_TOOL_OPTIONS 设置为启用启动代理 "-javaagent:/elastic/apm/agent/elastic-apm-agent.jar" ——这基本上是 attacher 如何自动附加 Java 代理的

有关配置选项的更多配置和详细信息,请参阅 此处,了解 Java 代理,以及 其他语言代理也可用。

使用新配置跟踪应用程序

最后,我们只需要使用更改后的 custom.yaml 升级 attacher

helm upgrade elastic-webhook elastic/apm-attacher --namespace=elastic-apm --create-namespace --values custom.yaml

这与原始安装的命令相同,但现在使用的是 upgrade。就是这样——将配置添加到 custom.yaml 并升级 attacher,就完成了!很简单。

当然,我们仍然需要在应用程序上使用新配置。在这种情况下,我们将编辑现有的 webhook-test.yaml 文件,将 java 替换为 java-interesting,因此注解行现在是

co.elastic.apm/attach: java-interesting

应用新的 pod 配置并重启 pod,您可以看到日志现在包含调试输出

$ kubectl delete -f webhook-test.yaml
pod "webhook-test" deleted
$ kubectl apply -f webhook-test.yaml
pod/webhook-test created
$ kubectl logs webhook-test
… StartupInfo - Starting Elastic APM 1.44.0 …
… DEBUG co.elastic.apm.agent. …
… DEBUG co.elastic.apm.agent. …

更有趣的是 UI。现在启用了推断跨度,完整的方法链是可见的。

这提供了 methodB 的详细信息(它花费了 211 毫秒,因为它调用了 methodC - 10 毫秒 - 而 methodC 又调用了 methodD - 200 毫秒)。methodC 和 methodD 的时间是推断出来的,而不是记录下来的(推断出来的而不是跟踪的——如果您需要准确的时间,您可以将这些方法添加到 trace_methods 并让它们也被跟踪)。

关于 ECK 操作符的说明

Kubernetes 上的 Elastic Cloud 操作符允许您在 Kubernetes 上安装和管理许多其他 Elastic 组件。在本文发布时,Elastic APM K8s Attacher 是一个单独的组件,这些管理机制之间没有冲突——它们应用于不同的组件并且彼此独立。

自己尝试一下!

此演练很容易在您的系统上重复进行,您可以通过将示例应用程序替换为您自己的应用程序以及 Docker 注册表替换为您使用的注册表来使其更有用。

了解有关使用 Kubernetes 和 Elastic Observability 进行实时监控的更多信息.

本文中描述的任何特性或功能的发布和时间安排仍由 Elastic 自行决定。任何目前不可用的特性或功能可能不会按时交付或根本不会交付。

分享这篇文章