CapsuleによるセキュアなKubernetesマルチテナンシー:クラスターの乱立を防いでチームを分離する

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

午前2時の呼び出し:なぜNamespaceだけでは不十分なのか

午前2時14分、電話が鳴り響きました。PagerDutyがステージングクラスター全体のダウンを報告していました。調査開始から10分、原因を特定しました。データサイエンスチームの開発者が、リソース制限を設定せずに128コアを要求するSparkジョブを実行していたのです。それが利用可能なすべてのCPUサイクルを食いつぶし、フロントエンドとAPIサービスがダウンするまで追い込みました。

本当の問題は、単なるクォータの欠如ではありませんでした。15もの異なるチームに対して個別のRBACロールを管理するのがフルタイムの仕事になりつつあったため、私は広範な権限を与えてしまっていたのです。私は「Namespace地獄」に陥っていました。境界は曖昧で、一つのミスが船全体を沈めかねない状況でした。

マルチテナンシーをマスターすることは、プラットフォームエンジニアにとって必須のスキルです。チームが自分の環境を所有していると感じられるクラウドのような体験を提供しつつ、影響範囲(ブラストライジアス)を制御し続ける必要があります。Capsuleは、これを可能にします。

マルチテナンシー手法の比較

適切な戦略の選択は、予算とチームの規模によって決まります。ここでは、最も一般的な手法とCapsuleを比較します。

1. 「チームごとにクラスターを用意する」アプローチ

これは最高の分離性を提供しますが、予算を破壊します。15チームをサポートする場合、15個のコントロールプレーン and 15組のロギングスタックの費用を支払うことになります。メンテナンスも悪夢です。15のクラスターを一つずつアップグレードするのは、生産的な時間の使い方とは言えません。

2. 標準的なKubernetes Namespace

これはデフォルトのフラットなアプローチです。Namespaceを作成し、RoleBindingを割り当てます。しかし、Namespaceをグループ化することはできません。「この特定のチームは、5つのプロジェクト全体で合計64GBのRAMを使用できる」とKubernetesに簡単に伝えることはできないのです。これは「全か無か」のゲームです。

3. Capsule(「テナント」オペレーター)

Capsuleは、Namespaceの上位にTenant(テナント)という抽象化レイヤーを追加します。これにより、複数のNamespaceを一つの管理単位としてグループ化できます。Admission Controllerを使用することでAPIコールをインターセプトし、チームがサンドボックス内に留まるように強制します。ユーザーがクラスター全体の権限を必要とすることはありません。

Capsuleを使用するメリットとデメリット

メリット デメリット
ネイティブな体験: チームは標準のkubectlを使用します。学習すべき独自のCLIはありません。 CRDの管理: クラスターのオーバーヘッドにカスタムリソース定義(CRD)が追加されます。
リソースの集約: 複数のNamespaceにわたる制限を設定できます(例:チームAは合計20 CPUまで)。 Webhookへの依存: CapsuleのPodが失敗すると、ユーザーがNamespaceを作成または更新できなくなる可能性があります。
自動化されたガバナンス: Ingress의 ホスト名やレジストリのホワイトリストを自動的に強制できます。 OIDCの設定: OktaやKeycloakなどのプロバイダーとの統合には、事前の計画が必要です。

推奨される本番環境スタック

オペレーターをインストールして終わりではありません。本番グレードのサンドボックスを真に安全にするには、いくつかの追加コンポーネントが必要です。

  • Cert-Manager: CapsuleのアドミッションWebhookで使用されるTLS証明書の管理に不可欠です。
  • OIDCプロバイダー (Dex/Keycloak): 社内のADグループをCapsuleのテナントに直接マッピングします。
  • Capsule Proxy: この巧妙なアドオンにより、ユーザーがkubectl get namespacesを実行した際、自分のNamespaceのみが表示されるようになります。

実装ガイド:サンドボックスの構築

「Fintech」チーム用のテナントを構築してみましょう。彼らには独自のNamespaceを作成する自由が必要ですが、RAMは32GBまで、ドメインは特定の社内ドメインに制限する必要があります。

ステップ1:HelmによるCapsuleのインストール

まずはコントローラーをデプロイします。クラスターが準備済みで、Helmがインストールされていることを前提とします。

# リポジトリを追加
helm repo add projectcapsule https://projectcapsule.github.io/charts

# アップデートとインストール
helm repo update
helm install capsule projectcapsule/capsule -n capsule-system --create-namespace

ステップ2:テナントの定義

Tenantオブジェクトは設定の核となります。このマニフェストは、Fintechチームに対する厳格な境界を定義します。

# fintech-tenant.yaml
apiVersion: capsule.clastix.io/v1beta2
kind: Tenant
metadata:
  name: fintech-team
spec:
  owners:
    - name: [email protected]
      kind: User
  namespaceOptions:
    quota: 10 # Aliceは最大10個のNamespaceを作成可能
  resourceQuotas:
    - scope: Tenant
      hard:
        requests.cpu: "8"
        requests.memory: 16Gi
        limits.cpu: "16"
        limits.memory: 32Gi
  ingressOptions:
    allowedHostnames:
      allowedRegex: ".*\.fintech.mycompany.com"
  limitRanges:
    - limits:
        - default:
            cpu: "500m"
            memory: "512Mi"
          defaultRequest:
            cpu: "100m"
            memory: "256Mi"
          type: Container

kubectl apply -f fintech-tenant.yamlでこれを適用します。これでAliceがこのサンドボックスの正式なオーナーになりました。

ステップ3:テナントオーナーとしてのNamespace作成

ここからワークフローが改善されます。Aliceはクラスター管理権限を必要としません。彼女が新しいNamespaceを要求すると、Capsuleはその要求がテナントの制限内であるかを検証します。パスすれば、Capsuleが彼女の代わりにNamespaceを作成します。

Aliceは以下のコマンドを実行できます:

kubectl create ns fintech-prod
kubectl create ns fintech-dev

もし彼女が11個目のNamespaceを作成しようとすると、Capsuleはその要求を拒否します。彼女のチームが合計メモリ使用量を33Giに押し上げるようなPodをデプロイしようとすれば、APIサーバーが即座にブロックします。

ステップ4:ネットワーク分離の自動化

標準のKubernetesでは、すべてのPodが互いに通信可能です。これはマルチテナント環境ではセキュリティリスクとなります。Capsuleは、Fintechチームが作成するすべての新しいNamespaceにNetwork Policyを自動的に注入できます。

# テナントのspecに追加
  networkPolicies:
    items:
      - policyTypes:
          - Ingress
        podSelector: {}
        ingress:
          - from:
              - podSelector: {} # 同一テナント内からのトラフィックのみを許可

よくある障害のトラブルシューティング

Namespaceが表示されない場合は、まずCapsuleのログを確認してください。次のコマンドを使用します:kubectl logs -l app.kubernetes.io/instance=capsule -n capsule-system

ほとんどの失敗は、Kubernetes APIとCapsule Webhook間の証明書の不一致に起因します。カスタムCAを使用している場合は、Capsuleがそれを信頼するように設定する必要があります。また、Capsuleはアイデンティティを管理するものであり、ユーザーそのものを管理するのではないことを忘れないでください。ユーザーがNamespace作成を試行できるようにするための基本的なClusterRoleBindingは依然として必要です。Capsuleは、そのアクションを承認または拒否するゲートキーパーとして機能します。

最後に

断片化していたクラスターをCapsuleで統合したことで、月間のAWSコストを約4,200ドル、つまり40%削減できました。さらに重要なのは、心の平穏を取り戻せたことです。もう、暴走したSparkジョブがミッションクリティカルなサービスを停止させることを心配する必要はありません。開発者には切望されていた自律性を与え、管理者には正気を保つために必要なガードレールを手に入れることができます。

Share: