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

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

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

始める前に

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

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

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

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

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

ポリシー評価階層

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

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

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

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

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

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

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

  • 拒否: トラフィックを直ちにブロックします。
  • 許可: トラフィックを許可します。どちらのアクションもパイプラインを即座にショートカットし、残りのポリシーはすべて無視されます。
  • パス: 制御を次の階層に転送します。これにより、プラットフォーム エンジニアは、包括的な管理制御を放棄することなく、特定のトラフィックの決定を標準の 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. 次の Deployment マニフェストを 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 オブザーバビリティを使用します。

次のステップ