K8s部署开启HTTP/2的Spring Boot应用出现NotSslRecordException如何解决
问题排查与解决方案
报错根因
你遇到的io.netty.handler.ssl.NotSslRecordException报错的核心原因是:Nginx Ingress默认会对客户端侧的HTTPS请求做SSL卸载,之后以明文HTTP协议转发到后端服务。而你的Spring Boot服务8443端口开启了SSL校验,无法解析明文HTTP请求,直接抛出非SSL记录异常。你提供的报错内的十六进制内容转ASCII后就是完整的明文HTTP请求,也可以佐证该问题。
可选解决方案
方案1:Ingress到后端走HTTPS(端到端加密场景适用)
该方案保留Spring Boot侧的SSL配置,要求Ingress以HTTPS协议转发请求,只需修改Ingress配置,新增对应注解即可:
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/force-ssl-redirect: "true" # 新增:指定向后端转发使用HTTPS协议 nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" # 新增:开启HTTP/2转发支持 nginx.ingress.kubernetes.io/http2-push-preload: "true" name: example namespace: http2 spec: rules: - host: domain.com http: paths: - backend: # 修正:和实际Service名称保持一致 serviceName: back-http2 servicePort: 8443 path: / tls: - hosts: - domain.com secretName: secret-tls
方案2:统一在Ingress层做SSL卸载(生产更推荐,运维成本更低)
该方案将SSL校验、HTTP/2支持都放在Ingress层处理,后端Spring Boot只需提供普通HTTP服务,是K8s集群下的主流部署方式:
- 修改Spring Boot的application.properties配置:
server.port=8080 # 关闭服务端SSL,由Ingress统一处理 server.ssl.enabled=false # 若Ingress层开启HTTP/2,后端无需单独配置HTTP/2 server.http2.enabled=false # 注释掉冗余的SSL keystore配置 # server.ssl.key-store=classpath:keystore/cert.p12 # server.ssl.key-store-type=PKCS12 # server.ssl.key-store-password=password
- 修改Ingress配置,调整转发端口并开启HTTP/2:
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/force-ssl-redirect: "true" # 开启HTTP/2支持 nginx.ingress.kubernetes.io/http2-push-preload: "true" name: example namespace: http2 spec: rules: - host: domain.com http: paths: - backend: serviceName: back-http2 # 转发到后端HTTP端口 servicePort: 8080 path: / tls: - hosts: - domain.com secretName: secret-tls
如果需要全局开启Ingress的HTTP/2支持,可在Ingress Nginx Controller的ConfigMap中添加配置项http2: "true"。
其他配置修正
- 证书转换时建议补充CA根证书链,避免出现信任问题,调整后的转换命令如下:
openssl pkcs12 -export -in exemple.cert -inkey key.key -certfile exemple.ca-bundle -out cert.p12
- 原Ingress配置中的serviceName为
service-http2,和实际创建的Service名称back-http2不匹配,需要修正为一致的名称。
内容的提问来源于stack exchange,提问作者samy
相关产品推荐
相关产品推荐

