EKSクラスタにAWS Load Balancer ControllerをインストールしてALBのIngressを立てる

kubernetesaws

AWS Load Balancer Controller は Kubernetes のリソースに対応する ELB を作成し管理するコントローラー。 必要な Policy を ServiceAccount に与えて Helm Chart でインストールできるが、CDK でクラスタを作る場合は albController でバージョンを指定することでこれをやってくれる

new eks.Cluster(this, 'Cluster', {
  ...
  albController: {
    version: eks.AlbControllerVersion.V2_6_2,
  },
})

次のような Ingress を作成すると ALB が作られる。 subnet は alb.ingress.kubernetes.io/subnets で指定することもできるが、 subnet に次のタグが付いている場合 auto discovery される。

  • kubernetes.io/role/elb : 1
  • kubernetes.io/cluster/${cluster-name}: owned or shared

alb.ingress.kubernetes.io/target-type は instance か ip を取り、 それぞれトラフィックがインスタンスまたは直接 Pod に向く。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/subnets: testpublicsubnet1, testpublicsubnet2
    alb.ingress.kubernetes.io/healthcheck-path: /health
    alb.ingress.kubernetes.io/target-group-attributes: deregistration_delay.timeout_seconds=5
spec:
  ingressClassName: alb
	rules:
    - http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: test
              port:
                number: 80

ip にすると ALB の deregistration より前に pod が停止することで接続に失敗し 5xx エラーになってしまうことがあるため、 Deregistration delay を短くした上で、それ以上の時間待つ必要がある。

 lifecycle:
  preStop:
    exec:
      command: ["sleep", "15s"]

また、ローリングアップデート時に ALB のヘルスチェックが通る前に pod が ready になってしまうと、古い pod が終了してリソースが不足してしまう。 これを防ぐには namespace に次のラベルを付けて Pod readiness gate が挿入されるようにする。

apiVersion: v1
kind: Namespace
metadata:
  name: app
  labels:
    elbv2.k8s.aws/pod-readiness-gate-inject: enabled

特定の Pod に負荷が集中するとヘルスチェックに失敗してリクエストがルーティングされなくなることで、残りの Pod に負荷が集中して全滅してしまう悪循環が起きてしまうことがあるが、デフォルトのラウンドロビンではなく処理中のリクエストが最も少ない Target にルーティングする Least Outstanding Requests (LOR) にすることで集中を解消できる可能性がある。 ただしリクエスト数に比例して負荷が高まるサイドカーがある場合はそちらの負荷が偏ってしまうことがある。

alb.ingress.kubernetes.io/target-group-attributes: load_balancing.algorithm.type=least_outstanding_requests

AccessDenied などで ALB が作られない場合は Policy が最新で ServiceAccount の annotations に誤りがないかを確認するとよい。

alb.ingress.kubernetes.io/security-groups で独自のセキュリティグループを設定できるが、そうする場合併せて alb.ingress.kubernetes.io/manage-backend-security-group-rules を true にしないとインスタンスの SG の inbound で許可されている Backend SG が ALB に追加されずアクセスできない。

参考

AWS Load Balancer Controller v2.3.0 から導入された Optimized SG rules について #AWS - Qiita

EKSコンテナ移行のトラブル事例:ALBの設定とPodのライフサイクル管理 - MonotaRO Tech Blog

ALB ターゲットグループのバランシングアルゴリズムを LOR にする - hagihala’s blog