このページでは、Google Kubernetes Engine(GKE)上のクラスタ マルチテナンシーについて説明します。これには、単一の組織で複数の異なるユーザーによって共有されるクラスタや、Software as a Service(SaaS)アプリケーションの顧客別インスタンスによって共有されるクラスタが含まれます。クラスタ マルチテナンシーは、多くの単一テナント クラスタを管理するための代替手段です。
このページでは、マルチテナント クラスタの管理に使用できる Kubernetes と GKE の機能についても簡単に説明します。
マルチテナンシーとは
マルチテナント クラスタは、「テナント」と呼ばれる複数のユーザーやワークロードによって共有されます。マルチテナント クラスタのオペレーターは、不正使用されたテナントや悪意のあるテナントがクラスタや他のテナントに与える可能性のある被害を最小限に抑えるために、テナントを互いに分離する必要があります。また、クラスタ リソースはテナント間で公平に割り当てられている必要があります。
マルチテナント アーキテクチャを計画する際には、Kubernetes のリソース分離のレイヤ(クラスタ、名前空間、ノード、Pod、コンテナ)を考慮する必要があります。また、テナント間でさまざまなタイプのリソースを共有することによるセキュリティへの影響も考慮する必要があります。たとえば、同じノード上の異なるテナントから Pod をスケジュールすると、クラスタに必要なマシンの数を減らすことができます。一方、特定のワークロードが同じ場所に集中しないようにする必要がある場合もあります。たとえば、組織の外部で作成された信頼できないコードは、機密情報を処理するコンテナと同じノードで実行しないようにします。
Kubernetes はテナント間の分離の完全な安全性を保証するわけではありませんが、特定のユースケースには十分と考えられる機能を備えています。各テナントとその Kubernetes リソースをそれぞれ独自の名前空間に分離できます。その後ポリシーを使用してテナントを強制的に分離できます。ポリシーは、通常、名前空間でスコープを指定し、API アクセスやコンテナでの操作を制限したり、リソースの使用に制約を設けたりする目的で使用できます。
マルチテナント クラスタのテナントは、次のものを共有します。
- 拡張機能、コントローラ、アドオン、カスタム リソース定義(CRD)。
- クラスタのコントロール プレーン。クラスタ オペレーション、セキュリティ、監査が一元管理されることを意味します。
マルチテナント クラスタの運用には、複数の単一テナント クラスタの運用と比較していくつかの利点があります。
- 管理オーバーヘッドの削減
- リソースの断片化を削減
- 新しいテナント用のクラスタの作成に伴う時間が不要
マルチテナンシーのユースケース
このセクションでは、さまざまなマルチテナンシーのユースケースに合わせてクラスタを構成する方法について説明します。
エンタープライズ マルチテナンシー
エンタープライズ環境では、クラスタのテナントは組織内の別々のチームです。通常、各テナントにはそれぞれ対応する名前空間があります。クラスタ別のテナントまたは Google Cloud プロジェクト別のテナントで構成される代替マルチテナンシー モデルは、管理が困難です。Namespace 内のネットワーク トラフィックは制限されません。Namespace でのネットワーク トラフィックは明示的に許可リストに登録する必要があります。これらのポリシーは、Kubernetes ネットワーク ポリシーを使用して適用できます。
クラスタのユーザーは、各自の権限に応じて次の 3 種類のロールに分けられます。
- クラスタ管理者
- このロールは、すべてのテナントの管理を担当するクラスタ全体の管理者用です。クラスタ管理者は、任意のポリシー オブジェクトの作成、読み取り、更新、削除を行うことができます。また、名前空間を作成し、名前空間管理者に割り当てることができます。
- 名前空間管理者
- このロールは、特定の単一テナントの管理者用です。名前空間管理者は、自分が担当する名前空間のユーザーを管理できます。
- デベロッパー
- このロールのメンバーは、Namespace が指定されたポリシー以外のオブジェクト(Pod、Job、Ingress など)の作成、読み取り、更新、削除が可能です。デベロッパーは、自分がアクセスできる Namespace でのみこれらの権限を持ちます。
企業組織用に複数のマルチテナント クラスタを設定する方法については、エンタープライズ マルチテナンシーのベスト プラクティスをご覧ください。
SaaS プロバイダ マルチテナンシー
SaaS プロバイダのクラスタのテナントは、アプリケーションの顧客別インスタンスおよび SaaS のコントロール プレーンです。名前空間でスコープを指定したポリシーを利用するには、SaaS のコントロール プレーンのコンポーネントと同様に、アプリケーション インスタンスを独自の名前空間別に編成する必要があります。エンドユーザーは、Kubernetes コントロール プレーンと直接対話することはできず、代わりに SaaS のインターフェースを使用して Kubernetes コントロール プレーンと対話します。
たとえば、ブログ プラットフォームはマルチテナント クラスタ上で実行できます。この場合、テナントは各顧客のブログ インスタンスとプラットフォーム独自のコントロール プレーンです。プラットフォームのコントロール プレーンとホストされている各ブログはすべて別々の名前空間で実行されます。顧客は、クラスタの動作状況を把握することなく、プラットフォームのインターフェースを介してブログの作成と削除、ブログ作成ソフトウェアのバージョンの更新を行うことができます。
マルチテナンシー ポリシーの適用
GKE と Kubernetes には、マルチテナント クラスタの管理に使用できるいくつかの機能が用意されています。次の各セクションでは、これらの機能の概要を説明します。
アクセス制御
GKE には、Identity and Access Management(IAM)とロールベース アクセス制御(RBAC)の 2 つのアクセス制御システムがあります。IAM は、Google Cloud リソースの認証と認可を管理する Google Cloud のアクセス制御システムです。IAM を使用して、GKE リソースと Kubernetes リソースへのアクセス権をユーザーに付与します。Kubernetes に組み込まれている RBAC を使用すると、クラスタ内の特定のリソースや操作に対する詳細な権限を付与できます。
これらのオプションとそれぞれを使用する状況の詳細については、アクセス制御の概要をご覧ください。
このアクセス制御システムの使用方法については、RBAC 入門ガイドおよび IAM 入門ガイドをご覧ください。
IAM と RBAC の権限を Namespace と併用すると、Google Cloud コンソールのクラスタ リソースに対するユーザー操作を制限できます。詳細については、アクセスを有効にしてクラスタ リソースを Namespace ごとに表示するをご覧ください。ネットワーク ポリシー
クラスタのネットワーク ポリシーを使用すると、クラスタの Pod 間の通信を制御できます。ポリシーでは、Pod が通信可能な名前空間、ラベル、IP アドレス範囲を指定します。
GKE でネットワーク ポリシーを適用できるようにする手順については、ネットワーク ポリシーの入門をご覧ください。
ネットワーク ポリシーの記述方法については、ネットワーク ポリシーのチュートリアルに従ってください。
リソースの割り当て
リソースの割り当てでは、名前空間内のオブジェクトで使用されるリソースの量を管理します。割り当ては、CPU とメモリ使用量の観点で設定するか、オブジェクト数の観点で設定できます。リソースの割り当てを通じて、各テナントで使用されるクラスタ リソースがそれぞれの割り当て量を超えないようにすることができます。
詳細については、リソースの割り当てに関するドキュメントをご覧ください。
ポリシーベースの Pod アドミッション制御
セキュリティ境界に違反する Pod がクラスタ内で実行されないようにするには、アドミッション コントローラを使用します。アドミッション コントローラを使用すると、定義したポリシーと照らし合わせて Pod の仕様を確認し、それらのポリシーに違反している Pod がクラスタで実行されるのを防ぐことができます。
GKE では、次のタイプのアドミッション制御がサポートされています。
- Policy Controller: 事前定義のポリシーまたはカスタム ポリシーを宣言し、フリートを使用して大規模にクラスタに適用します。Policy Controller は、オープンソースの Gatekeeper オープン ポリシー エージェントを実装したもので、GKE Enterprise の機能です。
- PodSecurity アドミッション コントローラ: 個々のクラスタまたは特定の Namespace の Pod のセキュリティ標準に対応する事前定義のポリシーを適用します。
Pod の反アフィニティ
Pod の反アフィニティを使用すると、異なるテナントの Pod が同じノードにスケジュールされないようにできます。反アフィニティの制約は、Pod のラベルに基づきます。たとえば、次の Pod 仕様では、"team":
"billing"
というラベルを適用した Pod を記述し、この Pod がラベルなしの近くの Pod にスケジュールされないようにするための反アフィニティ ルールを定義しています。
apiVersion: v1
kind: Pod
metadata:
name: bar
labels:
team: "billing"
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: "kubernetes.io/hostname"
labelSelector:
matchExpressions:
- key: "team"
operator: NotIn
values: ["billing"]
この手法の欠点は、悪意のあるユーザーが任意の Pod に team: billing
ラベルを適用してルールを回避する可能性があることです。Pod の反アフィニティだけでは、信頼できないテナントが存在するクラスタに安全にポリシーを適用することはできません。
詳細については、ポッドの反アフィニティに関するドキュメントをご覧ください。
taint と容認機能を使用した専用ノード
Node Taints は、ワークロードのスケジューリングを制御するもう 1 つの方法です。Node Taints を使用すると、特別なノードを特定のテナント専用として予約できます。たとえば、特定のテナントのワークロードで GPU が必要になる場合は、GPU 搭載ノードをそのテナント専用として扱うことができます。Autopilot クラスタの場合、Node Toleration はワークロードの分離に対してのみサポートされます。必要に応じて、Node Taints がノード自動プロビジョニングによって自動的に追加されます。
ノードプールを特定のテナント専用にするには、effect: "NoSchedule"
を指定した taint をノードプールに適用します。これにより、対応する容認機能を備えた Pod しかノードプールのノードにスケジュールできなくなります。
この手法の欠点は、悪意のあるユーザーが自分の Pod に容認機能を追加して専用ノードプールへのアクセスを取得する可能性があることです。ノード taint と toleration だけでは、信頼できないテナントが存在するクラスタにポリシーを安全に適用することはできません。
詳細については、Kubernetes ドキュメントの taint と toleration をご覧ください。