AWS Load Balancer Controllerを試してみる(EKS on Fargate with NLB)
AWS Load Balancer Controllerとは
で発表された、ALB Ingress Controllerに変わる新しいAWS EKS用のLB管理Controllerです。
できるようになったこと
EKS on FargateでNLBが利用できる
今までEKS on FargateではALBしか利用できなかったですが、NLBが利用可能になったことでHTTP/HTTPS以外のPortの利用や、PrivateLinkを利用したFargateでのPodの利用が可能になりました。
複数Ingressに対してグルーピングが可能に
今まではIngressリソースごとにALBが作成されましたが、グルーピングすることで一つのALBで複数のIngressリソースを管理可能になりました。
今回はEKS on Fargate with NLBを試してみました。
ドキュメント
現状ドキュメントの方ではなく、docsに手順が乗っています。
前提
- EKSのバージョンが1.18以上であること
- CertManagerをインストールしていること(ドキュメントにインストール方法があります)
上記のドキュメントの通りに作成(厳密にはTerraform管理しているため、実施内容は別ですが、やっていることは同じです)しました。また、自分の環境ではdefault/kube-systemもfargate profileに追加しております。
動作確認
実行に失敗する
ALB Ingress Controllerと同様に、region/vpc-idが必要となります。
kubectl logs aws-load-balancer-controller-8964bc966-55cpb
> {"level":"info","ts":1603606317.8964105,"msg":"version","GitVersion":"v2.0.0-dirty","GitCommit":"1028fa4f363a9a8e37b07ff6a093b7b422923512","BuildDate":"2020-10-23T01:34:38+0000"}
{"level":"error","ts":1603606324.157537,"logger":"setup","msg":"unable to initialize AWS cloud","error":"failed to introspect region from EC2Metadata, specify --aws-region instead if EC2Metadata is unavailable: EC2MetadataRequestError: failed to get EC2 instance identity document\ncaused by: RequestError: send request failed\ncaused by: Get \"http://169.254.169.254/latest/dynamic/instance-identity/document\": dial tcp 169.254.169.254:80: i/o timeout (Client.Timeout exceeded while awaiting headers)"}
そのため、以下のようにdeploymentにparameterを追加する必要があります。
apiVersion: apps/v1
kind: Deployment
metadata:
name: aws-load-balancer-controller
spec:
...snip...
containers:
- name: controller
args:
- --cluster-name=<my cluster name>
- --ingress-class=alb
- --aws-region=ap-northeast-1
- --aws-vpc-id=<my vpc id>
こちらをみたところ、EC2のPodであれば起きないかもしれないです。
Roleの権限がない
AWS Load Balancer Controllerの作成後、Podでエラーが発生しました。
kubectl logs aws-load-balancer-controller-79d6b9dc85-89stk
> E1025 07:26:49.919688 1 leaderelection.go:324] error initially creating leader election record: configmaps is forbidden: User "system:serviceaccount:kube-system:aws-load-balancer-controller" cannot create resource "configmaps" in API group "" in the namespace "kube-system"
そのため、install.yamlのRoleを以下に変更しました。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/name: aws-load-balancer-controller
name: aws-load-balancer-controller-leader-election-role
namespace: kube-system
rules:
- apiGroups:
- ""
# resourceNames:
# - aws-load-balancer-controller-leader
resources:
- configmaps
verbs:
- create
- get
- update
- patch
上記を適用した後、正常に起動しました。
{"level":"info","ts":1603611222.7421174,"msg":"version","GitVersion":"v2.0.0-dirty","GitCommit":"1028fa4f363a9a8e37b07ff6a093b7b422923512","BuildDate":"2020-10-23T01:34:38+0000"}
...snip...
{"level":"info","ts":1603611242.1381829,"logger":"controller","msg":"Starting workers","controller":"service","worker count":3}
{"level":"info","ts":1603611242.2380457,"logger":"controller","msg":"Starting workers","controller":"ingress","worker count":3}
{"level":"info","ts":1603611242.239579,"logger":"controller","msg":"Starting Controller","reconcilerGroup":"elbv2.k8s.aws","reconcilerKind":"TargetGroupBinding","controller":"targetGroupBinding"}
{"level":"info","ts":1603611242.239718,"logger":"controller","msg":"Starting workers","reconcilerGroup":"elbv2.k8s.aws","reconcilerKind":"TargetGroupBinding","controller":"targetGroupBinding","worker count":3}
EKS on FargateでNLB
サンプルとして、NginXをたてます。Manifestは以下の通りです。
ポイントは、service.beta.kubernetes.io/aws-load-balancer-type: "nlb-ip"
をannotationで追加する点です。
nginx.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: default
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: default
labels:
app: nginx
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb-ip"
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
type: LoadBalancer
kubectl apply -f nginx.yaml
動作確認
上記作成時に、AWS Load Balancer Controllerがfetchし、設定をしてくれます。
- Serviceの作成をControllerが検知
- TargetGroupを作成
- LoadBalancerを作成
- Listenerを作成
- targetGroupBindingを作成(ServiceとAWSのTargetGroupを紐づけるCRDです)
- securityGroupを作成
- TargetGroupにPodのIPを登録
その後、AWS側で確認すると、NLBでType: IPで作成できているのが確認できました。
疎通もOKです。
curl k8s-default-nginx-<domain>
>
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
annotation typeはこちらにあります。NLBの場合基本Internalに立てると思いますので、その場合にはservice.beta.kubernetes.io/aws-load-balancer-internal: true
を設定する必要があります。
削除
kubectl delete -f nginx.yaml
作成時と同様に、AWS Load Balancer Controllerがfetchし、AWSリソースを削除してくれます。
おわりに
これでNLBでもFargateが利用できるようになったので、EKS Fargateの幅も大きく広がったのかなと思います。EKS Master UpgradeでもFargateはPodを再作成するだけでバージョンがあげられるので、運用コストの削減ができれば良いかなと考えています。
また、複数Ingressに対してグルーピングが可能となる機能も次に試してみようと思います。
Discussion