You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Boot 3.3.9使用CertManager二次更新证书后SSL热重载失效

SSL Bundle热重载首次生效、二次失效问题排查

环境配置

  • Spring Boot版本:3.3.9
  • 证书管理:CertManager生成证书,存储为Kubernetes Secret并挂载到Pod

application.properties配置

#ssl bundle config
spring.ssl.bundle.pem.server.reload-on-update=true
spring.ssl.bundle.pem.server.keystore.certificate=file:/secret/tls.crt
spring.ssl.bundle.pem.server.keystore.private-key=file:/secret/tls.key
spring.ssl.bundle.pem.server.truststore.certificate=file:/secret/ca.crt
server.ssl.bundle=server 

Kubernetes Pod挂载配置

volumeMounts:
  - mountPath: /secret
    name: volume-secret
    readOnly: true 
volumes:
  - name: volume-secret
    projected:
      defaultMode: 420
      sources:
      - secret:
          name: secret-tls-springboot-app

观察到的现象

  • 启动阶段:CertManager签发证书并挂载到/secret目录,应用正常启动。
  • 首次证书更新:Spring Boot SSL热重载功能识别到变更,输出日志:
{"@timestamp":"2025-03-18T16:47:19.008+00:00","classname":"org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer","method":"update","file":"SslConnectorCustomizer.java","line":63,"thread":"ssl-bundle-watcher","level":"DEBUG","component":"springboot-app","message":"SSL Bundle for host _default_ has been updated, reloading SSL configuration","exception":""}
{"@timestamp":"2025-03-18T16:47:19.156+00:00","classname":"org.apache.juli.logging.DirectJDKLog","method":"log","file":"DirectJDKLog.java","line":173,"thread":"ssl-bundle-watcher","level":"INFO","component":"springboot-app","message":"Connector [https-jsse-nio-8443], TLS virtual host [_default_], certificate type [UNDEFINED] configured from keystore [/opt/dockeruser/.keystore] using alias [tomcat] with trust store [null]","exception":""}
  • 第二次证书更新:Spring Boot热重载未识别变更,应用仍使用旧证书,无相关日志输出,ssl-bundle-watcher线程未触发。

问题

为何SSL热重载能识别证书首次变更,却无法识别第二次变更?


可能原因分析

  1. Kubernetes Secret挂载的文件inode未变更:Kubernetes更新Secret时,尤其是使用projected volume的场景,可能通过硬链接替换文件内容而非创建新文件,导致文件inode保持不变。Spring Boot的SSL Bundle监听器默认依赖inode变化检测文件更新,因此第二次变更无法被感知。
  2. Spring Boot监听器缓存逻辑问题:首次重载后,监听器可能缓存了文件的旧状态(如修改时间、inode),未在更新后重置缓存,导致后续变更检查失效。
  3. CertManager Secret更新异常:第二次更新时,CertManager可能未正确更新Secret内容,或Pod挂载的文件未同步到最新版本。

排查与解决建议

  • 验证文件属性变化:在Pod内执行ls -li /secret/tls.crt,对比两次更新前后的inode和修改时间。若inode未变,说明是文件更新机制导致监听器失效。
  • 调整Kubernetes挂载方式:替换projected volume为直接secret volume挂载,避免硬链接更新问题:
volumeMounts:
  - mountPath: /secret
    name: volume-secret
    readOnly: true 
volumes:
  - name: volume-secret
    secret:
      secretName: secret-tls-springboot-app
  • 修改Spring Boot监听策略:尝试监听证书目录而非单个文件,调整配置为:
spring.ssl.bundle.pem.server.keystore.certificate=file:/secret/
spring.ssl.bundle.pem.server.keystore.private-key=file:/secret/
spring.ssl.bundle.pem.server.truststore.certificate=file:/secret/

确保/secret目录下仅包含tls.crttls.keyca.crt三个文件。

  • 升级Spring Boot版本:检查3.3.x版本的已知bug,若存在监听器多次更新失效的问题,升级到3.3.10或更高版本。
  • 手动触发重载:临时解决方案可通过发送POST /actuator/sslbundles/reload请求(需启用actuator)手动触发SSL Bundle重载。

内容的提问来源于stack exchange,提问作者Praveen

火山引擎 最新活动