クラスタ ネットワーク ポリシーを構成する

ClusterNetworkPolicy を使用すると、クラスタ全体でグローバル GKE セキュリティ ポスチャーを定義できます。このドキュメントは、必須のセキュリティ ガードレールを適用するか、ゼロトラスト ベースラインを確立する必要があるクラスタ管理者を対象としています。

このリソースは、標準の Namespace スコープの NetworkPolicy リソースよりも優先順位の高い厳密な評価階層に依存しています。ClusterNetworkPolicy リソースを使用して、明示的な Deny、Accept、Pass アクションを実装できます。これらのアクションを使用すると、グローバル許可ポリシーまたは拒否ポリシーを構成し、特定の Namespace にトラフィック制御を委任し、下り(外向き)トラフィックを CIDR ブロックに制限できます。

始める前に

クラスタ ネットワーク ポリシーを構成する前に、次の要件を満たしていることを確認してください。

  1. GKE クラスタでバージョン 1.36.0-gke.4447000 以降が実行されていることを確認します。
  2. クラスタで GKE Dataplane V2 が使用されていることを確認します。

サポートされているプロトコルとポート

ClusterNetworkPolicy ルールは、TCP、UDP、または SCTP プロトコルに基づいてトラフィックを照合できます。宛先ポートは次の方法で指定できます。

  • 特定のポート番号: destinationPort.number 設定を使用して、単一のポート(80 など)をターゲットにします。
  • ポート範囲: destinationPort.range 設定を使用して、ポートの範囲(8000~9000 など)をターゲットにします。
  • 名前付きポート: destinationNamedPort 設定を使用して、Pod 仕様で定義されたシンボリック名をターゲットにします。

ポリシー評価の階層

標準の加法的な NetworkPolicy とは異なり、ClusterNetworkPolicy(CNP)は、最初に一致したルールが優先される厳密な評価階層に依存します。トラフィックは、3 層のパイプラインを順次通過します。

  • 階層: 管理者ルールが最初に実行され、NetworkPolicy、Baseline の順にカスケードされます。
  • CNP 優先度: 階層内では、ポリシーは明示的な数値優先度に基づいて評価されます。
  • CNP ルールの順序: 単一のポリシー内では、ルールはアクセス制御リスト(ACL)のように上から下に処理されます。

GKE ネットワーク ポリシーの評価階層を示す図

上の図は、CNP 評価階層の決定フローを示しています。

  1. 管理者ティア: トラフィックは、まず Admin ティアの ClusterNetworkPolicy ルールに対して評価されます。許可または拒否の照合がある場合、評価は停止します。一致がない場合や Pass アクションの場合、トラフィックは NetworkPolicy 階層に進みます。
  2. NetworkPolicy ティア: トラフィックは標準の Namespace ポリシーに照らして評価されます。一致するものがある場合、トラフィックは許可されます。一致しない場合、トラフィックはベースライン ティアに進みます。
  3. ベースライン ティア: トラフィックはベースライン ティアの ClusterNetworkPolicy ルールに照らして評価されます。許可または拒否の一致がある場合、評価は停止します。一致しない場合、トラフィックはデフォルトの動作に進みます。
  4. デフォルトの GKE の動作: どの階層でもポリシーが一致しない場合、トラフィックは暗黙的な許可動作の対象になります。

判定アクション: 許可、拒否、パス

パケットが一致すると、すべてのルールで次の 3 つの厳格なアクションのいずれかがトリガーされます。

  • 拒否: トラフィックを直ちにブロックします。
  • Accept: トラフィックを許可します。どちらのアクションもパイプラインを即座にショートサーキットし、残りのポリシーをすべて無視します。
  • Pass: 制御を次の階層に転送します。これにより、プラットフォーム エンジニアは、包括的な管理制御を放棄することなく、特定のトラフィックの決定を標準の Namespace レベルのポリシーに委任できます。

グローバル拒否ポリシーを構成する

機密性の高い Namespace を他のすべてのクラスタ内部トラフィックから分離するには、オーバーライドできない拒否ルールを適用します。このデフォルト拒否ポリシーにより、機密性の高い Namespace との間で送受信されるトラフィックが管理レベルでブロックされます。このポリシーは、Namespace レベルのルールによって誤ってバイパスされることがない保護ベースラインとして機能します。

  1. 次のマニフェストを global-deny.yaml として保存します。

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: cluster-wide-deny-sensitive
    spec:
      tier: Admin
      priority: 10
      subject:
        namespaces:
          matchLabels:
            kubernetes.io/metadata.name: sensitive-ns
      ingress:
      - action: Deny
        name: deny-all-ingress
        from:
        - namespaces:
            matchLabels: {}
      egress:
      - action: Deny
        name: deny-all-egress
        to:
        - namespaces:
            matchLabels: {}
    
  2. マニフェストをクラスタに適用します。

    kubectl apply -f global-deny.yaml
    

グローバル許可ポリシーを構成する

グローバル許可ポリシーを使用すると、デベロッパーが作成したネットワーク ポリシーに関係なく、すべての Pod がクラスタ DNS サービスにアクセスできるようになります。

  1. 次のマニフェストを global-allow-dns.yaml として保存します。

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: allow-kube-dns-admin
    spec:
      tier: Admin
      priority: 20
      subject:
        namespaces: {}
      egress:
      - action: Accept
        name: allow-dns-egress
        to:
        - pods:
            namespaceSelector:
              matchLabels:
                kubernetes.io/metadata.name: kube-system
            podSelector:
              matchLabels:
                k8s-app: kube-dns
        protocols:
        - udp:
            destinationPort:
              number: 53
        - tcp:
            destinationPort:
              number: 53
    
  2. マニフェストをクラスタに適用します。

    kubectl apply -f global-allow-dns.yaml
    

トラフィックを Namespace ポリシーに委任する

特定のトラフィック パターンを標準の Namespace スコープの NetworkPolicy オブジェクトに委任する。

  1. 次のマニフェストを delegate-policy.yaml として保存します。

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: delegate-to-netpol
    spec:
      tier: Admin
      priority: 30
      subject:
        namespaces: {}
      egress:
      - action: Pass
        name: delegate-web-traffic
        to:
        - namespaces:
            matchLabels:
              app: web-backend
        protocols:
        - tcp:
            destinationPort:
              number: 8080
    
  2. マニフェストをクラスタに適用します。

    kubectl apply -f delegate-policy.yaml
    
  3. ターゲット Namespace 内で委任されたトラフィックを許可するには、次の標準 NetworkPolicy マニフェストを allow-web-backend.yaml として保存します。

    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-web-backend
      namespace: backend-ns
    spec:
      podSelector:
        matchLabels:
          app: web-backend
      ingress:
      - from:
        - namespaceSelector:
            matchLabels:
              app: web-frontend
        ports:
        - protocol: TCP
          port: 8080
    
  4. 標準の NetworkPolicy マニフェストをクラスタに適用します。

    kubectl apply -f allow-web-backend.yaml
    

ベースライン ガードレールを構成する

Namespace 管理者が標準のネットワーク ポリシーを使用してオーバーライドできるデフォルトの GKE セキュリティ ポスチャーを確立します。

  1. 次のベースライン マニフェストを baseline-deny.yaml として保存します。

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: default-deny-baseline
    spec:
      tier: Baseline
      priority: 100
      subject:
        namespaces: {}
      ingress:
      - action: Deny
        name: baseline-deny-all
        from:
        - namespaces: {}
    
  2. ベースライン マニフェストをクラスタに適用します。

    kubectl apply -f baseline-deny.yaml
    
  3. 次のデベロッパー オーバーライド マニフェストを developer-allow.yaml として保存します。

    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-frontend-access
      namespace: my-app-ns
    spec:
      podSelector:
        matchLabels:
          app: frontend
      ingress:
      - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: ingress-nginx
    
  4. オーバーライド マニフェストをクラスタに適用します。

    kubectl apply -f developer-allow.yaml
    

名前付きポートを使用してポリシーを構成する

セキュリティ ポリシーからポート番号を抽象化するには、Pod 仕様で定義された名前付きポートを参照します。

  1. 次のデプロイ マニフェストを app-deployment.yaml として保存します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-webapp
    spec:
      template:
        spec:
          containers:
          - name: web-container
            image: nginx
            ports:
            - name: http-web
              containerPort: 8080
    
  2. Deployment マニフェストをクラスタに適用します。

    kubectl apply -f app-deployment.yaml
    
  3. 次のポリシー マニフェストを named-port-policy.yaml として保存します。

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: allow-web-named-port
    spec:
      tier: Admin
      priority: 40
      subject:
        namespaces: {}
      egress:
      - action: Accept
        to:
        - namespaces:
            matchLabels:
              app: my-webapp
        protocols:
        - tcp:
            destinationNamedPort: http-web
    
  4. ポリシー マニフェストをクラスタに適用します。

    kubectl apply -f named-port-policy.yaml
    

下り(外向き)を CIDR ブロックに制限する

CIDR ブロックを指定して、外部リソースまたは企業イントラネットへのアクセスを制御します。

  1. 次のマニフェストを cidr-policy.yaml として保存します。

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: allow-egress-to-intranet
    spec:
      tier: Admin
      priority: 60
      subject:
        namespaces: {}
      egress:
      - action: Accept
        name: allow-intranet
        to:
        - networks:
          - 10.0.0.0/8
          - 192.168.0.0/16
    
  2. マニフェストをクラスタに適用します。

    kubectl apply -f cidr-policy.yaml
    

優先度の優先順位を構成する

同じ Pod に複数のポリシーが適用される場合に評価順序を制御するには、優先度を指定します。優先度の範囲は 0 ~ 1000 で、数値が小さいほど優先度が高くなります。1 つの ClusterNetworkPolicy オブジェクトに、最大 100 個の上り(内向き)ルールと 100 個の下り(外向き)ルールを含めることができます。

  1. 次のマニフェストを priority-policies.yaml として保存します。

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: deny-beta
    spec:
      tier: Admin
      priority: 10
      subject:
        namespaces:
          matchLabels:
            team: alpha
      ingress:
      - action: Accept
        name: allow-beta-monitoring
        from:
        - pods:
            namespaceSelector:
              matchLabels:
                team: beta
            podSelector:
              matchLabels:
                app: monitoring
      - action: Deny
        name: deny-all-other-ingress-from-beta
        from:
        - namespaces:
            matchLabels:
              team: beta
    ---
    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: allow-beta
    spec:
      tier: Admin
      priority: 50
      subject:
        namespaces:
          matchLabels:
            team: alpha
      ingress:
      - action: Accept
        name: allow-all-ingress-from-beta
        from:
        - namespaces:
            matchLabels:
              team: beta
    
  2. マニフェストをクラスタに適用します。

    kubectl apply -f priority-policies.yaml
    

トラブルシューティング

ポリシー エラーを診断して解決する方法については、次のコマンドを使用します。

クラスタ内のすべてのクラスタ ネットワーク ポリシーを一覧表示します。

kubectl get clusternetworkpolicies

特定のポリシーを記述して、そのステータスと評価階層を調べます。

kubectl describe clusternetworkpolicy/<policy-name>

出力の status.conditions フィールドには、クラスタのネットワーキング実装によってポリシーが正常に調整されたかどうかに関する情報が表示されます。

トラフィック フローとポリシーに関する決定をモニタリングするには、GKE Dataplane V2 のオブザーバビリティを使用します。

次のステップ