

# 在 Kubernetes 上启用应用程序
<a name="CloudWatch-Application-Signals-Enable-KubernetesMain"></a>

遵照本部分的自定义设置步骤，在 Kubernetes 上启用 CloudWatch Application Signals。

对于在 Kubernetes 上运行的应用程序，您可以自行安装并配置 CloudWatch 代理和 AWS Distro for OpenTelemetry。在这些启用了自定义 Application Signals 设置的架构上，Application Signals 不会自动发现您的服务的名称或运行这些服务的主机或集群。您必须在自定义设置期间指定这些名称，而您指定的名称就是显示在 Application Signals 控制面板上的名称。

**要求**
+ 您拥有启用 Application Signals 的 Kubernetes 集群的管理员权限。
+ 您必须在运行 Kubernetes 集群的环境中安装 AWS CLI。有关安装 AWS CLI 的更多信息，请参阅[安装或更新 AWS CLI 的最新版本](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。
+ 您已在本地终端上安装了 kubectl 和 helm。有关更多信息，请参阅 [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) 和 [Helm](https://helm.sh/) 文档。

## 步骤 1：在账户中启用 Application Signals
<a name="CloudWatch-Application-Signals-Kubernetes"></a>

必须先在账户中启用 Application Signals。如果还没有，请参阅[在账户中启用 Application Signals](CloudWatch-Application-Signals-Enable.md)。

## 步骤 2：在集群中安装 CloudWatch 代理 operator
<a name="Application-Signals-Enable-Kubernetes-agent"></a>

安装 CloudWatch 代理 operator 会将 operator、CloudWatch 代理和其他自动检测工具安装到您的集群中。为此，请输入以下命令。将 *\$1REGION* 替换为您的 AWS 区域。将 *\$1YOUR\$1CLUSTER\$1NAME* 替换为要在 Application Signals 控制面板中为集群显示的名称。

```
helm repo add aws-observability https://aws-observability.github.io/helm-charts
helm install amazon-cloudwatch-operator aws-observability/amazon-cloudwatch-observability \
--namespace amazon-cloudwatch --create-namespace \
--set region=$REGION \
--set clusterName=$YOUR_CLUSTER_NAME
```

有关更多信息，请参阅 GitHub 上的 [amazon-cloudwatch-observability](https://github.com/aws-observability/helm-charts/tree/main/charts/amazon-cloudwatch-observability)。

## 步骤 3：为 Kubernetes 集群设置 AWS 凭证
<a name="Application-Signals-Enable-Kubernetes-credentials"></a>

**重要**  
如果在 Amazon EC2 上托管您的 Kubernetes 集群，则可以跳过此部分并继续 [步骤 4：添加注释](#Application-Signals-Enable-Kubernetes-annotations)。

如果在本地托管您的 Kubernetes 集群，则必须按照本节中的说明向您的 Kubernetes 环境添加 AWS 凭证。

**设置本地 Kubernetes 集群的权限**

1. 创建用于向本地主机提供权限的 IAM 用户：

   1. 通过 [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/) 打开 IAM 控制台。

   1. 依次选择**用户**、**创建用户**。

   1. 在**用户详情**中，为**用户名**输入新 IAM 用户的名称。这是 AWS 的登录名，将用于对您的主机进行身份验证。然后选择**下一个**

   1. 在**设置权限**页面的**权限选项**下，选择**直接附加策略**。

   1. 从**权限策略**列表中，选择要添加到您的用户的 **CloudWatchAgentServerPolicy** 策略。然后选择**下一步**。

   1. 在**查看并创建**页面上，确保您对用户名满意，并且 **CloudWatchAgentServerPolicy** 策略位于**权限摘要**中。

   1. 选择 **Create user**。

1. 创建和检索您的 AWS 访问密钥和秘密密钥：

   1. 在 IAM 控制台的导航窗格中，选择**用户**，然后选择您在上一步中所创建用户的用户名。

   1.  在用户的页面上，选择**安全凭证**选项卡。然后，在**访问密钥**部分，选择**创建访问密钥**。

   1. 对于**创建访问密钥步骤 1**，选择**命令行界面 (CLI)**。

   1. 对于**创建访问密钥步骤 2**，（可选）输入标记，然后选择**下一步**。

   1. 对于**创建访问密钥步骤 3**，选择**下载.csv 文件**以保存包含您的 IAM 用户访问密钥和秘密访问密钥的 .csv 文件。您在后续步骤中需要此信息。

   1. 选择**完成**。

1. 通过输入以下命令，在本地主机中配置 AWS 凭证。将 *ACCESS\$1KEY\$1ID* 和 *SECRET\$1ACCESS\$1ID* 替换为您在上一步中下载的 .csv 文件中新生成的访问密钥和秘密访问密钥。默认情况下，凭证文件保存在 `/home/user/.aws/credentials.` 中

   ```
   $ aws configure --profile AmazonCloudWatchAgent
   AWS Access Key ID [None]: ACCESS_KEY_ID
   AWS Secret Access Key [None]: SECRET_ACCESS_ID
   Default region name [None]: MY_REGION
   Default output format [None]: json
   ```

1. 使用 Helm 图表编辑 CloudWatch 代理安装的自定义资源，以添加新创建的 AWS 凭证密钥。

   ```
   kubectl edit amazoncloudwatchagent cloudwatch-agent -n amazon-cloudwatch
   ```

1. 当您的文件编辑器处于打开状态时，通过将以下配置添加到部署顶部，将 AWS 凭证挂载到 CloudWatch 代理容器中。将路径 `/home/user/.aws/credentials` 替换为本地 AWS 凭证文件的位置。

   ```
   apiVersion: cloudwatch.aws.amazon.com/v1alpha1
   kind: AmazonCloudWatchAgent
   metadata:
     name: cloudwatch-agent
     namespace: amazon-cloudwatch
   spec:
     volumeMounts:
     - mountPath: /rootfs
       volumeMounts:
       - name: aws-credentials
         mountPath: /root/.aws
         readOnly: true
       volumes:
       - hostPath:
         path: /home/user/.aws/credentials
       name: aws-credentials
   ---
   ```

## 步骤 4：添加注释
<a name="Application-Signals-Enable-Kubernetes-annotations"></a>

**注意**  
要为使用 ESM 的 Node.js 应用程序启用 Application Signals，改为跳过本节中的步骤并参阅 [设置采用 ESM 模块格式的 Node.js 应用程序](#Kubernetes-NodeJs-ESM)。

下一步是通过向您的 Kubernetes [工作负载](https://kubernetes.io/docs/concepts/workloads/)或[命名空间](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)添加特定于语言的[注释](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)，为 CloudWatch Application Signals 检测您的应用程序。此注释会自动检测应用程序以向 Application Signals 发送指标、跟踪和日志。

**添加 Application Signals 的注释**

1. 您有两种注释选项：
   + **为工作负载添加注释**会自动检测集群中的单个工作负载。
   + **注释命名空间**会自动检测所选命名空间中部署的所有工作负载。

   选择其中一个选项，然后按照相应的步骤操作。

1. 要注释单个工作负载，请输入以下命令之一。将 *\$1WORKLOAD\$1TYPE* 和 *\$1WORKLOAD\$1NAME* 替换为工作负载的值。
   + 对于 Java 工作负载：

     ```
     kubectl patch $WORKLOAD_TYPE $WORKLOAD_NAME -p '{"spec": {"template": {"metadata": {"annotations": {"instrumentation.opentelemetry.io/inject-java": "true"}}}}}'
     ```
   + 对于 Python 工作负载：

     ```
     kubectl patch $WORKLOAD_TYPE $WORKLOAD_NAME -p '{"spec": {"template": {"metadata": {"annotations": {"instrumentation.opentelemetry.io/inject-python": "true"}}}}}'
     ```

     对于 Python 应用程序，还需要额外的配置。有关更多信息，请参阅 [启用 Application Signals 后，Python 应用程序无法启动](CloudWatch-Application-Signals-Enable-Troubleshoot.md#Application-Signals-troubleshoot-starting-Python)。
   + 对于 .NET 工作负载：

     ```
     kubectl patch $WORKLOAD_TYPE $WORKLOAD_NAME -p '{"spec": {"template": {"metadata": {"annotations": {"instrumentation.opentelemetry.io/inject-dotnet": "true"}}}}}'
     ```
**注意**  
要在基于 Alpine Linux (`linux-musl-x64`) 的映像上为 .NET 工作负载启用 Application Signals，请添加以下额外注释。  

     ```
     instrumentation.opentelemetry.io/otel-dotnet-auto-runtime: "linux-musl-x64"
     ```
   + 对于 Node.js 工作负载：

     ```
     kubectl patch $WORKLOAD_TYPE $WORKLOAD_NAME -p '{"spec": {"template": {"metadata": {"annotations": {"instrumentation.opentelemetry.io/inject-nodejs": "true"}}}}}'
     ```

1. 要注释命名空间中的所有工作负载，请输入以下命令之一。将 *\$1NAMESPACE* 替换为您的命名空间的名称。

   如果命名空间同时包含 Java、Python 和 .NET 工作负载，请将所有注释都添加到命名空间。
   + 对于命名空间中的 Java 工作负载：

     ```
     kubectl annotate ns $NAMESPACE instrumentation.opentelemetry.io/inject-java=true
     ```
   + 对于命名空间中的 Python 工作负载：

     ```
     kubectl annotate ns $NAMESPACE instrumentation.opentelemetry.io/inject-python=true
     ```

     对于 Python 应用程序，还需要额外的配置。有关更多信息，请参阅 [启用 Application Signals 后，Python 应用程序无法启动](CloudWatch-Application-Signals-Enable-Troubleshoot.md#Application-Signals-troubleshoot-starting-Python)。
   + 对于命名空间中的 .NET 工作负载：

     ```
     kubectl annotate ns $NAMESPACE instrumentation.opentelemetry.io/inject-dotnet=true
     ```
   + 对于命名空间中的 Node.js 工作负载：

     ```
     kubectl annotate ns $NAMESPACE instrumentation.opentelemetry.io/inject-nodejs=true
     ```

   添加注释后，通过输入以下命令重新启动命名空间中的所有容器组（pod）：

   ```
   kubectl rollout restart
   ```

1. 完成上述步骤后，在 CloudWatch 控制台中，依次选择 **Application Signals**、**服务**。这将打开控制面板，您可以在其中查看 Application Signals 收集的数据。可能需要几分钟才会显示数据。

   有关**服务**视图的更多信息，请参阅 [使用 Application Signals 监控应用程序的运行状况](Services.md)。

### 设置采用 ESM 模块格式的 Node.js 应用程序
<a name="Kubernetes-NodeJs-ESM"></a>

我们对采用 ESM 模块格式的 Node.js 应用程序提供有限的支持。有关更多信息，请参阅 [使用 ESM 的 Node.js 的已知限制](CloudWatch-Application-Signals-supportmatrix.md#ESM-limitations)。

对于 ESM 模块格式，通过注释清单文件来启用 Application Signals 不起作用。跳过之前的程序，改为执行以下操作：

**为使用 ESM 的 Node.js 应用程序启用 Application Signals**

1. 将相关依赖项安装到您的 Node.js 应用程序中以进行自动检测：

   ```
   npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation
   npm install @opentelemetry/instrumentation@0.54.0
   ```

1. 将以下环境变量添加到应用程序的 Dockerfile 中并构建映像。

   ```
   ...
   ENV OTEL_AWS_APPLICATION_SIGNALS_ENABLED=true
   ENV OTEL_TRACES_SAMPLER_ARG='endpoint=http://cloudwatch-agent.amazon-cloudwatch:2000'
   ENV OTEL_TRACES_SAMPLER='xray'
   ENV OTEL_EXPORTER_OTLP_PROTOCOL='http/protobuf'
   ENV OTEL_EXPORTER_OTLP_TRACES_ENDPOINT='http://cloudwatch-agent.amazon-cloudwatch:4316/v1/traces'
   ENV OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT='http://cloudwatch-agent.amazon-cloudwatch:4316/v1/metrics'
   ENV OTEL_METRICS_EXPORTER='none'
   ENV OTEL_LOGS_EXPORTER='none'
   ENV NODE_OPTIONS='--import @aws/aws-distro-opentelemetry-node-autoinstrumentation/register --experimental-loader=@opentelemetry/instrumentation/hook.mjs'
   ENV OTEL_SERVICE_NAME='YOUR_SERVICE_NAME' #replace with a proper service name
   ENV OTEL_PROPAGATORS='tracecontext,baggage,b3,xray'
   ...
   
   # command to start the application
   # for example
   # CMD ["node", "index.mjs"]
   ```

1. 将环境变量 `OTEL_RESOURCE_ATTRIBUTES_POD_NAME`、`OTEL_RESOURCE_ATTRIBUTES_NODE_NAME`、`OTEL_RESOURCE_ATTRIBUTES_DEPLOYMENT_NAME`、`POD_NAMESPACE` 和 `OTEL_RESOURCE_ATTRIBUTES` 添加到应用程序的部署 yaml 文件中。例如：

   ```
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: nodejs-app
     labels:
       app: nodejs-app
   spec:
     replicas: 2
     selector:
       matchLabels:
         app: nodejs-app
     template:
       metadata:
         labels:
           app: nodejs-app
         # annotations:
         # make sure this annotation doesn't exit
         #   instrumentation.opentelemetry.io/inject-nodejs: 'true'
       spec:
         containers:
         - name: nodejs-app
           image:your-nodejs-application-image #replace it with a proper image uri
           imagePullPolicy: Always
           ports:
           - containerPort: 8000
           env:
             - name: OTEL_RESOURCE_ATTRIBUTES_POD_NAME
               valueFrom:
                 fieldRef:
                   fieldPath: metadata.name
             - name: OTEL_RESOURCE_ATTRIBUTES_NODE_NAME
               valueFrom:
                 fieldRef:
                   fieldPath: spec.nodeName
             - name: OTEL_RESOURCE_ATTRIBUTES_DEPLOYMENT_NAME
               valueFrom:
                 fieldRef:
                   fieldPath: metadata.labels['app'] # Assuming 'app' label is set to the deployment name
             - name: POD_NAMESPACE
               valueFrom:
                 fieldRef:
                   fieldPath: metadata.namespace
             - name: OTEL_RESOURCE_ATTRIBUTES
               value: "k8s.deployment.name=$(OTEL_RESOURCE_ATTRIBUTES_DEPLOYMENT_NAME),k8s.namespace.name=$(POD_NAMESPACE),k8s.node.name=$(OTEL_RESOURCE_ATTRIBUTES_NODE_NAME),k8s.pod.name=$(OTEL_RESOURCE_ATTRIBUTES_POD_NAME)"
   ```

1. 将 Node.js 应用程序部署到 Kubernetes 集群。

## （可选）第 5 步：监控应用程序运行状况
<a name="CloudWatch-Application-Signals-Monitor-Kubernetes"></a>

在 Kubernetes 上启用应用程序后，就可以监控应用程序的运行状况。有关更多信息，请参阅 [使用 Application Signals 监控应用程序的运行状况](Services.md)。