ネットワーク ポリシーを使用して Pod と Service 間の通信を制御する


このページでは、GKE のネットワーク ポリシーを適用して、クラスタの Pod と Service 間の通信を制御する方法について説明します。

完全修飾ドメイン名(FQDN)ネットワーク ポリシーを使用して、クラスタ外のエンドポイントまたはサービスに対する Pod の下り(外向き)トラフィックを制御することもできます。詳細については、FQDN を使用して Pod と Service 間の通信を制御するをご覧ください。

GKE ネットワーク ポリシーの適用について

ネットワーク ポリシーを適用すると、クラスタ内に Kubernetes ネットワーク ポリシーを作成できます。ネットワーク ポリシーは、クラスタ内で相互にアクセスできる Pod と Service を決定する Pod レベルのファイアウォール ルールを作成します。

ネットワーク ポリシーを定義すると、クラスタがマルチレベルのアプリケーションを処理するときに多層防御のような機能を有効にすることができます。たとえば、アプリケーション内の不正使用されたフロントエンド サービスが数レベル下の課金サービスや会計サービスと直接通信できないようにするネットワーク ポリシーを作成することができます。

ネットワーク ポリシーを使用して、複数のユーザーが生成したデータを同時にホストするアプリケーションをより簡単に作成することもできます。たとえば、テナント単位の名前空間モデルを定義して、セキュアなマルチテナンシーを提供できます。このようなモデルでは、ネットワーク ポリシー ルールにより、特定の Namespace 内の Pod や Service が異なる Namespace 内の他の Pod や Service にアクセスできないようにできます。

始める前に

作業を始める前に、次のことを確認してください。

  • Google Kubernetes Engine API を有効にします。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化します。すでに gcloud CLI をインストールしている場合は、gcloud components update を実行して最新のバージョンを取得します。

要件と制限事項

次の要件と制限事項は、Autopilot クラスタと Standard クラスタの両方に適用されます。 次の要件と制限事項は Standard クラスタにのみ適用されます。

  • GKE 用 Workload Identity 連携でネットワーク ポリシーを使用する場合は、メタデータ サーバーへの下り(外向き)を許可する必要があります。
  • ネットワーク ポリシーの適用を有効にすると、kube-system プロセスのメモリ使用量が約 128 MB 増加し、約 300 ミリコアの CPU が必要になります。つまり、既存のクラスタに対してネットワーク ポリシーを有効にした場合、スケジュールされたワークロードの実行を継続するには、クラスタのサイズを大きくする必要があります。
  • ネットワーク ポリシーの適用を有効にする場合、ノードの再作成が必要になります。クラスタのメンテナンスの時間枠が有効になっている場合、次のメンテナンスの時間枠でノードが自動的に再作成されます。必要に応じて、いつでも手動でクラスタをアップグレードできます。
  • ネットワーク ポリシーの適用を行うために推奨されるクラスタの最小サイズは、3 つの e2-medium インスタンスです。
  • ノードが f1-micro インスタンスまたは g1-small インスタンスであるクラスタでは、リソース要件が高すぎるため、ネットワーク ポリシーはサポートされません。

ノードのマシンタイプと割り当て可能なリソースについて詳しくは、標準クラスタ アーキテクチャ - ノードをご覧ください。

ネットワーク ポリシーの適用を有効にする

Autopilot クラスタでは、ネットワーク ポリシーの適用はデフォルトで有効になっているため、ネットワーク ポリシーの作成にスキップできます。

Standard クラスタでネットワーク ポリシーの適用を有効にするには、gcloud CLI ツール、Google Cloud コンソール、または GKE API を使用します。

ネットワーク ポリシーの適用は、GKE Dataplane V2 に組み込まれています。GKE Dataplane V2 を使用するクラスタでネットワーク ポリシーの適用を有効にする必要はありません。

gcloud

  1. Google Cloud コンソールで、「Cloud Shell をアクティブにする」をクリックします。

    Cloud Shell をアクティブにする

    Google Cloud コンソールの下部で Cloud Shell セッションが開始し、コマンドライン プロンプトが表示されます。Cloud Shell はシェル環境です。Google Cloud CLI がすでにインストールされており、現在のプロジェクトの値もすでに設定されています。セッションが初期化されるまで数秒かかることがあります。

  2. クラスタの作成時にネットワーク ポリシーの適用を有効にするには、次のコマンドを実行します。

    gcloud container clusters create CLUSTER_NAME --enable-network-policy
    

    CLUSTER_NAME は、新しいクラスタの名前に置き換えます。

    既存のクラスタに対してネットワーク ポリシーの適用を有効にするには、次のタスクを実行します。

    1. 次のコマンドを実行して、アドオンを有効にします。

      gcloud container clusters update CLUSTER_NAME --update-addons=NetworkPolicy=ENABLED
      

      CLUSTER_NAME は、クラスタの名前に置き換えます。

    2. 次のコマンドを実行してクラスタでネットワーク ポリシーの適用を有効にします。これにより、ネットワーク ポリシーの適用が有効に設定されて、クラスタのノードプールが再作成されます。

      gcloud container clusters update CLUSTER_NAME --enable-network-policy
      

コンソール

新しいクラスタの作成時にネットワーク ポリシーの適用を有効にするには、次のようにします。

  1. Google Cloud コンソールで Google Kubernetes Engine のページに移動します。

    Google Kubernetes Engine に移動

  2. [ 作成] をクリックします。

  3. [クラスタを作成] ダイアログで、GKE Standard の [構成] をクリックします。

  4. 選択したとおりにクラスタを構成します。

  5. ナビゲーション パネルの [クラスタ] の下の [ネットワーキング] をクリックします。

  6. [ネットワーク ポリシーを有効にする] チェックボックスを選択します。

  7. [作成] をクリックします。

既存のクラスタに対するネットワーク ポリシーの適用を有効にするには、次の操作を行います。

  1. Google Cloud コンソールで Google Kubernetes Engine のページに移動します。

    Google Kubernetes Engine に移動

  2. クラスタのリストで、変更するクラスタの名前をクリックします。

  3. [ネットワーキング] の [ネットワーク ポリシー] フィールドで、 [ネットワーク ポリシーを編集] をクリックします。

  4. [マスターのネットワーク ポリシーの有効化] チェックボックスをオンにして、[変更を保存] をクリックします。

  5. 変更が適用されるのを待ってから、 [ネットワーク ポリシーを編集] を再度クリックします。

  6. [ノードのネットワーク ポリシーの有効化] チェックボックスをオンにします。

  7. [変更を保存] をクリックします。

API

ネットワーク ポリシーの適用を有効にするには、次のようにします。

  1. projects.zones.clusters.create または projects.zones.clusters.update に渡す cluster オブジェクト内に networkPolicy オブジェクトを指定します。

  2. networkPolicy オブジェクトには、使用するネットワーク ポリシー プロバイダを指定する列挙値と、ネットワーク ポリシーを有効にするかどうかを指定するブール値が必要です。ネットワーク ポリシーを有効にしてもプロバイダを設定しないと、create コマンドと update コマンドはエラーを返します。

Standard クラスタでネットワーク ポリシーの適用を無効にする

ネットワーク ポリシーの適用は、gcloud CLI、Google Cloud コンソール、または GKE API を使用して無効にできます。Autopilot クラスタまたは GKE Dataplane V2 を使用するクラスタでネットワーク ポリシーの適用を無効にすることはできません。

gcloud

  1. Google Cloud コンソールで、「Cloud Shell をアクティブにする」をクリックします。

    Cloud Shell をアクティブにする

    Google Cloud コンソールの下部で Cloud Shell セッションが開始し、コマンドライン プロンプトが表示されます。Cloud Shell はシェル環境です。Google Cloud CLI がすでにインストールされており、現在のプロジェクトの値もすでに設定されています。セッションが初期化されるまで数秒かかることがあります。

  2. ネットワーク ポリシーの適用を無効にするには、次のタスクを行います。

    1. クラスタでネットワーク ポリシーの適用を無効にします。
    gcloud container clusters update CLUSTER_NAME --no-enable-network-policy
    

    CLUSTER_NAME は、クラスタの名前に置き換えます。

    このコマンドを実行すると、GKE はネットワーク ポリシーの適用を無効にしたクラスタ ノードプールを再作成します。

  3. すべてのノードが再作成されたことを確認します。

    kubectl get nodes -l projectcalico.org/ds-ready=true
    

    オペレーションが成功すると、出力は次のようになります。

    No resources found
    

    出力が次のような場合は、GKE がノードプールの更新を完了するまで待つ必要があります。

    NAME                                             STATUS                     ROLES    AGE     VERSION
    gke-calico-cluster2-default-pool-bd997d68-pgqn   Ready,SchedulingDisabled   <none>   15m     v1.22.10-gke.600
    gke-calico-cluster2-np2-c4331149-2mmz            Ready                      <none>   6m58s   v1.22.10-gke.600
    

    ネットワーク ポリシーの適用を無効にすると、構成されたメンテナンスの時間枠または除外がクラスタにある場合、GKE がすぐにはノードを更新しないことがあります。詳細については、クラスタの更新が遅いをご覧ください。

  4. すべてのノードが再作成されたら、アドオンを無効にします。

    gcloud container clusters update CLUSTER_NAME --update-addons=NetworkPolicy=DISABLED
    

コンソール

既存のクラスタに対するネットワーク ポリシーの適用を無効にするには、次のようにします。

  1. Google Cloud コンソールで Google Kubernetes Engine のページに移動します。

    Google Kubernetes Engine に移動

  2. クラスタのリストで、変更するクラスタの名前をクリックします。

  3. [ネットワーキング] の [ネットワーク ポリシー] フィールドで、 [ネットワーク ポリシーを編集] をクリックします。

  4. [ノードのネットワーク ポリシーの有効化] チェックボックスをオフにして、[変更を保存] をクリックします。

  5. 変更が適用されるのを待ってから、 [ネットワーク ポリシーを編集] を再度クリックします。

  6. [マスターのネットワーク ポリシーの有効化] チェックボックスをオフにします。

  7. [変更を保存] をクリックします。

API

既存のクラスタに対するネットワーク ポリシーの適用を無効にするには、次のようにします。

  1. setNetworkPolicy API を使用して、networkPolicy.enabled: false を使用するようにクラスタを更新します。

  2. gcloud CLI を使用して、すべてのノードが再作成されたことを確認します。

    kubectl get nodes -l projectcalico.org/ds-ready=true
    

    オペレーションが成功すると、出力は次のようになります。

    No resources found
    

    出力が次のような場合は、GKE がノードプールの更新を完了するまで待つ必要があります。

    NAME                                             STATUS                     ROLES    AGE     VERSION
    gke-calico-cluster2-default-pool-bd997d68-pgqn   Ready,SchedulingDisabled   <none>   15m     v1.22.10-gke.600
    gke-calico-cluster2-np2-c4331149-2mmz            Ready                      <none>   6m58s   v1.22.10-gke.600
    

    ネットワーク ポリシーの適用を無効にすると、構成されたメンテナンスの時間枠または除外がクラスタにある場合、GKE がすぐにはノードを更新しないことがあります。詳細については、クラスタの更新が遅いをご覧ください。

  3. updateCluster API を使用して、update.desiredAddonsConfig.NetworkPolicyConfig.disabled: true を使用するようにクラスタを更新します。

ネットワーク ポリシーを作成する

ネットワーク ポリシーは、Kubernetes Network Policy API を使用して作成できます。

ネットワーク ポリシーの作成について詳しくは、Kubernetes ドキュメントの次のトピックをご覧ください。

ネットワーク ポリシーと GKE 用 Workload Identity 連携

GKE 用 Workload Identity 連携でネットワーク ポリシーを使用する場合は、Pod が GKE メタデータ サーバーと通信できるように、次の IP アドレスへの下り(外向き)を許可する必要があります。

  • GKE バージョン 1.21.0-gke.1000 以降を実行しているクラスタでは、ポート 988169.254.169.252/32 への下り(外向き)を許可します。
  • 1.21.0-gke.1000 より前の GKE バージョンを実行しているクラスタでは、ポート 988127.0.0.1/32 への下り(外向き)を許可します。
  • GKE Dataplane V2 を実行しているクラスタでは、ポート 80169.254.169.254/32 への下り(外向き)を許可します。

これらの IP アドレスとポートへの下り(外向き)を許可しない場合は、自動アップグレード中にサービスの中断が発生する可能性があります。

Calico から GKE Dataplane V2 への移行

ネットワーク ポリシーを Calico から GKE Dataplane V2 に移行する場合は、次の制限事項を考慮してください。

  • NetworkPolicy マニフェストの ipBlock.cidr フィールドに Pod または Service の IP アドレスを使用することはできません。ワークロードはラベルを使用して参照する必要があります。たとえば、次の構成は無効です。

    - ipBlock:
        cidr: 10.8.0.6/32
    
  • NetworkPolicy マニフェストで空の ports.port フィールドを指定することはできません。プロトコルを指定する場合は、ポートも指定する必要があります。たとえば、次の構成は無効です。

    ingress:
    - ports:
      - protocol: TCP
    

アプリケーション ロードバランサの操作

Ingress を Service に適用してアプリケーション ロードバランサを構築する場合は、Service の背後にある Pod に適用されるネットワーク ポリシーを構成して、適切なアプリケーション ロードバランサのヘルスチェック IP 範囲を許可する必要があります。内部アプリケーション ロードバランサを使用する場合は、プロキシ専用サブネットを許可するようにネットワーク ポリシーを構成する必要もあります。

ネットワーク エンドポイント グループでコンテナネイティブのロード バランシングを使用しない場合は、Service のノードポートが他のノードの Pod に接続を転送する可能性があります。これを回避するには、Service の定義で externalTrafficPolicyLocal設定します。externalTrafficPolicyLocal に設定しない場合は、ネットワーク ポリシーでクラスタ内の他のノード IP からの接続も許可する必要があります。

ipBlock ルールへの Pod IP 範囲の追加

特定の Pod のトラフィックを制御するには、NetworkPolicy の上り(内向き)ルールまたは下り(外向き)ルールで namespaceSelector フィールドと podSelector フィールドを使用して、Namespace または Pod ラベルごとに Pod を選択します。Pod の IP アドレス範囲を意図的に選択するために ipBlock.cidr フィールドを使用することは避けてください。これは本質的にエフェメラルです。Kubernetes プロジェクトで、Pod の IP アドレス範囲が含まれている場合の ipBlock.cidr フィールドの動作は明確に定義されていません。Pod の IP アドレス範囲を含めて、このフィールドに広い CIDR 範囲(0.0.0.0/0 など)を指定すると、NetworkPolicy のさまざまな実装で予期しない結果が生じる可能性があります。

以下の各セクションでは、GKE における NetworkPolicy のさまざまな実装で、ipBlock.cidr フィールドで指定した IP アドレス範囲がどのように評価され、それらが幅広い CIDR 範囲に本質的に含まれる Pod IP アドレス範囲にどのように影響するかについて説明します。実装間の動作の違いを理解しておくと、別の実装に移行する際の結果に備えることができます。

GKE Dataplane V2 での ipBlock の動作

NetworkPolicy の GKE Dataplane V2 実装では、Pod のトラフィックは ipBlock ルールの対象外です。したがって、cidr: '0.0.0.0/0' などの広範なルールを定義しても、Pod トラフィックは含まれません。たとえば、これは、Pod からのトラフィックを許可せずに、Namespace 内の Pod がインターネットからのトラフィックを受信することを許可する場合に便利です。Pod トラフィックも含めるには、NetworkPolicy の上り(内向き)ルールまたは下り(外向き)ルールの定義で、追加の Pod または Namespace セレクタを使用して、Pod を明示的に選択します。

Calico での ipBlock の動作

NetworkPolicy の Calico 実装では、Pod トラフィックが ipBlock ルールの対象となります。この実装で、Pod トラフィックを許可せずに広範な CIDR 範囲を構成するには、次の例のように、クラスタの Pod CIDR 範囲を明示的に除外します。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-non-pod-traffic
spec:
  ingress:
  - from:
    - ipBlock:
      cidr: '0.0.0.0/0'
      except: ['POD_IP_RANGE']

この例の POD_IP_RANGE は、クラスタの Pod の IPv4 アドレス範囲です(例: 10.95.0.0/17)。複数の IP 範囲がある場合は、配列に個別に含めることができます(例: ['10.95.0.0/17', '10.108.128.0/17'])。

トラブルシューティング

Pod が Private Service Connect を使用するクラスタ上のコントロール プレーンと通信できない

コントロール プレーンの内部 IP アドレスへの Pod の下り(外向き)が下り(外向き)ネットワークで制限されている場合、Private Service Connect を使用する GKE クラスタの Pod でコントロール プレーンとの通信に問題が発生する可能性があります。

この問題には次のように対処してください。

  1. クラスタで Private Service Connect を使用しているかどうかを確認します。詳細については、Private Service Connect を使用した一般公開クラスタをご覧ください。Private Service Connect を使用するクラスタでは、各コントロール プレーンがクラスタノードのサブネットから内部 IP アドレスに割り当てられます。

  2. コントロール プレーンの内部 IP アドレスへのトラフィックを許可するように、クラスタの下り(外向き)ポリシーを構成します。

    コントロール プレーンの内部 IP アドレスを確認するには:

    gcloud

    privateEndpoint を探すには、次のコマンドを実行します。

    gcloud container clusters describe CLUSTER_NAME
    

    CLUSTER_NAME はクラスタの名前で置き換えます。

    このコマンドは、指定したクラスタの privateEndpoint を取得します。

    コンソール

    1. Google Cloud コンソールで Google Kubernetes Engine のページに移動します。

      Google Kubernetes Engine に移動

    2. ナビゲーション パネルの [クラスタ] で、内部 IP アドレスを確認するクラスタをクリックします。

    3. [クラスタの基本] で、内部 IP アドレスが表示されている Internal endpoint に移動します。

    privateEndpoint または Internal endpoint が見つかったら、コントロール プレーンの内部 IP アドレスへのトラフィックを許可するようにクラスタの下り(外向き)ポリシーを構成します。詳細については、ネットワーク ポリシーを作成するをご覧ください。

クラスタの更新が遅い

既存のクラスタでネットワーク ポリシーの適用を有効または無効にすると、クラスタにメンテナンスの時間枠または除外が構成されている場合、GKE によってノードが直ちに更新されない場合があります。

ノードプールを手動でアップグレードするには、--cluster-version フラグをコントロール プレーンが実行中のものと同じ GKE バージョンに設定します。この操作は、Google Cloud CLI で行う必要があります。詳細については、メンテナンス時間枠の注意点をご覧ください。

手動でデプロイした Pod のスケジューリングが解除される

既存のクラスタのコントロール プレーンでネットワーク ポリシーの適用を有効にすると、GKE は、手動でデプロイされた ip-masquerade-agent や calico ノードの Pod のスケジュールを解除します。

クラスタノードでネットワーク ポリシーの適用が有効になり、ノードが再作成されるまで、GKE はこれらの Pod の再スケジュールを行いません。

メンテナンスの時間枠または除外を構成している場合は、これによって中断が延長される可能性があります。

この中断期間を最小限に抑えるために、次のラベルをクラスタノードに手動で割り当てできます。

  • node.kubernetes.io/masq-agent-ds-ready=true
  • projectcalico.org/ds-ready=true

ネットワーク ポリシーが機能しない

NetworkPolicy が有効でない場合は、次の手順でトラブルシューティングを行います。

  1. ネットワーク ポリシーの適用が有効になっていることを確認します。使用するコマンドは、クラスタで GKE Dataplane V2 が有効かどうかによって異なります。

    クラスタで GKE Dataplane V2 が有効になっている場合は、次のコマンドを実行します。

    kubectl -n kube-system get pods -l k8s-app=cilium
    

    出力が空の場合、ネットワーク ポリシーの適用は有効になっていません。

    クラスタで GKE Dataplane V2 が有効になっていない場合は、次のコマンドを実行します。

    kubectl get nodes -l projectcalico.org/ds-ready=true
    

    出力が空の場合、ネットワーク ポリシーの適用は有効になっていません。

  2. Pod のラベルを確認します。

    kubectl describe pod POD_NAME
    

    POD_NAME は、Pod の名前で置き換えます。

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

    Labels:        app=store
                   pod-template-hash=64d9d4f554
                   version=v1
    
  3. ポリシーのラベルが Pod のラベルと一致することを確認します。

    kubectl describe networkpolicy
    

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

    PodSelector: app=store
    

    この出力では、app=store ラベルは前の手順の app=store ラベルと一致します。

  4. ワークロードを選択するネットワーク ポリシーがあるかどうかを確認します。

    kubectl get networkpolicy
    

    出力が空の場合、Namespace に NetworkPolicy が作成されておらず、何もワークロードを選択していません。出力が空でない場合は、ポリシーでワークロードが選択されていることを確認します。

    kubectl describe networkpolicy
    

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

    ...
    PodSelector:     app=nginx
    Allowing ingress traffic:
       To Port: <any> (traffic allowed to all ports)
       From:
          PodSelector: app=store
    Not affecting egress traffic
    Policy Types: Ingress
    

既知の問題

Calico を使用した StatefulSet Pod の終了

Calico ネットワーク ポリシーが有効になっている GKE クラスタでは、Pod の削除時に StatefulSet Pod が既存の接続を切断するという問題が発生する場合があります。Pod が Terminating 状態になると、Pod 仕様の terminationGracePeriodSeconds 構成が優先されて、StatefulSet Pod との接続がすでに存在する他のアプリケーションが中断します。この問題の詳細については、Calico 問題 #4710 をご覧ください。

この問題は、次の GKE バージョンに影響します。

  • 1.18
  • 1.19~1.19.16-gke.99
  • 1.20~1.20.11-gke.1299
  • 1.21~1.21.4-gke.1499

この問題を軽減するには、GKE コントロール プレーンを次のいずれかのバージョンにアップグレードします。

  • 1.19.16-gke.100 以降
  • 1.20.11-gke.1300 以降
  • 1.21.4-gke.1500 以降

Pod が containerCreating 状態で停止する

Calico ネットワーク ポリシーが有効になっている GKE クラスタで、Pod が containerCreating 状態のままになる可能性があります。

Pod の [イベント] タブに、次のようなメッセージが表示されます。

plugin type="calico" failed (add): ipAddrs is not compatible with
configured IPAM: host-local

この問題を軽減するには、GKE クラスタの calico-ipam を使用するのではなく Calico のホストローカル ipam を使用します。

次のステップ