Helm部署Druid无法从PostgreSQL注入数据 报驱动类缺失错误
问题场景
参考Apache Druid官方Helm仓库部署指引完成Druid集群部署后,提交index_parallel类型的PostgreSQL数据摄入任务时触发报错,任务配置如下:
{ "type": "index_parallel", "id": "sairam_testing_postgresql_100", "spec": { "dataSchema": { "dataSource": "test-ingestion-postgresql-100", "timestampSpec": { "format": "iso", "column": "created_at" }, "dimensionsSpec": { "dimensions": [ "app_id","user_id" ] } }, "ioConfig": { "type": "index_parallel", "inputSource": { "type": "sql", "database": { "type": "postgresql", "connectorConfig": { "connectURI": "jdbc:postgresql://35.200.128.167:5432/mhere_trans", "user": "postgres@jiovishwam-frp-att-prod-mhere-trans-psql-db-1", "password": "lFRWncdXG4Po0e" } }, "sqls": [ "SELECT app_id ,user_id FROM transactions limit 10" ] } }, "maxNumConcurrentSubTasks": 2, "tuningConfig": { "type": "index_parallel", "partitionsSpec": { "type": "dynamic" } } } }
报错信息如下:
Failed to submit task: Cannot construct instance of org.apache.druid.firehose.PostgresqlFirehoseDatabaseConnector, problem: java.lang.ClassNotFoundException: org.postgresql.Driver at [Source: (org.eclipse.jetty.server.HttpInputOverHTTP); line: 1, column: 969] (through reference chain: org.apache.druid.indexing.common.task.batch.parallel.ParallelIndexSupervisorTask["spec"]->org.apache.druid.indexing.common.task.batch.parallel.ParallelIndexIngestionSpec["ioConfig"]->org.apache.druid.indexing.common.task.batch.parallel.ParallelIndexIOConfig["inputSource"]->org.apache.druid.metadata.input.SqlInputSource["database"])
备注:quickstart模式部署Druid时遇到同类问题,手动将PostgreSQL驱动jar包放入lib目录即可修复,但Helm部署的生产环境无法用该方式持久生效。
根因
官方Druid基础镜像默认未内置PostgreSQL JDBC驱动,Helm部署的分布式集群中,接收任务的Overlord节点、运行任务的MiddleManager/Indexer节点、临时启动的Peon任务进程都需要加载该驱动才能初始化PostgreSQL连接器。手动进入Pod拷贝jar的方式会在Pod重建、新任务Pod调度时失效,不适合生产环境。
生产环境解决方案
方案1:自定义镜像预安装驱动(推荐生产使用,稳定性最高)
- 下载与当前Druid版本、目标PostgreSQL版本兼容的JDBC驱动jar包
- 编写Dockerfile,基于当前部署使用的官方Druid镜像构建自定义版本:
# 替换为实际使用的Druid版本号 FROM apache/druid:28.0.1 # 将本地的PostgreSQL驱动拷贝到Druid的postgresql扩展目录,自动被类路径加载 COPY postgresql-42.6.0.jar /opt/druid/extensions/postgresql-metadata-storage/ - 构建镜像并推送到内部镜像仓库
- 修改Helm部署的values.yaml,将镜像地址替换为自定义镜像地址,重新执行
helm upgrade更新集群即可。
方案2:通过Helm配置初始化容器注入驱动(无需修改镜像)
在自定义values.yaml中添加全组件生效的初始化容器和卷配置,集群启动时自动拉取驱动挂载到所有节点的类路径:
common: extraVolumeMounts: - name: pg-jdbc-driver mountPath: /opt/druid/extensions/postgresql-metadata-storage/postgresql.jar subPath: postgresql.jar extraVolumes: - name: pg-jdbc-driver emptyDir: {} # 全局初始化容器,所有Druid组件Pod启动前都会执行 initContainers: - name: fetch-pg-driver image: busybox:stable command: - sh - -c # 替换为内部可访问的PostgreSQL驱动jar下载地址 - wget -O /tmp/driver/postgresql.jar http://your-internal-file-server/postgresql-42.6.0.jar volumeMounts: - name: pg-jdbc-driver mountPath: /tmp/driver
配置完成后执行helm upgrade更新所有Pod即可生效。
注意事项
- 不要仅给单个组件配置驱动:Overlord接收任务时就会校验连接器类,任务运行阶段的Peon进程也需要加载驱动,必须配置全集群所有组件都能访问到驱动包
- 如果集群本身已经使用PostgreSQL作为元数据库/深度存储,上述配置可直接复用,无需重复操作
- 驱动版本需要同时兼容Druid版本和目标PostgreSQL服务版本,避免出现类冲突、连接异常问题
内容的提问来源于stack exchange,提问作者Sai Ram

