AWS Load Balancer Controllerを試す

AWS Load Balancer Controllerを試してみたメモ。

コンポーネント バージョン 備考
eksctl 0.30.0
Kubernetes バージョン 1.18
プラットフォームのバージョン eks.1
aws-load-balancer-controller 2.0.0

参考リンク

概要

ALB Ingress Controllerを大幅にバージョンアップして名前も変えたもの。主な新機能は3つ。

  • NLB IPモードのサポート
  • 複数のIngressリソースでALBを共有できる
  • TargetGroupBindingカスタムリソース

導入

クラスターを作成する。

eksctl create cluster \
  --name=mycluster \
  --version 1.18 \
  --nodes=2 --managed \
  --ssh-access --ssh-public-key=default

OICDプロバイダーを作成する。

eksctl utils associate-iam-oidc-provider \
    --region ap-northeast-1 \
    --cluster mycluster \
    --approve

IAMポリシーを作成する。

curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json
aws iam create-policy \
    --policy-name AWSLoadBalancerControllerIAMPolicy \
    --policy-document file://iam-policy.json

IAMロールとServiceAccountを作成する。

eksctl create iamserviceaccount \
  --cluster=mycluster \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --attach-policy-arn=arn:aws:iam::XXXXXXXXXXXX:policy/AWSLoadBalancerControllerIAMPolicy \
  --override-existing-serviceaccounts \
  --approve

CRDを作成する。-kはKustomizeオプション。

kubectl apply -k "github.com/aws/eks-charts/stable/aws-load-balancer-controller//crds?ref=master"

チャートのリポジトリを追加する。

helm repo add eks https://aws.github.io/eks-charts

既にリポジトリが存在した場合は、チャートを更新する。

helm repo update

チャートを確認する。

$ helm search repo aws-load-balancer
NAME                                CHART VERSION   APP VERSION DESCRIPTION
eks/aws-load-balancer-controller    1.0.0           v2.0.0      AWS Load Balancer Controller Helm chart for Kub...

インストールする。

helm upgrade -i aws-load-balancer-controller eks/aws-load-balancer-controller \
  --set clusterName=mycluster \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller \
  -n kube-system

以下の様に出力される。

Release "aws-load-balancer-controller" does not exist. Installing it now.
NAME: aws-load-balancer-controller
LAST DEPLOYED: Tue Oct 27 00:37:31 2020
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
AWS Load Balancer controller installed!

Podが起動していることを確認する。

$ kubectl get pod -n kube-system
NAME                                            READY   STATUS    RESTARTS   AGE
aws-load-balancer-controller-6c4d8d8f64-6gsw7   1/1     Running   0          81s
aws-node-chr59                                  1/1     Running   0          7d8h
aws-node-xzsx5                                  1/1     Running   0          4d12h
coredns-86f7d88d77-d4969                        1/1     Running   0          7d8h
coredns-86f7d88d77-fntwt                        1/1     Running   0          7d8h
kube-proxy-bmp9g                                1/1     Running   0          4d12h
kube-proxy-r7hwz                                1/1     Running   0          7d8h

カスタムリソースを確認する。

$ kubectl api-resources | grep aws
eniconfigs                                     crd.k8s.amazonaws.com          false        ENIConfig
targetgroupbindings                            elbv2.k8s.aws                  true         TargetGroupBinding
securitygrouppolicies             sgp          vpcresources.k8s.aws           true         SecurityGroupPolicy

動作確認

NginxのPodを動かしてみる。

Namespaceを作成する。

$ kubectl create ns nginx
namespace/nginx created

Deploymentのyamlを用意する。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx

Deploymentを作成する。

$ kubectl apply -f nginx-deployment.yaml -n nginx
deployment.apps/nginx created

Podの起動を確認する。

$ kubectl get pod -n nginx
NAME                    READY   STATUS    RESTARTS   AGE
nginx-f89759699-f5r8h   1/1     Running   0          8m33s
nginx-f89759699-shdlx   1/1     Running   0          8m33s

NLB IPモード

Serviceのyamlを作成する。

apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: nlb-ip
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: nginx

Serviceを作成する。

$ kubectl apply -f nginx-service-nlb-ip.yaml -n nginx
service/nginx created

Serviceを確認する。

$ kubectl get svc -n nginx
NAME    TYPE           CLUSTER-IP      EXTERNAL-IP                                                                    PORT(S)        AGE
nginx   LoadBalancer   10.100.18.182   k8s-nginx-nginx-3507a5cb51-c613e91128d26166.elb.ap-northeast-1.amazonaws.com   80:30121/TCP   4m37s

TargetGroupBindingを確認する。

$ kubectl get TargetGroupBinding -n nginx
NAME                         SERVICE-NAME   SERVICE-PORT   TARGET-TYPE   AGE
k8s-nginx-nginx-1800f449e6   nginx          80             ip            6m4s
$ kubectl get TargetGroupBinding -n nginx k8s-nginx-nginx-1800f449e6 -o yaml | kubectl neat
apiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
  labels:
    service.k8s.aws/stack-name: nginx
    service.k8s.aws/stack-namespace: nginx
  name: k8s-nginx-nginx-1800f449e6
  namespace: nginx
spec:
  networking:
    ingress:
    - from:
      - ipBlock:
          cidr: 192.168.0.0/19
      - ipBlock:
          cidr: 192.168.64.0/19
      - ipBlock:
          cidr: 192.168.32.0/19
      ports:
      - port: 80
        protocol: TCP
  serviceRef:
    name: nginx
    port: 80
  targetGroupARN: arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXXX:targetgroup/k8s-nginx-nginx-1800f449e6/fcdb0e58910f7eb4
  targetType: ip

アクセスできることを確認する。

$ curl k8s-nginx-nginx-3507a5cb51-c613e91128d26166.elb.ap-northeast-1.amazonaws.com
<!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>

Serviceを削除する。

$ kubectl delete svc nginx -n nginx
service "nginx" deleted

TargetGroupBindingも削除される。

$ kubectl get TargetGroupBinding -n nginx
No resources found in nginx namespace.

ALB IPモード

ServiceのyamlをClusterIPで作成する。

apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  ports:
  - port: 80
  selector:
    app: nginx

Serviceを作成する。

$ kubectl apply -f nginx-service.yaml -n nginx
service/nginx created

Serviceを確認する。

$ kubectl get svc -n nginx
NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   10.100.55.63   <none>        80/TCP    5m25s

Ingressyamlを作成する。

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: nginx
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/group.name: mygroup
    alb.ingress.kubernetes.io/group.order: "1"
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: nginx
          servicePort: 80

Ingressを作成する。

$ kubectl apply -f nginx-ingress.yaml -n nginx
ingress.networking.k8s.io/nginx created

Ingressを確認する。

$ kubectl get ing -n nginx
NAME    CLASS    HOSTS   ADDRESS                                                                 PORTS   AGE
nginx   <none>   *       k8s-nginx-nginx-d736dcdd09-708216381.ap-northeast-1.elb.amazonaws.com   80      84s

TargetGroupBindingを確認する。

$ kubectl get TargetGroupBinding -n nginx
NAME                         SERVICE-NAME   SERVICE-PORT   TARGET-TYPE   AGE
k8s-nginx-nginx-950afbba61   nginx          80             ip            2m16s
$ kubectl get TargetGroupBinding -n nginx k8s-nginx-nginx-950afbba61 -o yaml | kubectl neat
apiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
  labels:
    ingress.k8s.aws/stack-name: nginx
    ingress.k8s.aws/stack-namespace: nginx
  name: k8s-nginx-nginx-950afbba61
  namespace: nginx
spec:
  networking:
    ingress:
    - from:
      - securityGroup:
          groupID: sg-060f79f358f95e020
      ports:
      - protocol: TCP
  serviceRef:
    name: nginx
    port: 80
  targetGroupARN: arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXXX:targetgroup/k8s-nginx-nginx-950afbba61/f413f7ba74cb55b0
  targetType: ip

ALB インスタンスモード

2つめのServiceのyamlをNodePortで作成する。バックエンドは同じにする。

apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx2
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: nginx

Serviceを作成する。

$ kubectl apply -f nginx2-service.yaml -n nginx
service/nginx2 created

Serviceを確認する。

$ kubectl get svc -n nginx
NAME     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
nginx    ClusterIP   10.100.55.63    <none>        80/TCP         13m
nginx2   NodePort    10.100.40.227   <none>        80:31721/TCP   6s

2つめのIngressyamlをし、同じグループを指定する。ターゲットタイプは指定しない。

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: nginx2
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/group.name: mygroup
    alb.ingress.kubernetes.io/group.order: "2"
spec:
  rules:
  - http:
      paths:
      - path: /test
        backend:
          serviceName: nginx
          servicePort: 80

Ingressを作成する。

$ kubectl apply -f nginx2-ingress.yaml -n nginx
ingress.networking.k8s.io/nginx2 created

Ingressを確認する。同じアドレスになっていることが確認できる。

$ kubectl get ing -n nginx
NAME     CLASS    HOSTS   ADDRESS                                                              PORTS   AGE
nginx    <none>   *       k8s-mygroup-013347b429-1627155524.ap-northeast-1.elb.amazonaws.com   80      13m
nginx2   <none>   *       k8s-mygroup-013347b429-1627155524.ap-northeast-1.elb.amazonaws.com   80      46s

TargetGroupBindingを確認する。

$ kubectl get TargetGroupBinding -n nginx -o wide
NAME                         SERVICE-NAME   SERVICE-PORT   TARGET-TYPE   ARN                                                                                                                AGE
k8s-nginx-nginx-8518c96606   nginx          80             instance      arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXXX:targetgroup/k8s-nginx-nginx-8518c96606/eb9c2fa6e1869391   2m11s
k8s-nginx-nginx-d2e1c8852a   nginx          80             ip            arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXXX:targetgroup/k8s-nginx-nginx-d2e1c8852a/b02b4bd445d1752c   4m5s
$ kubectl get TargetGroupBinding -n nginx k8s-nginx-nginx-8518c96606 -o yaml | kubectl neat
apiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
  labels:
    ingress.k8s.aws/stack: mygroup
  name: k8s-nginx-nginx-8518c96606
  namespace: nginx
spec:
  networking:
    ingress:
    - from:
      - securityGroup:
          groupID: sg-07588c5428ac89e2e
      ports:
      - protocol: TCP
  serviceRef:
    name: nginx
    port: 80
  targetGroupARN: arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXXX:targetgroup/k8s-nginx-nginx-8518c96606/eb9c2fa6e1869391
  targetType: instance

マネジメントコンソールを確認する。ALBが1つ作られている。

f:id:sotoiwa:20201027015614p:plain

ターゲットグループは2つ作られている。

f:id:sotoiwa:20201027015700p:plain

リスナールールを確認する。指定した通りルールができている(2つめに到達しないルールになってしまっている)。

f:id:sotoiwa:20201027015713p:plain