AWS Load Balancer Controllerお試し

K8sのIngressからALBを設定できるAWS Load Balancer Controllerというものがあります。(昔はALB Ingress Controllerと呼びました。)
基本metadata.annotations部分に特有の設定を書くのですが、複数のIngress設定を1本のALBにまとめるグルーピングなどが追加されてだいぶ便利になっているみたいなので試してみましょう。

# EKSの環境を用意

↓を参考にそのまま構築しました。

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started-console.html

バージョン等はこんな感じ。

```json
$ kubectl version -o json
{
  "clientVersion": {
    "major": "1",
    "minor": "20+",
    "gitVersion": "v1.20.4-eks-6b7464",
    "gitCommit": "6b746440c04cb81db4426842b4ae65c3f7035e53",
    "gitTreeState": "clean",
    "buildDate": "2021-03-19T19:35:50Z",
    "goVersion": "go1.15.8",
    "compiler": "gc",
    "platform": "linux/amd64"
  },
  "serverVersion": {
    "major": "1",
    "minor": "20+",
    "gitVersion": "v1.20.4-eks-6b7464",
    "gitCommit": "6b746440c04cb81db4426842b4ae65c3f7035e53",
    "gitTreeState": "clean",
    "buildDate": "2021-03-19T19:33:03Z",
    "goVersion": "go1.15.8",
    "compiler": "gc",
    "platform": "linux/amd64"
  }
}
```

# バックエンドを用意

今回はFargateオンリーで構築。ちょっと重いね。。。

```
$ kubectl get all,node -A
NAMESPACE     NAME                           READY   STATUS    RESTARTS   AGE
kube-system   pod/coredns-867ff8777b-6wr7z   1/1     Running   0          5m25s
kube-system   pod/coredns-867ff8777b-wt6kk   1/1     Running   0          5m25s

NAMESPACE     NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)         AGE
default       service/kubernetes   ClusterIP   10.100.0.1    <none>        443/TCP         10m
kube-system   service/kube-dns     ClusterIP   10.100.0.10   <none>        53/UDP,53/TCP   10m

NAMESPACE     NAME                        DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
kube-system   daemonset.apps/aws-node     0         0         0       0            0           <none>          10m
kube-system   daemonset.apps/kube-proxy   0         0         0       0            0           <none>          10m

NAMESPACE     NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   deployment.apps/coredns   2/2     2            2           10m

NAMESPACE     NAME                                 DESIRED   CURRENT   READY   AGE
kube-system   replicaset.apps/coredns-867ff8777b   2         2         2       5m29s
kube-system   replicaset.apps/coredns-86d9946576   0         0         0       10m

NAMESPACE   NAME                                                        STATUS   ROLES    AGE     VERSION
            node/fargate-ip-192-168-187-11.us-west-2.compute.internal   Ready    <none>   4m11s   v1.20.4-eks-6b7464
            node/fargate-ip-192-168-97-114.us-west-2.compute.internal   Ready    <none>   4m8s    v1.20.4-eks-6b7464
```

nginxイメージで適当に2つぐらいコンテナを立てておきます。


```
$ kubectl get pod,svc -owide
NAME                        READY   STATUS    RESTARTS   AGE   IP                NODE                                                    NOMINATED NODE   READINESS GATES
pod/pod1-7fcbd8bcc5-85fbc   1/1     Running   0          59m   192.168.190.214   fargate-ip-192-168-190-214.us-west-2.compute.internal   <none>           <none>
pod/pod2-7c899f6dff-ht2r6   1/1     Running   0          58m   192.168.108.37    fargate-ip-192-168-108-37.us-west-2.compute.internal    <none>           <none>

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE   SELECTOR
service/kubernetes   ClusterIP   10.100.0.1       <none>        443/TCP        75m   <none>
service/pod1-svc     NodePort    10.100.99.158    <none>        80:31102/TCP   59m   app=web-pod1
service/pod2-svc     NodePort    10.100.200.246   <none>        80:31240/TCP   58m   app=web-pod2
```

こんな感じでそれぞれ別のindex.htmlを置いています。

```
$ kubectl exec -it pod/pod1-7fcbd8bcc5-85fbc -- curl pod1-svc
pod1
$ kubectl exec -it pod/pod1-7fcbd8bcc5-85fbc -- curl pod2-svc
pod2
```

# AWS Load Balancer Controllerをインストール

↓を参考にインストールします。
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/aws-load-balancer-controller.html

途中AWS Load Balancer Controllerをインストールするところで、helmかKubernetes manifestを使うか選択できますが、fargateの場合にはHelmを使わないとうまくいきませんでした。気を付けてください。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/eks-alb-ingress-controller-fargate/#:~:text=system-,helm%20,-%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6

こんな感じになります。aws-load-balancer-controllerのpodが動いていれば大丈夫だと思います。

```
$ kubectl get all,ing -A                                                                                                                                                                                                NAMESPACE     NAME                                                READY   STATUS    RESTARTS   AGE                                                                                                                                     default       pod/pod1-7fcbd8bcc5-85fbc                           1/1     Running   0          139m                                                                                                                                    default       pod/pod2-7c899f6dff-ht2r6                           1/1     Running   0          137m                                                                                                                                    kube-system   pod/aws-load-balancer-controller-74d859d5f8-4c9jf   1/1     Running   0          8m13s                                                                                                                                   kube-system   pod/aws-load-balancer-controller-74d859d5f8-htgwt   1/1     Running   0          8m13s                                                                                                                                   kube-system   pod/coredns-867ff8777b-6wr7z                        1/1     Running   0          149m                                                                                                                                    kube-system   pod/coredns-867ff8777b-wt6kk                        1/1     Running   0          149m                                                                                                                                                                                                                                                                                                                                                                           NAMESPACE     NAME                                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE                                                                                                               default       service/kubernetes                          ClusterIP   10.100.0.1       <none>        443/TCP         154m
default       service/pod1-svc                            NodePort    10.100.99.158    <none>        80:31102/TCP    139m
default       service/pod2-svc                            NodePort    10.100.200.246   <none>        80:31240/TCP    137m
kube-system   service/aws-load-balancer-webhook-service   ClusterIP   10.100.76.88     <none>        443/TCP         19m
kube-system   service/kube-dns                            ClusterIP   10.100.0.10      <none>        53/UDP,53/TCP   154m

NAMESPACE     NAME                        DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
kube-system   daemonset.apps/aws-node     0         0         0       0            0           <none>          154m
kube-system   daemonset.apps/kube-proxy   0         0         0       0            0           <none>          154m

NAMESPACE     NAME                                           READY   UP-TO-DATE   AVAILABLE   AGE
default       deployment.apps/pod1                           1/1     1            1           139m
default       deployment.apps/pod2                           1/1     1            1           137m
kube-system   deployment.apps/aws-load-balancer-controller   2/2     2            2           19m
kube-system   deployment.apps/coredns                        2/2     2            2           154m

NAMESPACE     NAME                                                      DESIRED   CURRENT   READY   AGE
default       replicaset.apps/pod1-7fcbd8bcc5                           1         1         1       139m
default       replicaset.apps/pod2-7c899f6dff                           1         1         1       137m
kube-system   replicaset.apps/aws-load-balancer-controller-74d859d5f8   2         2         2       19m
kube-system   replicaset.apps/coredns-867ff8777b                        2         2         2       149m
kube-system   replicaset.apps/coredns-86d9946576                        0         0         0       154m
```


# 試す。

まずこんな感じのIngressをapplyしました。

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: alb-test-lb1
  namespace: default
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing # 内部向けか外向けか。
    alb.ingress.kubernetes.io/subnets: subnet-0f6c013aa25124503, subnet-0e83f3865dbd22f6f, subnet-04597c59e26beded5 # VPCで設定してあるPublic subnetを入れておく。tagでもできる。
    alb.ingress.kubernetes.io/group.name: zougumi # グループ名を同じにしておくと複数のIngressで1つのALBを共有する。（お得）
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]' # 受け付けるポート。デフォルト
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:723968481686:certificate/0dd5932b-e774-4bbf-bd6b-9d83435a9d96 # ACMで証明書を作っておく。
    alb.ingress.kubernetes.io/target-type: ip # fargateの場合ipにしておかないとだめ。
    alb.ingress.kubernetes.io/ssl-redirect: "443"
spec:
  rules:
    - host: pod1.alb-test.deroris.net # applyしたらroute53に登録すべし。
      http:
        paths:
          - pathType: Prefix
            path: /
            backend:
              service:
                name: "pod1-svc" # Podのservice名
                port:
                  number: 80
    - host: pod2.alb-test.deroris.net
      http:
        paths:
          - pathType: Prefix
            path: /
            backend:
              service:
                name: "pod2-svc" #  Podのservice名
                port:
                  number: 80

```

少し待つと、AWSコンソールにもALBが現れて、ターゲットグループも入ります。
出てこない場合はコントローラーのログを見ましょう。こんな感じ。 `$ kubectl logs -n kube-system pod/aws-load-balancer-controller-74d859d5f8-4c9jf -f`


# いくつかお試し。

なんて言ったって使いたかったのは`alb.ingress.kubernetes.io/group.name` 
こいつを使えば1つのALBで複数Ingressを束ねられてお得。

同じgroup.nameでalb-test-lb2を追加。hostは1-1とかにしてある。別のPod(Service)でもできるはず。

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: alb-test-lb2
  namespace: default
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/subnets: subnet-0f6c013aa25124503, subnet-0e83f3865dbd22f6f, subnet-04597c59e26beded5
    alb.ingress.kubernetes.io/group.name: zougumi
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:723968481686:certificate/0dd5932b-e774-4bbf-bd6b-9d83435a9d96
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/ssl-redirect: "443"
spec:
  rules:
    - host: pod1-1.alb-test.deroris.net
      http:
        paths:
          - pathType: Prefix
            path: /
            backend:
              service:
                name: "pod1-svc"
                port:
                  number: 80
    - host: pod1-2.alb-test.deroris.net
      http:
        paths:
          - pathType: Prefix
            path: /
            backend:
              service:
                name: "pod2-svc"
                port:
                  number: 80
```

2個になった。

```
$ kubectl get ing -A
NAMESPACE   NAME           CLASS    HOSTS                                                         ADDRESS                                                         PORTS   AGE
default     alb-test-lb1   <none>   pod1.alb-test.deroris.net,pod2.alb-test.deroris.net       k8s-zougumi-1361e979ce-1308419168.us-west-2.elb.amazonaws.com   80      72m
default     alb-test-lb2   <none>   pod1-1.alb-test.deroris.net,pod1-2.alb-test.deroris.net   k8s-zougumi-1361e979ce-1308419168.us-west-2.elb.amazonaws.com   80      108s
```

ALB自体は1つ。AWS Consoleからみるとリスナーが増えているだけ。

セキュリティグループを分けなればならない場合には、ALB自体も分けなければならない。それ以外なら共有してしまってよいのではないかと思う。1か月3,000円ぐらいするので。節約しなければならない場合にはよいと思う。

`alb.ingress.kubernetes.io/wafv2-acl-arn` でWAFも設定できる。

アノテーションの一覧はこちら。
https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/main/docs/guide/ingress/annotations.md