EKS Fargate で DNS (Route53) を使いたい時

## TL;DR

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

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

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

オリジナルの手順はここ

https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/aws.md

## モチベーション

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

https://artifacthub.io/packages/helm/bitnami/external-dns

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

https://qiita.com/exabugs/items/be9c6e6f36ed48462527

## 前提

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

  - 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.  ポリシーが記載された json ファイルを、テキストエディタ等で作成。ファイル名は iam_policy.json。

    ```json
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": ["route53:ChangeResourceRecordSets"],
          "Resource": ["arn:aws:route53:::hostedzone/*"]
        },
        {
          "Effect": "Allow",
          "Action": [
            "route53:ListHostedZones",
            "route53:ListResourceRecordSets"
          ],
          "Resource": ["*"]
        }
      ]
    }
    ```

2.  ポリシーの作成

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

3.  Arn をメモしておく

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

1.  作成

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

2.  確認

    ```
    $ kubectl describe sa/external-dns -n kube-system

    Name:                external-dns
    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 bitnami https://charts.bitnami.com/bitnami

    "bitnami" 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 "bitnami" chart repository
    Update Complete. ⎈Happy Helming!⎈
    ```

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

    ```
    helm install external-dns bitnami/external-dns \
        --set serviceAccount.create=false \
        --set serviceAccount.name=external-dns \
        --set policy=sync \
        --set aws.zoneType=public \
        --set txtOwnerId=<ホストゾーンID> \
        --set domainFilters[0]=<ドメイン> \
        -n kube-system

    NAME: external-dns
    LAST DEPLOYED: Tue Aug 24 13:46:57 2021
    NAMESPACE: kube-system
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    NOTES:
    ** Please be patient while the chart is being deployed **

    To verify that external-dns has started, run:

    kubectl --namespace=kube-system get pods -l "app.kubernetes.io/name=external-dns,app.kubernetes.io/instance=external-dns"
    ```

## 動作確認

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:
        - host: test-nginx1.<ドメイン>
          http:
            paths:
              - backend:
                  serviceName: service-nginx
                  servicePort: 80
    ```

3.  デプロイ

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

4.  ログ

    ```
    $ kubectl logs -f deployment/external-dns -n kube-system
    ```

5.  結果
DNS　の状況
![スクリーンショット_2021-08-24_23_12_51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69410/3652ab71-296c-7e71-d12d-18f11547374a.png)