このドキュメントでは、Google Distributed Cloud(GDC)のエアギャップ内の専用ノードプール内でコンテナ ワークロードを分離して、Kubernetes クラスタのセキュリティと管理を強化する方法について説明します。ワークロードを分離すると、Pod をより詳細に制御でき、Kubernetes クラスタでの権限昇格攻撃のリスクを軽減できます。専用ノードプールの利点と制限事項の詳細については、ノード分離の概要をご覧ください。
コンテナ ワークロードの分離には、次のようないくつかのワークフローがあります。
ノードプールに taint とラベルを適用する: ノードプールに taint とラベルを適用して、そこで実行するように明示的にラベル付けされていない限り、Pod がノードプールから離れるようにします。
toleration とノード アフィニティ ルールを追加する: toleration とルールを Pod に適用して、指定されたノードプールでのみ実行されるようにします。
分離が機能していることを確認する: 汚染されたノードプールで、実行するようにラベル付けした Pod のみが実行されていることを確認します。
これらのワークフローは、Kubernetes クラスタのノードプールを管理するプラットフォーム管理者グループ内の IT 管理者や、コンテナ ワークロードを管理するアプリケーション オペレータ グループ内のアプリケーション デベロッパーなどのユーザーを対象としています。詳細については、GDC エアギャップ ドキュメントの対象ユーザーをご覧ください。
始める前に
このドキュメントのタスクを完了するには、必要な権限をリクエストして環境を準備する必要があります。
IAM ロールをリクエストする
Kubernetes クラスタでコンテナ ワークロードを分離するために必要な権限を取得するには、特定のロールが必要です。必要なロールは、組織スコープの共有クラスタまたはプロジェクト スコープの標準クラスタで作業しているかどうかによって異なります。詳細については、Kubernetes クラスタ構成をご覧ください。
共有クラスタロール
組織の IAM 管理者に連絡して、共有クラスタ内のノードプールに taint とラベルを付けるために次のロールをリクエストします。
ユーザー クラスタ管理者(
user-cluster-admin): 管理 API サーバーでホストされている共有クラスタのリソースを作成、削除、編集、表示します。このロールは、共有クラスタのノードプールへのアクセス権を付与します。ユーザー クラスタ デベロッパー(
user-cluster-developer): 共有クラスタの作成、削除、編集、表示を行います。このロールは、共有クラスタ内でホストされているデータプレーン API へのアクセスを提供します。
これらのロールは Namespace にバインドされていません。
標準クラスタロール
プロジェクト IAM 管理者に連絡して、標準クラスタのノードプールに taint とラベルを付けるために次のロールをリクエストします。
クラスタ管理者(
cluster-admin): 標準クラスタ内のすべてのリソースの作成、削除、編集、表示を行います。このロールは、クラスタのリソースを管理する Standard クラスタ内でホストされているデータプレーン API へのアクセス権を付与します。クラスタ デベロッパー(
cluster-developer): 標準クラスタの作成、削除、編集、表示を行います。このロールは、クラスタを管理する標準クラスタ内でホストされているデータプレーン API へのアクセスを提供します。標準クラスタ管理者(
standard-cluster-admin): 管理 API サーバーでホストされている標準クラスタのリソースを作成、削除、編集、表示します。このロールは、標準クラスタのノードプールへのアクセスを提供します。
これらのロールはプロジェクトの Namespace にバインドされます。
環境を準備する
API を使用して Kubernetes クラスタに対してコマンドを実行するには、次のリソースがあることを確認してください。
Kubernetes クラスタの kubeconfig ファイルにログインして生成します。
これらの手順では、Kubernetes クラスタの kubeconfig パスを使用して
KUBERNETES_CLUSTER_KUBECONFIGを置き換えます。ログインして生成します。
これらの手順では、管理 API サーバーの kubeconfig パスを使用して
MANAGEMENT_API_SERVERを置き換えます。専用ノードプールに使用するノード taint とノードラベルに特定の名前を選択します。例:
workloadType=untrusted
新しいノードプールに taint とラベルを適用する
新しいノードプールに taint またはラベルを適用すると、後で追加されたノードを含むすべてのノードが、指定された taint とラベルを自動的に取得します。適用後にノードプールから taint またはラベルを削除することはできません。
新しいノードプールに taint とラベルを追加する手順は次のとおりです。
ノードプールを作成するときに、
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 キー部分。例:workloadTypeTAINT_VALUE: スケジュールするTAINT_EFFECTに関連付けられた Key-Value ペアの taint 値の部分。例:untrustedTAINT_EFFECT: 次のいずれかの効果値。NoSchedule: この taint を容認しない Pod はノード上にスケジュールされません。既存の Pod はノードから強制排除されません。PreferNoSchedule: Kubernetes は、この taint を容認しない Pod をノード上にスケジュールすることを避けます。NoExecute: ノードですでに実行されている Pod は、ノードから強制排除されます。ノードでまだ実行されていない Pod は、ノード上にスケジュールされません。
LABEL_KEY: LABEL_VALUE: ノードラベルの Key-Value ペア。ワークロード マニフェストで指定したセレクタに対応しています。
Clusterリソースを適用して、新しいノードプールを作成します。kubectl apply -f cluster.yaml --kubeconfig MANAGEMENT_API_SERVERMANAGEMENT_API_SERVERは、Kubernetes クラスタがホストされているゾーン API サーバーの kubeconfig パスに置き換えます。
既存のノードプールに taint とラベルを適用する
既存のノードプールに taint またはラベルを適用するには、既存の各ノードに変更を適用する必要があります。ノードプール構成を動的に更新することはできません。
ノードプールに適用された後で、ノードプールから taint またはラベルを削除することはできません。
既存のノードプールに taint とラベルを追加する手順は次のとおりです。
専用ノードプール内のノードを一覧表示します。
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 をメモします。
ノードプール内の各ノードに、次の 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=untrustedTAINT_EFFECT: 次のいずれかのエフェクト値。NoSchedule: この taint を容認しない Pod はノード上にスケジュールされません。既存の Pod はノードから強制排除されません。PreferNoSchedule: Kubernetes は、この taint を容認しない Pod をノード上にスケジュールすることを避けます。NoExecute: ノードですでに実行されている Pod は、ノードから強制排除されます。ノードでまだ実行されていない Pod は、ノード上にスケジュールされません。
KUBERNETES_CLUSTER_KUBECONFIG: Kubernetes クラスタの kubeconfig パス。
ノードプール内の各ノードに、コンテナ ワークロードで定義するセレクタに対応するラベルを適用します。
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 に指示することもできます。
専用ノードプールで実行するようにコンテナ ワークロードを構成する手順は次のとおりです。
コンテナ ワークロード マニフェスト ファイル(
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:NoExecutetaint の 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コンテナ ワークロードを更新します。
kubectl apply -f deployment.yaml -n NAMESPACE \ --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG次の変数を置き換えます。
NAMESPACE: コンテナ ワークロードの Namespace。共有クラスタの場合は、プロジェクト Namespace である必要があります。標準クラスタの場合は、任意の 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。共有クラスタの場合は、プロジェクト Namespace である必要があります。標準クラスタの場合は、任意の Namespace を指定できます。KUBERNETES_CLUSTER_KUBECONFIG: Kubernetes クラスタの kubeconfig パス。
出力は次のようになります。
pod/kube-abc-12tyuj pod/kube-abc-39oplef pod/kube-abc-95rzkapワークロードが専用ノードプールで実行されていることを確認します。