ワークロードを専用ノードプールに分離する

このページでは、特権付きのマネージド ワークロードとは別の専用ノードプールでワークロードをスケジュールするように GKE on Azure を構成することで、クラスタ内で権限昇格攻撃のリスクを軽減する方法について説明します。

概要

GKE on Azure クラスタは、Google が管理している特権付きのワークロードを使用して、指標の収集などの特定のクラスタ機能を実行できるようにします。これらのワークロードには、クラスタ内で正しく実行するための特別な権限が付与されます。

ノードにデプロイするワークロードは、悪意のあるエンティティによって侵害されるおそれがあります。特権付きのシステム ワークロードと一緒にこれらのワークロードを実行すると、コンテナを侵害した攻撃者が、ノード上の特権付きワークロードの認証情報を利用して、クラスタ内で権限昇格を実行できるようになります。

コンテナ ブレイクアウトの防止

基本的な防御対象はアプリケーションです。GKE on Azure には、クラスタと Pod の強化に使用できる複数の機能があります。ほとんどの場合、ワークロードを強化するために、Policy Controller とカーネル セキュリティ機能を使用することを強くおすすめします。セキュリティに関する推奨事項について詳しくは、セキュリティの概要をご覧ください。

権限昇格攻撃の回避

他の強化策に加えて分離を強化する場合は、ノード taintノード アフィニティを使用して、専用ノードプールでワークロードをスケジュールします。

ノード taint は、これらのノード上で対応する toleration のないワークロード(GKE on Azure マネージド ワークロードなど)のスケジューリングを回避するよう GKE on Azure に指示します。独自のワークロードのノード アフィニティは、Pod を専用ノードでスケジュールするように GKE on Azure に指示します。

ノード分離の制限事項

  • 攻撃者は、侵害されたノードからサービス拒否攻撃(DoS)を開始できます。
  • 侵害されたノードは、クラスタ内のすべての Pod や Namespace など、引き続き多くのリソースを読み取ることができます。
  • 侵害されたノードは、そのノードで実行されているすべての Pod が使用する Secret と認証情報にアクセスできます。
  • ワークロードを分離するために別のノードプールを使用すると、コスト効率、自動スケーリング、リソース使用率に影響を与える可能性があります。
  • 侵害されたノードは、下りネットワーク ポリシーを回避できます。
  • 一部の GKE on Azure マネージド ワークロードは、クラスタ内のすべてのノードで実行される必要があり、すべての taint を許容するように構成されています。
  • 昇格した権限を持ち、あらゆる taint を許容できる DaemonSet をデプロイすると、これらの Pod が、侵害されたノードからの権限昇格に利用される可能性があります。

ノード分離の仕組み

ワークロードにノード分離を実装するには、次のようにする必要があります。

  1. ワークロードのノードプールに taint とラベルを追加します。
  2. 対応する toleration とノード アフィニティ ルールでワークロードを更新します。

このガイドでは、クラスタ内の 1 つのノードプールから始めることを前提としています。ノード taint に加えてノード アフィニティを使用することは必須ではありませんが、スケジューリング全体をより詳細に管理できるようになるので、ノード アフィニティを使用することをおすすめします。

始める前に

このページで説明する操作を行う前に、次のことを完了しておいてください。

ワークロードのノードプールに taint とラベルを適用する

ワークロードの新しいノードプールを作成し、ノード taint とノードラベルを適用します。ノードプール レベルで taint またはラベルを適用すると、自動スケーリングによって作成された新しいノードなど、新しいノードはすべて、指定された taint とラベルを自動的に取得します。

ノード taint とノードラベルを既存のノードプールに追加することもできます。NoExecute 効果を使用すると、GKE on Azure は、新しい taint に対応する toleration がないノード上で実行されている Pod を強制排除します。

新しいノードプールに taint とラベルを追加するには、次のコマンドを実行します。

gcloud container azure node-pools create POOL_NAME \
    --cluster CLUSTER_NAME \
    --node-taints TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
    --node-labels LABEL_KEY=LABEL_VALUE

次のように置き換えます。

  • POOL_NAME: ワークロードの新しいノードプールの名前。
  • CLUSTER_NAME: GKE on Azure クラスタの名前。
  • TAINT_KEY=TAINT_VALUE: スケジュールする TAINT_EFFECT に関連付けられた Key-Value ペア。例: workloadType=untrusted
  • TAINT_EFFECT: NoSchedulePreferNoSchedule、または NoExecute のいずれかの効果値NoExecuteNoSchedule よりも強制排除が保証されています。
  • LABEL_KEY=LABEL_VALUE: ノードラベルの Key-Value ペア。ワークロード マニフェストで指定したセレクタに対応しています。

ワークロードに toleration とノード アフィニティ ルールを追加する

専用ノードプールに taint を追加しても、追加した taint に対応する toleration がなければ、ワークロードはそのノードプールでスケジュールできません。toleration をワークロードの仕様に追加して、taint が追加されたノードプールで Pod がスケジュールされるようにします。

専用ノードプールにラベルを付けた場合は、ノード アフィニティ ルールを追加して、そのノードプールにのみワークロードをスケジュールするように GKE on Azure に指示することもできます。

次の例では、workloadType=untrusted:NoExecute taint に対する toleration と workloadType=untrusted ノードラベルのノード アフィニティ ルールを追加します。

kind: Deployment
apiVersion: apps/v1
metadata:
  name: my-app
  namespace: default
  labels:
    app: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      tolerations:
      - key: TAINT_KEY
        operator: Equal
        value: TAINT_VALUE
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: LABEL_KEY
                operator: In
                values:
                - "LABEL_VALUE"
      containers:
      - name: sleep
        image: ubuntu
        command: ["/bin/sleep", "inf"]

次のように置き換えます。

  • TAINT_KEY: 専用ノードプールに適用した taint キー。
  • TAINT_VALUE: 専用ノードプールに適用した taint 値。
  • LABEL_KEY: 専用のノードプールに適用したノードラベルのキー。
  • LABEL_VALUE: 専用ノードプールに適用したノードラベル値。

kubectl apply で Deployment を更新すると、GKE on Azure では影響を受ける Pod が再作成されます。ノード アフィニティ ルールにより、作成した専用ノードプールに Pod が強制移動されます。この toleration によって、それらの Pod のみをノードに配置できます。

分離が機能していることを確認する

スケジューリングが正しく機能することを確認するには、次のコマンドを実行してワークロードが専用ノードプールにあるかどうかを確認します。

kubectl get pods -o=wide

推奨事項とベスト プラクティス

ノード分離を設定したら、次の作業を行うことをおすすめします。

  • components.gke.io/gke-managed-components taint を追加して、特定のノードプールを GKE on Azure マネージド ワークロードのみに制限します。この taint を追加すると、独自の Pod がこれらのノードでスケジュールされなくなり、分離が改善します。
  • 新しいノードプールを作成する場合、独自の taint をこれらの新しいノードプールに追加して、ほとんどの GKE on Azure マネージド ワークロードがこれらのノードで実行されないようにします。
  • サードパーティ ツールをインストールする場合など、クラスタに新しいワークロードをデプロイする際は、常に Pod に必要な権限を監査してください。可能であれば、昇格権限を使用するワークロードを共有ノードにデプロイすることは避けてください。

次のステップ