K3s搭配vcluster时,Traefik Ingress无法访问ClusterIP服务
问题场景
在默认安装的K3s环境中使用vcluster,尝试通过Ingress暴露ClusterIP类型服务到公网时遇到异常:
- 执行
curl 172.18.62.21/some_endpoint返回错误页面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /some_endpoint</pre> </body> </html>
- 直接访问ClusterIP端口
curl 10.42.0.39:8080可正常返回服务页面:
<!DOCTYPE html> <html> <head> <title>Hello Kubernetes!</title> <link rel="stylesheet" type="text/css" href="/css/main.css"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300" > </head> <body> <div class="main"> <img src="/images/kubernetes.png"/> <div class="content"> <div id="message"> Hello world! </div> <div id="info"> <table> <tr> <th>namespace:</th> <td>-</td> </tr> <tr> <th>pod:</th> <td>aida-temp-env-aida-api-deployment-c8092f93-f55885d6-zk9sk</td> </tr> <tr> <th>node:</th> <td>- (Linux 5.15.0-60-generic)</td> </tr> </table> </div> <div id="footer"> paulbouwer/hello-kubernetes:1.10.1 (linux/amd64) </div> </div> </div> </body>
kubectl describe ingress输出:
Handling connection for 12042 Name: aida-temp-env-ingress-c8343d74 Labels: <none> Namespace: default Address: 172.18.62.21,172.18.62.22,172.18.62.23 Ingress Class: traefik Default backend: aida-temp-env-aida-api-service-c86c8a2d:80 (10.42.0.39:8080) Rules: Host Path Backends ---- ---- -------- * /some_endpoint aida-temp-env-aida-api-service-c86c8a2d:80 (10.42.0.39:8080) Annotations: <none> Events: <none>
- 相关资源YAML配置:
kind: Secret metadata: name: aida-temp-env-dockerconfig-secret-c845f04c immutable: false stringData: .dockerconfigjson: ***** type: kubernetes.io/dockerconfigjson --- apiVersion: apps/v1 kind: Deployment metadata: name: aida-temp-env-aida-api-deployment-c8092f93 spec: minReadySeconds: 0 progressDeadlineSeconds: 600 replicas: 1 selector: matchLabels: cdk8s.io/metadata.addr: aida-temp-env-aida-api-deployment-c80a799a strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: labels: cdk8s.io/metadata.addr: aida-temp-env-aida-api-deployment-c80a799a spec: automountServiceAccountToken: false containers: - image: paulbouwer/hello-kubernetes:1 imagePullPolicy: Always name: main ports: - containerPort: 8080 resources: limits: cpu: 1500m memory: 2048Mi requests: cpu: 1000m memory: 512Mi securityContext: allowPrivilegeEscalation: false privileged: false readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 2000 dnsPolicy: ClusterFirst imagePullSecrets: - name: aida-temp-env-dockerconfig-secret-c845f04c restartPolicy: Always securityContext: fsGroupChangePolicy: Always runAsNonRoot: true setHostnameAsFQDN: false --- apiVersion: v1 kind: Service metadata: name: aida-temp-env-aida-api-service-c86c8a2d spec: externalIPs: [] ports: - port: 80 targetPort: 8080 selector: cdk8s.io/metadata.addr: aida-temp-env-aida-api-deployment-c80a799a type: ClusterIP --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: aida-temp-env-ingress-c8343d74 spec: defaultBackend: service: name: aida-temp-env-aida-api-service-c86c8a2d port: number: 80 rules: - http: paths: - backend: service: name: aida-temp-env-aida-api-service-c86c8a2d port: number: 80 path: /some_endpoint pathType: Prefix
- 补充信息:
- Traefik日志报错:
level=error msg="Skipping service: no endpoints found" namespace=vcluster-aida-api-pr-112 serviceName=aida-temp-env-aida-api-service-c86c8a2d-x-default-x--bcdba98931 servicePort="&ServiceBackendPort{Name:,Number:80,}" providerName=kubernetes ingress=aida-temp-env-ingress-c8343d74-x-default-x-aida-api-pr-112 - 执行
kubectl get endpoints aida-temp-env-aida-api-service-c86c8a2d-x-default-x--bcdba98931 -n vcluster-aida-api-pr-112输出:aida-temp-env-aida-api-service-c86c8a2d-x-default-x--bcdba98931 10.42.0.39:8080 6h5m
- Traefik日志报错:
问题分析与解决方案
核心问题1:路径转发不匹配
Ingress规则中配置的 path: /some_endpoint 结合 pathType: Prefix,会让Traefik将请求带着/some_endpoint前缀直接转发给后端服务,但后端服务的根路径是/,不存在/some_endpoint接口,因此返回Cannot GET /some_endpoint。
解决办法:添加路径重写
修改Ingress的metadata添加Traefik路径重写注解,同时调整path规则匹配格式:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: aida-temp-env-ingress-c8343d74 annotations: traefik.ingress.kubernetes.io/rewrite-target: /$1 traefik.ingress.kubernetes.io/path-prefix-type: Prefix spec: defaultBackend: service: name: aida-temp-env-aida-api-service-c86c8a2d port: number: 80 rules: - http: paths: - backend: service: name: aida-temp-env-aida-api-service-c86c8a2d port: number: 80 path: /some_endpoint(/|$)(.*) pathType: Prefix
该配置会将/some_endpoint及/some_endpoint/xxx这类路径的前缀去掉,把后续内容转发到后端服务的根路径。
核心问题2:vcluster服务端点同步异常
Traefik日志显示在vcluster命名空间下找不到服务的80端口端点,但实际端点存在且端口为8080——这是因为vcluster同步内部服务到宿主机集群时,服务端口映射未正确同步:内部服务是80端口映射到容器8080,但同步后的端点直接暴露了容器的8080端口,导致Traefik请求服务80端口时找不到对应端点。
解决办法:
- 检查vcluster同步配置:查看vcluster的values.yaml,确认
sync.services配置中端口映射同步规则是否正确,确保服务端口和端点端口匹配。 - 刷新Traefik缓存:执行
kubectl rollout restart deployment traefik -n kube-system,重启Traefik pods以加载最新的端点信息。 - 验证端点关联:执行
kubectl describe service aida-temp-env-aida-api-service-c86c8a2d-x-default-x--bcdba98931 -n vcluster-aida-api-pr-112,确认服务端口和端点端口的映射关系是否正确。
验证步骤
- 应用修改后的Ingress配置:
kubectl apply -f <ingress配置文件路径> - 等待1-2分钟,执行
curl 172.18.62.21/some_endpoint测试访问 - 查看Traefik日志确认是否还有端点错误:
kubectl logs -n kube-system deployment/traefik
内容的提问来源于stack exchange,提问作者PriestOfAdanos
相关产品推荐
相关产品推荐

