You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

K8s出口NetworkPolicy匹配标签时拒绝访问问题排查求助

Kubernetes最小权限网络策略失效:迁移Job无法通过Service访问PostgreSQL

问题概述

配置了最小权限的Kubernetes网络策略,仅允许带有networking/client: auth-api-postgresdb-migrations标签的迁移Job访问带有networking/client: auth-api-postgresdb标签的PostgreSQL资源:

  • PostgreSQL的Ingress策略正常生效
  • 迁移Job可直接连接PostgreSQL Pod,但无法通过ClusterIP Service访问
  • 移除Egress策略的podSelector限制后,Service访问恢复正常

现有配置

PostgreSQL Ingress策略

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: auth-api-postgres
spec:
  policyTypes:
    - Ingress
  podSelector:
    matchLabels:
      networking/client: auth-api-postgresdb
  ingress:
    - ports:
        - protocol: TCP
          port: 5432
      from:
        - podSelector:
            matchLabels:
              networking/client: auth-api-postgresdb-migrations

迁移Job Egress策略

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: auth-api-postgresdb-migrations
spec:
  policyTypes:
    - Egress
  podSelector:
    matchLabels:
      networking/client: auth-api-postgresdb-migrations
  egress:
    - ports:
        - protocol: TCP
          port: 5432
      to:
        - podSelector:
            matchLabels:
              networking/client: auth-api-postgresdb

命名空间全局策略

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns-access
spec:
  podSelector:
    matchLabels: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-istio-proxy-access
spec:
  podSelector:
    matchLabels: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: istio-system
          podSelector:
            matchLabels:
              app: istiod
      ports:
        - protocol: TCP
          port: 15012

资源与错误信息

资源列表

$ k get all -n test -l networking/client=auth-api-postgresdb
NAME                                   READY   STATUS    RESTARTS   AGE
pod/auth-api-postgresdb-postgresql-0   2/2     Running   0          3m42s

NAME                                             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/auth-api-postgresdb-postgresql           ClusterIP   172.20.130.101   <none>        5432/TCP   3m42s
service/auth-api-postgresdb-postgresql-hl        ClusterIP   None             <none>        5432/TCP   3m42s
service/auth-api-postgresdb-postgresql-metrics   ClusterIP   172.20.134.229   <none>        9187/TCP   3m42s

NAME                                              READY   AGE
statefulset.apps/auth-api-postgresdb-postgresql   1/1     3m42s

错误日志

...
Opening connection to database 'identity' on server 'tcp://auth-api-postgresdb-postgresql:5432'
...
Npgsql.NpgsqlException (0x80004005): Failed to connect to 172.20.130.101:5432
...

问题根源

标准Kubernetes NetworkPolicy的egress.to.podSelector仅匹配最终目标Pod的标签,但通过ClusterIP Service访问时,流量的初始目标IP是Service的ClusterIP,而非Pod IP。多数CNI插件(如kube-proxy的iptables模式)会在转发流量到Pod前检查Egress规则,此时规则仅允许到PostgreSQL Pod的流量,不允许到Service ClusterIP的流量,因此被default-deny策略拦截。

直接连接Pod时,目标IP是Pod IP,符合podSelector规则,所以能正常访问。


解决方案

方案1:使用Headless Service(最符合最小权限)

将迁移Job的数据库连接地址改为Headless Service auth-api-postgresdb-postgresql-hl:5432。Headless Service的DNS解析直接返回Pod IP,流量直接发往Pod,无需经过ClusterIP转发,现有Egress策略的podSelector规则即可匹配,无需修改任何网络策略。

方案2:允许到Service ClusterIP的流量(兼容普通Service)

修改迁移Job的Egress策略,添加对PostgreSQL Service ClusterIP的访问规则:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: auth-api-postgresdb-migrations
spec:
  policyTypes:
    - Egress
  podSelector:
    matchLabels:
      networking/client: auth-api-postgresdb-migrations
  egress:
    # 允许到PostgreSQL Pod的流量
    - ports:
        - protocol: TCP
          port: 5432
      to:
        - podSelector:
            matchLabels:
              networking/client: auth-api-postgresdb
    # 允许到PostgreSQL Service ClusterIP的流量
    - ports:
        - protocol: TCP
          port: 5432
      to:
        - ipBlock:
            cidr: 172.20.130.101/32 # 替换为你的PostgreSQL Service ClusterIP
    # 保留DNS访问(继承全局策略,若已覆盖可省略)
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53

方案3:允许到集群Service CIDR的流量(更灵活,权限略宽)

如果不想硬编码ClusterIP,可允许到整个集群Service CIDR的5432端口流量(需先通过kubectl cluster-info dump | grep -m 1 service-cluster-ip-range获取Service CIDR):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: auth-api-postgresdb-migrations
spec:
  policyTypes:
    - Egress
  podSelector:
    matchLabels:
      networking/client: auth-api-postgresdb-migrations
  egress:
    - ports:
        - protocol: TCP
          port: 5432
      to:
        - podSelector:
            matchLabels:
              networking/client: auth-api-postgresdb
        - ipBlock:
            cidr: 172.20.0.0/16 # 替换为你的集群Service CIDR
    # DNS访问规则
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53

内容的提问来源于stack exchange,提问作者APW

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 20:59:53