

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 可观察性
<a name="cost-opt-observability"></a>

## 简介
<a name="_introduction"></a>

可观测性工具可帮助您高效检测、修复和调查您的工作负载。随着您使用EKS的增加，遥测数据的成本自然会增加。有时，要平衡运营需求和衡量对业务至关重要的因素并控制可观察性成本，可能是一项艰巨的任务。本指南重点介绍可观测性的三个支柱的成本优化策略：日志、指标和跟踪。这些最佳实践中的每一种都可以独立应用，以适应组织的优化目标。

## 日志记录
<a name="_logging"></a>

日志在监控集群中的应用程序并对其进行故障排除方面起着至关重要的作用。有几种策略可以用来优化日志成本。下面列出的最佳实践策略包括检查您的日志保留策略以对日志数据的保留时间实施精细控制，根据重要性将日志数据发送到不同的存储选项，以及利用日志筛选来缩小存储的日志消息的类型。高效管理日志遥测可以为您的环境节省成本。

## EKS 控制飞机
<a name="_eks_control_plane"></a>

### 优化您的控制平面日志
<a name="_optimize_your_control_plane_logs"></a>

[Kubernetes 控制平面是一组用于管理集群[的组件](https://kubernetes.io/docs/concepts/overview/components/#control-plane-components)，这些组件将不同类型的信息作为日志流发送到 Amazon 中的日志组。 CloudWatch](https://aws.amazon.com/cloudwatch/)虽然启用所有控制平面日志类型有好处，但您应该了解每个日志中的信息以及存储所有日志遥测数据的相关成本。对于从您的集群发送到 Ama CloudWatch zon [CloudWatch Logs 的日志，您需要支付标准日志数据摄取和存储费用](https://aws.amazon.com/cloudwatch/pricing/)。在启用它们之前，请评估是否需要每个日志流。

例如，在非生产集群中，有选择地启用特定的日志类型，例如 api 服务器日志，仅用于分析，然后停用。但是对于生产集群，您可能无法重现事件，并且解决问题需要更多的日志信息，则可以启用所有日志类型。更多控制平面成本优化的实施细节请参见这篇[博客](https://aws.amazon.com/blogs/containers/understanding-and-cost-optimizing-amazon-eks-control-plane-logs/)文章。

#### 将日志流式传输到 S3
<a name="_stream_logs_to_s3"></a>

另一种成本优化最佳实践是通过 CloudWatch 日志订阅将控制平面日志流式传输到 S3。利用 CloudWatch 日志[订阅](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Subscriptions.html)，您可以有选择地将日志转发到 S3，与无限期保留日志相比，S3 提供了更具成本效益的长期存储。 CloudWatch例如，对于生产集群，您可以创建一个关键日志组，并利用订阅在 15 天后将这些日志流式传输到 S3。这将确保您可以快速访问日志进行分析，还可以通过将日志移动到更具成本效益的存储空间来节省成本。

**重要**  
自 2023 年 9 月 5 日起，EKS 日志在 Amazon 日志中被归类为销售日志。 CloudWatch Vended Logs 是 AWS 服务代表客户在本地发布的特定 AWS 服务日志，按批量折扣定价提供。请访问 [Amazon CloudWatch 定价页面](https://aws.amazon.com/cloudwatch/pricing/)，了解有关 Vended Logs 定价的更多信息。

## EKS 数据平面
<a name="_eks_data_plane"></a>

### 日志保留
<a name="_log_retention"></a>

Amazon CloudWatch 的默认保留政策是无限期保留日志且永不过期，这会产生适用于您的 AWS 地区的存储成本。为了降低存储成本，您可以根据工作负载要求为每个日志组自定义保留策略。

在开发环境中，可能不需要很长的保留期。但是在生产环境中，您可以设置更长的保留期策略以满足故障排除、合规性和容量规划要求。例如，如果您在假日旺季运行电子商务应用程序，则系统负载较重，并且可能会出现可能无法立即注意到的问题，则需要设置更长的日志保留时间，以便进行详细的故障排除和事件后分析。

[您可以在 AWS CloudWatch 控制台或 AW [S API](https://docs.aws.amazon.com/cli/latest/reference/logs/put-retention-policy.html) 中根据每个日志组将保留期配置](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html#SettingLogRetention)为 1 天到 10 年不等。灵活的保留期可以节省日志存储成本，同时还可以维护关键日志。

### 日志存储选项
<a name="_log_storage_options"></a>

存储是可观测性成本的重要驱动因素，因此优化日志存储策略至关重要。您的策略应与您的工作负载需求保持一致，同时保持性能和可扩展性。降低存储日志成本的一种策略是利用 AWS S3 存储桶及其不同的存储层。

#### 将日志直接转发到 S3
<a name="_forward_logs_directly_to_s3"></a>

考虑将不太重要的日志（例如开发环境）直接转发到 S3 而不是 Cloudwatch。这可能会对日志存储成本产生直接影响。一种选择是使用 Fluentbit 将日志直接转发到 S3。您可以在 “ FluentBit 传输容器日志以进行保留的目的地” 一`[OUTPUT]`节中对此进行定义。[在此处](https://docs.fluentbit.io/manual/pipeline/outputs/s3#worker-support)查看其他配置参数。

```
[OUTPUT]
        Name eks_to_s3
        Match application.*
        bucket $S3_BUCKET name
        region us-east-2
        store_dir /var/log/fluentbit
        total_file_size 30M
        upload_timeout 3m
```

#### 将日志转发到 CloudWatch 仅用于短期分析
<a name="_forward_logs_to_cloudwatch_only_for_short_term_analysis"></a>

对于更重要的日志，例如可能需要对数据进行即时分析的生产环境，可以考虑将日志转发到 CloudWatch。您可以在 “ FluentBit 传输容器日志以进行保留的目的地” 一`[OUTPUT]`节中对此进行定义。[在此处](https://docs.fluentbit.io/manual/pipeline/outputs/cloudwatch)查看其他配置参数。

```
[OUTPUT]
        Name eks_to_cloudwatch_logs
        Match application.*
        region us-east-2
        log_group_name fluent-bit-cloudwatch
        log_stream_prefix from-fluent-bit-
        auto_create_group On
```

但是，这不会立即影响您的成本节约。为了节省更多费用，您必须将这些日志导出到 Amazon S3。

#### 从以下地址导出到亚马逊 S3 CloudWatch
<a name="_export_to_amazon_s3_from_cloudwatch"></a>

为了长期存储亚马逊 CloudWatch 日志，我们建议将您的亚马逊 EKS CloudWatch 日志导出到亚马逊简单存储服务 (Amazon S3) Simple S3 Service。您可以通过[控制台](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/S3ExportTasksConsole.html)或 API 创建导出任务，将日志转发到 Amazon S3 存储桶。完成此操作后，Amazon S3 提供了许多选项来进一步降低成本。您可以定义自己的 [Amazon S3 生命周期规则](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html)，将日志移动到符合您需求的存储类别，或者利用 A [mazon S3 智能分层](https://aws.amazon.com/s3/storage-classes/intelligent-tiering/)存储类让 AWS 根据您的使用模式自动将数据移至长期存储。有关更多详细信息，请参阅此[博客](https://aws.amazon.com/blogs/containers/understanding-and-cost-optimizing-amazon-eks-control-plane-logs/)。例如，对于您的生产环境，日志存放时间超过 30 天，然后导出到 Amazon S3 存储桶。 CloudWatch 然后，如果您需要在以后参考日志，则可以使用 Amazon Athena 来查询 Amazon S3 存储桶中的数据。

### 降低日志级别
<a name="_reduce_log_levels"></a>

为您的应用程序练习选择性日志记录。默认情况下，您的应用程序和节点都会输出日志。对于应用程序日志，请调整日志级别，使其与工作负载和环境的重要性保持一致。例如，下面的 java 应用程序正在输出`INFO`日志，这是典型的默认应用程序配置，根据代码的不同，可能会生成大量的日志数据。

```
import org.apache.log4j.*;

public class LogClass {
   private static org.apache.log4j.Logger log = Logger.getLogger(LogClass.class);

public static void main(String[] args) {
      log.setLevel(Level.INFO);

   log.debug("This is a DEBUG message, check this out!");
   log.info("This is an INFO message, nothing to see here!");
   log.warn("This is a WARN message, investigate this!");
   log.error("This is an ERROR message, check this out!");
   log.fatal("This is a FATAL message, investigate this!");    } }
```

在开发环境中，将日志级别更改为`DEBUG`，因为这可以帮助你调试问题，或者在潜在问题进入生产之前抓住它们。

```
      log.setLevel(Level.DEBUG);
```

在生产环境中，可以考虑将日志级别修改为`ERROR`或`FATAL`。只有当您的应用程序出现错误时，它才会输出日志，从而减少日志输出，并帮助您专注于有关应用程序状态的重要数据。

```
      log.setLevel(Level.ERROR);
```

你可以微调各种 Kubernetes 组件的日志级别。例如，如果您使用 [Bottlerocket](https://bottlerocket.dev/) 作为 EKS 节点操作系统，则有一些配置设置允许您调整 kubelet 进程日志级别。此配置设置的片段如下所示。请注意，默认[日志级别](https://github.com/bottlerocket-os/bottlerocket/blob/3f716bd68728f7fd825eb45621ada0972d0badbb/README.md?plain=1#L528)为 **2**，它会调整进程的日志详细程度。`kubelet`

```
[settings.kubernetes]
log-level = "2"
image-gc-high-threshold-percent = "85"
image-gc-low-threshold-percent = "80"
```

对于开发环境，您可以将日志级别设置为大于 **2** 以查看其他事件，这有利于调试。对于生产环境，您可以将级别设置**为 0**，以便仅查看关键事件。

### 利用过滤器
<a name="_leverage_filters"></a>

使用默认 EKS Fluentbit 配置将容器日志发送到 Cloudwatch 时，请 FluentBit 捕获**所有**富含 Kubernetes 元数据的应用程序容器日志并将其发送到 Cloudwatch，如下面的配置块所示。`[INPUT]`

```
 [INPUT]
     Name                tail
     Tag                 application.*
     Exclude_Path        /var/log/containers/cloudwatch-agent*, /var/log/containers/fluent-bit*, /var/log/containers/aws-node*, /var/log/containers/kube-proxy*
     Path                /var/log/containers/*.log
     Docker_Mode         On
     Docker_Mode_Flush   5
     Docker_Mode_Parser  container_firstline
     Parser              docker
     DB                  /var/fluent-bit/state/flb_container.db
     Mem_Buf_Limit       50MB
     Skip_Long_Lines     On
     Refresh_Interval    10
     Rotate_Wait         30
     storage.type        filesystem
     Read_from_Head      ${READ_FROM_HEAD}
```

上面的`[INPUT]`部分正在摄取所有容器日志。这可能会生成大量可能不是必需的数据。筛选出这些数据可以减少发送到的日志数据量， CloudWatch 从而降低成本。您可以先对日志应用过滤器，然后再将其输出到 CloudWatch。Fluentbit 在本节中对此进行了定义。`[FILTER]`例如，过滤掉 Kubernetes 元数据以使其不被附加到日志事件可以减少日志量。

```
    [FILTER]
        Name                nest
        Match               application.*
        Operation           lift
        Nested_under        kubernetes
        Add_prefix          Kube.

    [FILTER]
        Name                modify
        Match               application.*
        Remove              Kube.<Metadata_1>
        Remove              Kube.<Metadata_2>
        Remove              Kube.<Metadata_3>

    [FILTER]
        Name                nest
        Match               application.*
        Operation           nest
        Wildcard            Kube.*
        Nested_under        kubernetes
        Remove_prefix       Kube.
```

## Metrics
<a name="_metrics"></a>

 [指标](https://aws-observability.github.io/observability-best-practices/signals/metrics/)提供了有关系统性能的宝贵信息。通过将所有与系统相关的或可用的资源指标整合到一个集中的位置，您可以比较和分析性能数据。这种集中式方法使您能够做出更明智的战略决策，例如扩大或缩减资源。此外，指标在评估资源运行状况方面起着至关重要的作用，使您能够在必要时采取主动措施。通常，可观测性成本会随着遥测数据的收集和保留而增加。以下是您可以实施的几种策略来降低公制遥测的成本：仅收集重要的指标，降低遥测数据的基数，以及微调遥测数据收集的粒度。

### 监控重要内容，只收集你需要的东西
<a name="_monitor_what_matters_and_collect_only_what_you_need"></a>

第一种降低成本的策略是减少您收集的指标数量，进而降低留存成本。

1. 首先，从您和/或利益相关者的要求向后推进[，以确定最重要的指标](https://aws-observability.github.io/observability-best-practices/guides/#monitor-what-matters)。每个人的成功指标都不一样！知道*好*看是什么样子，并据此进行衡量。

1. 考虑深入研究你所支持的工作负载，并确定其关键性能指标 (KPIs)，又名 “黄金信号”。这些应符合业务和利益相关者的要求。计算 SLIs SLOs、和 SLAs 使用 Amazon CloudWatch 和 Metric Math 对于管理服务可靠性至关重要。遵循本[指南](https://aws-observability.github.io/observability-best-practices/guides/operational/business/key-performance-indicators/#10-understanding-kpis-golden-signals)中概述的最佳实践，以有效监控和维护 EKS 环境的性能。

1. 然后继续浏览基础设施的不同层，[将 EKS 集群、节点和其他基础设施指标与您的工作负载 KPIs关联起来](https://aws-observability.github.io/observability-best-practices/signals/metrics/#correlate-with-operational-metric-data)。将您的业务指标和运营指标存储在系统中，您可以将它们关联在一起，并根据观察到的对两者的影响得出结论。

1. EKS 公开来自控制平面、集群 kube-state-metrics、Pod 和节点的指标。所有这些指标的相关性取决于您的需求，但是您可能不需要跨不同层次的每一个指标。您可以使用此 [EKS 基本指标](https://aws-observability.github.io/observability-best-practices/guides/containers/oss/eks/best-practices-metrics-collection/)指南作为监控 EKS 集群和工作负载整体运行状况的基准。

以下是 prometheus 抓`relabel_config`取配置的示例，我们在其中使用仅保留 kubelet 指标并`metric_relabel_config`删除所有容器指标。

```
  kubernetes_sd_configs:
  - role: endpoints
    namespaces:
      names:
      - kube-system
  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  tls_config:
    insecure_skip_verify: true
  relabel_configs:
  - source_labels: [__meta_kubernetes_service_label_k8s_app]
    regex: kubelet
    action: keep

  metric_relabel_configs:
  - source_labels: [__name__]
    regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s)
    action: drop
```

### 在适用的情况下减少基数
<a name="_reduce_cardinality_where_applicable"></a>

基数是指特定指标集的数据值与其维度（例如 prometheus 标签）相结合的唯一性。高基数指标具有多个维度，每个维度指标组合具有更高的唯一性。更高的基数会导致更大的公制遥测数据大小和存储需求，从而增加成本。

在下面的高基数示例中，我们看到指标 “延迟” 具有维度、requestID、CustomerID 和服务，每个维度都有许多唯一的值。基数是衡量每个维度可能值的数量组合的指标。在 Prometheus 中，每组唯一的维度/标签都被视为一个新的指标，因此高基数意味着更多的指标。

在每个指标（集群、命名空间、服务、Pod、容器等）都有许多指标和维度/标签的 EKS 环境中，基数往往会增长。为了优化成本，请仔细考虑您正在收集的指标的基数。例如，如果您要在集群级别聚合用于可视化的特定指标，则可以删除位于较低层的其他标签，例如命名空间标签。

为了识别 prometheus 中的高基数指标，您可以运行以下 PROMQL 查询来确定哪些抓取目标的指标数量最多（基数）：

```
topk_max(5, max_over_time(scrape_samples_scraped[1h]))
```

以下 PROMQL 查询可以帮助您确定哪些抓取目标的指标流失率最高（在给定的抓取中创建了多少新指标系列）：

```
topk_max(5, max_over_time(scrape_series_added[1h]))
```

如果你使用的是 grafana，你可以使用 Grafana Lab 的 Mimirtool 来分析你的 grafana 仪表板，使用 prometheus 规则来识别未使用的高基数指标。按照[本指南](https://grafana.com/docs/grafana-cloud/account-management/billing-and-usage/control-prometheus-metrics-usage/usage-analysis-mimirtool/?pg=blog&plcmt=body-txt#analyze-and-reduce-metrics-usage-with-grafana-mimirtool)，了解如何使用`mimirtool analyze`和`mimirtool analyze prometheus`命令来识别仪表板中未引用的活动指标。

### 考虑指标粒度
<a name="_consider_metric_granularity"></a>

以更高的精度（例如每秒与每分钟）收集指标可能会对收集和存储的遥测数据产生重大影响，从而增加成本。确定合理的抓取或指标收集间隔，在足够大的粒度以查看暂时性问题和足够低的粒度之间取得平衡，从而具有成本效益。降低用于容量规划和更大时间窗分析的指标的粒度。

[以下是默认的 AWS Distro for Opentelemetry (ADOT) EKS 插件收集器配置的片段。](https://docs.aws.amazon.com/eks/latest/userguide/deploy-deployment.html)

**重要**  
全局 prometheus 抓取间隔设置为 15 秒。此抓取间隔可以增加，从而减少在 prometheus 中收集的指标数据量。

```
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
  name: my-collector-amp

...

config: |
    extensions:
      sigv4auth:
        region: "+++<YOUR_AWS_REGION>+++" service: "aps"+++</YOUR_AWS_REGION>+++

 receivers:
   #
   # Scrape configuration for the Prometheus Receiver
   # This is the same configuration used when Prometheus is installed using the community Helm chart
   #
   prometheus:
     config:
       global:   scrape_interval: 15s
         scrape_timeout: 10s
```

## 跟踪
<a name="_tracing"></a>

与追踪相关的主要成本源于痕量存储的生成。通过跟踪，目的是收集足够的数据来诊断和了解性能方面。但是，由于 X-Ray 追踪的成本基于转发到 X-Ray 的数据，因此在转发轨迹后删除跟踪不会降低您的成本。让我们回顾一下在维护数据以便进行适当分析的同时降低追踪成本的方法。

### 应用采样规则
<a name="_apply_sampling_rules"></a>

默认情况下，X-Ray 采样率是保守的。定义采样规则，您可以在其中控制所收集的数据量。这将提高性能效率，同时降低成本。通过[降低采样率](https://docs.aws.amazon.com/xray/latest/devguide/xray-console-sampling.html#xray-console-custom)，您可以仅从请求中收集工作负载所需的跟踪，同时保持较低的成本结构。

例如，你有一个 java 应用程序，你想调试 1 条有问题的路由的所有请求的跟踪。

 **通过 SDK 进行配置以从 JSON 文档加载采样规则** 

```
{
"version": 2,
  "rules": [
    {
"description": "debug-eks",
      "host": "*",
      "http_method": "PUT",
      "url_path": "/history/*",
      "fixed_target": 0,
      "rate": 1,
      "service_type": "debug-eks"
    }
  ],
  "default": {
"fixed_target": 1,
    "rate": 0.1
  }
}
```

 **通过控制台** 

### 使用 AWS Distro 应用尾部采样适用于 OpenTelemetry (ADOT)
<a name="_apply_tail_sampling_with_aws_distro_for_opentelemetry_adot"></a>

ADOT Tail Sampling 允许您控制服务中摄取的迹线量。但是，Tail Sampling 允许您在请求中的所有跨度都完成之后而不是在开始时定义采样策略。这进一步限制了传输到的原始数据量 CloudWatch，从而降低了成本。

例如，如果您对登录页面流量的 1% 和 10% 的付款页面请求进行采样，则可能会在 30 分钟内留下 300 条跟踪记录。使用过滤特定错误的 ADOT Tail Sampling 规则，您可能只剩下 200 条轨迹，从而减少存储的跟踪数量。

```
processors:
  groupbytrace:
    wait_duration: 10s
    num_traces: 300
    tail_sampling:
    decision_wait: 1s # This value should be smaller than wait_duration
    policies:
      - ..... # Applicable policies**
  batch/tracesampling:
    timeout: 0s # No need to wait more since this will happen in previous processors
    send_batch_max_size: 8196 # This will still allow us to limit the size of the batches sent to subsequent exporters

service:
  pipelines:
    traces/tailsampling:
      receivers: [otlp]
      processors: [groupbytrace, tail_sampling, batch/tracesampling]
      exporters: [awsxray]
```

### 利用亚马逊 S3 存储选项
<a name="_leverage_amazon_s3_storage_options"></a>

您应该利用 AWS S3 存储桶及其不同的存储类来存储跟踪。在保留期到期之前将跟踪导出到 S3。使用 Amazon S3 生命周期规则将跟踪数据移至符合您要求的存储类别。

例如，如果您的跟踪记录已存在 90 天，[Amazon S3 智能分层](https://aws.amazon.com/s3/storage-classes/intelligent-tiering/)可以根据您的使用模式自动将数据移至长期存储。如果您需要稍后再参考跟踪记录，则可以使用 [Ama](https://aws.amazon.com/athena/) zon Athena 来查询 Amazon S3 中的数据。这可以进一步降低分布式跟踪的成本。

## 其他资源：
<a name="_additional_resources"></a>
+  [可观测性最佳实践指南](https://aws-observability.github.io/observability-best-practices/guides/) 
+  [最佳实践指标收集](https://aws-observability.github.io/observability-best-practices/guides/containers/oss/eks/) 
+  [AWS re: Invent 2022-亚马逊的可观察性最佳实践 () COP343](https://www.youtube.com/watch?v=zZPzXEBW4P8) 
+  [AWS re: Invent 2022-可观察性：现代应用程序的最佳实践 () COP344](https://www.youtube.com/watch?v=YiegAlC_yyc) 