Amazon EKS on Fargate上のPodログをCloudWatchLogsに送信する

Amazon EKS on Fargate上のPodログをCloudWatchLogsに送信する

はじめに

今回はAmazon EKS on Fargate上のPodログをAWS CloudWatch Logsに転送する手段並びに注意点について書かせていただきます。

以前ではAmazon EKS on Fargate上のPodログをAWS CloudWatch Logsに転送する際にはサイドカーを導入する必要がありましたが、
現在では組み込みのログルーターを利用することでサイドカーの導入が不要になりました。

今回はこの組み込みのログルーターを利用した方法を解説させていただきます。

手順

前提条件

  • kubectlがインストールされている
  • eksctlがインストールされている

1. EKSクラスターを作成する

まず今回のログ転送で使用する検証用のEKSクラスターを作成します。
eks-cluster-config.yaml

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: fluentbit
  region: us-east-1
  version: '1.16'
iam:
  withOIDC: true
fargateProfiles:
  - name: defaultfp
    selectors:
      - namespace: demo
      - namespace: kube-system
cloudWatch:
  clusterLogging:
    enableTypes: ["*"]

eksctlコマンドでEKSクラスターを作成します。

$ eksctl create cluster -f eks-cluster-config.yaml

完了すると、EKSクラスターが作成されています。

2. Fluent Bit for Amazon EKS on AWS Fargate専用のnamespaceを作成する

Fluent Bit for Amazon EKS on AWS Fargate専用のnamespaceを作成します。
この際、namespace名はaws-observabilityである必要があります。

aws-observability-namespace.yaml

kind: Namespace
apiVersion: v1
metadata:
  name: aws-observability
  labels:
    aws-observability: enabled

namespace用のマニフェストをapplyします

$ kubectl apply -f aws-observability-namespace.yaml
namespace/aws-observability created

3. ConfigMapを作成して、Fargateログの送信先を設定する

以下のようなファイルを作成します。

aws-observability-namespace.yaml

kind: ConfigMap
apiVersion: v1
metadata:
  name: aws-logging
  namespace: aws-observability
  labels:
data:
  output.conf: |
    [OUTPUT]
        Name cloudwatch
        Match   *
        region us-east-1
        log_group_name /aws/eks/fluent-bit-cloudwatch
        log_stream_prefix from-fluent-bit-
        auto_create_group true

region → ログ転送先となるCloudwatchLogsのAWSリージョン
log_group_name → ログ転送先となるCloudwatchLogsのロググループ名
log_stream_prefix → CloudwatchLogsログストリームのprefixにセットされる命名
auto_create_group → trueにすると、log_group_nameで指定したロググループがCloudwatchLogsにまだ実在しない場合、自動でそのロググループを作成してくれる

この際、NameにはOUTPUTプラグイン名をセットします。
利用可能なものとしてはC言語で書かれたcloudwatch_logsとGo言語で書かれたcloudwatchがありますが、実際の本番ワークロードでは
cloudwatch_logsではなく、cloudwatchをセットすることを推奨いたします。
cloudwatch_logsをセットしてしまった場合、ログの送信が停止してしまう不具合が生じてしまう可能性があるからです。(※公式AWSサポート問い合わせ済み)

ConfigMap用のファイルをapplyします

$ kubectl apply -f aws-observability-namespace.yaml
configmap/aws-logging created

4. CloudWatchLogsへの書き込み権限を付与する

EKS on Fargateのポッド実行ロールにCloudWatchLogsへのログ書き込み権限が許可されているIAMポリシーをアタッチします。

EKS on Fargate クラスターのポッド実行ロールはコンソール上などから確認できます。

# 今回検証用のサンプルIAMポリシーのjsonを取得
$ curl -o permissions.json \
https://raw.githubusercontent.com/aws-samples/amazon-eks-fluent-logging-examples/mainline/examples/fargate/cloudwatchlogs/permissions.json
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   215  100   215    0     0    689      0 --:--:-- --:--:-- --:--:--   686

# CloudWatchLogsへのログ書き込み権限が許可されているIAMポリシーを作成
$ aws iam create-policy \
--policy-name eks-fargate-fluent-bit-cloudwatch-sample \
--policy-document file://permissions.json
{
    "Policy": {
        "PolicyName": "eks-fargate-fluent-bit-cloudwatch-sample",
        "PolicyId": "ANPATELHUHM263Z5IG6S4",
        "Arn": "arn:aws:iam::xxxxxxxxxxxxxxxx:policy/eks-fargate-fluent-bit-cloudwatch-sample",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2021-07-24T12:13:20+00:00",
        "UpdateDate": "2021-07-24T12:13:20+00:00"
    }
}

# IAMポリシーをEKS on Fargateのポッド実行ロールにアタッチ
$ aws iam attach-role-policy \
--policy-arn arn:aws:iam::xxxxxxxxxxxxxxxx:policy/eks-fargate-fluent-bit-cloudwatch-sample \
--role-name eksctl-fluentbit-cluster-FargatePodExecutionRole-G5P7ZMG795KS

ポッド実行ロールにIAMポリシーがアタッチされています。

5. 検証用ログ出力リソースを構築する

最後に、Podログを検証用に生成させるリソース構築を行います。
以下の2つのマニフェストファイルを生成してapplyします。

demo-namespace.yaml

kind: Namespace
apiVersion: v1
metadata:
  name: demo

logger-server.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: logger-server
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: main
        image: nginx:1.14.2
        ports:
        - containerPort: 80
$ kubectl apply -f demo-namespace.yaml
namespace/demo created
$ kubectl -n demo apply -f logger-server.yaml && kubectl -n demo expose deploy logger-server
deployment.apps/logger-server created
service/logger-server exposed

マニフェストファイルapply後に、以下のコマンドを実行してログを生成します。

$ kubectl -n demo port-forward svc/logger-server 8080:80 
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
Handling connection for 8080

$ curl localhost:8080

本記事では、EKSクラスタ及びPod前提のアプリケーションの構築を行なっていますが、既に構築済みのPod上のアプリケーションログをCloudWatchLogsに転送したい場合は、対象Podの再起動を行います。

# 対象となるdeployment名の確認
$ kubectl -n {namespace} get deploy
# Pod再起動
$ kubectl -n {namespace} rollout restart deploy {deployment名}

6. CloudWatchLogsにログが転送されたことを確認する

実際に手順3.で指定したロググループ/aws/eks/fluent-bit-cloudwatchを確認すると、ログが転送されています。

まとめ

Fluent Bit for Amazon EKS on AWS Fargateを利用したCloudWatchLogsへのログ転送方法をご紹介させていただきました。
AWS公式ブログではOUTPUTプラグインにcloudwatch_logsを利用していますが、先述の通りcloudwatchのご利用をお勧めいたします。

参考

Fluent Bit for Amazon EKS on AWS Fargate をリリース
Fargate ログ記録