使用网络政策日志记录


本页面介绍了如何对 Google Kubernetes Engine (GKE) 使用网络政策日志记录功能。 Kubernetes 网络政策指定系统允许 Pod 发送和接收的网络流量。借助网络政策日志记录功能,您可以在网络政策允许或拒绝连接时进行记录。网络政策日志记录可帮助您排查网络政策问题。

概览

使用网络政策日志记录功能,您可以:

  • 验证您的网络政策是否按预期工作。
  • 了解集群中的哪些 Pod 正在与互联网进行通信。
  • 了解哪些命名空间彼此之间正在进行通信。
  • 识别拒绝服务攻击。

如果启用了 Cloud Logging,则系统会将网络政策日志上传到 Cloud Logging,以便进行存储、搜索、分析、发出提醒。默认情况下,新集群中会启用 Cloud Logging。如需了解详情,请参阅为 GKE 配置日志记录和监控

使用要求

  • 网络政策日志记录功能仅适用于使用 GKE Dataplane V2 的集群。
  • 网络政策日志记录需要使用 Google Cloud CLI 303.0.0 或更高版本。
  • Windows Server 节点池不支持网络政策日志记录功能。

价格

  • 网络政策日志记录不会产生日志生成费用。
  • 日志可以进一步路由到 Pub/Sub、Cloud Storage 或 BigQuery。您可能需要支付 Pub/Sub、Cloud Storage 或 BigQuery 费用。如需了解详情,请参阅路由和存储概览

配置网络政策日志记录

您可以通过修改集群中的 NetworkLogging 对象配置网络政策日志记录设置。GKE 会自动在新的 Dataplane V2 集群中创建名为 defaultNetworkLogging 对象。每个集群只能有一个 NetworkLogging 对象,并且无法重命名该对象。

您可以单独配置允许的连接的日志记录功能和被拒连接的日志记录功能。您还可以选择性地为某些网络政策启用日志记录功能。以下是 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.delegate 设置为 true 并将 spec.cluster.allow.log 设置为 false,则会发生配置错误。

cluster.deny struct 记录被拒连接的设置。
字段类型说明
log bool

如果设置为 true,则系统会记录集群中的被拒连接;否则,系统不会记录被拒连接。

delegate bool

如果为 false,则系统会记录所有被拒连接。

如果为 true,则只有在连接被拒的 Pod 位于具有 policy.network.gke.io/enable-deny-logging: "true" 注释的命名空间中时系统才会记录被拒连接。

如果您将 spec.cluster.deny.delegate 设置为 true 并将 spec.cluster.deny.log 设置为 false,则会发生配置错误。

访问网络政策日志

网络政策日志会自动上传到 Cloud Logging。您可以通过 Logs Explorer 或 Google Cloud CLI 访问日志。您还可以将日志路由到接收器

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:集群的 Compute Engine 位置
    • CLUSTER_NAME:您的集群的名称。
    • PROJECT_NAME:您的 Google Cloud 项目的名称。

如需了解如何使用日志浏览器,请参阅使用日志浏览器

您还可以使用查询构建器构建查询。如需为网络政策日志创建查询,请在日志名称下拉列表中选择 policy-action。 如果没有可用的日志,则 policy-action 不会显示在下拉列表中。

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 项目的名称。
  • CLUSTER_LOCATION:集群的 Compute Engine 位置
  • CLUSTER_NAME:您的集群的名称。

您可以添加其他条件以过滤结果。例如:

  • 显示特定时间范围内的日志:

    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"
    

如果您使用 Standard 集群,则还可以在本地查找每个集群节点上生成的网络政策日志 (/var/log/network/policy_action.log*)。如果当前日志文件达到 10 MB,则系统会创建一个带有编号的新日志文件。系统最多存储之前的五个日志文件。

网络政策日志格式

网络政策日志记录采用 JSON 格式。下表中介绍了此格式:

字段类型说明
connectionstruct 连接信息:
字段类型说明
src_ipstring连接的来源 IP 地址。
src_portint连接的来源端口。
dest_ipstring连接的目标 IP 地址。
dest_portint连接的目标端口。
protocolstring连接的协议,可以是 tcpudpicmp 之一。
directionstring连接的方向,可以是 ingressegress
srcstruct 来源的端点信息:
字段类型说明
pod_namestringPod 的名称(如果来源是 Pod)。
pod_namespace (deprecated)stringPod 的命名空间(如果来源是 Pod)。 pod_namespace 已弃用,请改用 namespace
namespacestringPod 的命名空间(如果来源是 Pod)。
workload_namestring工作负载的名称(如果来源工作负载可用)。
workload_kindstring工作负载的种类(如果来源工作负载可用)。
instancestring来源的 IP 地址(如果来源不是 Pod)。
deststruct 目标的端点信息:
字段类型说明
pod_namestringPod 的名称(如果目标是 Pod)。
pod_namespace (deprecated)stringPod 的命名空间(如果目标是 Pod)。 pod_namespace 已弃用,请改用 namespace
namespacestringPod 的命名空间(如果目标是 Pod)。
workload_namestring工作负载的名称(如果目标工作负载可用)。
workload_kindstring工作负载的种类(如果目标工作负载可用)。
instancestring来源的 IP 地址(如果目标不是 Pod)。
dispositionstring连接的处理方式,可以是 allowdeny
policieslist of structs

从强制执行的 Pod 来看的允许连接的匹配政策。对于入站连接,强制执行的 Pod 是目标 Pod。对于出站连接,强制执行的 Pod 是来源 Pod。如果多项政策与某个连接匹配,则系统会记录所有的这些政策。

此字段仅包含在允许连接的日志中

字段类型说明
namestring匹配的网络政策的名称。
namespacestring匹配的网络政策的命名空间。
countint用于被拒查询的日志汇总。对于允许的连接,该值始终为 1。
node_namestring运行生成此日志消息的 Pod 的节点。
timestampstring尝试连接的时间。

连接定义

对于 TCP 等面向连接的协议,系统会为每个允许或被拒的连接创建一条日志。对于 UDP 和 ICMP 等非面向连接的协议,数据包会分组到基于时间段的连接。

被拒连接的政策日志

被拒连接的日志记录不包含 policies 字段,因为 Kubernetes Network Policy API 没有明确的拒绝政策。如果一项或多项网络政策涉及某个 Pod,但不允许某个连接,则系统会拒绝该连接。这意味着,没有任何政策对阻止的连接单独负责。

被拒连接的日志汇总

客户端通常会重试被拒的连接。为了防止日志记录过大,系统会使用 count 字段将五秒时间段内重复记录的被拒连接汇总到一条日志消息中。

如果连接的 src_ip, dest_ip, dest_port, protocol,direction 与第一个被拒连接匹配,则后续的被拒连接会与之前的日志消息汇总。请注意,后续连接的 src_port 不必与第一个被拒的连接匹配,因为重试的连接可能来自其他端口。汇总的日志消息包含汇总时间段开始时第一个被拒连接的 src_prt

日志记录示例

以下名为 allow-green 且应用于 test-service 的示例网络政策允许从名为 client-green 的 Pod 连接到 test-service。此政策会隐式拒绝流向 test-service 的所有其他入站流量,包括来自 Pod client-red 的流量。

  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 的两个连接的影响。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",
      "namespace":"default",
      "workload_name":"client-green-7b78d7c957",
      "workload_kind":"ReplicaSet"
   },
   "dest":{
      "pod_name":"test-service-745c798fc9-sfd9h",
      "pod_namespace":"default",
      "namespace":"default",
      "workload_name":"test-service-745c798fc9",
      "workload_kind":"ReplicaSet"
   },
   "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",
      "namespace":"default",
      "workload_name":"client-red-5689846f5b",
      "workload_kind":"ReplicaSet"
   },
   "dest":{
      "pod_name":"test-service-745c798fc9-sfd9h",
      "pod_namespace":"default",
      "namespace":"default",
      "workload_name":"test-service-745c798fc9",
      "workload_kind":"ReplicaSet"
   },
   "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. 一个节点每秒最多可以记录 500 个连接,然后才会开始丢弃日志,从而限制日志记录所用的 CPU 利用率。系统仍会对节点强制执行网络政策。可以通过检查是否有任何错误计数器正在递增,查看是否有丢弃的政策日志:

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

    ANETD_POD_NAME 替换为 anetd Pod 的名称。检查每个节点。anetd 是 Dataplane V2 的网络控制器。

对于采用默认拒绝政策的 Pod,系统显示没有名称的日志

活跃性、就绪性和启动探测要求 Pod 接受来自 kubelet 的探测发起的 Ingress 连接。为确保这些探测正确运行,GKE 会自动允许发送到所选 Pod 的探测流量(根据 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",
      "namespace":"default",
      "workload_name":"testpod-745c798fc9",
      "workload_kind":"ReplicaSet"
   },
   "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 或节点。

后续步骤