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

Google Distributed Cloud(GDC)エアギャップの専用ノードプールを使用すると、コンテナ ワークロードを分離して Kubernetes クラスタのセキュリティを強化し、Pod の配置を制御できます。この分離により、権限昇格攻撃のリスクを軽減できます。専用プールを設定するには、taint とラベルを適用し、ワークロードの toleration とノード アフィニティ ルールに一致させて、スケジューリングを確認します。

このドキュメントは、Kubernetes クラスタを管理するプラットフォーム管理者グループの IT 管理者と、コンテナを実行するアプリケーション オペレーター グループのデベロッパーを対象としています。詳細については、ノード分離の概要と GDC エアギャップ ドキュメントの対象読者をご覧ください。

始める前に

このドキュメントのタスクを完了するには、必要な権限をリクエストして環境を準備する必要があります。

IAM ロールをリクエストする

Kubernetes クラスタでコンテナ ワークロードを分離するために必要な権限を取得するには、特定のロールが必要です。必要なロールは、組織スコープの共有クラスタとプロジェクト スコープの標準クラスタのどちらで作業しているかによって異なります。詳細については、Kubernetes クラスタの構成をご覧ください。

共有クラスタロール

共有クラスタ内のノードプールに taint とラベルを適用するには、IAM 組織管理者に連絡して、次のロールをリクエストしてください。

  • ユーザー クラスタ管理者(user-cluster-admin): Management API サーバーでホストされている共有クラスタのリソースを作成、削除、編集、表示します。このロールは、共有クラスタのノードプールへのアクセス権を付与します。

  • ユーザー クラスタ デベロッパー(user-cluster-developer): 共有クラスタの作成、削除、編集、表示。このロールは、共有クラスタ内でホストされているデータプレーン API へのアクセス権を付与します。

これらのロールは Namespace にバインドされていません。

標準クラスタロール

IAM プロジェクト管理者に連絡して、Standard クラスタのノードプールに taint とラベルを適用するために、次のロールをリクエストします。

  • クラスタ管理者(cluster-admin): 標準クラスタ内のすべてのリソースを作成、削除、編集、表示します。このロールは、クラスタのリソースを管理する標準クラスタ内でホストされているデータプレーン API へのアクセス権を付与します。

  • クラスタ デベロッパー(cluster-developer): 標準クラスタを作成、削除、編集、表示します。このロールは、クラスタを管理する標準クラスタ内でホストされているデータプレーン API へのアクセス権を付与します。

  • 標準クラスタ管理者(standard-cluster-admin): 管理 API サーバーでホストされている標準クラスタのリソースを作成、削除、編集、表示します。このロールは、Standard クラスタのノードプールへのアクセス権を付与します。

これらのロールは、プロジェクトの Namespace にバインドされます。

環境を準備する

API を使用して Kubernetes クラスタに対してコマンドを実行するには、次のリソースがあることを確認してください。

新しいノードプールに taint とラベルを適用する

新しいノードプールに taint またはラベルを適用すると、後で追加されたノードを含むすべてのノードに、指定された taint とラベルが自動的に適用されます。適用後にノードプールから taint やラベルを削除することはできません。

新しいノードプールに taint とラベルを追加するには、次の手順を完了します。

  1. ノードプールを作成するときに、Cluster カスタム リソースの nodePools セクションを直接編集します。

    nodePools:
      # Several lines of code are omitted here.
      - machineTypeName: n2-standard-2-gdc
        name: nodepool-1
        nodeCount: 3
        taints:
        - key: "TAINT_KEY"
          value: "TAINT_VALUE"
          effect: "TAINT_EFFECT"
        labels:
          LABEL_KEY: LABEL_VALUE
    

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

    • TAINT_KEY: スケジュール設定 TAINT_EFFECT に関連付けられた Key-Value ペアの taint キー部分。例: workloadType
    • TAINT_VALUE: スケジュール設定 TAINT_EFFECT に関連付けられた Key-Value ペアの taint 値部分。例: untrusted
    • TAINT_EFFECT: 次のいずれかの効果値。
      • NoSchedule: この taint を容認しない Pod はノード上にスケジュールされません。既存の Pod はノードから強制排除されません。
      • PreferNoSchedule: Kubernetes は、この taint を容認しない Pod をノード上にスケジューリングしません。
      • NoExecute: ノードですでに実行されている Pod は、ノードから強制排除されます。ノードでまだ実行されていない Pod は、ノード上にスケジュールされません。
    • LABEL_KEY: LABEL_VALUE: ノードラベルの Key-Value ペア。ワークロード マニフェストで指定したセレクタに対応しています。
  2. Cluster リソースを適用して、新しいノードプールを作成します。

    kubectl apply -f cluster.yaml --kubeconfig MANAGEMENT_API_SERVER
    

    MANAGEMENT_API_SERVER は、Kubernetes クラスタがホストされているゾーン API サーバーの kubeconfig パスに置き換えます。

既存のノードプールに taint とラベルを適用する

既存のノードプールに taint またはラベルを適用するには、既存の各ノードに変更を適用する必要があります。ノードプールの構成を動的に更新することはできません。

適用後にノードプールから taint やラベルを削除することはできません。

既存のノードプールに taint とラベルを追加するには、次の手順を完了します。

  1. 専用ノードプール内のノードを一覧表示します。

    kubectl get node --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG \
        -l baremetal.cluster.gke.io/node-pool=NODE_POOL_NAME
    

    次の変数を置き換えます。

    • KUBERNETES_CLUSTER_KUBECONFIG: Kubernetes クラスタの kubeconfig パス。
    • NODE_POOL_NAME: 専用ノードプールの名前。

    出力から、ノードプール内のすべてのノードの各ノード ID をメモします。

  2. ノードプール内の各ノードに taint を適用します。

    kubectl taint nodes NODE_ID \
        TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    次の変数を置き換えます。

    • NODE_ID: 専用ノードプール内のワーカーノードの ID。
    • TAINT_KEY=TAINT_VALUE: スケジュールする TAINT_EFFECT に関連付けられた Key-Value ペア。例: workloadType=untrusted
    • TAINT_EFFECT: 次のいずれかの効果値。
      • NoSchedule: この taint を容認しない Pod はノード上にスケジュールされません。既存の Pod はノードから強制排除されません。
      • PreferNoSchedule: Kubernetes は、この taint を容認しない Pod をノード上にスケジューリングしません。
      • NoExecute: ノードですでに実行されている Pod は、ノードから強制排除されます。ノードでまだ実行されていない Pod は、ノード上にスケジュールされません。
    • KUBERNETES_CLUSTER_KUBECONFIG: Kubernetes クラスタの kubeconfig パス。
  3. ノードプール内の各ノードに、コンテナ ワークロードで定義するセレクタに対応するラベルを適用します。

    kubectl label NODE_ID \
        LABEL_KEY:LABEL_VALUE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    次の変数を置き換えます。

    • NODE_ID: 専用ノードプール内のワーカーノードの ID。
    • LABEL_KEY:LABEL_VALUE: ノードラベルの Key-Value ペア。ワークロード マニフェストで指定したセレクタに対応しています。
    • KUBERNETES_CLUSTER_KUBECONFIG: Kubernetes クラスタの kubeconfig パス。

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

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

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

専用ノードプールで実行するようにコンテナ ワークロードを構成するには、次の操作を行います。

  1. コンテナ ワークロード マニフェスト ファイル(Deployment カスタム リソースなど)の .spec.template.spec セクションに次のセクションを追加します。

    tolerations:
    - key: TAINT_KEY
      operator: Equal
      value: TAINT_VALUE
      effect: TAINT_EFFECT
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: LABEL_KEY
              operator: In
              values:
              - "LABEL_VALUE"
    

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

    • TAINT_KEY: 専用ノードプールに適用した taint キー。
    • TAINT_VALUE: 専用ノードプールに適用した taint 値。
    • TAINT_EFFECT: 次のいずれかの効果値。
      • NoSchedule: この taint を容認しない Pod はノード上にスケジュールされません。既存の Pod はノードから強制排除されません。
      • PreferNoSchedule: Kubernetes は、この taint を容認しない Pod をノード上にスケジューリングしません。
      • NoExecute: ノードですでに実行されている Pod は、ノードから強制排除されます。ノードでまだ実行されていない Pod は、ノード上にスケジュールされません。
    • LABEL_KEY: 専用のノードプールに適用したノードラベルのキー。
    • LABEL_VALUE: 専用ノードプールに適用したノードラベル値。

    たとえば、次の Deployment リソースは、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: workloadType
            operator: Equal
            value: untrusted
            effect: NoExecute
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: workloadType
                    operator: In
                    values:
                    - "untrusted"
          containers:
          - name: my-app
            image: harbor-1.org-1.zone1.google.gdc.test/harborproject/my-app
            ports:
            - containerPort: 80
          imagePullSecrets:
          - name: SECRET
    
  2. コンテナ ワークロードを更新します。

    kubectl apply -f deployment.yaml -n NAMESPACE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    次の変数を置き換えます。

    • NAMESPACE: コンテナ ワークロードの Namespace。共有クラスタの場合、これはプロジェクトの名前空間である必要があります。Standard クラスタの場合は、任意の Namespace を指定できます。
    • KUBERNETES_CLUSTER_KUBECONFIG: Kubernetes クラスタの kubeconfig パス。

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

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

指定した Pod が、ラベル付けされたノードプールで実行されていることを確認します。

  • 指定された Namespace 内の Pod を一覧表示します。

    kubectl get pods -o=wide -n NAMESPACE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    次の変数を置き換えます。

    • NAMESPACE: コンテナ ワークロードの Namespace。共有クラスタの場合、これはプロジェクトの名前空間である必要があります。Standard クラスタの場合は、任意の Namespace を指定できます。
    • KUBERNETES_CLUSTER_KUBECONFIG: Kubernetes クラスタの kubeconfig パス。

    出力は次のようになります。

    pod/kube-abc-12tyuj
    pod/kube-abc-39oplef
    pod/kube-abc-95rzkap
    

    ワークロードが専用ノードプールで実行されていることを確認します。

次のステップ