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ロールの作成、関連付けを行うこともできます。
今回はTerraformを用いてより簡単にIAMロールの作成、関連付けを行います。
以下のterraform moduleを使って、IAMロールのセットアップを行います。
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を使ってインストールすることができます。
ドキュメントにある通り、以下のコマンドを実行して、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証明書も指定しています。利用可能なアノテーションについては以下を参照してください。
[発展]TargetGroupBindingを使用した公開(ALB)
AWS LBC + Ingressリソースでのサービスの公開は、設定が非常に簡単で管理コストも低いですが、AWS固有のアノテーションへの強い依存(多数のアノテーションの学習・管理が必要)があったり、クラスターの移行時にはサービスが止まってしまうなどの課題があります。このような課題への解決策として、TargetGroupBindingを利用することができます。
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の設定を変更することができます。便利にこれらを使っていきましょう。
参考
Discussion