NRIのコンテナ、Kubernetes活用事例を紹介する本連載。最終回はマルチテナンシー構成を活用した大規模な基幹システム開発の事例を紹介する。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
2020年現在、ソフトウェアやサービスの開発において、開発速度の向上やリリースサイクルの短期化はより強く求められるようになっている。野村総合研究所(以後、NRI)でも「アジャイル」や「DevOps」といった開発手法に加えて「マイクロサービスアーキテクチャ」といった設計思想が現場になじみつつある。本連載のテーマでもある、コンテナを効率的に運用するためのオーケストレーターである「Kubernetes」の普及も進んでいる。
第2回と第3回で述べたように、小規模チームによるコンテナ活用やDevOpsチームによるKubernetesの利用事例はあるが、大規模な基幹システム開発においてKubernetesを導入する事例は少ない。今回はNRIのクラウド環境における「大規模基幹システムをマルチテナンシーKubernetesに導入した事例」を紹介する。
大規模な基幹システムの開発においては、業務知識やアプリケーション開発のスペシャリストである「アプリケーション開発チーム」と、ネットワークの設計やコンピュートリソースの整備を担う「基盤チーム」に分かれてプロジェクトを進めることが一般的だ。大規模である分、業務が多岐にわたっているため、アプリケーション開発チームはそれぞれの担当に分かれており、独立した開発体制を持っている。
従来のシステム開発におけるアーキテクチャの設計は、システムごとにそれぞれのチームが個別に検討、対応することが多く大きな負担になっていた。自社のクラウド環境でシステムを構築する場合、縮退運用や一時的なアクセス増加に対処するための余剰リソースを常に用意しておく必要もある。リスクを十分に考慮した上で、システムごとの余剰リソースをいかに有効活用するかが重要な設計要素になった結果、設計や見積もりにかかるコストも高まっていた。
こうした状況を改善するには、システム構築を進める上で下記要件を満たす環境が必要だと考えた。
この要件を満たす一つの解としてNRIが検討したのが、マルチテナンシーKubernetesの導入だった。
Kubernetesには、同一の物理クラスタ上に複数の仮想クラスタを構築できる「Namespace」と呼ばれる機能が存在する。基盤チームはNamespaceを活用することで、Kubernetesクラスタを1つ構築して、アプリケーション開発チームごとに分離された実行環境を提供できると考えた。
しかし、Namespaceを分割するだけでは、特定のコンテナのせいでコンピュートリソースが枯渇したり、誤操作で他のNamespaceにアクセスしてしまったりする可能性がある。そのため、複数のアプリケーション開発チームで構成される大規模システムを運用するには十分な機能とはいえない。Namespaceで環境を分割する際、考慮すべきポイントになった。
また、大規模開発においては開発者のスキルレベルもさまざまであり、コンテナに詳しいメンバーばかりとはいえない。コンテナが稼働するマシン(Node)に不要なアクセスを禁止するなど、コンテナ実行時の権限制御も不可欠だ。
ネットワークも同様に、クラスタ内で他チームが開発するAPIへのアクセスを禁止し、外部アクセスの際には特定のエンドポイントのみを許可するといった制御も必要だ。
従って、下記を要件としたマルチテナンシーKubernetesを構築した(※)。
(※)これは単一のクラスタを異なる会社やクライアントに分割して提供するハードマルチテナンシーを想定したものではない。あくまで同一組織内の信頼できるチームによるソフトマルチテナンシーを前提とした。
Kubernetesには、「ServiceAccount」と通常の「UserAccount」の2種類のユーザーがある。
Kubernetesにアプリケーションをデプロイする場合、Kubernetes APIを介して実行する。それぞれのユーザーに対してKubernetes APIのアクセス制御を実現する機能として、Kubernetesは「Role Base Access Control」(RBAC)を提供している。この機能を利用することで「どのユーザーが」「どのKubernetesのリソースにアクセスできるか」を制御できる。マルチテナンシーのKubernetesクラスタを構築する中で、このアクセス制御は特に重要だ。
ユーザーによるKubernetes APIのアクセス制御の実装方針として、各テナントのNamespaceとテナント管理用UserAccountは基盤チームが作成し、権限を付与した上でテナントのアプリケーション開発者に提供する方式とした。
テナント管理用UserAccountには「どのリソースにどういった操作ができるか」を表した「Role」と、「誰にRoleを与えるか」を表した「RoleBinding」の機能を用いてNamespace内に閉じた権限が与えられている。
これで、各テナント管理者はNamespace外のリソースや他Namespaceのリソースにアクセスできない状態となる。これにより、誤ったManifestの適用や誤操作による他テナントへの影響をなくすことができる。
ServiceAccountはKubernetesで稼働するアプリケーションなどを表すものである。各テナントで稼働するコンテナにはKubernetes APIのアクセス要件はないため、ServiceAccountへKubernetes APIのアクセス権限は付与しないこととした。
特定のアプリケーションによるコンピュートリソースの枯渇を防ぐため、Kubernetesには各Namespaceに使用可能なコンピュートリソースの制限をかけられる「ResourceQuota」という機能がある。
ResourceQuotaによってテナントごとに利用可能なコンピュートリソースを制限し、指定以上のコンピュートリソースが利用されそうになった場合はPodのスケジューリングをさせないことで、他テナントへの影響を抑えられる。
Kubernetesは、Namespace内でのPodやコンテナへのコンピュートリソース割り当てを制御する「LimitRange」と呼ばれる機能を提供している。Podやコンテナへのコンピュートリソース割り当ては、DeploymentのManifestのテンプレートにて設定するためLimitRangeによる制限は実施していない。こちらも要件と照らし合わせて利用可否を決めるとよい。
なお、コンピュートリソースを制限していないベストエフォートなコンテナがある場合、同じNode上で稼働する他のコンテナに影響を与える可能性がある。そのテナントで稼働するシステムの要件も踏まえLimitRangeを利用してコンピュートリソースをクラスタ管理者側で制御するか、(リソース集約の観点ではあまり推奨されないが)特定のNodeにベストエフォートなコンテナが含まれるPodを寄せてしまう方法を採ることもできる。
セキュアなKubernetesを構築するには、コンテナからKubernetesのNodeに不要なアクセスができないように制御する必要がある。Kubernetesには「PodSecurityPolicy」と呼ばれる機能があり、「rootユーザーでの動作を想定したコンテナの実行」や「ホストネットワークの使用」「hostPathの使用」などNodeに影響を与え得るコンテナの稼働を制限できる。
実装方針として、上記に述べたようなNodeへの影響を与える可能性のあるコンテナはデフォルトで実行できないように設定した。root実行の許可やNodeへのアクセスを許可するPodSecurityPolicyの作成とServiceAccountへのひも付けを基盤チームが実施し、要件に応じて各アプリケーション開発チームに提供している。
Kubernetesで通信を制御しない場合、AというNamespaceのPodからBというNamespaceのPodにアクセス可能だ。マルチテナンシーを考慮する場合は通信も制御すべきポイントになる。
Kubernetesには「NetworkPolicy」と呼ばれるPod間通信やクラスタ外部とのエンドポイント通信を制御するためのリソースが用意されている。対応したSDNプラグインを利用することでPodの通信制御が可能だ。
各アプリケーション開発チームのAPIは一部を除いて互いに実行できないよう制御できること、外部エンドポイントへのアクセスも同様に制御できることが要件にあったため、NetworkPolicyを導入し通信を制御するようにした。
上記以外にも、Kubernetesの「Multi-tenancy SIG(Special Interest Group)」によって「Hierarchical Namespace Controller」といったマルチテナンシーなKubernetesのための機能開発が進められている。
マルチテナンシーKubernetesを実現するメリットは複数あるが、課題もある。
まず、Namespace外のリソースをテナントにどう提供するかだ。アプリケーション開発チームにはNamespace内に閉じた権限を付与しているため、Namespace外のリソースが作成できない。
実例として、急きょストレージが必要になった際に、アプリケーション開発チームでNamespace外のリソースであるPersistentVolumeを作成できなかったため、クラスタ管理者側がリソースを作成して対処したことがある。頻度や作業量が増えた場合は細かいアクセスコントロールの検討が必要になるだろう。
また、Kubernetesの機能を拡張するための考え方として「Operator Pattern」と呼ばれるものがある。Operator Patternでは「CustomResourceDefinition」(CRD)と呼ばれるリソースを用いて、独自のリソース定義を追加するが、このCRDもNamespace外のリソースになる。
現状、各テナントによるOperatorの利用要件はないが、Operator Patternが一般的になり、CRDの適用が増えていくと考えられる。Namespace外のリソースをどのように提供していくかは今後検討すべきポイントになるだろう。
今回紹介した内容はソフトマルチテナンシーであったため、共通化可能な部分は集約したが、クラスタ上に構築するシステムの要件によっては個別対応が必要なケースも考えられる。どこまでを共通化し、どこから個別対応とするかの見極め、各テナントの開発者が利用しやすいようにスコープを決めることも難易度が高い。
本記事では大規模な基幹システム開発における問題を解決する手段として、NRIが採用したマルチテナンシーKubernetesを紹介した。だが、システムの特性、要件によってはクラスタ自体を分けてしまった方が良い場合もあるだろう。
本連載では、NRI内に存在する組織間の壁を乗り越える一手段として、Kubernetesをはじめとするクラウドネイティブ技術の取り組みを紹介してきた。
第2回、第3回ではNRIが得意とする金融分野のプロジェクトでの例、生産性向上のサービスそのものをKubernetes上に構築した事例を紹介した。今回は、大規模なプロジェクトにおいて、従来の仮想化技術によるプロビジョニングではなく、Kubernetesを利用したマルチテナンシー構成を採用した例を紹介した。
もちろん、こうした対応で組織に遍在する課題を全て解決したとはいえない。それでも小規模なスピード重視のプロジェクトなど、企業としての対応力を高め、「顧客とともに栄える」べく、社内での挑戦は続いている。NRIの取り組みが同様の課題に取り組み、コンテナやKubernetesの技術採用で悩む読者の背中を押すものとなれば望外の喜びである。
野村総合研究所でKubernetes導入支援や周辺のインフラ設計を担当。
野村総合研究所でデータベースを中心としたインフラ設計を担当。
Copyright © ITmedia, Inc. All Rights Reserved.