k8s環境のメトリクスやログを取得するマネージドサービス「CloudWatch Container Insights」が発表されました!

289件のシェア(すこし話題の記事)

現在開催されているKubeCon + CloudNativeCon Europe 2019 - Linux Foundation Eventsにおいて、Kubernetes環境のコンテナ環境のメトリクスを取得する「CloudWatch Container Insights」が発表されました!

従来、EKSにおいてPodの状態を監視したり各種ログを取得するには、サードパーティーのOSSや監視用のSaaSなどが実質的にほぼ必須だったんですが、これによりAWSのマネージドサービス(CloudWatch)だけで、それらが完結します。

パブリックプレビューなので、今すぐ動作確認できます。もちろん、東京リージョンもあるよ!!

  • Canada (Central)
  • US East (N. Virginia)
  • US East (Ohio)
  • US West (N. California)
  • US West (Oregon)
  • EU (Frankfurt)
  • EU (Paris)
  • Asia Pacific (Mumbai)
  • Asia Pacific (Singapore)
  • Asia Pacific (Sydney)
  • Asia Pacific (Tokyo)
  • Asia Pacific (Seoul)
  • South America (São Paulo)

CloudWatch Container Insightsは、2019年5月21日現在、まだ正式リリースされていないパブリックプレビューの状態で、サービス内容はいつでも変更される可能性があることご注意ください。

k8sコンテナ丸見えきたか…!!

  ( ゚д゚) ガタッ
  /   ヾ
__L| / ̄ ̄ ̄/_
  \/   /

CloudWatch Container Insightsとは?

公式ドキュメント:Using Container Insights - Amazon CloudWatch

従来、AWSにおけるk8s環境(EKS含む)において、そのNode(EC2)や各コンテナ、ネットワークのメトリクスやログを収集するためのマネージドの仕組みは存在せず、別途FluentdやDatadogなどのオープンソースやSaaSなどを利用する必要がありました。

今回のCloudWatch Container Insightsの登場により、CPU、メモリー、ディスク、ネットワークを収集し、かつコンテナ環境の問題の特定と解決に重要な、コンテナの再起動の失敗などの診断情報も取得できます。さらに、CloudWatchアラームとの連携ももちろんできます!

さらに、運用データはログイベントとして収集可能で、それらを組み合わせたダッシュボードやメトリクスを提供します。

EKS環境のセットアップ

もし、手元にEKSの環境がない場合は、クイックスタートを使うのが一番はやいです。こちらの記事を参考にしてみてください。

Container Insightsのセットアップ方法

まず最初に、導入の前提条件を確認します。

1. 導入前提条件の確認

改めて、現在利用できるリージョンを確認します。

導入にはkubectlが必要となります。こちら(kubectl のインストール - Amazon EKS)を確認してください。

また、すでにk8s環境を動作させている場合は、いかが必要となります。

2. ワーカーノードへのIAMロールの割当

k8sのワーカーノードとして動作しているEC2インスタンスのIAMロールにCloudWatchAgentServerPolicyをアタッチします。

3. クラスターメトリクス収集のためのCloudWatch Agentの設定

CloudWatch用のネームスペースの作成

CloudWatch用のネームスペースをk8sクラスターに作成します。

$ curl -O https://s3.amazonaws.com/cloudwatch-agent-k8s-yamls/kubernetes-monitoring/cloudwatch-namespace.yaml

yamlの中はこんな感じです。

apiVersion: v1
kind: Namespace
metadata:
  name: amazon-cloudwatch
  labels:
    name: amazon-cloudwatch

kubectl applyで、名前空間を適用します。

$ kubectl apply -f cloudwatch-namespace.yaml

こんな感じでネームスペースが作成されていればOkです。

$ kubectl get namespace
NAME                STATUS    AGE
amazon-cloudwatch   Active    16s
default             Active    33m
kube-public         Active    33m
kube-system         Active    33m

クラスター内にサービスアカウントを追加

まだ設定していない状態であれば、下記手順で、CloudWatch Agentのサービスアカウントを作成します。

$ curl -O https://s3.amazonaws.com/cloudwatch-agent-k8s-yamls/kubernetes-monitoring/cwagent-serviceaccount.yaml
$ kubectl apply -f cwagent-serviceaccount.yaml

CloudWatch Agent用のConfigMapを追加

CloudWatch agent用のConfigMapを追加します。CloudWatch agentの設定情報は、ConfigMapを利用して設定するのでkubernetesのバージョンは1.12以上が必要となります。

$ curl -O https://s3.amazonaws.com/cloudwatch-agent-k8s-yamls/kubernetes-monitoring/cwagent-configmap.yaml

ファイルの中身はこんな感じになっています。

apiVersion: v1
data:
  # Configuration is in Json format. No matter what configure change you make,
  # please keep the Json blob valid.
  cwagentconfig.json: |
    {
      "structuredlogs": {
        "metrics_collected": {
          "kubernetes": {
            "cluster_name": "{{cluster-name}}",
            "metrics_collection_interval": 60
          }
        },
        "force_flush_interval": 5
      }
    }
kind: ConfigMap
metadata:
  name: cwagentconfig
  namespace: amazon-cloudwatch

{{cluster-name}}の部分を、適用するk8sクラスターのクラスター名に変更します。これにより、CloudWatch agentがEC2タグからクラスタ名をEC2タグから取得可能となります。

以下のコマンドで、ConfigMapを適用します。

$ kubectl apply -f cwagent-configmap.yaml

CloudWatch Agentをデーモンセットとして配置

最後に、CloudWatch agentを各ワーカーノードにデーモンセットとして配置します。

$ curl -O https://s3.amazonaws.com/cloudwatch-agent-k8s-yamls/kubernetes-monitoring/cwagent-daemonset.yaml

ファイルの内容はこんな感じ。

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: cloudwatch-agent
  namespace: amazon-cloudwatch
spec:
  selector:
    matchLabels:
      name: cloudwatch-agent
  template:
    metadata:
      labels:
        name: cloudwatch-agent
    spec:
      containers:
        - name: cloudwatch-agent
          image: amazon/cloudwatch-agent:latest
          imagePullPolicy: Always
          #ports:
          #  - containerPort: 8125
          #    hostPort: 8125
          #    protocol: UDP
          resources:
            limits:
              cpu:  200m
              memory: 100Mi
            requests:
              cpu: 200m
              memory: 100Mi
          # Please don't change below envs
          env:
            - name: HOST_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
            - name: HOST_NAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            - name: K8S_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          # Please don't change the mountPath
          volumeMounts:
            - name: cwagentconfig
              mountPath: /etc/cwagentconfig
      volumes:
        - name: cwagentconfig
          configMap:
            name: cwagentconfig
      terminationGracePeriodSeconds: 60
      serviceAccountName: cloudwatch-agent

適用します。

$ kubectl apply -f cwagent-daemonset.yaml

配置結果を確認します。

$ kubectl get pods -n amazon-cloudwatch
NAME                     READY     STATUS    RESTARTS   AGE
cloudwatch-agent-6dwzv   1/1       Running   0          14s
cloudwatch-agent-khmkx   1/1       Running   0          14s
cloudwatch-agent-kq57t   1/1       Running   0          14s

ひとまずここまでで、最低限のインストールは完了です。

CloudWatchを確認してメトリクスとログを確認する

早速、CloudWatchを確認してみましょう。

ロググループに、以下のようなロググループが作成されていればOKです。

ドリルダウンすると、各ワーカーノード毎のログストリームが作成されています。

さらにドリルダウンすると、ワーカーノードで出力されたログが確認できます。

もちろん、CloudWatch Logs Insightsと統合されているため、クエリによるログの分析も可能です。

メトリクスももちろん取得可能。メトリクス直下にContainerInsightsのメトリクスが自動的に取得されています。

メトリクス名の「自動ダッシュボードの表示」から、各メトリクスの一覧をグラフ形式で表示可能です。

左上のドロップダウンからPodを選択すると…

Pod単位でのCPU、メモリ、ネットワーク関連のメトリクスを一括ダッシュボード表示可能です。いやぁこれは感動するわ。もちろん、このメトリクスからCloudWatch Alarmも設定が可能。

取得できるメトリクスやLogイベントは、下記ページに纏められています。合わせて参照ください。

Fluentdを利用したコンテナログのCloudWatch Logsへの転送

ここまでで、基本的なメトリクスやインフラ関連のログがCloudWatch Logsに転送されているところまで確認しました。

ここからは、肝心要のコンテナログのCloudWatch Logsへの転送設定をやります。ここでは、Fluentdを利用します。

この設定により、以下のロググループがCloudWatch Logsに作成されます。

Log Group Name Log Source
/aws/containerinsights/Cluster_Name/application All log files in /var/log/containers
/aws/containerinsights/Cluster_Name/host Logs from /var/log/dmesg, /var/log/secure, and /var/log/messages
/aws/containerinsights/Cluster_Name/dataplane Logs from /var/log/journal

CloudWatch用のネームスペース作成

これはCloudWatchエージェント導入したときと同じです。既に導入してたら、不要です。

$ curl -O https://s3.amazonaws.com/cloudwatch-agent-k8s-yamls/kubernetes-monitoring/cloudwatch-namespace.yaml
$ kubectl apply -f cloudwatch-namespace.yaml

Fluentdのインストール

Fluentdデプロイ用の設定ファイルをダウンロードします。

$ curl -O https://s3.amazonaws.com/cloudwatch-agent-k8s-yamls/fluentd/fluentd.yml

ログを送信するクラスターとリージョン名を設定して、configmapを作成します。cluster_nameregion_nameは、それぞれの環境に合わせて変更してください。

$ kubectl create configmap cluster-info \
--from-literal=cluster.name=cluster_name \
--from-literal=logs.region=region_name -n amazon-cloudwatch

上記コマンドでConfigmapの作成が完了したら、Fluentdをデーモンセットとしてクラスターに設定します。

$ kubectl apply -f fluentd.yml

しばらく待って、各ノードにデーモンセットとして、以下のpodが起動しているのが確認できればOKです。

$ kubectl get pods -n amazon-cloudwatch
NAME                       READY     STATUS    RESTARTS   AGE
cloudwatch-agent-6dwzv     1/1       Running   0          4h21m
cloudwatch-agent-khmkx     1/1       Running   0          4h21m
cloudwatch-agent-kq57t     1/1       Running   0          4h21m
fluentd-cloudwatch-6v6cv   1/1       Running   0          9m31s
fluentd-cloudwatch-ccqzs   1/1       Running   0          9m31s
fluentd-cloudwatch-j7hzx   1/1       Running   0          9m31s

CloudWatch Logsへのログ転送の確認

CloudWatch Logsコンソールを開いて、以下のロググループが作成されていればOKです。

ロググループの中に、アプリケーションログが転送されていることを確認できました。素晴らしい!

まとめ「Container InsightsでEKSのメトリクス監視〜ログ管理が超絶進化」

AWSの代表的なコンテナワークロードのECSやFargateは、既にCloudWatchと密接に統合されているため、ログの管理やメトリクスの取得は、他のAWSサービスと同じ手法で設定することができていました。はっきり言って設定はめっちゃ簡単です。

ただ、EKSに関しては、別途監視用のSaaSを契約したりPrometheusやGrafanaの導入が必要でした。

今回のContainer Insightsの発表により、サードパーティーのツールを組み合わせる面倒くささが解消され、慣れ親しんだCloudWathを使うことで、ログの管理、メトリクスの管理、アラームの設定が全て一括してマネージドサービスで完結します!

設定も特段難しいことはなく、k8sに適用するマニフェストファイルがAWSより提供されるので、それを順番にkubect applyしていくだけです。後は、ワーカーノードのEC2のIAMロールにポリシーを追加するぐらいですね。

2019年5月21日時点では、まだパブリックベータという位置付けですが、従来のEKS運用の面倒くささを大きな部分で解消するでかいアップデートなので、まずは手元の検証環境にいれて動作確認してみてください。

やっぱり、AWSのサービスはマネージド統合されてこそですから。

それでは、今日はこのへんで。濱田(@hamako9999)でした。