使用K8s Ingress对接Knative Service与Contour的问题排查
Knative + Contour环境下K8s Ingress路由404问题解决
问题场景
在POC环境中运行Knative与Contour,当前使用Kubernetes Ingress路由流量。测试转发流量到helloworld Knative服务时:
- 当Ingress配置指向Knative服务关联的
helloService时,请求经contour-internal命名空间的Envoy返回404错误; - 直接路由到
hello-00001这类具体版本的服务时,Ingress可正常工作。
需求:仅通过K8s Ingress路由Knative服务,需理清Contour网络逻辑并解决该问题。
相关配置与日志
Ingress配置
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: knative-hello-ingress annotations: external-dns.alpha.kubernetes.io/hostname: "hello-world.my-domain.com" spec: ingressClassName: "generic-class" rules: - host: "hello-world.my-domain.com" http: paths: - pathType: Prefix path: "/" backend: service: name: hello # 关联Knative服务的Service port: number: 80
K8s服务列表
hello ClusterIP None <none> 80/TCP 5d6h hello-00001 ClusterIP <redacted> <none> 80/TCP,443/TCP 5d6h hello-00001-private ClusterIP <redacted> <none> 80/TCP,443/TCP,9090/TCP,9091/TCP,8022/TCP,8012/TCP 5d6h hello-00002 ClusterIP <redacted> <none> 80/TCP,443/TCP 5d6h hello-00002-private ClusterIP <redacted> <none> 80/TCP,443/TCP,9090/TCP,9091/TCP,8022/TCP,8012/TCP 5d6h
Envoy错误日志
[<timestamp>] "GET / HTTP/1.1" 404 NR 0 0 0 - "<IP redacted>" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36" "<redacted>" "hello-world.my-domain.com" "-"
问题分析
helloService属性:它是Knative自动生成的Headless Service(ClusterIP为None),仅作为不同版本服务(如hello-00001)的DNS服务发现入口,本身不具备流量转发能力,也没有可直接访问的ClusterIP。- Contour路由逻辑:默认情况下,Contour Envoy处理Ingress请求时,会直接尝试访问Service的ClusterIP。对于Headless Service,由于没有ClusterIP,Envoy无法找到有效路由,因此返回404(日志中的
NR代表"No Route")。 - 具体版本服务正常的原因:
hello-00001这类服务是标准ClusterIP Service,有明确的IP地址,Envoy可以直接转发流量到后端。
解决方案
要让Contour正确路由到Knative的Headless Service,需通过注解配置让Contour自动解析Headless Service关联的后端端点:
修改Ingress配置
添加Contour专属注解,启用端点发现与负载均衡:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: knative-hello-ingress annotations: external-dns.alpha.kubernetes.io/hostname: "hello-world.my-domain.com" projectcontour.io/upstream-endpoint-discovery: "true" # 启用Headless Service的端点发现 projectcontour.io/load-balancer: "true" # 对后端端点做负载均衡 spec: ingressClassName: "generic-class" rules: - host: "hello-world.my-domain.com" http: paths: - pathType: Prefix path: "/" backend: service: name: hello port: number: 80
验证步骤
- 应用修改后的Ingress:
kubectl apply -f knative-hello-ingress.yaml - 检查Contour是否成功发现端点:
确认对应Upstream的kubectl get upstream -n contour-internalEndpoints字段已显示有效后端地址。 - 测试请求:
curl hello-world.my-domain.com
注意:该方案要求Contour版本≥v1.18,确保
upstream-endpoint-discovery注解受支持。
内容的提问来源于stack exchange,提问作者i-haidar
相关产品推荐
相关产品推荐

