4. Ingress与Route基础
在OpenShift中,把集群内部的服务暴露给集群外部的客户端访问,有两条主要路径:一条是Kubernetes原生的Ingress资源,另一条是OpenShift特有的Route资源。理解这两者的关系、Route的三种TLS终止类型,以及HAProxy Ingress Controller如何选择路由,是排查“域名访问不通”“证书不匹配”“路径走错后端”等问题的基础。
Ingress与Route:同一目标的两套API
Ingress是Kubernetes社区定义的资源,它描述“哪个主机名和路径应该转发到哪个Service”,但Ingress本身只是一个声明,真正让它生效的是Ingress Controller。OpenShift默认部署的Ingress Controller基于HAProxy实现,通常运行在openshift-ingress命名空间中,以Deployment形式提供多个副本,并通过一个名为router-default的Service对外暴露80/443端口。
Route是OpenShift在Ingress之前就存在的资源,功能与Ingress高度重叠,但表达能力更强,尤其是TLS终止方式、路径匹配、权重分流等。OpenShift的Ingress Controller同时监听Ingress和Route两类对象:当你创建Ingress时,控制器会把它转换成内部的Route逻辑;当你直接创建Route时,控制器直接使用它。因此,在OpenShift里更推荐直接使用Route,能获得更完整的特性支持。
一个典型的Route定义如下,它把app.example.com的流量转发到web-svc的8080端口:
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: web-route
spec:
host: app.example.com
to:
kind: Service
name: web-svc
port:
targetPort: 8080
tls:
termination: edge
创建后,HAProxy Ingress Controller会为该主机名生成对应的前端(frontend)和后端(backend)配置,并重新加载HAProxy。此时用oc get route web-route可以看到HOST/PORT列显示app.example.com,ADMITTED为True表示已被控制器接受。
Route的三种TLS终止类型
Route的spec.tls.termination字段决定TLS在链路的哪一段被处理,这是最容易混淆也最影响证书配置的地方。
- edge(边缘终止):客户端到HAProxy之间是HTTPS,HAProxy解密后以HTTP转发给后端Pod。证书配置在Route上,后端不需要证书。这是最常用的方式,适合后端只提供HTTP服务的场景。此时后端Pod看到的请求是明文HTTP,如果需要知道原始协议,可依赖
X-Forwarded-Proto头。 - passthrough(透传):HAProxy不解密,直接把TLS字节流转发给后端Pod,由后端自己完成TLS握手和解密。证书必须配置在后端Pod上,Route上不配置证书。适合后端必须自己处理TLS的场景,例如需要端到端加密或后端使用SNI做多租户路由。此时HAProxy无法读取HTTP层信息,基于路径的路由和HTTP头改写都不可用。
- re-encrypt(重新加密):客户端到HAProxy是HTTPS,HAProxy解密后再用另一套证书重新加密转发给后端。Route上配置前端证书,同时通过
destinationCACertificate指定后端证书的CA,用于校验后端。适合既要在边缘做统一入口,又要求集群内网段也加密的场景。
三者的链路差异可以用下面的信号链图表示,注意TLS终止点的位置不同,证书的放置位置也随之不同。
HAProxy Ingress Controller的工作方式
控制器持续watch Ingress、Route、Service、EndpointSlice和Secret等对象。当发现变化时,它把当前所有路由规则渲染成一份HAProxy配置文件,写入Pod内的/var/lib/haproxy/conf/haproxy.config,然后触发HAProxy平滑重载。每个Route对应一个frontend(按主机名和路径匹配)和一个backend(指向Service的Endpoints)。
默认情况下,控制器使用共享的VIP和端口,通过SNI和Host头区分不同Route。如果某个Route需要独立IP,可以设置spec.host之外再配合oc expose或自定义Service,但大多数场景共享入口即可。
控制器的健康状态可通过以下命令观察:
oc get pods -n openshift-ingress
oc logs -n openshift-ingress deploy/router-default --tail=50
oc get route -A -o wide
如果Route创建后ADMITTED为False,通常是因为主机名与已有Route冲突,或证书Secret不存在。日志中会出现host already used或secret not found之类的提示。
路由选择与优先级
当多个Route声明了相同的主机名时,HAProxy Ingress Controller需要决定用哪一个。选择顺序大致如下:
- 先比较主机名,精确匹配优先于通配符匹配。例如
app.example.com优先于*.example.com。 - 主机名相同时,比较路径长度,路径更长的优先。例如
/api/v1优先于/api。 - 路径也相同时,比较Route的创建时间,更早创建的优先;若时间相同,则按名称字典序。
- 如果Route设置了
spec.alternateBackends和权重,则按权重把流量分摊到多个后端。
路径匹配默认是前缀匹配(PathPrefix),即/api会匹配/api、/api/v1、/api/v1/users。如果需要精确匹配,可在Ingress中使用pathType: Exact,Route本身不直接暴露该字段,但可通过注解或Ingress转换实现。
一个可复现的验证示例
假设已有Service web-svc监听8080,我们创建两个Route:一个edge终止,一个passthrough,分别用不同主机名,观察证书来源和访问结果。
# edge 路由,证书来自 Secret
oc create route edge web-edge --service=web-svc --host=web-edge.example.com \
--cert=server.crt --key=server.key
# passthrough 路由,证书在后端
oc create route passthrough web-pass --service=web-svc --host=web-pass.example.com
# 查看结果
oc get route web-edge web-pass -o custom-columns=NAME:.metadata.name,HOST:.spec.host,TERM:.spec.tls.termination,ADMITTED:.status.ingress[0].conditions[0].status
预期输出中,web-edge的TERM为edge,ADMITTED为True;web-pass的TERM为passthrough,ADMITTED为True。用curl -k https://web-edge.example.com应能拿到后端响应,且证书是Route上配置的那张;用curl -k https://web-pass.example.com时,证书由后端Pod提供,若后端未配置TLS则会握手失败。这就是判断终止类型是否配置正确的直接依据。
掌握Ingress与Route的对应关系、三种TLS终止的链路差异,以及HAProxy Ingress Controller的选择顺序,就能在遇到域名冲突、证书错误或路径走错后端时,快速定位是资源定义问题还是控制器选择问题。