K8sのIngressからALBを設定できるAWS Load Balancer Controllerというものがあります。(昔はALB Ingress Controllerと呼びました。)
基本metadata.annotations部分に特有の設定を書くのですが、複数のIngress設定を1本のALBにまとめるグルーピングなどが追加されてだいぶ便利になっているみたいなので試してみましょう。
EKSの環境を用意
↓を参考にそのまま構築しました。
バージョン等はこんな感じ。
$ 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しました。
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)でもできるはず。
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