5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

既存のALBを削除せずにALB Ingress ControllerからALB LoadBalancer Controllerに移行する

Last updated at Posted at 2021-03-14

はじめに

ALB LoadBalancer ControllerはKubernetesからELBを操作するためのものです。
元々はALB Ingress Controllerという名称で、複数NamespaceのIngressリソースを1つのALBで対応することができませんでした。

これは以前記事に書いた通り、NGINX Ingress ControllerをALBとアプリケーションの間に挟むことで解決することができました。

ALB Ingress ControllerとNGINX Ingress Controllerを使用するときの構成は下図になります。

alb-loadbalancer-controller-Page-1.png

一方、ALB LoadBalancer Controllerでは下図のようにIngressリソースなしで1つのALBで複数Namespace上のアプリケーションにルーティングさせることができます。

alb-loadbalancer-controller-Page-3.png

今回は既存のALBを削除せずにALB Ingress Controller + NGINX Ingress Controllerの構成からALB LoadBalancer Controllerの構成に移行する手順を説明します。

事前準備

ALB Ingress ControllerとNGINX Ingress ControllerをHelmでデプロイします。IAM Role for ServiceAccountを使用しています。

aws-alb-ingress-controller-values.yaml
clusterName: <CLUSTER_NAME>
awsRegion: ap-northeast-1
awsVpcID: <VPC_ID>
rbac:
  serviceAccountAnnotations: 
    eks.amazonaws.com/role-arn: <IAM_ROLE_ARN>
nginx-ingress-values.yaml
controller:
  service:
    type: NodePort
$ helm install aws-alb-ingress-controller \
  incubator/aws-alb-ingress-controller \
  -f aws-alb-ingress-controller-values.yaml \
  --version 0.1.11 \
  -n kube-system
$ helm install nginx-ingress \
  stable/nginx-ingress \
  -f nginx-ingress-values.yaml \
  --version 1.39.0 \
  -n kube-system

ALB Ingress Controllerで使用するIAM RoleにアタッチするIAM Policyは以下になります。
後述するALB LoadBalancer Controllerでも同じIAM Roleを使用します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "acm:DescribeCertificate",
                "acm:ListCertificates",
                "acm:GetCertificate"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:AuthorizeSecurityGroupIngress",
                "ec2:CreateSecurityGroup",
                "ec2:CreateTags",
                "ec2:DeleteTags",
                "ec2:DeleteSecurityGroup",
                "ec2:DescribeAccountAttributes",
                "ec2:DescribeAddresses",
                "ec2:DescribeInstances",
                "ec2:DescribeInstanceStatus",
                "ec2:DescribeInternetGateways",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeSubnets",
                "ec2:DescribeTags",
                "ec2:DescribeVpcs",
                "ec2:ModifyInstanceAttribute",
                "ec2:ModifyNetworkInterfaceAttribute",
                "ec2:RevokeSecurityGroupIngress"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:AddListenerCertificates",
                "elasticloadbalancing:AddTags",
                "elasticloadbalancing:CreateListener",
                "elasticloadbalancing:CreateLoadBalancer",
                "elasticloadbalancing:CreateRule",
                "elasticloadbalancing:CreateTargetGroup",
                "elasticloadbalancing:DeleteListener",
                "elasticloadbalancing:DeleteLoadBalancer",
                "elasticloadbalancing:DeleteRule",
                "elasticloadbalancing:DeleteTargetGroup",
                "elasticloadbalancing:DeregisterTargets",
                "elasticloadbalancing:DescribeListenerCertificates",
                "elasticloadbalancing:DescribeListeners",
                "elasticloadbalancing:DescribeLoadBalancers",
                "elasticloadbalancing:DescribeLoadBalancerAttributes",
                "elasticloadbalancing:DescribeRules",
                "elasticloadbalancing:DescribeSSLPolicies",
                "elasticloadbalancing:DescribeTags",
                "elasticloadbalancing:DescribeTargetGroups",
                "elasticloadbalancing:DescribeTargetGroupAttributes",
                "elasticloadbalancing:DescribeTargetHealth",
                "elasticloadbalancing:ModifyListener",
                "elasticloadbalancing:ModifyLoadBalancerAttributes",
                "elasticloadbalancing:ModifyRule",
                "elasticloadbalancing:ModifyTargetGroup",
                "elasticloadbalancing:ModifyTargetGroupAttributes",
                "elasticloadbalancing:RegisterTargets",
                "elasticloadbalancing:RemoveListenerCertificates",
                "elasticloadbalancing:RemoveTags",
                "elasticloadbalancing:SetIpAddressType",
                "elasticloadbalancing:SetSecurityGroups",
                "elasticloadbalancing:SetSubnets",
                "elasticloadbalancing:SetWebACL"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:CreateServiceLinkedRole",
                "iam:GetServerCertificate",
                "iam:ListServerCertificates"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "cognito-idp:DescribeUserPoolClient"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "waf-regional:GetWebACLForResource",
                "waf-regional:GetWebACL",
                "waf-regional:AssociateWebACL",
                "waf-regional:DisassociateWebACL"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "tag:GetResources",
                "tag:TagResources"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "waf:GetWebACL",
                "wafv2:GetWebACLForResource"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateTags",
                "ec2:DeleteTags"
            ],
            "Resource": "arn:aws:ec2:*:*:security-group/*",
            "Condition": {
                "Null": {
                    "aws:ResourceTag/ingress.k8s.aws/cluster": "false"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:AddTags",
                "elasticloadbalancing:RemoveTags",
                "elasticloadbalancing:DeleteTargetGroup"
            ],
            "Resource": [
                "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*",
                "arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*",
                "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*"
            ],
            "Condition": {
                "Null": {
                    "aws:ResourceTag/ingress.k8s.aws/cluster": "false"
                }
            }
        }
    ]
}

次に、ALBに設定するためのIngressリソースをデプロイします。
annotationsにalb.ingress.kubernetes.io/load-balancer-attributesで削除保護を設定しています。これによりIngressリソースを削除してもALBが削除されることはなくなります。

alb-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/load-balancer-attributes: deletion_protection.enabled=true
  name: alb-ingress
  namespace: kube-system
spec:
  rules:
    - http:
        paths:
          - backend:
              serviceName: nginx-ingress-controller
              servicePort: 80
$ kubectl apply -f alb-ingress.yaml

次に、2つのNamespaceにアプリケーションをデプロイします。今回はNGINXを使用しています。
FQDNは例としてそれぞれapp1.sample.comapp2.sample.comと記述しています。

app.yaml
kind: Namespace
apiVersion: v1
metadata:
  name: app1
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: app1-ing
  namespace: app1
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: app1.sample.com
      http:
        paths:
          - backend:
              serviceName: app1-svc
              servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: app1-svc
  namespace: app1
spec:
  type: ClusterIP
  ports:
    - name: http-port
      protocol: TCP
      port: 80
      targetPort: 80
  selector:
    app: app1
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app1-deploy
  namespace: app1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app1
  template:
    metadata:
      labels:
        app: app1
    spec:
      containers:
        - name: app1
          image: nginx:1.13
          ports:
            - containerPort: 80
---
kind: Namespace
apiVersion: v1
metadata:
  name: app2
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: app2-ing
  namespace: app2
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: app2.sample.com
      http:
        paths:
          - backend:
              serviceName: app2-svc
              servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: app2-svc
  namespace: app2
spec:
  type: ClusterIP
  ports:
    - name: http-port
      protocol: TCP
      port: 80
      targetPort: 80
  selector:
    app: app2
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app2-deploy
  namespace: app2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app2
  template:
    metadata:
      labels:
        app: app2
    spec:
      containers:
        - name: app2
          image: nginx:1.13
          ports:
            - containerPort: 80
$ kubectl apply -f app.yaml

ALB LoadBalancer Controllerへの移行

ここでは、移行する手順を説明します。

1. ALB Ingress Controllerの削除

既存のALB Ingress Controllerを削除します。Ingressリソースは削除しないことに注意します。

$ helm uninstall aws-alb-ingress-controller -n kube-system

2. ALB LoadBalancer Controllerのデプロイ

TargetGroupBindingのCRDをデプロイします。

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

ALB LoadBalancer ControllerをHelmでデプロイします。バージョンに気をつけます。

aws-load-balancer-controller-values.yaml
clusterName: <CLUSTER_NAME>
region: ap-northeast-1
vpcId: <VPC_ID>
serviceAccount:
  annotations:
    "eks.amazonaws.com/role-arn": <IAM_ROLE_ARN>
$ helm install aws-load-balancer-controller \
  eks/aws-load-balancer-controller \
  -f aws-load-balancer-controller-values.yaml \
  --version 1.0.8 \
  -n kube-system

3. Ingressリソースの削除

ALBの設定をKubernetesリソースから操作することはやめます。Ingressリソースは不要になるため削除します。

$ kubectl delete -f alb-ingress.yaml

4. TargetGroupの作成

Serviceへのルーティングを設定するためにTargetGroupをAWSコンソールから作成していきます。下画像ではALB Ingress Controllerが作成したものが残っていますが、まだ削除しません。

スクリーンショット 2021-03-14 18.55.16.png

target typeはIP addressにします。

スクリーンショット 2021-03-14 19.03.12.png

Register targetsには何も記入せず作成します。

スクリーンショット 2021-03-14 19.03.57.png

今回は2つのアプリケーションをデプロイするので2つ分TargetGroupを追加しました。

スクリーンショット 2021-03-14 19.06.34.png

5. リスナールールの変更

ALB Ingress Controllerが作成したALBのリスナールールを変更していきます。

スクリーンショット 2021-03-14 19.10.50.png

全てのリクエストがNGINX Ingress Controllerに向かうようになっています。これにルールを追加します。

スクリーンショット 2021-03-14 19.09.14.png

ホスト名に合わせて宛先を先ほど作成したTargetGroupになるようにしています。

スクリーンショット 2021-03-14 19.19.49.png

6. TargetGroupBindingリソースの作成

TargetGroupとServiceを紐づけるための設定を加えます。SecurityGroupはALBに設定されているものを使用します。

targetgroupbinding.yaml
apiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
  name: app1-tgb
  namespace: app1
spec:
  serviceRef:
    name: app1-svc
    port: 80
  targetGroupARN: <TARGET_GROUP_ARN>
  targetType: ip
  networking:
    ingress:
    - from:
      - securityGroup:
          groupID: <SECURITY_GROUP_ID>
      ports:
      - protocol: TCP
---
apiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
  name: app2-tgb
  namespace: app2
spec:
  serviceRef:
    name: app2-svc
    port: 80
  targetGroupARN: <TARGET_GROUP_ARN>
  targetType: ip
  networking:
    ingress:
    - from:
      - securityGroup:
          groupID: <SECURITY_GROUP_ID>
      ports:
      - protocol: TCP
$ kubectl apply -f targetgroupbinding.yaml

7. ゴミ掃除

ALBリスナールールからNGINX Ingress Controller向けの設定を削除します。

スクリーンショット 2021-03-14 19.19.49.png

スクリーンショット 2021-03-14 19.26.21.png

IngressリソースとNGINX Ingress Controllerは不要なので削除します。

$ kubectl delete ing app1-ing -n app1
$ kubectl delete ing app2-ing -n app2
$ helm uninstall nginx-ingress -n kube-system

確認

移行前のURLでアプリケーションにアクセスできることを確認します。

スクリーンショット 2021-03-14 19.37.24.png

スクリーンショット 2021-03-14 19.38.23.png

まとめ

既存のALBを削除せずにALB Ingress Controller + NGINX Ingress ControllerからALB LoadBalancer Controllerに移行する手順を説明しました。
これによりALBをKubernetes側で管理する必要がなくなり、且つ複数Namespace上のアプリケーションにアクセスする時も1つのALBで事足りるので移行するメリットは大きいです。

参考

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?