Amazon EKSでNGINX Ingress ControllerにS3ログ出力を設定する

# はじめに
Amazon EKSで[NGINX Ingress Controller](https://github.com/kubernetes/ingress-nginx)にS3ログ出力を設定する方法をまとめます。
Mac環境を想定しています。

# 実行環境の準備
1.  AWS CLIの設定
[AWS CloudFormationを動かすためのAWS CLIの設定](https://qiita.com/miyabiz/items/fed11796f0ea2b7608f4)を参考にしてください。

1.  EKSクラスタの構築
[Macでeksctlを利用してAmazon EKSのクラスターを構築する](https://qiita.com/miyabiz/items/75f83237795b0b7d52bd)を参考にしてください。

1.  EKSのコンテキストの設定
[MacにてAmazon EKSの設定をする](https://qiita.com/miyabiz/items/b98d145cedb35dab9524)を参考にしてください。

1.  Helmの設定
[Amazon EKSでHelmを利用する](https://qiita.com/miyabiz/items/453361e6af64b324443c)を参考にしてください。

1.  NGINX Ingress Controllerの設定
[Amazon EKSでNGINX Ingress Controllerを利用する](https://qiita.com/miyabiz/items/33258b8fefb9b161a2dd)を参考にしてください。

1.  NGINX Ingress ControllerのAWS Certificate Managerの設定
[Amazon EKSでNGINX Ingress ControllerにAWS Certificate Managerを利用する](https://qiita.com/miyabiz/items/67b3c14f44c66c24aabc)を参考にしてください。

# S３バケットの作成

1. S３バケットを作成する
    ※今回は `akane-dev-elb-access-log` というバケット名にする
    ```sh
    BUCKET_NAME=akane-dev-elb-access-log
    aws s3api create-bucket \
      --bucket ${BUCKET_NAME} \
      --create-bucket-configuration LocationConstraint=ap-northeast-1
    ```

1.  バケットポリシーを設定する
    ※[Classic Load Balancer のアクセス ログを有効にする](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html)を参考にしてください。
    ※今回は東京リージョンのため、ELBのサービスアカウント(ELBのAWSアカウントID)である`582318560864`を設定する
    ※今回はプレフィクスを`public-elb`にする。

    ```sh
    export ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account)
    BUCKET_NAME=akane-dev-elb-access-log
    PREFIX=public-elb
    BUCKET_POLICY=$(echo -n '{
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::582318560864:root"
          },
          "Action": "s3:PutObject",
          "Resource": "arn:aws:s3:::'; echo -n "${BUCKET_NAME}"; echo -n '/'; echo -n "${PREFIX}"; echo -n '/AWSLogs/'; echo -n "${ACCOUNT_ID}"; echo -n '/*"
        }
      ]
    }')
    aws s3api put-bucket-policy \
    --bucket ${BUCKET_NAME} \
    --policy "${BUCKET_POLICY}"
    ```

# 環境設定
1.  `patch.yaml` を作成する
    ※[ELB Access Logs on AWS](https://kubernetes.io/docs/concepts/services-networking/service/#elb-access-logs-on-aws)を参考にしてください。
    ※バケット名、プレフィクスを設定する
    ※今回は `akane-dev-elb-access-log` というバケット名にする。
    ※今回はプレフィクスを`public-elb`にする。

    ```yaml:paatch.yaml
    controller:
      service:
        targetPorts:
          http: http
          https: http
        annotations:
          service.beta.kubernetes.io/aws-load-balancer-ssl-cert: ${ACMのARN}
          service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
          service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
          service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: '3600'
          # Specifies whether access logs are enabled for the load balancer
          service.beta.kubernetes.io/aws-load-balancer-access-log-enabled: "true"
          # The interval for publishing the access logs. You can specify an interval of either 5 or 60 (minutes).
          service.beta.kubernetes.io/aws-load-balancer-access-log-emit-interval: "60"
          # The name of the Amazon S3 bucket where the access logs are stored
          service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-name: "akane-dev-elb-access-log"
          # The logical hierarchy you created for your Amazon S3 bucket, for example `my-bucket-prefix/prod`
          service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-prefix: "public-elb/prod"
    ```

1.  NGINX Ingress ControllerのチャートをHelmでアップグレードする
    ※事前にKubernetesクラスターのコンテキストの設定をします。

    ```sh
    helm upgrade -i nginx-ingress-controller \
        ingress-nginx/ingress-nginx \
        -n nginx-ingress-controller \
        -f patch.yaml
    ```

# クリーンアップ

1.  NGINX Ingress ControllerをHelmで削除する

    ```sh
    helm delete nginx-ingress-controller -n nginx-ingress-controller
    ```

1.  Namespaceを削除する

    ```sh
    kubectl delete ns nginx-ingress-controller
    ```

1.  S3バケットを削除する
    ※今回は `akane-dev-elb-access-log` というバケット名にする。

    ```sh
    aws s3 rb s3://akane-dev-elb-access-log --force
    ```