ネットワーク ポリシー ロギングの使用


このページでは、Google Kubernetes Engine(GKE)でネットワーク ポリシー ロギングを使用する方法について説明します。

概要

ネットワーク ポリシーでは、Pod で送受信できるネットワーク トラフィックを指定します。ネットワーク ポリシー ロギングを使用すると、ネットワーク ポリシーによって接続が許可または拒否された時間を記録できます。ネットワーク ポリシー ロギングを使用すると、次のことができます。

  • ネットワーク ポリシーが予期したとおり機能していることを確認する。
  • クラスタ内のどの Pod がインターネットと通信しているかを把握する。
  • 互いに通信している Namespace を把握する。
  • サービス拒否攻撃を認識する。

Cloud Logging が有効になっている場合、ネットワーク ポリシーのログは Cloud Logging にアップロードされて保存され、検索、分析、アラートに使用されます。新しいクラスタでは、Cloud Logging がデフォルトで有効になります。詳細については、GKE 用 Cloud Operations サポートのインストールをご覧ください。

要件

  • ネットワーク ポリシー ロギングは、Dataplane V2 を使用するクラスタでのみ利用できます。
  • ネットワーク ポリシー ロギングには Cloud SDK 303.0.0 以降が必要です。
  • ネットワーク ポリシー ロギングは、Windows Server ノードプールではサポートされていません。

料金

  • ベータ版では、ネットワーク ポリシー ロギングのログ生成に料金はかかりません。
  • Cloud Logging にログを保存すると、Cloud Logging の標準料金が適用されます。
  • さらに、ログを Pub/Sub、Cloud Storage、BigQuery にエクスポートできます。Pub/Sub、Cloud Storage、BigQuery の料金が適用される場合があります。ログのエクスポートの詳細については、ログのエクスポートの概要をご覧ください。

ネットワーク ポリシー ロギングを構成する

ネットワーク ポリシー ロギングは、クラスタの NetworkLogging オブジェクトを編集して構成します。GKE では、新しい Dataplane V2 クラスタdefault という名前の NetworkLogging オブジェクトが自動的に作成されます。NetworkLogging オブジェクトは 1 つのクラスタに 1 つだけ存在し、その名前は変更できません。

許可された接続と拒否された接続のロギングを別々に構成できます。一部のネットワーク ポリシーでは、ロギングを選択的に有効にすることもできます。NetworkLogging 仕様の例を次に示します。ここには、許可された接続と拒否された接続をすべてログに記録する際に指定する指定が含まれています。

kind: NetworkLogging
apiVersion: networking.gke.io/v1alpha1
metadata:
  name: default
spec:
  cluster:
    allow:
      log: true
      delegate: false
    deny:
      log: true
      delegate: false

kubectl を使用して構成を編集します。

kubectl edit networklogging default

NetworkLogging の仕様

NetworkLogging オブジェクトの仕様は YAML 形式で記述されています。次の表に、この形式の説明を示します。

フィールド説明
cluster.allowstruct 許可された接続のロギングの設定。
フィールド説明
log bool

true に設定すると、クラスタ内で許可された接続がログに記録されます。それ以外の場合、許可された接続は記録されません。

Pod を選択し、接続に一致するルールを含むネットワーク ポリシーがログメッセージに含まれます。

delegate bool

false の場合、許可された接続がすべてログに記録されます。複数のネットワーク ポリシーで接続が許可されている場合、一致するすべてのポリシーがログメッセージに含まれます。

true の場合、ロギング アノテーション policy.network.gke.io/enable-logging: "true" を含むネットワーク ポリシーで許可されている場合に限り、許可された接続がログに記録されます。複数のネットワーク ポリシーで接続が許可されている場合、enable-logging アノテーションを含み、一致するすべてのポリシーがログメッセージに含まれます。

spec.cluster.allow.delegatetruespec.cluster.allow.logfalse に設定した場合は、構成エラーが発生します。

cluster.deny struct 拒否された接続のロギングの設定。
フィールド説明
log bool

true に設定すると、クラスタ内で拒否された接続がログに記録されます。それ以外の場合、拒否された接続は記録されません。

delegate bool

false の場合、拒否された接続はすべてログに記録されます。

true の場合、接続が拒否された Pod がアノテーション policy.network.gke.io/enable-deny-logging: "true" 付きの名前空間にある場合にのみ、拒否された接続が記録されます。

spec.cluster.deny.delegatetruespec.cluster.deny.logfalse に設定した場合は、構成エラーが発生します。

ログへのアクセス

各クラスタノードで生成されたネットワーク ポリシーのログは、ローカルの /var/log/network/policy_action.log* に保存されます。現行のログファイルが 10 MB になると、新しい番号の付いたログファイルが作成されます。ログファイルは最大 5 世代まで保存されます。

ネットワーク ポリシーのログは、Cloud Logging に自動的にアップロードされます。ログにアクセスするには、ログ エクスプローラまたは gcloud コマンドライン ツールを使用します。任意のシンクに Cloud Logging からログをエクスポートすることもできます。

gcloud

gcloud logging read --project "PROJECT_NAME" 'resource.type="k8s_node" \
    resource.labels.location="CLUSTER_LOCATION" \
    resource.labels.cluster_name="CLUSTER_NAME" \
    logName="projects/PROJECT_NAME/logs/policy-action"'

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

  • PROJECT_NAME: Google Cloud Platform プロジェクトの名前です。
  • CLUSTER_LOCATION: クラスタが配置されているゾーン。
  • CLUSTER_NAME: クラスタの名前。

Cloud Logging

  1. Google Cloud のナビゲーション メニュー に移動し、[ロギング] > [ログ エクスプローラ] を選択します。
    ログ エクスプローラに移動
  2. [クエリビルダー] をクリックします。
  3. 次のクエリを使用して、すべてのネットワーク ポリシーのログレコードを検索します。

    resource.type="k8s_node"
    resource.labels.location="CLUSTER_LOCATION"
    resource.labels.cluster_name="CLUSTER_NAME"
    logName="projects/PROJECT_NAME/logs/policy-action"
    

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

    • CLUSTER_LOCATION: クラスタが配置されているゾーン。
    • CLUSTER_NAME: クラスタの名前。
    • PROJECT_NAME: Google Cloud Platform プロジェクトの名前です。

ログ エクスプローラの使い方については、ログ エクスプローラの使用をご覧ください。

また、クエリビルダーを使用してクエリを作成することもできます。ネットワーク ポリシーログのクエリを作成するには、[ログ名] プルダウン リストから [policy-action] を選択します。 使用可能なログがない場合、policy-action はプルダウン リストに表示されません。

さらに条件を追加して、結果をフィルタリングすることもできます。例:

  • 特定期間のログを表示する。

    timestamp>="2020-06-22T06:30:51.128Z"
    timestamp<="2020-06-23T06:30:51.128Z"
    
  • 拒否された接続のログを表示する。

    jsonPayload.disposition="deny"
    
  • 「redis」という名前のデプロイにログを表示する。

    jsonPayload.dest.pod_name=~"redis"
    jsonPayload.dest.pod_namespace="default"
    
  • クラスタ外部接続のログを表示する。

    jsonPayload.dest.instance != ""
    
  • 特定のネットワーク ポリシー(この場合は allow-frontend-to-db)と一致するログを表示する。

    jsonPayload.policies.name="allow-frontend-to-db"
    jsonPayload.policies.namespace="default"
    

ログ形式

ネットワーク ポリシー ログは JSON 形式で記録されます。次の表に、この形式の説明を示します。

フィールド説明
connectionstruct 接続情報
フィールド説明
src_ipstring接続の送信元 IP アドレス。
src_portint接続の送信元ポート。
dest_ipstring接続の宛先 IP アドレス。
dest_portint接続の宛先ポート。
protocolstring接続のプロトコル(tcpudpicmp のいずれか)。
directionstring接続の方向(ingress または egress のいずれか)。
srcstruct 送信元のエンドポイント情報。
フィールド説明
pod_namestringPod の名前(送信元が Pod の場合)。
pod_namespacestringPod の名前空間(送信元が Pod の場合)。
instancestring送信元の IP アドレス(送信元が Pod でない場合)。
deststruct 宛先のエンドポイント情報。
フィールド説明
pod_namestringPod の名前(宛先が Pod の場合)。
pod_namespacestringPod の名前空間(宛先が Pod の場合)。
instancestring送信元の IP アドレス(宛先が Pod でない場合)。
dispositionstring接続の処理(allow または deny のいずれか)。
policieslist of structs

適用された Pod から許可された接続に一致したポリシー。上り(内向き)接続の場合、適用された Pod は宛先 Pod になります。下り(外向き)接続の場合、適用された Pod は送信元 Pod になります。一致したポリシーが複数ある場合は、一致したポリシーすべてが記録されます。

このフィールドは、許可された接続のログにのみ含まれます

フィールド説明
namestring照合するネットワーク ポリシーの名前。
namespacestring照合するネットワーク ポリシーの Namespace。
countint拒否されたクエリのログ集計に使用されます。許可される接続の値は常に 1 になります。
node_namestringこのログメッセージを生成した Pod が実行されているノード。
timestampstring接続の試行日時。

接続の定義

TCP などのコネクション型のプロトコルでは、許可された接続または拒否された接続ごとにログが作成されます。UDP や ICMP などのコネクション型以外のプロトコルの場合、パケットは時間枠に基づく接続に分類されます。

拒否された接続のポリシーログ

Kubernetes ネットワーク ポリシー API には明示的な拒否ポリシーがありません。このため、拒否された接続のログレコードに policies フィールドは含まれません。Pod が 1 つ以上のネットワーク ポリシーで処理され、その接続を許可するポリシーがない場合、接続は拒否されます。これは、接続がブロックされた根拠となるポリシーが存在しないことを意味します。

拒否された接続のログ集計

一般に、クライアントは拒否された接続を再試行します。過剰なロギングを防ぐため、5 秒以内に連続して拒否された接続は、count フィールドを使用して 1 つのログメッセージに集約されます。

接続の src_ip, dest_ip, dest_port, protocol,direction が最初に拒否された接続と一致すると、後続の接続は前のログメッセージに集計されます。接続の再試行が別のポートから行われることもあるため、後続の接続の src_port を照合する必要はありません。集計されたログメッセージには、集計期間中に最初に拒否された接続の src_prt が含まれます。

ログレコードの例

次のネットワーク ポリシーの例では、ポリシー名が allow-green で、client-green という Pod から test-service への接続を test-service で許可しています。このポリシーでは、Pod client-red から test-service への上り(内向き)トラフィックをすべて暗黙的に拒否されます。

  apiVersion: networking.k8s.io/v1
  kind: NetworkPolicy
  metadata:
    name: allow-green
    namespace: default
    annotations:
      policy.network.gke.io/enable-logging: "true"
  spec:
    podSelector:
      matchLabels:
        app: test-service
    ingress:
    - from:
      - podSelector:
          matchLabels:
            app: client-green
    policyTypes:
    - Ingress

次の図は、allow-green ポリシーが test-service との 2 つの接続に与える影響を示しています。allow-green ポリシーは client-green からの接続を許可します。ポリシーで client-red からの接続が許可されないため、接続は拒否されます。

client-green からの接続が許可された場合、ログは次のようになります。

{
   "connection":{
      "src_ip":"10.84.0.252",
      "dest_ip":"10.84.0.165",
      "src_port":52648,
      "dest_port":8080,
      "protocol":"tcp",
      "direction":"ingress"
   },
   "disposition":"allow",
   "policies":[
      {
         "name":"allow-green",
         "namespace":"default"
      }
   ],
   "src":{
      "pod_name":"client-green-7b78d7c957-68mv4",
      "pod_namespace":"default"
   },
   "dest":{
      "pod_name":"test-service-745c798fc9-sfd9h",
      "pod_namespace":"default"
   },
   "count":1,
   "node_name":"gke-demo-default-pool-5dad52ed-k0h1",
   "timestamp":"2020-06-16T03:10:37.993712906Z"
}

client-red からの接続が拒否された場合、ログは次のようになります。

{
   "connection":{
      "src_ip":"10.84.0.180",
      "dest_ip":"10.84.0.165",
      "src_port":39610,
      "dest_port":8080,
      "protocol":"tcp",
      "direction":"ingress"
   },
   "disposition":"deny",
   "src":{
      "pod_name":"client-red-5689846f5b-b5ccx",
      "pod_namespace":"default"
   },
   "dest":{
      "pod_name":"test-service-745c798fc9-sfd9h",
      "pod_namespace":"default"
   },
   "count":3,
   "node_name":"gke-demo-default-pool-5dad52ed-k0h1",
   "timestamp":"2020-06-15T22:38:32.189649531Z"
}

拒否された接続のログに policies フィールドは含まれません。これについては、前のセクションの拒否された接続のポリシーログで説明しています。

拒否された接続のログには、拒否された接続を集計する count フィールドが含まれます。

トラブルシューティング

  1. NetworkLogging オブジェクトのエラーイベントを確認します。

    kubectl describe networklogging default
    

    ロギング構成が無効な場合、構成が無効になり、イベント セクションにエラーが報告されます。

    Name:         default
    Namespace:
    Labels:       addonmanager.kubernetes.io/mode=EnsureExists
    Annotations:  API Version:  networking.gke.io/v1alpha1
    Kind:         NetworkLogging
    Metadata:
      Creation Timestamp:  2020-06-20T05:54:08Z
      Generation:          8
      Resource Version:    187864
      Self Link:           /apis/networking.gke.io/v1alpha1/networkloggings/default
      UID:                 0f1ddd6e-4193-4295-9172-baa6a52aa6e6
    Spec:
      Cluster:
        Allow:
          Delegate:  true
          Log:       false
        Deny:
          Delegate:  false
          Log:       false
    Events:
      Type     Reason                 Age                From                                                               Message
      ----     ------                 ----               ----                                                               -------
      Warning  InvalidNetworkLogging  16s (x3 over 11h)  network-logging-controller, gke-anthos-default-pool-cee49209-0t09  cluster allow log action is invalid: delegate cannot be true when log is false
      Warning  InvalidNetworkLogging  16s (x3 over 11h)  network-logging-controller, gke-anthos-default-pool-cee49209-80fx  cluster allow log action is invalid: delegate cannot be true when log is false
    
  2. 1 ノードで 1 秒あたり最大 500 件の接続をログに記録できます。エラーカウンタの増加を確認して、削除されたポリシーログがあるかどうかを確認します。

    kubectl exec ANETD_XYZ -n kube-system -- curl -s http://localhost:9990/metrics |grep policy_logging
    

    ANETD_XYZ は、anetd Pod の名前に置き換えます。各ノードを確認します。anetd は Dataplane V2 のネットワーク コントローラです。

デフォルトの拒否ポリシーを持つ Pod には、名前のないログが表示されます。

liveness、readiness、startup のプローブでは、kubelet からのプローブによる Ingress 接続を Pod が受け入れる必要があります。これらのプローブが正常に機能するように、GKE は Pod に適用されているネットワーク ポリシーに関係なく、選択した Pod に構成されたプローブ トラフィックを自動的に許可します。この動作は変更できません。

プローブ接続のログは次のようになります。

{
   "connection":{
      "src_ip":"10.88.1.1",
      "dest_ip":"10.88.1.4",
      "src_port":35848,
      "dest_port":15021,
      "protocol":"tcp",
      "direction":"ingress"
   },
   "disposition":"allow",
   "src":{
      "instance":"10.88.1.1"
   },
   "dest":{
      "pod_name":"testpod-745c798fc9-sfd9h",
      "pod_namespace":"default"
   },
   "count":1,
   "policies": [
     {
       "name":""
     }
    ],
   "node_name":"gke-demo-default-pool-5dad52ed-k0h1",
   "timestamp":"2021-04-01T12:42:32.1898720941Z"
}

ログには次の特性があります。

  • policies.name の値は空です。接続を許可するネットワーク ポリシーがないためです。
  • connection.src_ip の値はどの Pod やノードにも一致しません。

次のステップ