连接外部 PostgreSQL 失败,提示 SSL is not enabled on the server

问题描述

当 SonarQube 实例配置为使用外部 PostgreSQL 数据库时,SonarQube Pod 无法启动,其日志中会包含类似以下消息:

org.postgresql.util.PSQLException: The server does not support SSL.

或者:

FATAL: no pg_hba.conf entry for host "...", user "...", database "...", SSL on

由于 Web 进程在数据库初始化期间退出,SonarQube UI 始终无法访问。

根本原因

PostgreSQL JDBC driver 默认会在每次新连接时协商 SSL。如果目标 PostgreSQL 禁用了 SSL(或者未配置为接受来自该客户端的 TLS 握手),driver 会以 The server does not support SSL 终止连接,SonarQube Pod 也就无法完成启动。

修复方法是通过在 JDBC URL 中设置 sslmode=disable,明确告诉 JDBC driver 不要尝试使用 SSL。

故障排查

检查 SonarQube Pod 日志:

kubectl -n <NAMESPACE> logs <RELEASE>-sonarqube-xxxxx

如果日志中提到 The server does not support SSLSSL is not enabled on the server,则说明属于该问题。

你也可以从任何能够访问该 PostgreSQL 的主机上,使用 psql 独立确认目标 PostgreSQL 是否接受 SSL:

PGSSLMODE=require psql "host=<PG_HOST> port=<PG_PORT> user=<PG_USER> dbname=<PG_DATABASE>"

如果该命令因 SSL 相关错误而失败,则说明服务器在此连接上不支持 SSL,下面的解决方法适用。

解决方案

在 SonarQube CR 中声明的 JDBC URL 后追加查询参数 sslmode=disable。其他 JDBC 参数(例如 socketTimeout 等)保持不变;sslmode 通过 & 追加:

apiVersion: operator.alaudadevops.io/v1alpha1
kind: Sonarqube
metadata:
  name: <RELEASE>
  namespace: <NAMESPACE>
spec:
  helmValues:
    jdbcOverwrite:
      enable: true
      jdbcSecretName: <PG_SECRET_NAME>
      jdbcUrl: jdbc:postgresql://<PG_HOST>:<PG_PORT>/<PG_DATABASE>?socketTimeout=1500&sslmode=disable
      jdbcUsername: <PG_USER>

引用的 secret 只需要包含密码——有关标准 secret schema,请参见 配置 PostgreSQL 和账户访问凭证。相关的 key 是 jdbc-password

kubectl -n <NAMESPACE> create secret generic <PG_SECRET_NAME> \
  --from-literal=jdbc-password=<PG_PASSWORD>

将更改应用到 CR。operator 会将新的 jdbcUrl 协调到 SonarQube ConfigMap 中;重新创建 SonarQube Pod,以便使用新模式重新建立 JDBC 连接:

kubectl -n <NAMESPACE> rollout restart deployment <RELEASE>-sonarqube

说明

  • 当 SonarQube 和 PostgreSQL 通过受信任的专用网络通信时,禁用 SSL 是合适的。对于数据库流量会跨越不受信任边界的部署,请在 PostgreSQL 端配置 SSL,并在 URL 中不要设置 sslmode(此时 driver 的默认值 prefer 将会成功)。
  • 支持的 sslmode 值遵循标准 libpq 约定(disableallowpreferrequireverify-caverify-full)。请选择与数据库实际 TLS 配置相匹配的值。