如何在GitLab Kubernetes自托管运行器中配置Postgres服务运行Maven集成测试
别担心,完全可以在Kubernetes自托管GitLab Runner上运行这些Postgres集成测试——只是需要调整一些配置来适配K8s的网络和容器调度逻辑,我给你拆解下解决办法:
先搞懂问题根源
GitLab共享Runner用的是Docker executor,Job容器和Service容器会共享网络栈;但Kubernetes Runner会为每个Job和对应的Service创建独立的Pod,这些Pod在同一个K8s Namespace下,但网络连通性、数据库认证配置的行为会和Docker executor略有不同,这就是你遇到差异的核心原因。
方案1:修复Postgres认证兼容性(最常见的坑)
最新的Postgres镜像默认启用scram-sha-256认证,但和JDK8搭配的旧版JDBC驱动往往不支持这种认证方式,直接导致连接失败。你可以给Postgres服务添加环境变量,强制使用兼容的认证方式:
test: image: maven:3.6.0-jdk-8 services: - name: postgres:latest variables: POSTGRES_DB: postgres POSTGRES_USER: runner POSTGRES_PASSWORD: runner POSTGRES_HOST_AUTH_METHOD: md5 # 新增这行,兼容旧JDBC驱动 stage: verify script: - "mvn $MAVEN_CLI_OPTS --quiet -Dspring.profiles.active=dev clean test"
方案2:确保测试代码用对数据库地址
在Kubernetes Runner中,Service的主机名就是你在services里指定的名称(这里是postgres),绝对不能用localhost——这是和Docker Runner的关键区别。你的Spring dev配置文件里的JDBC URL必须写成:
# application-dev.properties spring.datasource.url=jdbc:postgresql://postgres:5432/postgres spring.datasource.username=runner spring.datasource.password=runner
方案3:检查K8s集群的网络权限
如果上述配置还是不行,就要排查你的K8s Namespace是否有NetworkPolicy规则,阻止了Job Pod和Service Pod之间的流量。需要添加允许5432端口(Postgres默认端口)通信的规则,比如:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-test-postgres namespace: <你的GitLab Runner命名空间> spec: podSelector: matchLabels: <你的Job Pod标签> ingress: - from: - podSelector: matchLabels: app: postgres # 匹配Postgres Service对应的Pod标签 ports: - port: 5432
方案4:替代方案——用集群内持久化Postgres实例
如果你不想每次测试都启动临时Postgres,可以在K8s集群里部署一个专门的测试用Postgres实例(比如用StatefulSet),然后直接连接这个实例的ClusterIP Service:
- 先在K8s里部署Postgres,创建名为
test-postgres的ClusterIP Service - 修改
gitlab-ci.yml去掉services配置,直接传入数据库地址:
test: image: maven:3.6.0-jdk-8 stage: verify script: - "mvn $MAVEN_CLI_OPTS --quiet -Dspring.profiles.active=dev -Dspring.datasource.url=jdbc:postgresql://test-postgres:5432/postgres clean test"
调试小技巧
如果还是有问题,可以在Job的脚本里先加一行测试命令,验证网络连通性:
- psql -h postgres -U runner -d postgres -c "SELECT 1;"
这能快速判断是网络问题还是数据库配置问题。
内容的提问来源于stack exchange,提问作者Noah Martin

