LINEヤフー Tech Blog

LINEヤフー株式会社のサービスを支える、技術・開発文化を発信しています。

Kubernetes Controller Sharding を用いた、3世代以上にわたるカスタムコントローラーの水平スケールを実現(インターンレポート)

東京大学大学院 情報理工学系研究科 修士1年の加藤大翔と申します。

私は、LINEヤフーの社内PaaSの開発チームにおいて、4週間のインターンシップに参加しました。本レポートでは、私のインターンシップで取り組んだ「Kubernetes カスタムコントローラーの水平スケールの実現」について紹介します。

背景

LINEヤフーでは、Webアプリケーションのデプロイを容易にする基盤として「LINEヤフー社内向けPaaS」を開発しています。このLINEヤフー社内向けPaaSは Kubernetes をベースに構築されており、開発者向けに抽象化されたマニフェストを適用するだけで、アプリケーションが起動し、自動でユーザーに公開できます。さらに管理コンソールやテレメトリ情報の自動送信、認証・認可、シークレットマネージャーとの連携による機密情報の管理なども一元的に提供しています。

LINEヤフー社内向けPaaS上には、LINEヤフーの多数のサービスが稼働しており、1万以上のノード、10万以上のPodが存在する、非常に大規模な環境です。そのため、LINEヤフー社内向けPaaSでは、アプリケーションクラスター(アプリケーションが実際に稼働するクラスター)と、それらを統括する管理クラスターという複数のKubernetes クラスターを組み合わせてプラットフォームを構成しています。

詳細は、LINEヤフーにおける超大規模プラットフォーム実現への挑戦と学びをご参照ください。

この管理クラスターでは、Kubernetes カスタムコントローラーが使用されています。これは全アプリケーションクラスター上のアプリケーションを統合的に管理するため、非常に高い負荷がかかっています。しかし、Kubernetes コントローラーには、管理リソースの競合を避けるため、基本的に1インスタンスのみが稼働する(水平スケールできない)という制約があり、スケーラビリティに課題がありました。

本インターンシップでは、このカスタムコントローラーの水平スケールを可能にすることを目的に取り組みました。

Kubernetes Controller Sharding

Kubernetes Controller Sharding は、Tim Ebert 氏の修士研究をもとに開発されたOSS(Open Source Software)で、2025年の KubeCon Europe でも発表されています(参考: Beyond the Limits: Scaling Kubernetes Controllers Horizontally - Tim Ebert, STACKIT)。この仕組みのコアアイデアは、管理対象リソースに担当コントローラーのラベルを付与し、競合を避けつつコントローラーの水平スケールを可能にするというものです。

しかし、Kubernetes Controller Sharding をそのままLINEヤフー社内向けPaaSに導入するのは困難でした。理由は、ラベル付けに使用されるハッシュキーの生成方法にあります。この仕組みでは、ハッシュキーとカスタムコントローラーの Lease を用いて consistent hashing を計算し、その計算結果をもとにリソースへラベル付けを行います。親リソースと子リソースで同一のラベルを持たせるには、同じハッシュキーが必要になります。このハッシュキーの導出には、親リソースのNamespace、GVK(Kubernetes のリソースを区別するための Group・Version・Kind のセット)、リソース名の組み合わせが利用されます。一方、子リソースは親への ownerReference(参考:Owners and Dependents - Kubernetes)をもとに同一のキーを導出しています。

ただし、3世代以上のリソース構造を持つ場合、孫リソースは親リソースへの直接的な ownerReference を持たないため、同一のハッシュキーを付与することができません。

3世代以上の��リソース構造を持つときに同一ハッシュキーを付与できない図

LINEヤフー社内向けPaaS環境への Controller Sharding の導入

最初のタスクとして、2世代のコントローラーに対して Controller Sharding をLINEヤフー社内向けPaaSの検証環境に導入し、社内のKubernetes 環境でも相性などの問題がなく、期待どおりに機能することを確認しました。この際、controller-shardingリポジトリでデモ用のサンプルとして提供されている checksum-controller を使用しました。

LINEヤフー社内向けPaaSは、非常に大規模ということもあり、強固なセキュリティや大規模なシステムを維持するための独自のツールが多く存在し、それらの挙動を理解して使いこなすのに、やや苦戦しました。

Namespace ベースの Controller Sharding

前述のとおり、既存のKubernetes Controller Shardingでは3世代以上のリソースを扱うことができないという課題があります。そこで、Namespace ベースの Controller Sharding を導入することでこの課題を解決できないか検討しました。つまり、個々のリソースごとにハッシュを計算してコントローラーを割り当てるのではなく、Namespace 単位でコントローラーを割り当てることで、3世代にわたるリソースも分散して処理できるようにする方法です。

Namespace単位で割り当てることで3世代あるリソースでも処理できる図

一方で、この方法には以下の制約があります。

  1. 管理対象のリソースがすべて Namespaced リソースである必要がある
  2. Namespace 単位での割り当てとなるため、Namespace 数が少ない場合はリソース分散が偏る

それぞれについて説明します。1の制約により、Namespace のような cluster-scoped リソースを扱うコントローラーや、異なる Namespace 間でリソースを生成するコントローラーには適用できません。2については、Namespace 間でリソースの偏りがある場合、負荷の均等化が難しくなります。さらに、consistent hashing を用いるため、例えば Namespace 数が4・コントローラー数が3のような場合には、特定のコントローラーに集中するケースも発生します。

このように大きな制約が課される解決策ではありますが、LINEヤフー社内向けPaaSで利用されているコントローラーはこれらの制約に該当しておらず、本手法を導入可能でした。

実装方法としては以下の2案を検討しました。

  • Namespace をそのままハッシュキーとして使用する
  • Namespace リソースにラベルを付与し、都度そのラベルを参照する

後者の案は、コントローラーの割り当てを決める際に毎回APIサーバーにアクセスしてNamespaceのラベルを参照する必要があるため、一見パフォーマンスの悪化が懸念されますが、Kubernetes のカスタムコントローラーを実装する際のデファクトフレームワークである controller-runtimeは強力なキャッシュ機構を備えているため、これは問題にならないということがわかりました。

実装と検証

2案それぞれに対して、Controller Sharding のコンポーネントである sharder を修正して実際に動かしてみることで、実現性の確認を行いました。また、並行して Design Doc(設計書)を作成し、レビューを通じて実装方針の確認を行いました。

結果として、前者は比較的容易に実装できましたが、後者は controller-runtime で動的にキャッシュ対象の Namespace を変更する方法が見つからず、不採用としました。

また、3世代以上のコントローラーを実際に作成し(メンターの方にご協力いただきました)、動作検証を行いました。今回は説明のために、App → Secret → ConfigMap のようなカスタムコントローラーを実装したものとして進めます。

App のマニフェストを適用後、同一 Namespace 内の3世代リソースに同一のラベルが付与されることを確認しました。

$ kubectl apply -f apps.yaml
$ kubectl get app, secret, configmap -L shard.alpha.sharding.timebertt.dev/paas-controller
NAME  AGE   PAAS-CONTROLLER
app/foo1  12s   paas-controller-5f959fd568-wwp79

NAME          TYPE     DATA   AGE   PAAS-CONTROLLER
secret/foo1   Opaque   0      12s   paas-controller-5f959fd568-wwp79

NAME                         DATA   AGE     PAAS-CONTROLLER
configmap/foo1     0      12s     paas-controller-5f959fd568-wwp79

また、別の Namespace で同様に調べてみると、異なるコントローラーに割り当てられており、Namespace 間での負荷分散ができていることも確認できました。

$ kubectl get app, secret, configmap -L shard.alpha.sharding.timebertt.dev/paas-controller
NAME  AGE   PAAS-CONTROLLER
app/foo2  12s   paas-controller-5f959fd568-hz9sr
app/foo3  12s   paas-controller-5f959fd568-hz9sr

NAME          TYPE     DATA   AGE   PAAS-CONTROLLER
secret/foo2   Opaque   0      12s   paas-controller-5f959fd568-hz9sr
secret/foo3   Opaque   0      12s   paas-controller-5f959fd568-hz9sr

NAME                         DATA   AGE     PAAS-CONTROLLER
configmap/foo2     0      12s     paas-controller-5f959fd568-hz9sr
configmap/foo3     0      12s     paas-controller-5f959fd568-hz9sr

感想

インターンへの参加を通じて、LINEヤフーの大規模な基盤を支える高度な技術力に驚かされました。多くの社内基盤やツールが存在し、かつ高度に抽象化されており、アプリケーション開発者はその大規模さを意識せずに利用できる環境が整っていました。

また、プライベートクラウドを自社運用していることもあり、一口にインフラを扱う組織でも、レイヤーごとにその分野に精通したプロフェッショナルなチームが存在することも刺激的でした。

インターン期間中はチームで行われているミーティングに参加し、アジャイル開発を体験しました。普段アジャイル開発を体感する機会は少ないですが、チームが大規模なだけに、ゆっくりだとしても着実に前に進んでいくための工夫を随所に感じることができました。

おわりに

本インターンでは、LINEヤフー社内向けPaaSで利用されているカスタムコントローラーの水平スケールに挑戦しました。Kubernetes Controller Sharding を3世代以上のリソースに対応できるよう修正・実装し、検証環境で動作を確認できました。

4週間という短い期間でしたが、メンターの方やチームの方々をはじめ、多くの社員の皆様にご支援いただきました。技術力の高い方々に囲まれながら開発に携われたことは、大変刺激的な経験でした。

本当にありがとうございました!

メンターからの一言

本インターンにて社内PaaSチームでメンターをさせていただいていた中村です。今回のインターンの課題としてはKubernetes コントローラーの分散ということで弊社の規模感だからこそ必要となる課題でしたが、現役社員も構想段階から毎日頭を抱えながら取り組んでいる内容です。そんな内容をインターン生が実施するのは非常にハードルが高く開始前は難しかったという感想のみにならないかと不安になることもありました。しかし、実際に加藤さんが参加してもらい、複雑な課題ではあるものの着実に課題に取り組んでいるところを見ると、良い経験につながったのだと安心しました。

また、社内PaaSチームは技術に熱意があったり、安定性のある働き方をしていたりと非常に個性豊かなメンバーで構成されています。そんなメンバーと共に協働したことでおそらく普段では体感できないような体験ができたのではないかと思います。ぜひ今後ともこの経験を生かしていただければと思います。

4週間という非常に短い期間でしたが、お疲れさまでした。加藤さんの今後の活躍に期待しています!