Amazon Web Services ブログ
Amazon Elastic Kubernetes Service で Kiosk にソフトマルチテナンシーをセットアップする
はじめに
現在、同じ Kubernetes クラスターで実行されている複数のテナント間を完全に分離することは不可能です。その理由は、Kubernetes がクラスターごとに 1 つのコントロールプレーンを持ち、クラスターで実行されているすべてのテナントが同じコントロールプレーンを共有するように設計されているためです。1 つのクラスターで複数のテナントをホストすると、いくつかの利点がもたらされます。主な利点には、効率的なリソースの利用と共有、コストの削減、設定のオーバーヘッドの削減があります。
ただし、マルチテナントの Kubernetes セットアップでは、リソースの共有とセキュリティに関して特殊な課題が生じます。これについての理解を深めましょう。共有クラスターの目標の 1 つは、各テナントが利用可能なリソースを公平に共有し、その要件を満たすことです。この場合に緩和する必要があると考えられる副作用に、ノイズの多い隣接効果があります。これは、テナント間で適切なレベルのリソース分離を保証することにより対処します。2 番目の課題にして主な課題は、セキュリティです。悪意のあるテナントが他のテナントを危険にさらすことを避けるには、テナント間の分離が必須です。分離メカニズムによって実装されるセキュリティレベルに応じて、業界では共有テナンシーモデルをハードとソフトのマルチテナンシーに分割しています。
マルチテナンシー
ハードマルチテナンシーは、テナント間の信頼がないことを意味し、1 つのテナントは他のテナントの何にもアクセスできません。このアプローチは、たとえば、互いに知られていない複数のテナントをホストするサービスプロバイダーに適しています。このセットアップの主な焦点は、テナント間でビジネスを完全に分離することです。オープンソースコミュニティでは、この課題を解決するための作業が進行中ですが、このアプローチはまだ本番ワークロード全体では広く使用されていません。
ハードマルチテナンシーの対極にあるのが、ソフトマルチテナンシーです。これは、同じ組織またはチームの一部である可能性のあるテナント間に信頼関係があることを表します。このアプローチの主な焦点は、セキュリティの分離ではなく、テナント間のリソースの公平な利用です。
オープンソースコミュニティには、ソフトマルチテナンシーを実装するための取り組みがいくつかあり、その 1 つが Kiosk です。Kiosk は、Kubernetes クラスターにソフトマルチテナンシーを実装するためのオープンソースフレームワークです。この記事では、Amazon Elastic Kubernetes Service (Amazon EKS) クラスターに実装するためのステップバイステップガイドを示します。
初期設定
セットアップを続行する前に、次の前提条件を満たしていることを確認してください。
- AWS アカウントにログインします。
- AWS マネジメントコンソールで Amazon EKS クラスターを作成します。
- ローカルマシンから Amazon EKS クラスターに接続します。
- ローカルマシンに kubectl をインストールします。これは、Kubernetes クラスターを制御するためのコマンドラインツールです。
- ローカルマシンに helm バージョン 3 をインストールします。これは Kubernetes のパッケージマネージャーです。
- Kiosk には、Kubernetes バージョン 1.14 以降が必要です。
チュートリアル
Amazon EKS で Kiosk をセットアップする方法を示すために、次のアーキテクチャを展開します。これは、Node.js アプリケーションと Redis データストアの 2 つのテナント間で共有される 1 つの Kubernetes クラスターを示しています。
セットアップを始める前に、Kiosk の基本的な構成要素をいくつか示します。
- クラスター管理者 – クラスター全体で任意の操作を実行する管理者権限を持っています。
- アカウント – テナントに関連付けられたリソース。これは、クラスター管理者が定義および管理します。
- アカウントユーザー – Kubernetes ユーザー、グループ、またはサービスアカウントである可能性があります。これは Cluster Admin によって管理され、複数のアカウントに関連付けることができます。
- スペース – 通常の Kubernetes 名前空間の仮想表現であり、単一のアカウントに属する可能性があります。
- アカウントクォータ – アカウントのクラスター全体の集約的な制限を定義します。
- テンプレート – 一連の Kubernetes リソースでスペースを初期化するために使用します。テンプレートは、アカウント設定を通じて適用されます。これは、クラスター管理者が定義および管理します。
- テンプレートインスタンス – スペースに適用されたときのテンプレートの実際のインスタンスです。これには、インスタンス化に使用されるテンプレートとパラメータに関する情報が含まれています。
アカウント、スペース、アカウントクォータ、テンプレート、およびテンプレートインスタンスは、Kiosk チャートのインストール時にクラスターに作成されるカスタムリソースです。きめ細かなアクセス許可をこれらのリソースに追加できるため、テナントの分離が可能になります。
Kiosk のインストール
1.EKS クラスターのノードグループのワーカーノードを表示できることを確認します。このガイドで使用する EKS クラスターは、3 x m5.large (2 vCPU および 8 GiB) インスタンスで構成されています。
$kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-192-168-xxx-xxx.ec2.internal Ready <none> 48m v1.16.8-eks-e16311
ip-192-168-xxx-xxx.ec2.internal Ready <none> 48m v1.16.8-eks-e16311
ip-192-168-xxx-xxx.ec2.internal Ready <none> 48m v1.16.8-eks-e16311
2.専用の名前空間を作成し、helm を使用して Kiosk をインストールします。Helm は Kubernetes のパッケージマネージャーです。
$kubectl create namespace kiosk
$helm install kiosk --repo https://charts.devspace.sh/ kiosk --namespace kiosk --atomic
この手順では、kiosk
名前空間にポッドを作成します。
ユーザーの作成
2 つの IAM (Identity and Access Management) ユーザー dev
と dba
を作成し、それぞれが個別のテナントを管理します。EKS は、AWS IAM Authentication for Kubernetes を介した Kubernetes RBAC (ロールベースのアクセス制御) と IAM サービスの統合をサポートしているため、次のステップは、2 人のユーザーに RBAC アクセスを追加することです。
1.次の手順に従って、ユーザー dev
と dba
を作成します。IAM サービスは認証のみに使用されるため、ユーザーの作成中にアクセス許可を付与する必要はありません。Kubernetes クラスター内の各ユーザーのアクセス許可は、以降の手順で RBAC メカニズムを介して付与されます。
初期設定フェーズで EKS クラスターを作成した IAM ユーザーには、クラスターの管理者権限が自動的に付与されるため、このガイドではクラスター管理者として使用します。クラスター管理者用の IAM アクセスキーがまだ作成されていない場合は、次の手順に従って作成し、こちらで説明されているように、認証ファイル中の kube-cluster-adminと名前がつけられたプロファイルに含めます。
注: このガイドのすべてのコマンドは、kubectl
コマンドで明示的に指定されていない限り、クラスター管理者として実行されます。クラスター管理 IAM 認証情報を使用するには、AWS_PROFILE
環境変数をオーバーライドします。
Linux または macOS の場合
$export AWS_PROFILE=kube-cluster-admin
Windows の場合
2.aws-auth
ConfigMap を更新して、2 人のユーザーに RBAC アクセスを追加します。
$kubectl edit configmap aws-auth -n kube-system
3.data.mapUsers
の下に 2 人のユーザーを追加します。ユーザー ARN は IAM コンソールからコピーできます。
注: クラスターを作成する IAM エンティティには、クラスターの RBAC 設定で system:masters
アクセス許可が自動的に付与されます。ユーザー dev
と dba
は、どのグループにも追加されていないため、デフォルトで読み取り専用アクセス許可があります。
偽装ユーザー
Kubernetes では、コマンドラインから user impersonation を介して kubectl
コマンドを実行するときに、ユーザーが別のユーザーとして行動することができます。これを行うには、偽装ユーザーに、偽装する属性のタイプ (この場合は user
) に対して impersonate
アクションを実行する権限が必要です。クラスター管理者はデフォルトで system:masters
権限を持っているため、ユーザー dev
と dba
に偽装することができます。ユーザーに偽装するには、kubectl
コマンドの -as=<username>
フラグを使用します。
各テナントに Kiosk アカウントを作成する
1.Node.js アプリケーションのアカウントの定義ファイルを作成します。
アカウントは、アカウントにアクセスできるアカウントユーザーであるサブジェクトを定義します。アカウントユーザーは、Kubernetes ユーザー、グループ、またはサービスアカウントである可能性があります。この場合のアカウントユーザーは dev
です。これは以前に aws-auth
ConfigMap に追加されています。
2.アカウントを作成する
$kubectl apply -f node-account.yml
3.Redis アプリケーションに対してこの手順を繰り返します。metadata.name
を redis-account
に、spec.subjects[0].name
を dba
に更新します。
4.作成したアカウントをクラスター管理者として表示します。
$kubectl get accounts
5.作成したアカウントをユーザー dev
として表示します。このユーザーに関連付けられているアカウントのみを表示するアクセス権があります。
$kubectl get accounts --as=dev
アカウントごとに Kiosk スペースを作成する
1.デフォルトでは、クラスター管理者のみがスペースを作成できます。アカウントユーザーがスペースを作成できるようにするには、Kubernetes RBAC ClusterRoleBinding
を作成します。ユーザー dev
と dba
がアカウントにスペースを作成できるようにします。
注: kiosk-edit
は、Kiosk のグラフがクラスターにインストールされたときに作成された ClusterRole
です。これは、ClusterRoleBinding
設定に含まれるサブジェクトによるスペースリソースの作成、更新、削除アクションを許可します。kiosk-edit
ロールの完全な設定は、次のコマンドを実行して確認できます。
$kubectl get clusterroles kiosk-edit -n kiosk -o yaml
2.クラスター管理者として ClusterRoleBinding
を作成します。
$kubectl apply -f cluster-role-binding.yml
3.Node.js アプリケーション用のスペースを作成します。まず、定義ファイルを作成します。
4.ユーザー dev
に偽装し、node-account
用のスペースを作成します。
$kubectl apply -f node-space.yml --as=dev
5.Redis アプリケーションに対してこの手順を繰り返します。metadata.name
を redis-space
に、spec.account
を redis-account
に更新します。
6.ユーザー dev
として redis-account
にスペースを作成しようとすると、エラーが発生することに注意してください。
7.現在のスペースをクラスター管理者として表示します。node-space
と redis-space
の両方が表示されます。
$kubectl get spaces
8.現在のスペースをユーザー dev
として表示します。ユーザー dev
が所有するスペースのみにアクセスできることに注意してください。この場合、これは node-space
で、node-account
に属しています。
$kubectl get spaces --as=dev
9.スペースは Kubernetes 名前空間の仮想表現であるため、コマンドラインで同じ構文を使用できます。たとえば、スペース内のすべてのポッドを一覧表示するには:
$kubectl get pods -n redis-space
Kiosk アカウントに制限を適用する
アカウントごとのスペース数を制限する
1.アカウントに関連付けることができるスペースの数を制限します。定義ファイル node-account.yml
を更新して、スペース制限を追加してみましょう。
2.変更をクラスター管理者として node-account
に適用します。
$kubectl apply -f node-account.yml
現在、node-account
は 2 つのスペースのみを持つことができます。3 番目のスペースを作成しようとすると、エラーがスローされます。
3.定義ファイル redis-account.yml
を更新して、2 番目のアカウントに同じ制限を適用します。
既存のアカウントにアカウントクォータを適用する
1.アカウントクォータを定義して、アカウントのコンピューティングリソースの制限を定義します。クォータ定義ファイルを作成します。
2.クラスター管理者としてアカウントクォータを作成します。
$kubectl apply -f node-quota.yml
AccountQuotas は、同じリソースを制限する点で Kubernetes リソースクォータと非常に似ていますが、単一の名前空間に適用されるリソースクォータとは異なり、アカウントのすべてのスペースに制限が適用されるという利点があります。
3.AccountQuota は、クラスター管理者のみが作成できます。アカウントユーザーとしてアカウントクォータを作成しようとすると、エラーが発生します。
$kubectl apply -f node-quota.yml –-as=dev
User "dev" cannot get resource "accountquotas" in API group "config.kiosk.sh" at the cluster scope
4.クラスター管理者として、クラスター全体のアカウントクォータを表示します。
$kubectl get accountquotas
スペース用のテンプレートを作成する
1.Kiosk のテンプレートは、スペースの設計図として機能します。テンプレートは、デフォルトでクラスター管理者が定義および管理します。
2.このスペースにデプロイされたすべてのコンテナに 500 milli CPU の CPU リクエストと 1 CPU の CPU 制限が割り当てられるように制限するテンプレートを作成してみましょう。
3.テンプレートをクラスター管理者として作成します。
$kubectl apply -f template-definition.yml
4.デフォルトでは、テンプレートはオプションです。テンプレートルールに従うようにスペースの作成を強制するには、これをアカウント設定に追加する必要があります。アカウント内にスペースが作成されたときにテンプレートに従うように redis-account
を更新しましょう。
5.クラスター管理者としてアカウントに変更を適用します。
$kubectl apply -f redis-account.yml
6.redis-account
内にスペースを作成して、これをテストしてみましょう。
7.クラスター管理者としてスペースを作成します。
$kubectl apply -f redis-mandatory-space.yml
8.スペースが作成されると、LimitRange
リソースが作成されたことを確認できます。
$kubectl get limitrange -n redis-mandatory-space
9.テンプレートから作成されたスペースごとに、テンプレートインスタンスが作成されます。テンプレートインスタンスを使用して、テンプレートから作成されたリソースを追跡できます。新しいスペースのインスタンスを表示します。
$kubectl get templateinstances -n redis-mandatory-space
10.テンプレートが適用されていることをテストするには、新しいスペースにテストポッドをデプロイし、制限範囲が適用されているかどうかを確認します。
$kubectl run nginx --image nginx -n redis-mandatory-space --restart=Never
11.ポッド設定を確認し、適用されたリソース制限を確認します。
$kubectl describe pod nginx -n redis-mandatory-space
12.ポッドを削除してセットアップを続行します。
$kubectl delete pod nginx -n redis-mandatory-space
2 つのアカウントでアプリケーションをデプロイする
1.node-account
のアカウントクォータが作成されているため、必要なコンピューティングリソースをデプロイの定義ファイルで指定する必要があります。
$kubectl apply -f node-deployment.yml -n node-space --as=dev
2.Redis データストアをユーザー dba
として 2 番目のアカウントにデプロイします。
$kubectl create deploy redis --image redis -n redis-space --as=dba
アカウントの分離を確認する
1.アカウントユーザー dev
がアクセスできるリソースを確認します。
$kubectl get all -n node-space --as=dev
2.アカウントユーザー dev
が redis-space
のリソースにアクセスできるかどうかを確認します。多くのエラーが発生するでしょう。
$kubectl get all -n redis-space --as=dev
テナント間のアクセスを確認する
1.node-account
のポッドを確認します。ポッドの名前をメモします。
$kubectl get pods -n node-space --as=dev
2.redis-account
のポッドを確認します。ポッドの IP アドレスをメモします。
$kubectl get pods -n redis-space -o wide --as=dba
3.2 つのポッド間の接続をテストします。
$kubectl exec -n node-space <pod-name> --as=dev -- ping <ip-address>
テナントはスペースを越えてアクセスできることがわかります。より厳密なセキュリティ制御のために、ネイティブの Kubernetes Network Policies と Pod Security Policies を利用できます。
クリーンアップ
Amazon Elastic Kubernetes Service クラスターを削除して、コストが余計にかかるのを回避しましょう。
まとめ
プラットフォームの進化とこの機能を実装する複雑さのため、最近では、Kubernetes のマルチテナンシーがオープンソースコミュニティのホットトピックになっています。最新情報を取得するには、kubernetes-sigs/multi-tenancy で Kubernetes マルチテナンシー Special Interest Group コミュニティをフォローできます。
この記事では、Kiosk の 1 つの Kubernetes クラスターでソフトマルチテナンシーを簡単に設定できることと、ネイティブの Kubernetes 機能にはない利点があることについて説明しました。アカウントクォータを通じてクラスター全体でリソースを分離し、アカウント、アカウントユーザー、スペースなどのプリミティブを通じてセキュリティ境界を実装しました。