在Kubernetes中通过Traefik Ingress部署Docker Registry后镜像推送失败
在Kubernetes集群使用Traefik作为Ingress Controller部署Docker Registry,发现Traefik默认拦截非GET请求,于是添加了允许所有请求类型的Middleware。测试POST、PATCH请求可正常访问Registry,Docker登录、浏览器查看仓库也正常,但推送镜像时请求始终被Traefik处理,未转发至集群内容器,尝试使用Traefik的IngressRoute后问题依旧。
已配置的Middleware
apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: reg-methods spec: headers: accessControlAllowMethods: - "GET" - "PUT" - "POST" - "PATCH" - "HEAD" - "DELETE" - "OPTIONS"
已配置的Ingress
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: registry-ingress annotations: traefik.ingress.kubernetes.io/router.entrypoints: web traefik.ingress.kubernetes.io/auth-type: basic traefik.ingress.kubernetes.io/proxy-body-size: "0" traefik.ingress.kubernetes.io/buffering: "off" traefik.ingress.kubernetes.io/router.middlewares: default-reg-methods@kubernetescrd spec: rules: - host: registry.my.domain http: paths: - path: / pathType: Prefix backend: service: name: registry-service port: name: registry-port
相关日志
Docker登录日志
172.16.225.8 - - [19/Mar/2023:15:05:39 +0000] "GET /v2/ HTTP/1.1" - - "-" "-" 2680 "-" "-" 0ms 172.16.225.8 - - [19/Mar/2023:15:05:39 +0000] "GET /v2/ HTTP/1.1" - - "-" "-" 2681 "-" "-" 0ms 172.16.225.8 - - [19/Mar/2023:15:05:40 +0000] "GET /v2/ HTTP/1.1" 401 87 "-" "-" 2682 "default-registry-ingress-registry-my-domain@kubernetes" "http://192.168.138.205:5000" 7ms 172.16.225.8 - - [19/Mar/2023:15:05:40 +0000] "GET /v2/ HTTP/1.1" 200 2 "-" "-" 2683 "default-registry-ingress-registry-my-domain@kubernetes" "http://192.168.138.205:5000" 16ms
镜像推送日志
172.16.225.8 - - [19/Mar/2023:15:05:50 +0000] "GET /v2/ HTTP/1.1" - - "-" "-" 2688 "-" "-" 0ms 172.16.225.8 - - [19/Mar/2023:15:05:51 +0000] "HEAD /v2/pg/postgres/blobs/sha256:3e290cb732cdbd2d83459c0e06d4bdf152f5372ab9493c7f52170dce457a5636 HTTP/1.1" - - "-" "-" 2689 "-" "-" 0ms 172.16.225.8 - - [19/Mar/2023:15:05:51 +0000] "HEAD /v2/pg/postgres/blobs/sha256:a6e09efc43e8ce56effd722e9f03250c8269ece949c2736b27d38e0f696bb047 HTTP/1.1" - - "-" "-" 2690 "-" "-" 1ms
解决方案
1. 补全Basic Auth配置
当前Ingress仅指定了auth-type: basic,但缺少认证凭证的来源配置。推送镜像时的PUT/POST请求需要携带认证信息,Traefik找不到凭证会直接拦截请求。
在Ingress的annotations中添加:
traefik.ingress.kubernetes.io/auth-secret: <你的basic-auth-secret名称>
确保该Secret已包含正确的用户名和密码哈希值。
2. 修正Middleware的认知误区
你配置的accessControlAllowMethods是用来设置CORS响应头的,不是用来允许Traefik转发请求方法的。Traefik默认不会拦截非GET请求,之前的拦截现象大概率是认证缺失导致的,而非请求方法限制。
如果不需要CORS支持,直接删除该Middleware;如果需要CORS,需补充accessControlAllowOrigin等必要配置,但这和请求转发无关。
3. 检查Traefik EntryPoint配置
确认Traefik的web EntryPoint静态配置中没有添加method相关的限制规则,比如:
# 错误示例,会限制请求方法 [entryPoints.web] address = ":80" [entryPoints.web.http] [entryPoints.web.http.middlewares] middlewares = ["method-restrict"] [entryPoints.web.http.middlewares.method-restrict.method] allowedMethods = ["GET", "HEAD"]
若存在此类限制,删除后重启Traefik。
4. 启用调试日志定位问题
临时调高Traefik的日志级别到DEBUG,查看请求被拦截的具体原因:
# 修改Traefik Deployment的args args: - --log.level=DEBUG
重启Traefik Pod后,查看日志能获取镜像推送请求的完整处理链路,精准定位拦截点。
5. 验证后端连通性
在集群内部测试Registry Service的可用性,确认PUT/POST请求能正常响应:
curl -X PUT http://registry-service:5000/v2/test/blobs/uploads/ -u <用户名>:<密码>
如果后端响应正常,说明问题出在Traefik配置;如果后端无响应,检查Registry的Deployment和Service是否正常运行。
内容的提问来源于stack exchange,提问作者Juri

