EKS Ingress Resourse(ALB)を作成する

## What's This

AWSにおいて、k8sでいうIngressはどう作成するのか調査。
ALBを使うのだろうということは想定していたが、どうやって作成するのか気になった。

AWS Load Balancer Controllerを使用して、Ingress を作成したメモです。
あくまでメモなので、参考にされる場合は、公式ドキュメント等の副読的な感じで読まれると幸いです。

## 概念
### 大まかな概念

ALBは、Kubernetes Manifestから、ALB Ingress Controllerを使用して作成できる。
このControllerは、元々はAWS ALB Ingress Controllerだったものが、
Rename & Redesignedされて、AWS Load Balancer Controllerに変わったらしい。
（何が変わったのかよくわかっていない）

＊元々ALBしか作成できなかったが、ALBとNLBも作成できるようになった、という変更があるらしい。
前者の方はもう開発もされておらず、最新のk8s Versionもサポートしないらしい。

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/aws-load-balancer-controller.html
https://kubernetes.io/ja/docs/tutorials/kubernetes-basics/expose/expose-intro/

### modeについて

#### Instance mode
クラスター内のノードをALBのターゲットとして登録する。
デフォルトのモード。
サービスの NodePort にルーティングされてから、pods にプロキシされる。
(NodePortはKubernetesのNodeのランダムなポートを使用して外部のサーバーからの疎通性を取ってくれる。)

以下のように、Annotationで明示的に指定することもできる。

```
alb.ingress.kubernetes.io/target-type: instance
```

#### IP mode
Podを ALBのターゲットとして設定する。
ALB に到達するトラフィックは、サービスの pods に直接ルーティングされる。
このトラフィックモードを使用するには、 以下のように、Annotationで指定する。

```
alb.ingress.kubernetes.io/target-type: ip 
```

### イメージ

![スクリーンショット 2022-08-10 15.34.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/30266ede-f075-4d75-61fc-20213adb1aae.png)

## やってみた

ALB Ingress Controllerを使用して、ALBを作成する。DNS名でアプリを開けるか検証する。

### ALB Ingress Controller用にIAMを整える

```
# Cluster Create
eksctl create cluster --name=`Cluster Name` --nodes=1 --node-type=t3.small --zones=ap-northeast-1a,ap-northeast-1c --without-nodegroup 

# eksctl versionが最新であることを確認
$ eksctl version
0.107.0

# OIDC Create
$ eksctl utils associate-iam-oidc-provider --region ap-northeast-1 --cluster `Cluster Name` --approve

# NodeGroup Create
$ eksctl create nodegroup --cluster=`Cluster Name` --region=ap-northeast-1 --name=`NodeGroup Name` --node-type=t3.medium --nodes-min=2 --nodes-max=4 --node-volume-size=20 --ssh-access --managed --asg-access --external-dns-access --full-ecr-access --appmesh-access --alb-ingress-access 
$ eksctl get nodegroup --cluster=`Cluster Name`

# Context 設定
$ aws eks --region ap-northeast-1 update-kubeconfig --name `Cluster Name`

# Nodeができていることを確認
$ kubectl get nodes

# AWS Load Balancer ControllerにIAMポリシーを作成し、AWS APIへの呼び出しを代行させる。
$ curl -o iam_policy_latest.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json

＃ Create Policy
$ aws iam create-policy \
>     --policy-name AWSLoadBalancerControllerIAMPolicy \
>     --policy-document file://iam_policy_latest.json

# Create IAM Role using eksctl
# kube-system名前空間に、作成予定のサービスアカウントがないことを確認。
$ kubectl get sa -n kube-system
$ kubectl get sa aws-load-balancer-controller -n kube-system
Error from server (NotFound): serviceaccounts "aws-load-balancer-controller" not found

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

$ eksctl  get iamserviceaccount --cluster `Cluster Name`
NAMESPACE       NAME                            ROLE ARN
kube-system     aws-load-balancer-controller    arn:aws:iam::

$ kubectl get sa aws-load-balancer-controller -n kube-system
NAME                           SECRETS   AGE
aws-load-balancer-controller   1         7m8s

$ 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::
Image pull secrets:  <none>
Mountable secrets:   aws-load-balancer-controller-token-
Tokens:              aws-load-balancer-controller-token-
Events:              <none>
```

### Helm & aws-load-balancer-controller Install 

```
# Helm Install
$ brew install helm
$ helm version
$ helm repo update

# ECRについてはコード外の資料を参照
$ helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=`Cluster Name`　--set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller --set image.repository=602401143452.dkr.ecr.ap-northeast-1.amazonaws.com/amazon/aws-load-balancer-controller

NAME: aws-load-balancer-controller
LAST DEPLOYED: 
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
AWS Load Balancer controller installed!

$ kubectl -n kube-system get deployment 

NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   2/2     2            2           36s
coredns                        2/2     2            2           60m

$ kubectl -n kube-system describe deployment aws-load-balancer-controller

# Webhook-svcが作成されていることを確認。
$ kubectl -n kube-system get svc 
NAME                                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)         AGE
aws-load-balancer-webhook-service   ClusterIP   xx.xxx.xx.x   <none>        443/TCP         73s
kube-dns                            ClusterIP   xx.xxx.x.x    <none>        53/UDP,53/TCP   60m

$ kubectl -n kube-system describe svc aws-load-balancer-webhook-service
$ kubectl -n kube-system get svc aws-load-balancer-webhook-service -o yaml
$ kubectl -n kube-system get deployment aws-load-balancer-controller -o yaml

$ kubectl get pods -n kube-system
NAME                                            READY   STATUS    RESTARTS   AGE
aws-load-balancer-controller-xxxxxxxxxxxxxxxxx  1/1     Running   0          8m12s
aws-load-balancer-controller-xxxxxxxxxxxxxxxx   1/1     Running   0          8m12s
aws-node-xxxxx                                  1/1     Running   0          43m
aws-node-xxxxx                                  1/1     Running   0          43m
coredns-xxxxxxxxxxxxxxxx                        1/1     Running   0          67m
coredns-xxxxxxxxxxxxxxxx                        1/1     Running   0          67m
kube-proxy-xxxxx                                1/1     Running   0          43m
kube-proxy-xxxxx                                1/1     Running   0          43m

# Log 確認
$ kubectl -n kube-system logs -f aws-load-balancer-controller-xxxxxxxxxxxxxxxxx

# Secretが作成されていることを確認
$ kubectl -n kube-system get sa aws-load-balancer-controller -o yaml
$ kubectl -n kube-system get secret aws-load-balancer-controller-token-xxxxx -o yaml
$ kubectl -n kube-system get secret aws-load-balancer-controller-token-xxxxx
NAME                                       TYPE                                  DATA   AGE
aws-load-balancer-controller-token-xxxxx   kubernetes.io/service-account-token   3      28m

$ kubectl -n kube-system get secret aws-load-balancer-controller-token-xxxxx -o yaml

# kube-system内のdeployment確認
$ kubectl get deployment.apps -n kube-system
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   2/2     2            2           48m
coredns                        2/2     2            2           107m

$ kubectl describe deployment.apps/aws-load-balancer-controller -n kube-system
```
ECRについては以下参照
https://docs.aws.amazon.com/eks/latest/userguide/add-ons-images.html

### Sample Application Deploy

```
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.2/docs/examples/2048/2048_full.yaml
namespace/game-2048 created
deployment.apps/deployment-2048 created
service/service-2048 created
ingress.networking.k8s.io/ingress-2048 created

$ kubectl get ingress/ingress-2048 -n game-2048
NAME           CLASS   HOSTS   ADDRESS  PORTS   AGE
ingress-2048   alb     *       k8s-game2048-ingress2-xxx.ap-northeast-1.elb.amazonaws.com   80      22s
```

ADDRESSにアクセス。表示されました。

![スクリーンショット 2022-08-08 15.39.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/66336e97-69df-e6fd-a5c6-2eb87d380750.png)

## Conclusion
この検証では、バージョン関係でエラーになり、最初からやり直すことが多かったので、
もし試す際には、その辺りを意識されると手戻りが少なく済むかもしれないです。

`例`
https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/ `v2.4.2` /
https://kubernetes-sigs.github.io/aws-load-balancer-controller/ `v2.3` /

こんな感じで、kubernetes sigsのリソースを使用する際は、バージョンが最新か確認するといいかもしれないです。

## Refference 
・https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/alb-ingress.html
・https://www.eksworkshop.com/beginner/130_exposing-service/ingress/
・https://dev.classmethod.jp/articles/eks-aws-alb-ingress-controller/
・https://developer.mamezou-tech.com/containers/k8s/tutorial/ingress/ingress-aws/
・https://github.com/stacksimplify/aws-eks-kubernetes-masterclass/tree/master/08-NEW-ELB-Application-LoadBalancers/08-01-Load-Balancer-Controller-Install

参考にさせていただきました。ありがとうございます。