本页面介绍了如何对 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 节点池不支持网络政策日志记录功能。
价格
- 网络政策日志记录不会产生日志生成费用。
- 如果您将日志存储在 Cloud Logging 中,则需要支付标准 Cloud Logging 费用。
- 日志可以进一步路由到 Pub/Sub、Cloud Storage 或 BigQuery。您可能需要支付 Pub/Sub、Cloud Storage 或 BigQuery 费用。如需了解详情,请参阅路由和存储概览。
配置网络政策日志记录
您可以通过修改集群中的 NetworkLogging
对象配置网络政策日志记录设置。GKE 会自动在新的 Dataplane V2 集群中创建名为 default
的 NetworkLogging
对象。每个集群只能有一个 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.allow | struct |
记录允许的连接的设置。
|
|||||||||
cluster.deny |
struct |
记录被拒连接的设置。
|
访问网络政策日志
网络政策日志会自动上传到 Cloud Logging。您可以通过 Logs Explorer 或 Google Cloud CLI 访问日志。您还可以将日志路由到接收器。
Cloud Logging
转到 Google Cloud 控制台中的日志浏览器页面。
点击查询构建器。
使用以下查询查找所有网络政策日志记录:
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 项目的名称。
如需了解如何使用 Logs Explorer,请参阅使用 Logs Explorer。
您还可以使用查询构建器构建查询。如需为网络政策日志创建查询,请在日志名称下拉列表中选择 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 格式。下表中介绍了此格式:
字段 | 类型 | 说明 | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
connection | struct |
连接信息:
|
|||||||||||||||||||||
src | struct |
来源的端点信息:
|
|||||||||||||||||||||
dest | struct |
目标的端点信息:
|
|||||||||||||||||||||
disposition | string | 连接的处理方式,可以是 allow 或 deny 。 | |||||||||||||||||||||
policies | list of structs |
从强制执行的 Pod 来看的允许连接的匹配政策。对于入站连接,强制执行的 Pod 是目标 Pod。对于出站连接,强制执行的 Pod 是来源 Pod。如果多项政策与某个连接匹配,则系统会记录所有的这些政策。 此字段仅包含在允许连接的日志中。
|
|||||||||||||||||||||
count | int | 用于被拒查询的日志汇总。对于允许的连接,该值始终为 1。 | |||||||||||||||||||||
node_name | string | 运行生成此日志消息的 Pod 的节点。 | |||||||||||||||||||||
timestamp | string | 尝试连接的时间。 |
连接定义
对于 TCP 等面向连接的协议,系统会为每个允许或被拒的连接创建一条日志。对于 UDP 和 ICMP 等非面向连接的协议,数据包会分组到基于时间段的连接。
被拒连接的政策日志
被拒连接的日志记录不包含 policies
字段,因为 Kubernetes 网络政策 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
字段,用于汇总被拒连接。
网络政策日志问题排查
检查
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
一个节点每秒最多可以记录 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 或节点。