EKS Fargate で ALB を使いたい時

## TL;DR

EKS で ALB を使いたいので、その辺りをうまくやってくれるコントローラをセットアップする

関連プロジェクトにある、AWS Load Balancer コントローラ

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/related-projects.html

オリジナルの手順はここ

https://aws.amazon.com/jp/premiumsupport/knowledge-center/eks-alb-ingress-controller-fargate/

## モチベーション

なるべく、helm を使ってセットアップしたい

https://artifacthub.io/packages/helm/aws/aws-load-balancer-controller

DNS もセットで使いたい場合はこちら参照

https://qiita.com/exabugs/items/9e9e41a526f99a6c1d55

## 前提

- 以下のコマンドをインストール済み
  - eksctl
  - aws
  - kubectl

## 手順

1. クラスタ作成
1. クラスターの IAM OIDC プロバイダーを作成
1. ポリシー作成
1. サービスアカウント作成
1. helm でインストール

### クラスタ作成

これは略

### クラスターの IAM OIDC プロバイダーを作成

これも、一回だけやっておけば良いから、略。
一応

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/enable-iam-roles-for-service-accounts.html

1.  OIDC プロバイダーの URL を取得

    ```
    $ aws eks describe-cluster --name <cluster_name> --query "cluster.identity.oidc.issuer" --output text
    ```

2.  まだ作成してないことを確認

    ```
    $ aws iam list-open-id-connect-providers
    ```

3.  OIDC プロバイダーを作成

    ```
    $ eksctl utils associate-iam-oidc-provider --cluster <cluster_name> --approve
    ```

4.  作成されたことを確認

    ```
    $ aws iam list-open-id-connect-providers
    ```

### ポリシー作成

1.  ポリシーの記載された json ファイルを取ってくる

    ```
    $ curl -o iam_policy.json \
        https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.2.0/docs/install/iam_policy.json
    ```

2.  ポリシーの作成

    ```
    $ aws iam create-policy \
       --policy-name AWSLoadBalancerControllerIAMPolicy \
       --policy-document file://iam_policy.json
    ```

3.  Arn をメモしておく

### サービスアカウント作成

1.  作成

    ```
    $ eksctl create iamserviceaccount \
        --cluster=<YOUR_CLUSTER_NAME> \
        --namespace=kube-system \
        --name=aws-load-balancer-controller \
        --attach-policy-arn=arn:aws:iam::<AWS_ACCOUNT_ID>:policy/AWSLoadBalancerControllerIAMPolicy \
        --override-existing-serviceaccounts \
        --approve
    ```

2.  確認

    ```
    $ kubectl describe sa/aws-load-balancer-controller -n kube-system

    Name:                aws-load-balancer-controller
    Namespace:           kube-system
    Labels:              app.kubernetes.io/managed-by=eksctl
    Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::xxx:role/xxx
    ...
    ```

### helm でインストール

1.  Amazon EKS チャートレポを Helm に追加

    ```
    $ helm repo add eks https://aws.github.io/eks-charts

    "eks" has been added to your repositories
    ```

2.  念のため、更新しておく

    ```
    $ helm repo update

    Hang tight while we grab the latest from your chart repositories...
    ...Successfully got an update from the "eks" chart repository
    Update Complete. ⎈Happy Helming!⎈
    ```

3.  TargetGroupBinding カスタムリソース定義 (CRD) をインストール

    ```
    $ kubectl apply -k "github.com/aws/eks-charts/stable/aws-load-balancer-controller/crds?ref=master"

    customresourcedefinition.apiextensions.k8s.io/ingressclassparams.elbv2.k8s.aws created
    customresourcedefinition.apiextensions.k8s.io/targetgroupbindings.elbv2.k8s.aws created
    ```

4.  Helm チャートをインストール

    ```
    $ helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
        --set serviceAccount.create=false \
        --set serviceAccount.name=aws-load-balancer-controller \
        --set clusterName=<YOUR_CLUSTER_NAME> \
        --set region=<REGION_CODE> \
        --set vpcId=<VPC_ID> \
        -n kube-system

    NAME: aws-load-balancer-controller
    LAST DEPLOYED: Thu Aug 19 16:46:36 2021
    NAMESPACE: kube-system
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    NOTES:
    AWS Load Balancer controller installed!
    ```

## 動作確認

test-nginx1 というネームスペースに nginx を起動させてみる

1.  まず、fargate profile を作成する。忘れがち。

    ```
    $ eksctl create fargateprofile \
        --cluster <YOUR_CLUSTER_NAME> \
        --region <REGION_CODE> \
        --name test-nginx1 \
        --namespace test-nginx1
    ```

2.  マニフェストを準備

    ```yaml
    ---
    apiVersion: v1
    kind: Namespace
    metadata:
      name: test-nginx1
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      namespace: test-nginx1
      name: deployment-nginx
    spec:
      selector:
        matchLabels:
          app.kubernetes.io/name: app-nginx
      replicas: 1
      template:
        metadata:
          labels:
            app.kubernetes.io/name: app-nginx
        spec:
          containers:
            - image: nginx:1.16.1
              imagePullPolicy: Always
              name: app-nginx
              ports:
                - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      namespace: test-nginx1
      name: service-nginx
    spec:
      ports:
        - port: 80
          targetPort: 80
          protocol: TCP
      type: NodePort
      selector:
        app.kubernetes.io/name: app-nginx
    ---
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      namespace: test-nginx1
      name: ingress-nginx
      annotations:
        kubernetes.io/ingress.class: alb
        alb.ingress.kubernetes.io/scheme: internet-facing
        alb.ingress.kubernetes.io/target-type: ip
        # group.name 使うと ALB を共有できる
        alb.ingress.kubernetes.io/group.name: my-group
    spec:
      rules:
        - http:
            paths:
              - path: "/*"
                backend:
                  serviceName: service-nginx
                  servicePort: 80
    ```

3.  デプロイ

    ```
    $ kubectl apply -f ./test-nginx1.yml
    ```

4.  ログ

    ```
    $ kubectl logs -f deployment/aws-load-balancer-controller -n kube-system
    ```

5.  結果
リスナーの状況
![スクリーンショット 2021-08-24 23.08.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69410/d2262be8-b296-2030-39e7-64af642ff500.png)