Kubernetes初心者が今日から始めるEKS on Fargate(その2:ログをCloudWatch Logsに出力する)

# はじめに
EKS on Fargate記事第2弾。

[前回](https://qiita.com/neruneruo/items/f043370ceca855547bdf)は、EKS on Fargate でサービスを公開するところまでを自動構築してみたが、この状態だと、Kubernetes の Pod が出力するログは ```kubectl logs``` しないと確認できなくて非常に使いづらい。
やはり、ログは CloudWatch Logs 等のサービスで確認できるようにしておきたいところだろう。

ということで、[ユーザーガイドのFargateログ記録の項](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/fargate-logging.html)ほぼそのままの内容であるが、Terraform に組み込んで自動構築できるようにしていこう。

構成については、前回の Terraform リソースに付け足すかたちになるので、まずは前回記事に目を通していただきたい。

# IAM の準備
Pod から CloudWatch Logs に出力する権限を付与する必要がある。
[前回作った](https://qiita.com/neruneruo/items/f043370ceca855547bdf#iam-%E3%81%AE%E6%BA%96%E5%82%99)、```aws_iam_role.ekspodexecution``` に、以下のポリシーを付与しよう。

```HCL
resource "aws_iam_policy" "ekspodexecution_cloudwatchlogs" {
  name   = local.ekspodexecution_policy_cloudwatchlogs_name
  policy = data.aws_iam_policy_document.ekspodexecution_cloudwatchlogs.json
}

data "aws_iam_policy_document" "ekspodexecution_cloudwatchlogs" {
  statement {
    effect = "Allow"

    actions = [
      "logs:CreateLogStream",
      "logs:CreateLogGroup",
      "logs:DescribeLogStreams",
      "logs:PutLogEvents"
    ]

    resources = [
      "*",
    ]
  }
}

resource "aws_iam_role_policy_attachment" "ekspodexecution_cloudwatchlogs" {
  role       = aws_iam_role.ekspodexecution.name
  policy_arn = aws_iam_policy.ekspodexecution_cloudwatchlogs.arn
}
```

# Kubernetes の監視設定のマニフェストの準備
まずは CloudWatch Logs 監視用の名前空間を作成する。

```YAML:aws-observability-namespace.yaml
kind: Namespace
apiVersion: v1
metadata:
  name: aws-observability
  labels:
    aws-observability: enabled
```

次に、この名前空間に監視設定を入れる。

```YAML:aws-logging-cloudwatch-configmap-template.yaml
kind: ConfigMap
apiVersion: v1
metadata:
  name: aws-logging
  namespace: aws-observability
  labels:
data:
  output.conf: |
    [OUTPUT]
        Name cloudwatch_logs
        Match   *
        region ${eks_cluster_region}
        log_group_name ${cloudwatch_loggroup_name}
        log_stream_prefix from-fluent-bit-
        auto_create_group true
```

リージョンとロググループ名を環境に合わせて変更する必要があるので、以下のように ```template_file``` を使って置換しよう。
```aws_cloudwatch_log_group.example``` はあらかじめリソースを用意しておこう。

```HCL
data "aws_region" "current" {}

resource "local_file" "awslogging_cloudwatch_configmap" {
  filename = "./output_files/aws-logging-cloudwatch-configmap.yaml"
  content  = data.template_file.awslogging_cloudwatch_configmap.rendered
}

data "template_file" "awslogging_cloudwatch_configmap" {
  template = file("${path.module}/kubernetes_template/aws-logging-cloudwatch-configmap-template.yaml")

  vars = {
    eks_cluster_region       = data.aws_region.current.name
    cloudwatch_loggroup_name = aws_cloudwatch_log_group.example.name
  }
}
```

# Kubernetes への適用
前項で準備したリソースに対して適用を行う。
依存関係は Pod 起動の前が良いだろう。サンプルでは [CoreDNS の変更](https://qiita.com/neruneruo/items/f043370ceca855547bdf#coredns-%E3%82%92-fargate-%E5%90%91%E3%81%91%E3%81%AB%E6%9B%B8%E3%81%8D%E6%8F%9B%E3%81%88%E3%82%8B)後に実行している。
後続リソース作成の depends_on も忘れないように。

```HCL
resource "null_resource" "create_namespace_awsobservability" {
  depends_on = [null_resource.coredns_restart]

  provisioner "local-exec" {
    environment = {
      KUBECONFIG = local_file.kubeconfig.filename
    }
    command = "kubectl apply -f ./output_files/aws-observability-namespace.yaml"

    on_failure = fail
  }
}

resource "null_resource" "apply_awslogging_cloudwatch_configmap" {
  depends_on = [null_resource.create_namespace_awsobservability]

  provisioner "local-exec" {
    environment = {
      KUBECONFIG = local_file.kubeconfig.filename
    }
    command = "kubectl apply -f ./output_files/aws-logging-cloudwatch-configmap.yaml"

    on_failure = fail
  }
}
```

# 後片付け
これはおそらく不要だと思うが、もし後片付けで完全にキレイにするなら、```terraform destroy``` 時に ```null_resource``` 内で以下も実行するようにしておこう。

```shell
      kubectl delete -f ./output_files/aws-logging-cloudwatch-configmap.yaml --grace-period=0 --force &&
      kubectl delete -f ./output_files/aws-observability-namespace.yaml --grace-period=0 --force &&
```

これで、指定したロググループに "from-fluent-bit-*" なファイル名で Pod のログが出力されるようになった！