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

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

阅读时间:12分钟
How to easily add application monitoring in Kubernetes pods

Elastic® APM K8s Attacher 允许自动安装 Elastic APM 应用程序代理(例如,Elastic APM Java 代理)到 Kubernetes 集群中运行的应用程序。该机制使用变异 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

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

安装 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 文件来保存这些变量。

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"

自定义 yaml 文件是我们安装 attacher 所需的一切(请注意,我们目前只为代理自动安装指定了默认命名空间——这可以很容易地更改,正如您稍后将看到的)。接下来,我们将 Elastic charts 添加到 helm——这只需执行一次,然后所有 Elastic charts 都可用于 helm。这是通常的 helm add repo 命令,具体如下:

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

现在 Elastic charts 可用于安装(helm search repo 将显示所有可用的 charts)。我们将使用“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 中看到它。

请注意,代理将 Testing.methodB 方法标识为跟踪根,因为 ELASTIC_APM_TRACE_METHODS 环境变量在 custom.yaml 中设置为 test.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.0
      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 而不是最新版本
  • 我们需要指定代理 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”——这从根本上来说就是连接器自动连接 Java 代理的方式

更多配置和有关配置选项的详细信息,Java 代理的配置信息在此处,并且还提供其他语言的代理

使用新的配置跟踪应用程序

最后,我们只需要使用更改后的 custom.yaml 升级连接器。

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

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

当然,我们仍然需要在应用程序上使用新的配置。在本例中,我们将编辑现有的 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 运算符的说明

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

自己试试!

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

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

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