K8s集群出口流量多IP健康检查主备故障切换配置方法
原生Kubernetes Service默认采用轮询策略转发流量到后端Endpoints,不支持按优先级优先转发到指定IP的主备切换逻辑,你之前尝试的普通Ingress规则仅支持七层HTTP/HTTPS流量路由,本身不适用于Postgres使用的四层TCP协议场景,因此无法直接配置目标IP实现需求。可根据实际场景选择以下两种落地方案:
方案1:基于Nginx Ingress四层转发实现全局无感知切换
不需要额外部署组件,复用现有Nginx Ingress Controller即可实现全局统一的主备流量切换,业务侧不需要修改数据库连接逻辑,仅需调整访问地址:
- 调整现有Service为无头Service,关闭kube-proxy默认的负载均衡逻辑:
apiVersion: v1 kind: Service metadata: name: postgre-service namespace: test spec: clusterIP: None ports: - name: postgre port: 5432 protocol: TCP targetPort: 5432
原有Endpoints配置不需要调整,可保留三个IP配置。
2. 修改Nginx Ingress Controller所在命名空间下的tcp-services ConfigMap,添加TCP转发规则,配置主备优先级与主动健康检查:
apiVersion: v1 kind: ConfigMap metadata: name: tcp-services namespace: ingress-nginx # 替换为实际部署Nginx Ingress的命名空间 data: 5432: | upstream postgres_backend { server first-ip:5432 max_fails=3 fail_timeout=30s weight=100; server second-ip:5432 backup max_fails=3 fail_timeout=30s; server third-ip:5432 backup max_fails=3 fail_timeout=30s; } server { listen 5432; proxy_pass postgres_backend; proxy_connect_timeout 5s; proxy_socket_keepalive on; }
配置说明:
- 第一个IP设置最高权重,所有流量优先转发到该节点
- 其余两个IP标记为
backup备节点,仅当主节点连续3次连接失败、30s内不可用时才会接收流量 - 主节点恢复后,流量会自动切回主节点
- 调整Nginx Ingress Controller的DaemonSet/Deployment配置与对应Service,添加5432端口的暴露规则,业务侧将数据库访问地址改为Nginx Ingress Controller的Service地址+5432端口即可。
方案2:基于Postgres原生连接串实现客户端侧故障切换
如果允许调整业务侧的数据库连接配置,不需要修改任何K8s资源,直接使用Postgres官方支持的多主机连接串格式即可实现优先连接主节点、故障自动切换的逻辑:
postgresql://<数据库账号>:<数据库密码>@first-ip:5432,second-ip:5432,third-ip:5432/<库名>?target_session_attrs=read-write
该配置下,业务驱动会优先尝试连接第一个IP,连接失败时自动按顺序尝试后续IP,target_session_attrs=read-write参数会自动校验连接的数据库是否为主库可写,避免切到只读备库。该方案的缺点是故障切换逻辑由每个业务客户端独立判断,没有全局统一的流量调度。
注意:你当前使用的普通Service+Endpoints配置,默认只会在节点整体下线时才会移除异常IP,数据库进程崩溃、端口不通等场景不会被kube-proxy及时感知,会出现业务连接报错的问题,不适合直接用于数据库主备访问场景。
内容的提问来源于stack exchange,提问作者Mark

