如何配置Kubernetes Ingress的TLS passthrough?

来源:AI技术网作者:霓渡头衔:草根站长
导读:本期聚焦于霓渡创作的《如何配置Kubernetes Ingress的TLS passthrough?》,敬请观看详情。还在为Kubernetes集群中某些服务无法在Ingress层终止TLS而烦恼吗?比如需要将TLS连接原样透传到后端Pod,以便后端自行处理证书或支持非HTTP协议。TLS passthrough正是为解决这类需求而生,它基于SNI将加密流量直接转发,Ingress Controller不参与解密。本文从原理出发,一步步演示如何启用Nginx Ingress Controller的passthrough功能、编写Ingress注解、部署测试服务,并对比TLS termination的差异。同时会涵盖常见的坑与生产建议,帮你彻底理清在K8s中实现端到端TLS透传的最佳路径。

Kubernetes Ingress默认的TLS处理方式是在Ingress Controller处终止TLS连接,解密后再将HTTP请求转发给后端Service。这种方式适用于绝大多数Web应用,但在某些特殊场景下,我们需要把TLS流量原封不动地送到后端Pod,由后端自行完成TLS握手和证书处理。例如后端服务本身实现了基于TLS的私有协议、需要验证客户端证书、或者要求端到端加密合规性。这时TLS passthrough就成了唯一的选择。

如何配置Kubernetes Ingress的TLS passthrough?

本篇文章将以最常见的Nginx Ingress Controller为例,深入讲解TLS passthrough的配置方法、工作原理以及生产环境中的注意事项。即使你使用的是Traefik、HAProxy等其他Ingress Controller,其核心概念也是相通的。

一、TLS passthrough与TLS termination的本质区别

要理解TLS passthrough,必须先清楚Ingress Controller处理TLS的两种基本模式:TLS termination(TLS终止)和TLS passthrough(TLS透传)。

在TLS termination模式下,Ingress Controller负责解密所有进入集群的HTTPS流量。它需要持有对应域名的TLS证书和私钥,当客户端发起TLS握手时,Controller作为服务端完成握手,解密出HTTP请求,再以明文HTTP的形式转发给后端的Service。这种模式的好处是:后端应用无需关心TLS细节,可以专注于业务逻辑;同时Ingress层可以统一管理证书、做HTTP路由、修改请求头等。但缺点是:流量在Controller和后端之间是明文传输(通常通过集群内部网络),并且后端无法获取到客户端的原始证书信息(除非Controller额外传递)。

而TLS passthrough则完全绕开了Controller的解密步骤。Controller在接收到TLS ClientHello时,会根据其中的SNI(Server Name Indication)字段判断该连接应该路由到哪个后端Service,然后直接将整个TCP连接(包括TLS握手和数据)原样转发过去。Controller不拥有任何证书,也不解密任何数据,它只做一个四层转发器。后端Service必须自己持有证书并完成TLS握手。这种模式带来了几个显著优势:

  • 端到端加密:从客户端到后端Pod的整条链路上,数据始终保持加密状态,满足严格的安全合规要求。
  • 后端证书控制:后端可以自行管理证书轮换、客户端证书验证等,无需在Ingress层重复配置。
  • 支持非HTTP协议:由于不解析HTTP,任何基于TLS的应用层协议(如gRPC over TLS、数据库代理、私有二进制协议)都可以通过passthrough暴露。

当然,passthrough也有代价:Ingress Controller失去了对HTTP层内容的可见性,无法基于路径、Header等做七层路由,也无法修改请求或响应。因此,是否使用passthrough需要根据具体场景权衡。

二、使用Nginx Ingress Controller启用TLS passthrough

Nginx Ingress Controller从0.22.0版本开始支持TLS passthrough,但默认并不开启。需要满足两个条件:

  1. Controller启动参数中必须添加--enable-ssl-passthrough
  2. Ingress资源上添加注解nginx.ingress.kubernetes.io/ssl-passthrough: "true"

先来看启动参数。如果你使用Helm部署ingress-nginx,可以在values.yaml中设置:

controller:
  extraArgs:
    enable-ssl-passthrough: "true"

如果你使用Deployment直接部署,需要修改部署清单,在容器的args中加入--enable-ssl-passthrough。注意:一旦启用passthrough,Controller会监听一个额外的TCP端口(通常为442,或者通过--ssl-passthrough-proxy-port自定义),所有被标记为passthrough的流量都会进入这个端口处理。同时,controller会为每个passthrough的Ingress创建对应的TCP代理配置。

接下来准备一个后端服务用于测试。这里我们使用一个简单的TCP服务,它会在8443端口监听TLS连接,并返回握手成功后的信息。为了演示方便,我们可以直接用openssl的s_server命令作为Pod的主进程:

apiVersion: v1
kind: Pod
metadata:
  name: tls-backend
  labels:
    app: tls-backend
spec:
  containers:
  - name: ssl-server
    image: alpine/openssl
    command: ["/bin/sh", "-c"]
    args:
    - |
      openssl req -x509 -newkey rsa:2048 -keyout /tmp/key.pem -out /tmp/cert.pem -days 365 -nodes -subj "/CN=tls.ippipp.com"
      openssl s_server -accept 8443 -cert /tmp/cert.pem -key /tmp/key.pem -www
    ports:
    - containerPort: 8443

再创建一个对应的Service:

apiVersion: v1
kind: Service
metadata:
  name: tls-backend-svc
spec:
  selector:
    app: tls-backend
  ports:
  - port: 443
    targetPort: 8443

注意Service的port设为443,这样在Ingress中可以直接引用443端口,语义更清晰。

现在编写Ingress资源,关键点是添加passthrough注解,并指定backend.protocol为HTTPS(可选,但建议明确):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-passthrough-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  rules:
  - host: tls.ippipp.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: tls-backend-svc
            port:
              number: 443

应用以上配置后,Nginx Ingress Controller会为tls.ippipp.com创建一个基于SNI的TCP转发规则。当客户端访问该域名时,TLS握手会直接穿透Controller到达后端Pod,由后端的openssl s_server完成握手。

需要特别强调的是:passthrough模式下,Ingress资源中不能同时配置TLS证书(即spec.tls段),因为Controller不会用到它们。如果配置了,Controller会忽略并可能报错。另外,Ingress Controller必须能够通过SNI识别流量对应的后端,因此客户端请求必须携带正确的SNI,即使用-servername参数或直接使用域名访问。

三、测试验证TLS passthrough是否生效

部署完成后,我们可以使用curl来验证passthrough是否正常工作。假设Controller的外部IP为192.168.1.100,域名tls.ippipp.com解析到该IP(可以在本地hosts文件添加)。执行以下命令:

curl -k -v https://tls.ippipp.com

在输出中,你应该能看到类似这样的信息:

* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
...
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server did not agree to a protocol

如果能看到证书信息,并且证书的CN是tls.ippipp.com(因为后端openssl自签名证书的CN我们指定了该域名),说明TLS握手确实是后端完成的,而不是Ingress Controller。你也可以通过查看后端Pod日志来确认:

kubectl logs tls-backend

日志中会显示来自客户端的连接信息,证明流量到达了后端。

如果测试失败,最常见的错误是502 Bad Gateway。这通常意味着Controller无法正确转发连接或后端没有监听正确端口。检查以下几点:

  • Controller是否真的启用了--enable-ssl-passthrough?可以通过查看Controller Pod的启动命令或日志确认。
  • Ingress注解是否拼写正确?注意注解值必须是字符串"true",且不能有多余空格。
  • Service的targetPort是否指向后端容器实际监听的端口。
  • 后端是否真的支持TLS?如果后端是普通HTTP服务,passthrough会失败,因为后端无法完成TLS握手。
  • 客户端是否发送了正确的SNI?使用curl时可以添加--resolve tls.ippipp.com:443:192.168.1.100来强制指定。

另一个常见问题是:Ingress Controller默认监听的是80和443端口,而passthrough流量可能需要走另一个内部代理端口。实际上,启用passthrough后,Controller会在内部启动一个TCP代理监听在--ssl-passthrough-proxy-port指定的端口(默认442),而外部443端口仍然接收所有流量,Controller根据SNI判断该走HTTP/HTTPS还是passthrough,再将连接转发到内部代理端口。因此,外部端口443必须保持开放,并且流量能够路由到Controller的443端口。

四、生产环境中的注意事项与最佳实践

在生产环境中使用TLS passthrough时,有几个关键点需要牢记。

首先是SNI的唯一性。由于passthrough依赖SNI进行路由,如果多个Ingress使用相同的域名但不同的后端,Controller将无法区分。因此,每个passthrough的Ingress必须使用唯一的域名,且客户端必须发送SNI。不支持不带SNI的TLS连接(例如某些旧客户端或使用IP直连的场景)。

其次是性能影响。passthrough模式下,Controller对每个连接只进行TCP转发,不解析HTTP,因此CPU开销比TLS termination要低。但同时,Controller无法复用HTTP层面的连接管理(如keep-alive优化),后端需要自行处理TCP连接的建立与销毁。在高并发场景下,需要评估后端服务的TCP连接处理能力。

再者是证书管理。由于证书完全由后端管理,Ingress层面无法提供证书自动更新、监控和告警。你需要为每个后端Pod建立独立的证书轮换机制,比如使用cert-manager配合CSI驱动为Pod挂载证书,或者让后端应用直接集成证书管理逻辑。

还要注意与Nginx其他功能的兼容性。开启passthrough后,该Ingress上的很多七层注解会失效,例如nginx.ingress.kubernetes.io/rewrite-targetnginx.ingress.kubernetes.io/auth-url等,因为Controller无法解析HTTP内容。你需要重新设计认证、限流等横切关注点,这些逻辑可能需要下沉到后端应用或改用其他机制。

最后,如果集群中同时存在TLS termination和TLS passthrough的Ingress,它们可以共存,但要注意域名不能冲突。Controller会根据Ingress注解和SNI来决定处理方式,通常建议将passthrough的域名单独规划,避免与常规HTTPS应用混淆。

总结来说,Kubernetes Ingress的TLS passthrough是一项强大但相对小众的功能,它解决了特定场景下端到端加密和非HTTP协议暴露的问题。通过合理配置Nginx Ingress Controller的启动参数和Ingress注解,你可以轻松实现TLS流量的原样透传。但在生产环境中,务必做好SNI规划、后端证书管理和性能测试,才能确保服务稳定可靠。

Kubernetes IngressTLS passthroughSNI修改时间:2026-08-22 13:49:16

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。