K8s环境下Pod访问外部PostgreSQL如何固定出口IP配置白名单
K8s Pod访问外部服务固定出口IP实现方案
集群内Pod访问外部服务的出站场景,完全可以实现固定出口IP,不需要依赖Pod调度所在节点的临时IP,和入站场景通过Service/Endpoint提供固定访问锚点的逻辑对应,出站场景有成熟的落地路径,不需要依赖手动配置主机端口转发这种高维护成本的方式。
按场景选择落地方式
方案1:CNI原生Egress网关(最适配当前PostgreSQL白名单需求,推荐优先用)
这个方案是生产环境最常用的实现,配置逻辑和你熟悉的Service/Endpoint逻辑高度匹配:
- 先筛选1~2台IP固定的集群节点作为专属出口网关节点,给节点打上标签比如
egress-gw=true,提前把这几台节点的IP加到PostgreSQL的pg_hba.conf白名单里,这部分IP是节点固有固定地址,不会随Pod调度变化。 - 给外部PostgreSQL创建一个不带Selector的ClusterIP类型Service,手动配置对应的Endpoint,把Endpoint地址指向外部PG的实际IP和端口,相当于给外部PG在集群内部做了一个固定的访问入口锚点,业务Pod统一访问这个集群内部Service地址即可,不需要直接连外部PG地址。
- 如果你集群用的是Calico、Cilium这类主流CNI插件,直接用插件自带的Egress策略能力做流量转发即可:Calico创建
EgressGateway资源绑定之前打了标签的出口节点,再创建EgressPolicy匹配发往PG Service的流量,指定流量从绑定的Egress网关出;Cilium直接创建CiliumEgressGatewayPolicy资源,匹配目标PG的地址段,指定出口节点即可。配置完成后CNI会自动做节点间的流量路由和出口SNAT,不管业务Pod调度到哪个节点,访问PG的流量最终都会从你提前加了白名单的固定节点IP出去,不会因为Pod漂移导致白名单失效。
方案2:固定节点代理转发(适合CNI不支持Egress网关的小规模集群)
如果你的集群CNI不支持原生Egress能力,可以用四层代理的方式实现固定出口:
- 把TCP代理组件(比如HAProxy、Nginx Stream)以DaemonSet或者固定副本数的Deployment形式,强制调度到之前选好的固定IP节点上,给代理组件创建ClusterIP类型Service。
- 提前把代理所在节点的固定IP加到PG白名单里,代理配置里写好外部PG的转发规则。
- 业务Pod统一访问代理Service的地址,由代理把流量转发到外部PG,此时PG看到的连接来源IP永远是代理所在节点的固定IP。
- 注意这个方案要提前做好代理的性能预留和高可用配置,避免代理单点故障导致PG访问中断。
方案3:全局出口SNAT(适合多外部服务统一白名单场景)
如果你集群有多个外部服务都需要固定出口IP,可以直接把所有访问外部网段的出站流量,全部通过静态路由转发到固定的出口网关节点做SNAT,所有外部服务看到的集群来源IP都是统一的固定出口IP,不需要为单个服务单独配置规则。
不推荐的实现方式
不要手动配置主机端口转发来实现需求:这类手动配置的规则是节点级的临时规则,节点重启、kubelet升级、集群组件更新都可能导致规则丢失,且需要手动逐节点维护iptables或者路由规则,Pod漂移后规则不会自动适配,维护成本极高,很容易出现随机访问不通的问题。
配置验证方式
规则配置完成后,可以启动一个临时测试Pod,用psql客户端连接PG实例,在PG侧执行查询语句select client_addr from pg_stat_activity where datname='你的业务库名' and state='active';,如果返回的client_addr是你提前配置的固定出口IP,就说明规则生效,后续Pod重启、调度到任意节点都不会触发PG的IP白名单拦截。
内容的提问来源于stack exchange,提问作者ntg
相关产品推荐
相关产品推荐

