Quarkus部署K8s集群时staging环境错误加载prod配置文件问题
Quarkus在K8s中激活staging profile却读取prod配置的解决方案
问题根因
日志打印Profile staging activated仅代表运行时识别到了QUARKUS_PROFILE环境变量,不代表对应profile的配置文件被成功加载,问题本质是Quarkus的构建时优化机制和本地、K8s运行环境的差异:
- Quarkus默认使用prod profile执行构建(包含jar包、native镜像、容器镜像全场景),构建阶段默认做两类处理:
- 未显式标记为运行时可配置的参数(包括自定义配置项),会直接将构建阶段读取到的prod环境值固化到最终产物中,运行时切换profile无法覆盖这类固化值。
- 构建时默认仅保留prod和内置dev/test profile对应的配置文件,自定义的staging等环境的
application-staging.properties会被排除,不会打入最终镜像。
- 本地运行镜像时如果存在本地代码目录挂载、或者用开发模式启动,能读到全量配置文件,因此staging配置可以正常加载;K8s中运行的是无额外挂载的原生构建镜像,镜像内不存在staging配置文件,对应配置项只能回退到构建时固化的prod值,就会出现日志显示激活staging但实际用prod配置的现象。
- 可直接进入K8s运行中的容器查看内部文件,会发现镜像内不存在
application-staging.properties文件,即可验证该结论。
修复方案
方案1:构建时保留自定义profile配置(推荐,符合一次构建多环境部署原则)
在基础配置application.properties中添加配置,告诉Quarkus构建时保留自定义环境的配置文件,且将自定义配置标记为运行时可覆盖:
# 声明所有运行时需要用到的自定义profile,构建时保留对应配置文件 quarkus.build.additional-profiles=staging,dev # 声明自定义配置前缀为运行时可配置,不做构建时固化 quarkus.config.mapping.runtime-names=xxxx.confluence.private
重新构建镜像后部署,即可正常读取staging环境的配置值。
方案2:通过K8s ConfigMap挂载外部配置
不将环境相关配置打入镜像,把各环境配置存放在K8s ConfigMap中,通过卷挂载到容器的Quarkus配置读取路径(默认/work/config),无需重新构建镜像即可调整配置:
- 创建存储staging配置的ConfigMap:
apiVersion: v1 kind: ConfigMap metadata: name: calendar-service-staging-config data: application-staging.properties: | xxxx.confluence.private.url = http://xxxx-test
- 修改Deployment配置,挂载ConfigMap到容器:
spec: containers: - name: calendar-service image: xxxx:k8s ports: - containerPort: 8080 protocol: TCP env: - name: QUARKUS_PROFILE value: staging volumeMounts: - name: config-volume mountPath: /work/config volumes: - name: config-volume configMap: name: calendar-service-staging-config imagePullSecrets: - name: xxxx
方案3:按环境单独构建镜像(不推荐)
如果不需要多环境复用同一镜像,构建staging环境镜像时直接指定构建profile,构建产物会直接固化staging配置:
./mvnw package -Dquarkus.profile=staging -Dquarkus.container-image.build=true
该方式需要为每个环境单独构建镜像,不符合云原生应用交付最佳实践,仅适合简单场景使用。
内容的提问来源于stack exchange,提问作者SirHawrk
相关产品推荐
相关产品推荐

