Amazon Web Services ブログ

Fluent Bit for Amazon EKS on AWS Fargate をリリース

本投稿は、Akshay Ram, Prithvi Ramesh, Michael Hausenblas による寄稿を翻訳したものです。

 

Container roadmap 上の issue 701 では、 EKS on Fargate 利用時の CNCF Fluent Bit を利用したログルーターのサポートについて議論していました。このブログ記事では、EKS on Fargete利用時におけるいくつかの設定ステップによってCloudWatch へ直接ログを送信する事が出来る新しい機能とそれを利用する流れをみていきましょう。

以前は、AWS Fargate 上で動くAmazon EKS の Pod から コンテナログを送信するためには サイドカーコンテナを動かす必要がありましたが、組み込みのログルーターを利用出来るようになりました。これはサイドカーをインストールしたり維持する必要が無いという事を意味しています。ユーザーはデータの送信先を選択するだけで、ログは選択した送信先にルーティングされます。

私たちは、2つの設計原則を維持しながらこの機能を構成しました。

  1. 一貫性:必要に応じて、ネイティブの Kubernetes オブジェクトを利用して、コンピューティングタイプ(EC2、マネージドノードグループ、Fargate)に渡った一貫したインターフェイスをお客様に提供する
  2. シンプル:お客様のインフラストラクチャーや add-ons をさらに管理する

この設計原則に従う事で、Fluent Bit 設定言語と Kubernetes Config Map を、プライマリインターフェイスとして選択し、 Kubernetes クラスターにおける標準的な方法としてロギングを設定する様にしました。Fluent Bit をプラットフォームの中に含める事で、Fluent Bit のライフサイクル管理をシンプルにしました。ログを何処に送るかを指定するだけで、後はAWSによって管理されます。

 

新しい組み込みロギングのサポートにより、ユーザはデータの送信先を選択するだけで、ログは選択した送信先にルーティングされます。その裏側では、EKS on Fargateは Fluent Bit for AWSを利用しています。Flunet Bit for AWS は AWSによって管理されている Fluent Bit でアップストリームに準拠したディストリビューションです。

EKS on Fargate上でFluent Bit を利用したロギングを行うためには、Fluent Bit の設定を記述した ConfigMap を Amazon EKS クラスターに対して適用します。

このロギング用 ConfigMap は、aws-observability という固定の namespaceを利用していて、 クラスター全体に適用されます。つまり、任意のnamespaceにある任意のアプリケーションのログを送信する事が出来る事を意味しています。選択したログ送信先の定義には Fluent Bit 設定言語が利用できます。 CloudWatch 、ElasticSearch 、 Kinesis Firehose、Kinesis Streams を output として選択可能です。

CloudWatch へのログ送信

下の図では、cloudwatch_logs (C言語で書かれたFluentBit output plugin) を使って、 EKS on Fargate クラスター上で動いているワークロードから CloudWatchにログを送る方法を示しています。

以下の様に、最初にEKS on Fargate クラスターを作成します。eksctl 設定ファイルとして、以下の内容をeks-cluster-config.yamlとして保存してください。

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

続いて、次のコマンドでEKS クラスターを作成します。

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

EKS コントロールプレーンと Fargate プロファイルの作成が完了するまでに、15-20分の時間がかかることに注意してください。

続いて、以下の内容を保存した fluent-config.yaml を利用して、専用の aws-observability namespace、ConfigMapを作成します。

 

kind: Namespace
apiVersion: v1
metadata:
  name: aws-observability
  labels:
    aws-observability: enabled
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: aws-logging
  namespace: aws-observability
data:
  output.conf: |
    [OUTPUT]
        Name cloudwatch_logs
        Match   *
        region eu-west-1
        log_group_name fluent-bit-cloudwatch
        log_stream_prefix from-fluent-bit-
        auto_create_group On

 

上記の YAML マニフェストでは、 アプリケーションがログを出力すると直ぐに、CloudWatch log group の名前として記載されている fluent-bit-cloudwatch が自動作成されます。

それでは、以下のコマンドを利用して、Fluent Bit 設定を作成していきます。

kubectl apply -f fluentbit-config.yaml

Fluent Bit ConfigMap が設定されたかを確認するため、次のコマンドを実行し、同様の内容が出力されるか確認しましょう。

$ kubectl -n aws-observability get cm
NAMESPACE           NAME                                 DATA   AGE
aws-observability   aws-logging   

Fluent Bitをセットアップするために、次はCloudWatchへの書き込み権限を付与します。まず最初に以下のポリシーをローカルにダウンロードします。

$ curl -o permissions.json \ 
      https://raw.githubusercontent.com/aws-samples/amazon-eks-fluent-logging-examples/mainline/examples/fargate/cloudwatchlogs/permissions.json

 

続いてポリシーを作成し、 EKS on Fargate クラスターの pod execution role にポリシーをアタッチしましょう。

aws iam create-policy \
        --policy-name FluentBitEKSFargate \
        --policy-document file://permissions.json 

aws iam attach-role-policy \
        --policy-arn arn:aws:iam::123456789012:policy/FluentBitEKSFargate \
        --role-name eksctl-fluentbit-cluster-FargatePodExecutionRole-XXXXXXXXXX

 

上記のコマンドでは、eksctl-fluentbit-cluster-FargatePodExecutionRole-XXXXXXXXXXとなっている部分をご自身の環境に合わせて変更してください(例えば、 EKS コンソールから Fargate profileにアクセスして確認します)。同様にarn:aws:iam::123456789012:policy/FluentBitEKSFargateにあるアカウントID (123456789012)もご自身のアカウント IDに入れ替えてください。

 

ロギングインフラストラクチャーのセットアップを実施するとCloudWatchへ送信するログを生成する事が出来る様になります。

最初に、HTTP インターフェイスを利用したログを生成する Service を作成します。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

 

続いて、Deployment、Pod 、トラフィックをルーティングする Service を作成します。

 

$ kubectl -n demo apply -f logger-server.yaml && kubectl -n demo expose deploy logger-server

それでは、logger-server Deploymentが管理するPodが、実際に期待した通りにロギングが有効化されているかを確認しましょう。

 

# find the name of the logger-server pod:
$ kubectl -n demo get po -l app=nginx
NAME                            READY   STATUS    RESTARTS   AGE
logger-server-fb8546f69-qflh2   1/1     Running   0          21h

# get details about the logger-server pod:
$ kubectl -n demo describe po/logger-server-fb8546f69-qflh2    
Name:                 logger-server-fb8546f69-qflh2
Namespace:            demo
Priority:             2000001000
Priority Class Name:  system-node-critical
Node:                 fargate-ip-192-168-147-211.eu-west-1.compute.internal/192.168.147.211
Start Time:           Wed, 25 Nov 2020 16:01:51 +0000
Labels:               app=nginx
                      eks.amazonaws.com/fargate-profile=defaultfp
                      pod-template-hash=fb8546f69
Annotations:          CapacityProvisioned: 0.25vCPU 0.5GB
                      Logging: LoggingEnabled
...
Events:
  Type    Reason          Age   From               Message
  ----    ------          ----  ----               -------
  Normal  LoggingEnabled  2m7s  fargate-scheduler  Successfully enabled logging for pod
  Normal  Scheduled       44s   fargate-scheduler  Successfully assigned demo/logger-server-fb8546f69-qflh2 to fargate-ip-192-168-147-211.eu-west-1.compute.internal
  Normal  Pulling         45s   kubelet            Pulling image "nginx:1.14.2"
  Normal  Pulled          40s   kubelet            Successfully pulled image "nginx:1.14.2"
  Normal  Created         39s   kubelet            Created container main
  Normal  Started         39s   kubelet            Started container main

 

正しく動いている様です。Successfully enabled logging for podとイベントに出力されていることを確認できます。これは、次の手順に進める事が出来る事を意味しています。最後の手順はログの生成です。

logger-serverがログを生成するために、サービスをローカル環境に転送し、クライアントとしてcurlを使用してGETリクエストを発行します。加えてローカルのログをみてみましょう。3つのterminalを使って実行します。

 

# [terminal 1] forward the logger-server traffic locally:
$ 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

# [terminal 2] watch logs locally:
$ kubectl -n demo logs deploy/logger-server -f
127.0.0.1 - - [25/Nov/2020:16:03:41 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.1" "-"
127.0.0.1 - - [25/Nov/2020:16:03:42 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.1" "-"
127.0.0.1 - - [25/Nov/2020:16:03:43 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.1" "-"

# [terminal 3] generate HTTP traffic:
$ curl localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

 

Fluent Bit config mapで特定したロググループ名は fluent-bit-cloudwatchです。CloudWatch consoleで確認してみましょう。

全て期待通りに動いてます!まとめる前に、 Fluent Bit を EKS Fargateで正常に利用するたの、ヒントやTipsを紹介します。

使用上の考慮事項

ログルーターによって使用される追加のリソースについて考慮する事をお奨めします。私たちのテストでは、50MBのメモリを追加リソースとして考慮した方が良い事を示唆しています。そのため、 Fluent Bit プロセスが並んで動くために、ドキュメントに記載されている resource requestにより、アプリケーション podに対してリソースを追加しましょう。アプリケーションが大量のログを生成する事を想定している場合は、suggeted headroom として 100MBを考慮しましょう。

プラグイン (ログ送信先)の選択に依存して、ログ収集とストレージコストを別々に支払います。詳細については、CloudWatch 料金 ページを参照してください。

ローンチ時点では、以下の KubernetesおよびEKS platform versionでサポートされています。

  • Kubernetes 1.15: platform version eks.6
  • Kubernetes 1.16: platform version eks.5
  • Kubernetes 1.17: platform version eks.5
  • Kubernetes 1.18: platform version eks.3

このインテグレートされたロギングを使った感想を教えてください。また container roadmapを通じた提案をお待ちしています。追加の詳細やアナウンスメントについては re:Invent 2020 セッションを視聴してください。

 

翻訳はソリューションアーキテクトの浅野 佑貴が担当しました。原⽂はこちらです。