BLUF(結論から)
Kubernetesコミュニティには、本体に組み込まれた機能の名前には kubernetes.io を使い、Kubernetesアドオンには使わないという慣例があります。アドオンは ebs.csi.aws.com のように自己説明的な命名規則に従い、見ただけでアドオンだと判別できるのが一般的です。ところが、aws-load-balancer-controllerアドオンはこの慣例から外れています。
対象読者
本記事は次の3種類の読者・目的を想定しています。
1. AWS上でEKSや汎用Kubernetesディストリビューションを運用しているKubernetes管理者の方。今すぐ読む必要はありませんが、ブックマークしておくことをおすすめします。service.beta.kubernetes.io/aws-load-balancer-* のようなアノテーションを付けたKubernetes Service経由でAWSロードバランサーをプロビジョニングする際にデバッグが必要になったら、参考資料として戻ってきてください。
2. Kubernetesをより深く理解するための踏み込んだ解説記事を好む方。
3. EKS、aws-cloud-controller-manager、aws-load-balancer-controller、AWSドキュメントの各メンテナーの方々。本記事の狙いは、AWS上のKubernetesロードバランサープロビジョニング特有の、紛らわしい不整合に光を当てることです。Kubernetesコミュニティ全体の慣例に揃える方向への変化を後押しできればと考えています(この問題は複数のGitリポジトリやドキュメントサイトにまたがるため、いくつかのマージリクエストで簡単に解決できるものではありません)。
はじめに
最近、EKS(Elastic Kubernetes Service)クラスターに対して、type: LoadBalancerのKubernetes Serviceと service.beta.kubernetes.io/aws-load-balancer-* 形式のアノテーション(一覧はこちらのページにあります)を使ってAWSロードバランサーをプロビジョニングするPoCに着手しました。
当初は一部のアノテーションが想定どおりに動作せず、トラブルシュートには「なぜ動かないのか」を理解する必要がありました。リンク先のドキュメントは仕組みをそれなりに説明していますが、初心者向けとは言いがたい内容です。
そこで本記事では、以下のトピックを掘り下げて解説します。
- aws-load-balancer-controllerが紛らわしい理由
- 初心者がスムーズに理解するための背景情報
- なぜ今のような仕組みになっているのか、その理由の詳細
- 基本的ながら役立つトラブルシューティングのヒント
- 各メンテナーグループが今後の混乱を減らすためにできること
課題:取り違えやすい正体
先ほど、リンク先のページは初心者向けではないと述べました。具体的には、私自身、内容を整理するのに丸1日かかるほど混乱しました。2018年7月からKubernetesのSMEを務めてきた身としては、これはよろしくない兆候です。理解した直後の最初の感想は「なるほど、そういうことか。type: LoadBalancerのKubernetes Serviceに付けたアノテーションを使ってAWS LBをプロビジョニング・管理できるAWS固有のKubernetesコントローラーが、実は2種類あるとは今日まで知らなかった」というものでした。続いて思ったのが「専門家のいない環境で、他の人はこれをどうやって理解すればいいのか。記事にしておこう」ということです。
AWS Load Balancer Controllerプロジェクトを分かりにくくしている要因の一覧:
1.) 公式の組み込み機能のように見えるが、そうではない
「aws service of type lb」でGoogle検索すると、
1番目の結果:docs.aws.amazon.com/eks/latest/userguide/network-load-balancing.html
2番目の結果:kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/service/annotations/
そして「kubernetes service of type loadbalancer」で検索したときに1番目に出てくる、Kubernetes公式ドキュメントの該当セクション:
https://kubernetes.io/docs/concepts/services-networking/service/
これら3つのページはどれも公式ドキュメントのように見え、同じアノテーションが3つすべてに登場するため、同じトピックを扱っているように映ります。
3つのページで以下を検索してみてください。
service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags
同じリソースが3つすべてのページに現れます。一見すると、3つのサイトが同じものを説明しているように思えてしまいます。
しかし実際には、aws-load-balancer-controllerは組み込み機能を拡張するKubernetesアドオンです。つまり、上記のうち2つは組み込み機能を扱い、もう1つは拡張機能を提供するアドオンを扱っているのです。
2.) プロジェクトのウェブサイトとアノテーションで使われている命名規則が直感的でなく、組み込み機能を参照していると勘違いさせられます。
2A.) プロジェクトのドキュメントのホスト先DNS名が kubernetes-sigs.github.io で、Kubernetes本体の機能のように見えてしまいます。
2B.) アドオンのアノテーションが service.beta.kubernetes.io を参照しており、これは通常、組み込み機能のために予約された名前空間です。
3.) プロジェクトのドキュメントサイトのトップページからは、これが組み込み機能を拡張するKubernetesアドオンであることがすぐには分かりません。
ドキュメントの2ページ目の下のほうにたどり着き、
helm install aws-load-balancer-controller を見つけて、ようやく「ああ、これはアドオンか、なるほど」と腑に落ちるのです。
4.) このAPIが採用しているパターンが、Kubernetesコミュニティ全体で使われている通常のパターンと一致していません。 通常のパターンの例として、Cert ManagerとEBS Volume CSI(Container Storage Interface)Driverの2つを取り上げます。
- cert-managerのドキュメントでは、アノテーションの95%が
cert-manager.ioを使っています。これにより、サードパーティ製アドオンを参照していることが一目で直感的に分かります。 - ドキュメントのランディングページの冒頭の文は「cert-manager adds certificates and certificate issuers as resource types in Kubernetes clusters…」となっており、本プロジェクトが機能を追加する拡張であることを冒頭で明確にしています。
- EBS Volume CSI Driverの場合、組み込み機能とは別物だと一目で直感的に分かる命名規則が採用されています。
組み込みのAWS StorageClassは provisioner: kubernetes.io/aws-ebs を使います。
EBSアドオンのStorageClassは provisioner:ebs.csi.aws.com を使います。
- EBS CSI関連の複数のドキュメントサイトのトップページでは、デフォルトではインストールされないアドオンであることを冒頭で繰り返し明示するのが一般的です。このプロジェクトのドキュメントでは、より直感的に伝わるよう「driver」というキーワードをあえて含めています:「The Amazon EBS CSI driver isn't installed when you first create a cluster. To use the driver, you must add it as an Amazon EKS add-on or as a self-managed add-on.」さらに、ドキュメントではなくGitHubページにたどり着いた人のためにも、プロジェクトのGitHubトップページに「Driver Installation」へのリンクが用意されています。
5.) AWSのUIとドキュメントもaws-load-balancer-controllerの扱いに一貫性がありません。 AWS Load Balancer Controllerには、docs.aws.amazon.comに「Installing the AWS Load Balancer Controller add-on」というタイトルのユーザーガイドがあります。
ところがGUIを見ると公式アドオンとしては表示されません。「Get more add-ons」をクリックしてAmazon EBS CSI DriverやAWS Distro for OpenTelemetryが見えても、そこにすら出てきません。
6.) 背景情報が不足している
ドキュメントのサービスアノテーションのページでは、理解しておくと有用(理解はトラブルシュートの助けになります)でありながら、初心者が追加説明なしに把握するのはほぼ不可能な2つのトピックが、ごく簡単に触れられているだけです。これらのトピックをGoogleで調べても、見つかる情報は非常に曖昧で断片的、しかも多くのニュアンスを汲み取れない限り矛盾しているように映ります。
ドキュメント内で説明なしに簡単に触れられている2つのトピックとは、次のものです。
1. 「in-tree」:「the k8s in-tree kube-controller-manager」
2. 「Legacy AWS Cloud Provider」:「The AWS Load Balancer Controller manages Kubernetes Services in a compatible way with the legacy aws cloud provider.」
理想を言えば、これらの語が何を意味するかを要約した定義と、興味のある人向けの追加読み物へのリンクがあるべきです。私なりに要約すると次のとおりです。技術的には別物ですが、実質的には同じものと考えて差し支えありません。Legacy AWS Cloud Providerは、AWS上で動作するKubernetesクラスターに対してtype: LoadBalancerのServiceをプロビジョニングするデフォルトの組み込み機能を提供しているものです。
背景情報
何かをトラブルシュートするとき、私はまずそれを理解しようとします。AWS LBのプロビジョニングというトピックを完全に理解するには、相当量の背景情報が必要です。残念ながら、これまでこの情報は分散していて、深く解説されたこともなく、把握しづらいニュアンスに満ちていました。本記事は、いくつかの重要な背景情報を集約し、分かりやすく整理する試みです。
主要トピックの背景情報
1.) kube-controller-manager vs cloud-controller-manager vs aws-cloud-controller-manager 「in-tree」と「Legacy AWS Cloud Provider」が指すものには、関連する背景を理解しないと把握しづらいニュアンスがあるため、まずはここから始めましょう。
かつてKubernetesにはコントロールプレーンの構成要素が4つありました。controller-manager、scheduler、api-server、etcdです。kube-controller-managerかcloud-controller-managerのどちらか一方を実行し、両方を同時に動かすことはありませんでした。
cloud-controller-managerは95%のケースで使われていた選択肢でした。kube-controller-managerと同じ機能を備えつつ、複数のCSP(Cloud Service Provider)APIと連携するためのサポートが組み込まれていました。CSP APIと対話できるため、AWS EBSボリュームやAWSロードバランサーのプロビジョニングといった処理が可能だったわけです。
kube-controller-managerはクラウド非依存の実装で、CSPストレージやCSPロードバランサーを自動プロビジョニングするような機能は組み込まれていません。
現在のKubernetesでは、通常コントロールプレーンの構成要素は5つに増えています。
etcd、kube-api-server、kube-scheduler、kube-controller-manager、そしてaws-cloud-controller-managerなどのCSP固有のcontroller managerです。公式Kubernetesドキュメント内の図もこの新しいアーキテクチャを反映するよう更新されました。kopsやkubeadmなど、コントロールプレーンを確認できるデプロイ方法でも検証可能です。主な変更点は、特定のクラウドサービスプロバイダー専用のcloud controller managerが用意され、それらをkube-controller-managerと並行して実行する設計になったことです。一方、元のcloud-controller-managerはどちらかと言えば汎用のオールインワン的なソリューションでした。
2.) 「In-tree」とは、複数のCSP APIと連携する方法を知るGo言語のライブラリ群がKubernetesリポジトリ内にあり、それらから汎用のKubernetes Cloud Controller Managerコンテナイメージをビルドしていた時代を指します。
In-tree:Kubernetesコアリポジトリ k8s.io/kubernetes 内に存在するコード。
Out-of-Tree:k8s.io/kubernetes Gitリポジトリの外部リポジトリに存在するコード。
Kubernetes 1.14のコードベースには8種類のCSP用APIが組み込まれていました。さらに追加したいという要望もありましたが、すべてが一緒にバンドルされていたため、リリースのたびに同時に安定化を達成する必要がありました。これは保守性の観点で持続不可能なパターンでした。この問題に対処するため、CSP機能をKubernetesから切り離してアドオンとしてリファクタリングするというKEP(Kubernetes Enhancement Proposal)が承認されました。
この機能の分離により、Kubernetesのリリースプロセスは簡素化され、クラウドプロバイダーはKubernetesのリリースサイクルやプロセスとは独立して機能とバグ修正をリリースできるようになります。プロジェクトの長期的な健全性を確保するため、技術的負債を返済する決断だったわけです。
3.) このトピックを自分で調べてみると、複数のニュアンスを汲み取れるまでは矛盾しているように見える情報に容易に出くわします。順不同でいくつか挙げます。
- in-treeからout-of-treeへの移行は、何年もかかっているように見えます。一方で、ずっと前に始まりずっと前に完了したとする情報もたくさんあります。さらに、開始と完了の時期が情報源によって食い違っていたり、いまだ進行中とされていたりもします。
- 先ほど、Kubernetes 1.14のコードベースには8種類のCSP用APIが組み込まれていたと述べました。Kubernetes 1.26のコードベースを見ると、いまだにin-treeに4つのCSPが残っています。AWSもin-tree CSPの一覧に表示されています。しかしaws-cloud-providerを参照するout-of-treeのGitリポジトリの記述からは、AWSは1.20で移行を完了したように読み取れます。
ところがKEPでは、移行は1.27ごろに完了する見込みとされていますが…?
こうした事情があるため、ドキュメントの問題修正に貢献するのではなく、この記事を書くことを選びました。AWSや他のCSPは依然としてin-tree/汎用CSP版のcloud controller managerに存在していますが、実運用ではそのバージョンは使われていません。AWSや他のCSPは、aws-cloud-controller-managerのような自社CSP専用の実装を使っており、古いin-treeの汎用オールインワンcloud-controller-managerは使っていません。
各CSPは、汎用的なin-treeから自社CSP固有のout-of-treeへの移行を、それぞれ異なるペースで進めてきました。もう一つ少し紛らわしいのは、この複雑な取り組みが2つに分割されたことです。元のin-tree組み込み機能には、CSPストレージとCSP LBをプロビジョニングするロジックが含まれていました。これがout-of-treeへ切り出されただけでなく、さらに分離が進められ、CSPストレージ用のCSIドライバーは独自の移行スケジュールを持つ独立したコンポーネントとなりました。
- このリファクタリングの複雑さの規模を理解すると、いくつかの点が腑に落ちます。第一に、リファクタリングが4年以上を要したのも無理はありません。Out-of-treeのクラウドプロバイダー実装機能は2019年5月のバージョン1.11でベータステータスに到達しました。第二に、移行プロセスを支えるために複数のフィーチャーフリーズが実施されたと知ると、AWS LBで
ExternalTrafficPolicy: Localを実装する際のバグが修正されるまで何年もかかった理由が見えてきます。組み込みのAWS LBプロビジョニングロジックに何年も大きな機能拡張がなかった理由も同様です。
4.) 「Legacy AWS Cloud Provider」とは、ざっくり言えば、EKSやAWS上のKubernetesのデフォルトインストールで利用できる、デフォルトのロードバランサープロビジョニング機能を指します。
厳密には100%正確とは言えないニュアンスがいくつかありますが、実用上はほぼ正しい説明です。
そのニュアンスは次のとおりです。
- Legacy AWS Cloud Providerは、(汎用CSPの)cloud-controller-manager内のin-treeに存在し、AWS EBSボリュームやAWS LBをプロビジョニングできたAWS固有のロジックを指す場合があります。
- Legacy AWS Cloud Providerは、aws-cloud-controller-manager内に存在するデフォルトのロードバランサープロビジョニングロジックを指す場合もあります。
- aws-cloud-controller-managerはユーザーから見えないことが多いです。
– EKSを使っている場合、aws-cloud-controller-managerはマネージドのマスターノード上で動作しており、ユーザーから見ることはできません。
– kopsやkubeadmのようにセルフホストのマスターノードを使う場合は見えます。
– RKE2を使う場合は見えません。これは、特定のコントロールプレーンコンポーネントをKubernetesから隔離されたプロセスとして実行する、多層防御のセキュリティ実装上の都合によるものです。
- Legacy AWS Cloud Providerは2つの異なるものを指しうるものの、AWS LBの文脈ではどちらも同じアノテーションをサポートするため、実質的に同じものです。元の22個のアノテーションは、こちらのページで
const ServiceAnnotationLoadBalancerという文字列を検索すると見つかります。本記事執筆時点では、ドキュメントページでservice.beta.kubernetes.io/aws-load-balancerを検索すると21個しか表示されませんが、これはドキュメント側の問題であり、コードの変更ではありません。
デフォルトで利用できる22個のアノテーションは次のとおりです。
service.beta.kubernetes.io/aws-load-balancer-type
service.beta.kubernetes.io/aws-load-balancer-internal
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol
service.beta.kubernetes.io/aws-load-balancer-access-log-emit-interval
service.beta.kubernetes.io/aws-load-balancer-access-log-enabled
service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-name
service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-prefix
service.beta.kubernetes.io/aws-load-balancer-connection-draining-enabled
service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled
service.beta.kubernetes.io/aws-load-balancer-extra-security-groups
service.beta.kubernetes.io/aws-load-balancer-security-groups
service.beta.kubernetes.io/aws-load-balancer-ssl-cert
service.beta.kubernetes.io/aws-load-balancer-ssl-ports
service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy
service.beta.kubernetes.io/aws-load-balancer-backend-protocol
service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags
service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold
service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold
service.beta.kubernetes.io/aws-load-balancer-healthcheck-timeout
service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval
5.) AWS Load Balancer ControllerプロジェクトはAWS EBS CSI Driverプロジェクトと概念的に似ています。 いずれも、汎用オールインワンのcloud-controller-manager内のin-treeに存在していたKubernetesコントローラーロジックを切り出したものです。両者とも後方互換性の確保を共通の目的としていました。一部のアノテーションを再利用するという判断にも、これが影響しているのかもしれません。
6.) EBS CSI DriverアドオンとAWS LB Controllerアドオンの両プロジェクトは、それぞれ別のグループによって始められました。
EBS CSI Driverアドオンプロジェクトを始めたのはAWSです。AWS LB ControllerアドオンプロジェクトはもともとTicketmasterとCoreOSによって始められ、かつては「AWS ALB Ingress Controller」と呼ばれていました。2018年にKubernetes SIG-AWSへ寄贈されています。当初のALB Ingress Controllerは、その名のとおりApplication Load Balancer Controllerと表現するのが最も適切でした。その後、プロジェクトのスコープが広がりNLBの制御もカバーするようになり、2021年7月に「AWS Load Balancer Controller」へリブランディングされました。
なぜ今のような形になっているのか
もし、オールインワンの汎用cloud-controller-managerのロジックをout-of-treeの分離されたアドオンへ移行していなかったら、技術的負債が今後の機能開発とバグ修正を恒久的に遅らせていたでしょう。externalTrafficPolicy: local 関連のバグが繰り返し発生し、適切に修正されるまで何年もかかった時期を覚えています。今ではこのロジックは、公式Kubernetesプロジェクトのコード、リリースプロセス、テストから切り離されており、バグは数年ではなく数か月で修正され、機能リクエストも再び検討されるようになりました。
開発の高速化は、大きな改善ももたらしました。たとえば、AWS CognitoとALBプロビジョニングロジックの新たな統合のおかげで、Authn/zプロキシによるソフトウェア定義境界(Software Defined Perimeter)の実装がしやすくなりました。AWS LB Controllerプロジェクトでは、アノテーションによるNLBプロビジョニングのオプションも増えています。個人的に気に入っているのが service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: アノテーションで、これによりバックエンドPodへのトラフィック経路を選択できます。デフォルト値の "instance" ではトラフィックは nELB → NodePort → Kube service → Pod の順に流れます。新たに追加された "ip" 値では、aELBのように nELB → Pod という経路でトラフィックを流せます。
略語リファレンス:
nELB = network Elastic Load Balancer(L4 LBサービス)
aELB/ALB = application Elastic Load Balancer(L7 LBサービス)
cELB = classic Elastic Load Balancer(L4/L7 LBサービス)
かつてALB Ingress Controllerと呼ばれていたプロジェクトに、nELBの管理までスコープが広がっていった理由のひとつは、当時aws-cloud-controller-managerがin-tree移行支援のためにフィーチャーフリーズ中で、ALB Ingress Controllerプロジェクトの方が変更や新機能を受け入れやすい状況にあったからではないかと推測しています。
では、なぜAWS Load Balancer ControllerはAWS EBS CSI Driverアドオンほどには整っていないのでしょうか。これは、AWSがEBS CSIプロジェクトを最初から最後までコントロールしていたのに対し、LB Controllerプロジェクトは途中で引き継いだものであり、大きな組織はブルックスの法則により変更の実施が遅くなりがちだ、という事情に関係していると思います(大きな組織ではコミュニケーションのオーバーヘッドが変更を大幅に遅らせます)。
AWS LB Controllerのトラブルシューティングのヒント
これらのヒントは網羅的・万能を目指したものではありません。行き詰まりを解消し、追加調査すべきトピックの方向を示す程度に役立つことを意図しています。
1.) AWS LB Controllerがインストールされているか確認するkubectl get deployments --namespace=kube-system
これが重要なのは、挙動に大きな違いをもたらしうるからです。99%同じYAMLのワークロードと設定がデプロイされた2つのクラスターがあり、1%の違いがAWS LB Controllerの有無だけだったとします。99%一致したYAMLでも、結果は異なる可能性があるのです。
2.) 最新バージョンへのアップデートを強く推奨
使用中のバージョンは次のコマンドで確認できます。
kubectl get deploy aws-load-balancer-controller -n=kube-system -o yaml | grep image:
image: public.ecr.aws/eks/aws-load-balancer-controller:v2.4.6
最新を維持する習慣が役立った最近の実例を紹介します。
EKS 1.21は2023年2月15日にEnd of Lifeを迎えました。AWS LB Controllerのユーザーの一部は、2.3.x → 2.4.xへ更新するまで障害に見舞われました。原因は、Kubernetes 1.21から1.22へのアップグレードで多くの非推奨APIが削除されたことです。AWS LB Controller 2.4.xは新しい networking.k8s.io/v1 Ingress APIをサポートしますが、2.3.xはKubernetes 1.22で削除された古いAPI networking.k8s.io/v1beta1 しかサポートしていませんでした。aws-lb-controllerプロジェクトのissueチケットでこの問題が認識され、2.4.xはKubernetes 1.19以降で動作するようにされたため、各組織には移行のための時間が確保されました。アドオンを最新に保つベストプラクティスに従う組織は障害を回避できました。最低限のメンテナンスしか行わない他の組織は、サポート対象のリリースに留まるためにKubernetesを更新したタイミングでこの問題に直面した可能性が高いでしょう。
3.) インストールドキュメントを最初から最後までしっかり読み通すこと。要件を見落としやすいです。
kube-system名前空間にaws-load-balancer-controllerをインストールし、IAMロールを正しく設定するのに加えて、VPCのサブネットにも正しくタグ付けする必要があります。
# Terraform VPC設定(IaC)の抜粋
module vpc {
...
public_subnet_tags = {
"kubernetes.io/role/elb" = "1"
}
private_subnet_tags = {
"kubernetes.io/role/internal-elb" = "1"
}
}
/*
追加の背景情報:
EKSのドキュメントを見ると
https://aws.amazon.com/premiumsupport/knowledge-center/eks-load-balancer-controller-subnets/
以下への参照があります
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
このタグは、古いバージョンのaws-load-balancer-controllerでは必須でした
*/
4.) Ingressオブジェクトをデバッグする必要があるなら、インストール済みのIngressClassを確認する
kubectl get ingressclass
複数表示される場合は kubectl describe ingressclass を実行し、いずれかのIngressClassがデフォルトとマークされたアノテーションを持っているか確認しましょう。
albのIngressClassがデフォルトとしてマークされていない場合は、デバッグ対象のIngressオブジェクトに使用するIngressClassを明示的に指定するべきです。
5. Serviceオブジェクト固有のLBプロビジョニングアノテーションをデバッグする必要がある場合、話はもう少し複雑になります……
複雑になる理由:
- 事実上、2つの異なるコントローラーが同じクラスター内で同時に動作することになります。
- EKSの場合、マネージドサービスでマスターノードもマネージドであるため、2つのコントローラーのうち1つしか視覚的に確認できません(aws-cloud-controller-managerはマネージドマスターノード上で動作しているため見えません)。
- 2つのコントローラーは、機能や担当オブジェクトに大きな重なりがあります。
– aws-cloud-controller-manager:cELBとnELBをプロビジョニング
– aws-load-balancer-controller:aELBとnELBをプロビジョニング
5A.) Kubernetes Serviceオブジェクトを実際にどちらのコントローラーが管理しているかを判別する。 このドキュメントのとおり、Kubernetes Serviceに以下のいずれかのアノテーションを付けると、
service.beta.kubernetes.io/aws-load-balancer-type: nlb-ip service.beta.kubernetes.io/aws-load-balancer-type: external
aws-cloud-controller-managerコントローラーはそのオブジェクトを無視するようになり、aws-load-balancer-controllerが管理できるようになります。
5B.) aws-load-balancer-controllerがServiceを管理している場合、kubectl describe serviceが役に立ちます。 高度なLBオプションを試した方の多くは、LBがstatus pendingで止まり、いつまでもプロビジョニングされないシナリオに遭遇したことがあるはずです。デバッグのために kubectl describe service $NAME を実行したとしましょう。Legacy AWS Controller Managerが管理している場合、得られるエラーメッセージは役に立たないことが多いです。aws-load-balancer-controllerが管理している場合は、デバッグに有用なエラーメッセージが実際に得られます(IAM権限不足やサブネットのタグ付け漏れなど、インストール手順のミスを示してくれるのに非常に役立ちます)。
5C.) リリースノートにざっと目を通し、考慮すべき変更点を確認する
- aws-cloud-controller-managerはデフォルトでパブリックIPのLBをプロビジョニングします。プライベートIPのプロビジョニングには設定の追加が必要です。aws-load-balancer-controllerは逆の挙動です(v2.2.0以降)。
- aws-cloud-controller-managerはデフォルトでcELBをプロビジョニングします。aws-load-balancer-controllerはデフォルトでnELBをプロビジョニングします(
service.beta.kubernetes.io/aws-load-balancer-type: externalが付いたものについて。これがどちらのコントローラーが担当するかを制御します)。 - aws-cloud-controller-managerのコンテナイメージは以前はDocker Hubで提供されていましたが、v2.4.6以降は public.ecr.aws コンテナレジストリでのみホストされるようになります。
5D.) ほとんどのKubernetesオブジェクトは現在の状態を望ましい状態へ遷移させるリコンサイル(調整)ループをサポートしていますが、ロードバランサー系のコントローラーには、変更を反映させるために削除と再作成が必要なエッジケースがいくつかあります。
普段は不要ですが、試す価値がある場合もあります。5Aのアノテーションは、ドキュメントが変更ではなく再作成を推奨している例です。なお、nlb-ip や external という値はAWS LB Controller固有のものである点にも触れておきます。Legacy Controllerでは値としてnlbを使い(空欄ならcELBがプロビジョニングされます)。この落とし穴は、ArgoCDやFluxのようなGitOpsコントローラーで段階的に変更を行う場合に重要になりうる点です。これらは通常、リソースを削除・再作成するのではなくマニフェストを更新するためです。よって、開発環境でArgoCDやFluxのユーザーが段階的な変更をテストするときには、変更を反映させるためにこのエッジケースで手動介入が必要になることがあります。
本記事を書いた主な理由は2つあります。1つは知識の共有で、その目的はこれで達成できました。もう1つは、混乱を減らすための変化を後押しすることです。プロジェクトとドキュメントのメンテナーが行えば、混乱解消に大きく貢献する変更が3つあります。いずれもaws-load-balancer-controllerをEBS-CSIプロジェクトに近づけるものです。
- 本プロジェクトを、AWSコンソールGUIからインストール可能なEKSの公式アドオン一覧に追加する。
- aws-load-balancer-controllerがアドオンであることが一目で明らかになるよう、複数の場所のドキュメントを更新する。
- アノテーションの参照を
kubernetes.ioからebs.csi.aws.comのような形式へ更新する。これにより、見ただけでアドオンと分かるようになり、関連ドキュメントを検索する際のユーザー体験を向上させるSEO(検索エンジン最適化)効果も得られます。