Amazon Web Services ブログ

Amazon DevOps Guru による Amazon EKS クラスターのコンテナ異常監視の自動化

この記事は Automate Container Anomaly Monitoring of Amazon Elastic Kubernetes Service Clusters with Amazon DevOps Guru (記事公開日: 2021 年 12 月 15 日) を翻訳したものです。

コンテナ中心の環境でのオブザーバビリティは、抽象化やサポートするインフラストラクチャーの数が増えているため、運用者にとって新たな課題となっています。多くの場合、組織は数百のクラスターと数千のサービス / タスク / Pod を同時に実行できます。この記事では、運用者の機能を簡素化し、拡張するのに役立つ Amazon DevOps Guru の新機能を紹介します。新機能には、異常をメトリクスやコンテナクラスターごとにグループ化することによって、コンテキストを改善してアクセスを簡素化することや、追加の Amazon CloudWatch Container Insights メトリクスをサポートすることなどが含まれます。これらの機能の実例として、Amazon DevOps Guru は、Amazon Elastic Kubernetes Service (EKS) 内のCPU、メモリ、またはネットワークの異常を識別し、運用者に通知して、影響を受けるクラスターに簡単に移動して収集されたデータを調べることができるようになります。

Amazon DevOps Guru は、フルマネージドの AIOps プラットフォームサービスを提供します。これにより、開発者と運用者は、アプリケーションの可用性を向上させ、運用上の問題をより迅速に解決できます。 Amazon DevOps Guru は、機械学習 (ML) を活用したレコメンデーションにより、手動による作業を最小限に抑えます。その ML モデルには、20 年以上にわたり世界最大の e コマースビジネス向けの可用性の高いアプリケーションを運用してきた AWS のノウハウが活かされています。DevOps Guru は、運用上の問題を自動的に検出し、差し迫ったリソースの枯渇を予測し、考えられる原因を詳細に説明し、改善策を提案します。

ソリューションの概要

この記事では、クラスターのグループ化と追加でサポートされる Amazon EKS メトリクスに関する Amazon DevOps Guru の新機能を説明します。これらの機能を説明するために、Kubernetes クラスターを作成し、AWS Distro for OpenTelemetry を使用してクラスターをインストルメントし、そして EKS メトリクスの異常検出を自動化するために Amazon DevOps Guru を構成する方法を示します。以前のブログ記事 (日本語訳) では、ここで使用している AWS Distro for OpenTelemetry コレクターの詳細を紹介しています。

前提条件

EKS クラスターの作成

Amazon EKS クラスターの作成には、eksctl という CLI ツールを使用します。eksctl を使用すると、コマンドラインでクラスターの詳細を指定したり、マニフェストファイルを指定したりできます。以下のマニフェストは、Amazon Elastic Compute Cloud (EC2) を使用して 1 台のマネージド型ノードを作成します。ノードは metadata/region エントリを介して指定されたリージョンと、managedNodeGroups/availabilityZones エントリを介して指定されたアベイラビリティーゾーンに作成され制限されます。デフォルトでは、新しい VPC とサブネットが作成されます。

# An example of ClusterConfig object using Managed Nodes
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: devopsguru-eks-cluster
  region: <SPECIFY_REGION_HERE>
  version: "1.21"

availabilityZones: ["<FIRST_AZ>","<SECOND_AZ>"]
managedNodeGroups:
  - name: managed-ng-private
    privateNetworking: true
    instanceType: t3.medium
    minSize: 1
    desiredCapacity: 1
    maxSize: 6
    availabilityZones: ["<SPECIFY_AVAILABILITY_ZONE(S)_HERE"]
    volumeSize: 20
    labels: {role: worker}
    tags:
      nodegroup-role: worker
cloudWatch:
  clusterLogging:
    enableTypes:
      - "api"
  • eksctl とマニフェストファイルを使用して Amazon EKS クラスターを作成するには、以下のように eksctl create を使用します。なお、クラスターの作成には 10 〜 15 分かかります。
$ eksctl create cluster -f devopsguru-managed-node.yaml
2021-10-13 10:44:53 [i] eksctl version 0.69.0
…
2021-10-13 11:04:42 [✔] all EKS cluster resources for "devopsguru-eks-cluster" have been created
2021-10-13 11:04:44 [i] nodegroup "managed-ng-private" has 1 node(s)
2021-10-13 11:04:44 [i] node "<ip>.<region>.compute.internal" is ready
2021-10-13 11:04:44 [i] waiting for at least 1 node(s) to become ready in "managed-ng-private"
2021-10-13 11:04:44 [i] nodegroup "managed-ng-private" has 1 node(s)
2021-10-13 11:04:44 [i] node "<ip>.<region>.compute.internal" is ready
2021-10-13 11:04:47 [i] kubectl command should work with "/Users/<user>/.kube/config"
  • これが完了すると、Kubernetes CLI である kubectl を使って、実行中のマネージド型ノードを確認できるようになります。
$ kubectl get nodes
NAME                             STATUS   ROLES    AGE   VERSION
<ip>.<region>.compute.internal   Ready    <none>   76m   v1.21.4-eks-033ce7e

AWS Distro for OpenTelemetry コレクターのインストール

AWS Distro for OpenTelemetry コレクターを使用して、Amazon EKS で実行中の Pod からメトリクスを抽出します。コレクターによって、Kubernetes クラスター内のメトリクスを収集し、Amazon CloudWatch に表示させます。アクセスを許可するポリシーの定義から始めます。以下の情報は、こちらのブログ記事 (日本語訳) からのものです。

CloudWatchAgentServerPolicy IAM ポリシーをワーカーノードにアタッチする

  • Amazon EC2 コンソールを開きます。
  • ワーカーノードインスタンスの 1 つを選択し、詳細にある IAM ロールを選択します。
  • IAM ロールのページで、Attach policies を選択します。
  • ポリシーのリストで、CloudWatchAgentServerPolicy の横のチェックボックスを選択します。検索ボックスを使用して、このポリシーを見つけることができます。
  • Attach policies を選択します。

AWS OpenTelemetry コレクターを Amazon EKS にデプロイする

次に、GitHub でホストされているマニフェストを使用して、AWS Distro for OpenTelemetry をデプロイします。

  • 以下のコマンドを使用して、アーティファクトを Amazon EKS クラスターにデプロイします。
$ curl https://raw.githubusercontent.com/aws-observability/aws-otel-collector/main/deployment-template/eks/otel-container-insights-infra.yaml | kubectl apply -f -
  • aws-otel-eks Namespace 内のリソースを表示します。
$ kubectl get pods -l name=aws-otel-eks-ci -n aws-otel-eks
NAME                    READY   STATUS    RESTARTS   AGE
aws-otel-eks-ci-jdf2w   1/1     Running   0          107m

Container Insights のメトリクスを Amazon CloudWatch で表示する

Amazon CloudWatch にアクセスし、MetricsAll metrics を選択して、発行されたメトリクスを表示します。カスタム名前空間の ContainerInsights を選択できます。この下では、クラスター、ノード、Pod、Namespace、Service の粒度でメトリクスを表示できます。以下の例では、CPU の Pod レベルのメトリクスを表示しています。

AWS コンソールでの Amazon CloudWatch Container Insights の Pod レベルの CPU 使用率の表示。

Amazon Simple Notification Service

Amazon SNS がイベントをパブリッシュするためには、Amazon DevOps Guru による Amazon SNS へのアクセスを許可する必要があります。セットアッププロセスでは、Amazon SNS トピックが作成され、以下のリソースポリシーが適用されます。

{
    "Sid": "DevOpsGuru-added-SNS-topic-permissions",
    "Effect": "Allow",
    "Principal": {
        "Service": "region-id.devops-guru.amazonaws.com"
    },
    "Action": "sns:Publish",
    "Resource": "arn:aws:sns:region-id:topic-owner-account-id:my-topic-name",
    "Condition" : {
      "StringEquals" : {
        "AWS:SourceArn": "arn:aws:devops-guru:region-id:topic-owner-account-id:channel/devops-guru-channel-id",
        "AWS:SourceAccount": "topic-owner-account-id"
    }
  }
}

Amazon DevOps Guru

Amazon DevOps Guru を活用して、Amazon EKS クラスターとマネージド型ノードグループを監視する準備ができました。これを行うには、Amazon DevOps Guru コンソールに移動し、次の画面キャプチャに示されている Get started を選択します。

AWS コンソールから Amazon DevOps Guru サービスを利用。

選択すると、Get started コンソールが表示され、DevOps Guru が適切なリソースにアクセスするための IAM ロールを確認することができます。

サービスの仕組み、IAM ロールのアクセス許可、Amazon DevOps Guru の分析カバレッジについての説明を含む、Amazon DevOps Guru の Get started ダイアログ。

Amazon DevOps Guru analysis coverage の下で、Choose later を選択します。これにより、後で監視する CloudFormation スタックを指定することができます。Create a new SNS topic を選択して、名前を指定します。これは、通知を収集し、サブスクライバーが通知を受けられるようにするために使用します。完了したら Enable を選択します。

Amazon DevOps Guru の分析カバレッジでは、ユーザーはリージョンのすべてのリソースを選択するか、後から選択することができます。さらに画像は、インサイトが発生したときに通知するための Amazon SNS トピックの指定をユーザーに要求するダイアログを示しています。

Manage DevOps Guru analysis coverage で、Analyze all AWS resources in the specified CloudFormation stacks in this Region を選択します。次に、DevOps Guru が Amazon EKS を監視できるように、EKS クラスターとマネージド型ノードグループの CloudFormation スタックを選択します。

分析の対象となるリージョン内の CloudFormation スタックを指定するダイアログが表示されます。EKS クラスターと EKS クラスターのマネージド型ノードグループの 2 つのスタックが選択されています。

選択すると、表示が更新され、2 つの CloudFormation スタックが追加されたことが確認できます。

Amazon DevOps Guru の分析カバレッジや Amazon SNS の通知を含む、Amazon DevOps Guru の設定。

Amazon DevOps Guru は、これらの 2 つのスタックの分析を開始します。データを収集し、正常な動作状態を特定するために数時間かかります。このプロセスが完了すると、次の画面キャプチャに示すように、ダッシュボードにそれらのリソースが分析されたことが表示されます。

DevOps guru による 2 つの CloudFormation スタックの分析が完了し、2 つのスタックが健全な状態であることがわかりました。

Amazon SNS トピックの暗号化を有効にする

Amazon DevOps Guru によって作成された Amazon SNS トピックは、デフォルトでは暗号化が有効ではありません。保管中の通知を暗号化するためには、この機能を有効にすることが重要です。Amazon SNS にアクセスして、作成されたトピックを選択し、Edit topic を選択します。Encryption ダイアログボックスを開き、次の画面キャプチャのように暗号化を有効にし、KMS キーのエイリアスを指定するか、デフォルトを受け入れます。

Amazon SNS トピックの暗号化ダイアログで設定を編集する。

サンプルアプリケーションを Amazon EKS にデプロイしてインサイトをトリガーする

AWS Distro for OpenTelemetry コレクターに含まれるサンプルアプリケーションを使用して障害をシミュレートします。以下のマニフェストを使用して、メモリと CPU のリソース制限を持つサンプルアプリケーションをデプロイします。これらの制限は意図的に低く設定されており、Pod の実行には不十分です。Pod はメモリ使用量を超過し、Amazon EKS によって退避 (Eviction) のために識別されます。退避されると、レプリカのマニフェストの要件に従って、再デプロイが施行されます。次に、これによりプロセスが繰り返され、Amazon CloudWatch でメモリと Pod の再起動エラーを生成します。この例では、Deployment が 1 時間以上放置されていたため、Pod の障害が何度も繰り返されています。ファイルシステムに作成するマニフェストは以下の通りです。

kind: Deployment
apiVersion: apps/v1
metadata:
  name: java-sample-app
  namespace: aws-otel-eks
  labels:
    name: java-sample-app
spec:
  replicas: 1
  selector:
    matchLabels:
      name: java-sample-app
  template:
    metadata:
      labels:
        name: java-sample-app
    spec:
      containers:
        - name: aws-otel-emitter
          image: aottestbed/aws-otel-collector-java-sample-app:0.9.0
          resources:
            limits:
              memory: "128Mi"
              cpu: "200m"
          ports:
          - containerPort: 4567
          env:
          - name: OTEL_OTLP_ENDPOINT
            value: "localhost:4317"
          - name: OTEL_RESOURCE_ATTRIBUTES
            value: "service.namespace=AWSObservability,service.name=CloudWatchEKSService"
          - name: S3_REGION
            value: "us-east-1"
          imagePullPolicy: Always

アプリケーションをデプロイするには、次のコマンドを使用します。

$ kubectl apply -f <manifest file name>
deployment.apps/java-sample-app created

シナリオ: DevOpsGuru のコンテナクラスターのグループ化とメトリクスの追加によるコンテキストの改善

このシナリオでは、Amazon DevOps Guru は追加の EKS の Amazon CloudWatch Container Insights メトリクスを監視しています。次の図は、運用者が Amazon DevOps Guru Insights を調べることができるようするための、情報の流れと運用者へのイベント通知を示しています。ステップ 1 では、コンテナエージェント (AWS Distro for OpenTelemetry) は、コンテナメトリクスを Amazon CloudWatch に転送します。ステップ 2 では、Amazon DevOps Guru が継続的にそれらのメトリクスを使用し、異常検知を実行します。異常が検出されると、これによりインサイトが生成され、ステップ 3 に示すように Amazon SNS 通知がトリガーされます。ステップ 4 では、運用者は Amazon DevOps Guru コンソールにアクセスしてインサイトを調べます。そして、運用者は、どのクラスター、Namespace、Pod / Service が影響を受けたかを、関連する Amazon EKS メトリクスとともに表示する新しいユーザーインタフェース機能を活用することができます。

運用者が Amazon DevOps Guru Insights を調べることができるようするための、情報の流れと運用者へのイベント通知を示しています。ステップ 1 では、コンテナエージェント (AWS Distro for OpenTelemetry) は、コンテナメトリクスを Amazon CloudWatch に転送します。ステップ 2 では、Amazon DevOps Guru が継続的にそれらのメトリクスを使用し、異常検知を実行します。異常が検出されると、これによりインサイトが生成され、ステップ 3 に示すように Amazon SNS 通知がトリガーされます。ステップ 4 では、運用者は Amazon DevOps Guru コンソールにアクセスしてインサイトを調べます。そして、運用者は、どのクラスター、Namespace、Pod / Service が影響を受けたかを、関連する Amazon EKS メトリクスとともに表示する新しいユーザーインタフェース機能を活用することができます。

DevOps Guru の新しい EKS コンテナメトリクス

このリリースの一環として、次の Pod とノードのメトリクスが DevOps Guru によって追跡されるようになりました。

  • pod_number_of_container_restarts – Pod が再起動された回数 (イメージプルの問題、コンテナの障害など) 。
  • pod_memory_utilization_over_pod_limit – Podのリソース制限に対する、Pod で使用されている CPU の割合。
  • pod_cpu_utilization_over_pod_limit – Pod のリソース制限に対する、Pod によって使用されているメモリの割合。
  • pod_cpu_utilization – Pod が使用している CPU 使用率。
  • pod_memory_utilization – Pod が使用しているメモリ使用率。
  • node_network_total_bytes – クラスターのノード (EC2 インスタンスなど) のネットワークインターフェース上の送信及び受信バイト数。
  • node_filesystem_utilization – クラスターのノード (EC2 インスタンスなど) のファイルシステム使用率。
  • node_cpu_utilization – クラスターのノード (EC2 インスタンスなど) の CPU 使用率。
  • node_memory_utilization – クラスターのノード (EC2 インスタンスなど) のメモリ使用率。

運用者のシナリオ

Kubernetes の運用者は、Amazon SNS を介してインサイトを通知されます。Amazon SNS のメッセージ内容は以下のコードのように、発信元と InsightDescription、InsightSeverity、コンテナメトリクスの名前、Pod / EKS クラスターを特定する情報が表示されます。

{
  "AccountId": "XXXXXXX",
  "Region": "<REGION>",
  "MessageType": "NEW_INSIGHT",
  "InsightId": "ADFl69Pwq1Aa6M373DhU0zkAAAAAAAAABuZzSBHxeiNexxnLYD7Lhb0vuwY9hLtz",
  "InsightUrl": "https://<REGION>.console.aws.amazon.com/devops-guru/#/insight/reactive/ADFl69Pwq1Aa6M373DhU0zkAAAAAAAAABuZzSBHxeiNexxnLYD7Lhb0vuwY9hLtz",
  "InsightType": "REACTIVE",
  "InsightDescription": "ContainerInsights pod_number_of_container_restarts Anomalous In Stack eksctl-devopsguru-eks-cluster-cluster",
  "InsightSeverity": "high",
  "StartTime": 1636147920000,
  "Anomalies": [
    {
      "Id": "ALAGy5sIITl9e6i66eo6rKQAAAF88gInwEVT2WRSTV5wSTP8KWDzeCYALulFupOQ",
      "StartTime": 1636147800000,
      "SourceDetails": [
        {
          "DataSource": "CW_METRICS",
          "DataIdentifiers": {
            "name": "pod_number_of_container_restarts",
            "namespace": "ContainerInsights",
            "period": "60",
            "stat": "Average",
            "unit": "None",
            "dimensions": "{\"PodName\":\"java-sample-app\",\"ClusterName\":\"devopsguru-eks-cluster\",\"Namespace\":\"aws-otel-eks\"}"
          }
....
  "awsInsightSource": "aws.devopsguru"
}

Amazon DevOps Guru コンソールは、次の画面キャプチャのように Insights の項目でインサイトを収集します。詳細を表示するには Insights を選択します。

Amazon DevOps Guru Insights。あるインサイトが、ステータスが Ongoing、Severity が High で表示されています。

Aggregated Metrics (集約されたメトリクス) は、エラーが発生した EKS コンテナメトリクスを識別できるようにします。この例では、pod_memory_utilization_over_pod_limit と pod_number_of_container_restarts です。

Amazon EKS クラスター 名 devopsguru-eks-cluster の pod_memory_utilization_over_pod_limit と pod_number_of_container_restarts を持つ集約されたメトリクスのパネル。異常の長さを伝えるために、時間と日付を含むタイムラインがグラフィカルに表示されます。

次の画面キャプチャのように、各インサイトを選択して展開することで、さらに詳細を確認することができます。

クラスターメトリクスを展開する機能によって PodName、Namespace、ClusterName の詳細情報が提供されます。さらに、検索バーによって名前、スタック、サービス名で検索できます。

クラスター、PodName、Namespace の情報が表示されていることに注意してください。これにより、多数の EKS クラスターを管理している運用者は、問題のある Pod、その動作している Namespace、およびその Pod が属する EKS クラスターを迅速に切り分けることができます。検索バーでは、メトリクス名、スタック、またはサービス名で表示をさらに絞り込むことができます。

クリーンアップ

追加料金がアカウントに計上されないように、次のリソースを削除する手順に従ってください。

Amazon EKS クラスターの削除

以下の手順に従って、カスタマー管理ポリシーをデタッチし、クラスターを削除します。

  • IAM コンソールでカスタマー管理ポリシー AWSDistroOpenTelemetryPolicy をデタッチします。
  • eksctl を使用してクラスターを削除します。
$ eksctl delete cluster devopsguru-eks-cluster --region <region>
2021-10-13 14:08:28 [i] eksctl version 0.69.0
2021-10-13 14:08:28 [i] using region <region>
2021-10-13 14:08:28 [i] deleting EKS cluster "devopsguru-eks-cluster"
2021-10-13 14:08:30 [i] will drain 0 unmanaged nodegroup(s) in cluster "devopsguru-eks-cluster"
2021-10-13 14:08:32 [i] deleted 0 Fargate profile(s)
2021-10-13 14:08:33 [✔] kubeconfig has been updated
2021-10-13 14:08:33 [i] cleaning up AWS load balancers created by Kubernetes objects of Kind Service or Ingress
2021-10-13 14:09:02 [i] 2 sequential tasks: { delete nodegroup "managed-ng-private", delete cluster control plane "devopsguru-eks-cluster" [async] }
2021-10-13 14:09:02 [i] will delete stack "eksctl-devopsguru-eks-cluster-nodegroup-managed-ng-private"
2021-10-13 14:09:02 [i] waiting for stack "eksctl-devopsguru-eks-cluster-nodegroup-managed-ng-private" to get deleted
2021-10-13 14:12:30 [i] will delete stack "eksctl-devopsguru-eks-cluster-cluster"
2021-10-13 14:12:30 [✔] all cluster resources were deleted

まとめ

前述のシナリオでは、新しいクラスター組織と追加のコンテナメトリクスのデモを行いました。これらの機能はどちらも、Amazon DevOps Guru が異常を検出したときに、運用者がコンテナクラスター内の問題をより簡単に特定する機能を、さらに簡素化し拡張します。ドキュメントを読むことで、Amazon CloudWatch エージェント / AWS Distro for OpenTelemetry エージェントおよび Amazon DevOps Guru を使用する独自のソリューションの構築を始めることができます。これは、Amazon DevOps Guru が提供する機能とその使用方法を理解するのに役立つ、概念的な概要と実践的な例を提供します。

翻訳はプロフェッショナルサービスの杉田が担当しました。原文はこちらです。