🐈

AWS Load Balancer Controller (LBC)でkubernetesのServiceを外部に公開する

に公開

はじめに

AWS LBC(Load Balancer Controller)は、EKS上のリソースとしてALBを構成するための機能です。今回はこの機能の基本的な使い方や、より高度な構成について説明します。

AWS LBCとはなにか

AWS LBC(Load Balancer Controller)は、Kubernetesのリソースを監視し、AWS Elastic Load Balancerをそれにあわせて管理するコンポーネントです。AWS LBCが監視する対象は、EKS内のIngressリソースとService Type LoadBalancerリソースです。これらのKubernetesリソースの状態に合うように、AWS LBCはALBやNLBを作成したり、設定を変更したりします。

今回のテーマである、Kubernetes Serviceの外部公開には、Ingressリソースを使用します。Ingressリソースは、Kubernetesのリソースで、HTTP(S)トラフィックをルーティングするためのものです。AWS LBCは、Ingressリソースを監視し、ALBを作成して、トラフィックを指定したServiceにルーティングします。

今回利用しないService Type LoadBalancerリソースは、EKS内にL4のNLBを展開する機能であり、主にTCPやUDPレベルのロードバランシングを提供します。

AWS LBCのインストール

権限の付与

AWS LBCは、IAMを利用してAWSのリソースにアクセスをします。そのため、まずはLBCが使用するKubernetesサービスアカウントにはAWSのIAMロールを紐づける必要があります。

以下のドキュメントのように、eksctlを使用してIAMロールの作成、関連付けを行うこともできます。

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/lbc-helm.html

今回はTerraformを用いてより簡単にIAMロールの作成、関連付けを行います。

https://zenn.dev/kamos/articles/873ecca3f9bab0#terraform-moduleの紹介

以下のterraform moduleを使って、IAMロールのセットアップを行います。

https://registry.terraform.io/modules/terraform-aws-modules/eks-pod-identity/aws/latest

module "aws_lb_controller_pod_identity" {
  source = "terraform-aws-modules/eks-pod-identity/aws"

  name = "aws-lbc"

  attach_aws_lb_controller_policy = true

  # Pod Identity Associations
  associations = {
    "aws-load-balancer-controller" = {
      cluster_name    = "my-cluster" # EKSクラスター名。環境に合わせて変更してください。
      namespace       = "kube-system"
      service_account = "aws-load-balancer-controller"
    }
  }
}

これをapplyすることで、AWS LBCに必要な権限が付与されたIAMロールが作成され、Kubernetesサービスアカウントとの関連付けが行われます。

AWS LBCのインストール

AWS LBCはhelmを使ってインストールすることができます。

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/lbc-helm.html

ドキュメントにある通り、以下のコマンドを実行して、AWS LBCをインストールします。

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

helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=<クラスター名> \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller

また、ArgoCDを用いても同様にHelmチャートをインストールすることができます。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: aws-load-balancer-controller
  namespace: argocd
spec:
  project: default
  destination:
    name: "in-cluster"
    namespace: kube-system
  sources:
    - repoURL: https://aws.github.io/eks-charts
      chart: aws-load-balancer-controller
      targetRevision: 1.12.0
      helm:
        valuesObject:
          clusterName: <クラスター名>
          serviceAccount.create: false
          serviceAccount.name: aws-load-balancer-controller

これらをapplyすることで、EKS上にAWS LBCがインストールできます。

サービスの公開方法

1. Ingressを使用した公開(ALB)

Ingressリソースを使用してALBを作成し、KubernetesのServiceにトラフィックをルーティングします。以下は、Ingressリソースの基本的な設定例です。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-name
  namespace: app-namespace
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/subnets: subnet-xxxxxxxx1,subnet-xxxxxxxx2,subnet-xxxxxxxx3
    alb.ingress.kubernetes.io/inbound-cidrs: xxx.xxx.xxx.xxx/32,xxx.xxx.xxx.xxx/32
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: service-name
                port:
                  number: 80

LBCはKubernetesリソース(今回はIngressリソース)に付与されたアノテーションを設定値としてALBを作成します。上記の例では、ALBはインターネットからアクセス可能で、指定されたサブネットに配置されます。また、特定のCIDRからのトラフィックのみを許可し、SSL/TLS証明書も指定しています。利用可能なアノテーションについては以下を参照してください。

https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.7/guide/ingress/annotations/

[発展]TargetGroupBindingを使用した公開(ALB)

AWS LBC + Ingressリソースでのサービスの公開は、設定が非常に簡単で管理コストも低いですが、AWS固有のアノテーションへの強い依存(多数のアノテーションの学習・管理が必要)があったり、クラスターの移行時にはサービスが止まってしまうなどの課題があります。このような課題への解決策として、TargetGroupBindingを利用することができます。

https://aws.amazon.com/jp/blogs/news/patterns-for-targetgroupbinding-with-aws-load-balancer-controller/

TargetGroupBindingは、ALBのターゲットグループをKubernetesのServiceにバインドするためのリソースです。これによりALBの管理がKubernetesマニフェストの責務ではなくなり、Terraform等の他のIaCツールでALBを管理することができます。Target GroupがEKS内で仮想的なLoadBalancerとして機能し、KubernetesのServiceにトラフィックをルーティングします。

以下は、TargetGroupBindingリソースの基本的な設定例です。

apiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
  namespace: app-namespace
  name: app-tgb
spec:
  serviceRef:
    name: service-name
    port: 80
  targetGroupARN: arn:aws:elasticloadbalancing:ap-northeast-1:xxxxxxxxxxxx:targetgroup/app-xxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxx
  targetType: ip
  networking:
    ingress:
      - from:
          - securityGroup:
              groupID: sg-xxxxxxxxxxxxx
        ports:
          - protocol: TCP

ALB側でプロビジョニングした内容をもとに、TargetGroupBindingリソースを作成します。これにより、ALBは指定されたKubernetesのServiceにトラフィックをルーティングします。上記の例では、ALBは特定のセキュリティグループからのトラフィックのみを許可し、TCPプロトコルでポート80にアクセスします。

これによってALBの設定はTerraform等のIaCツールで管理できるようになり、Kubernetesのリソースに依存しなくなります。これにより、クラスターの移行時にもサービスが止まることなく、ALBの設定を変更することができます。また、AWS Global Accelerator連携やNLB->ALB構成など、複雑なネットワークパターンに対応可能であるため、より柔軟な構成が可能になります。

そしてこの柔軟性でも足りない場合、より高度な構成が必要な場合は、IstioなどのService Meshを利用することができます。Istioは、Kubernetes上でのトラフィック管理やセキュリティ、監視などを提供するためのフレームワークです。Istioを使用することで、より高度なトラフィックルーティングやセキュリティポリシーの適用が可能になります。Istioは、KubernetesのService Meshとして非常に人気がありますが、導入には学習コストや運用コストがかかるため、必要な機能を見極めて導入することが重要です。

まとめ

AWS LBCを使用することで、KubernetesのServiceを簡単に外部に公開することができます。Ingressリソースを使用することで、ALBを作成し、トラフィックを指定したServiceにルーティングすることができます。また、TargetGroupBindingを使用することで、ALBの設定をTerraform等のIaCツールで管理できるようになり、クラスターの移行時にもサービスが止まることなく、ALBの設定を変更することができます。便利にこれらを使っていきましょう。

参考

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/aws-load-balancer-controller.html

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/lbc-helm.html

https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.1/guide/targetgroupbinding/targetgroupbinding/

Discussion