0

I'm running docker-registry inside a deployment with ingress setup (nginx-ingress), and I use cloudflare. I started getting issues when trying to push images larger then 1GB if a layer is bit larger then that I just get "Retrying in x", and it begins from 0. Strange enough pushing any layer below that threshold just passes without issue and push succeeds.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
    name: {{ .Values.name }}
    annotations:
        kubernetes.io/ingress.class: nginx
        cert-manager.io/cluster-issuer: {{ .Values.certManager.name }}
        nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
        nginx.ingress.kubernetes.io/ssl-redirect: "false"
        nginx.org/client-max-body-size: "0"
        nginx.ingress.kubernetes.io/proxy-buffering: "off"
        nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
        nginx.ingress.kubernetes.io/proxy_ignore_headers: "X-Accel-Buffering"
        nginx.ingress.kubernetes.io/connection-proxy-header: "keep-alive"
        nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
        nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
        nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
        nginx.ingress.kubernetes.io/proxy-next-upstream-timeout: "600"
        nginx.ingress.kubernetes.io/proxy-next-upstream-tries: "10"
        nginx.ingress.kubernetes.io/proxy-request-buffering: "off"
        nginx.ingress.kubernetes.io/proxy-body-size: "8192m"
        kubernetes.io/tls-acme: 'true'
        nginx.ingress.kubernetes.io/configuration-snippet: |
            more_set_headers "proxy_http_version 1.1";
            more_set_headers "X-Forwarded-For $proxy_add_x_forwarded_for";
            more_set_headers "Host $http_host";
            more_set_headers "Upgrade $http_upgrade";
            more_set_headers "Connection keep-alive";
            more_set_headers "X-Real-IP $remote_addr";
            more_set_headers "X-Forwarded-For $proxy_add_x_forwarded_for";
            more_set_headers "X-Forwarded-Proto: https";
            more_set_headers "X-Forwarded-Ssl on";
           
 
    labels:
        app: {{ .Values.name }}
spec:
    tls:
        - hosts: {{- range  .Values.certificate.dnsNames }}
               - {{ . }}
            {{- end}}
          secretName: {{ .Values.certificate.secretName }}
    rules:
        - host: {{ .Values.certManager.mainHost }}
          http:
              paths:
                  - path: /
                    pathType: Prefix
                    backend:
                        service:
                            name: {{ .Values.service.name }}
                            port:
                                number: {{ .Values.service.port }}

I want to be able to upload any size image as long as storage is available.

Immutable
  • 75
  • 1
  • 7

2 Answers2

2

First, verify you are using nginx-ingress and not ingress-nginx, which uses a different configuration for the body size:

nginx.ingress.kubernetes.io/proxy-body-size: "0"

Next, track down where the connection is getting dropped by checking the proxy and registry logs. This includes cloudflare, the nginx pod, and the registry pod. There's no need to debug all three simultaneously, so figure out which one of these is rejecting the large put requests. If the issue is cloudflare, e.g. if you don't see any logs in your nginx ingress instance or registry containers, then consider pushing directly to your nginx ingress rather than cloudflare. Those logs may also indicate if the issue is based on time rather than size, which would be a different setting to adjust.

And finally, as a workaround if you can't push with one large blob, there is an option to do a chunked blob put to a registry, which breaks the upload up into smaller requests, each of which should be below the proxy limits. Docker by default does a chunked upload but with only a single chunk, and I'm not aware of any way to change it's settings. My own project is regclient, and it can copy images in an OCI layout or exported from the docker engine to a registry. With regclient/regctl working with an exported OCI Layout or docker save output, that could be implemented with the following:

regctl registry login $registry
# when a blob exceeds 500M, push it as 50M chunks, note each chunk is held in ram
regctl registry set --blob-max 500000000 --blob-chunk 50000000 $registry
regctl image import $registry/$repo:$tag $file_tar
BMitch
  • 231,797
  • 42
  • 475
  • 450
  • Do you have some suggestions to test cloudflare ? I'm unable to find anything in logs of registry (with debug mode) and ingress logs (verbose logging) I only see that the invalid authorization context happens as soon as I run `docker push` command. Also I will try your repositry, and let you know if it works later. – Immutable Jan 09 '23 at 17:57
  • 1
    I'm indeed able to confirm that this work ! but I would still like to understand what is causing the issue, and try to fix it. – Immutable Jan 09 '23 at 18:33
  • Also I'm using `ingress-nginx` and I tried setting that `nginx.ingress.kubernetes.io/proxy-body-size: "0"` but it does not solve it for me any suggestions? Also I think I need to contact cloudflare team to see if they can provide me with more logs. – Immutable Jan 09 '23 at 18:43
  • @Immutable If you don't see anything in the logs, that points to cloudflare. If the network permits, try pushing directly to your kubernetes nodes. – BMitch Jan 09 '23 at 19:42
  • I will try when I get home after work and let you know – Immutable Jan 10 '23 at 06:18
  • I can now for sure mark this as solved.. It turns out it was really cloudflare. After I disabled proxy in CF it started working without issues. Can you edit your input to add this as well so I can mark it as correct ? – Immutable Jan 10 '23 at 19:31
0

Blob unknown Error: This error may be returned when a blob is unknown to the registry in a specified repository. This can be returned with a standard get or if a manifest references an unknown layer during upload.

On Failure: Authentication Required

401 Unauthorized
WWW-Authenticate: <scheme> realm="<realm>", ..."
Content-Length: <length>
Content-Type: application/json

{
    "errors": [
        {
            "code": <error code>,
            "message": "<error message>",
            "detail": ...
        },
        ...
    ]
}

The client is not authenticated.

How to authenticate : Registry V1 clients first contact the index to initiate a push or pull. Under the Registry V2 workflow, clients should contact the registry first. If the registry server requires authentication it will return a 401 Unauthorized response with a WWW-Authenticate header detailing how to authenticate to this registry.

Error authorizing context: May be the issue while trying to push an image on a slow broadband connection. It was only 200MB - not quite the 5GB above which suggests this is definitely a timeout problem and not a size problem.

Check the Docker Context and Large Docker Images Cause Authorization Errors #1944 for more information.

Cloudflare side : Also check the output of $ time docker push {your-image}

Seems Cloudflare successfully connected to the origin web server, but the origin did not provide an HTTP response before the default 100 second connection timed out. Try checking troubleshooting Cloudflare 524 timeout error.

Edit :

Check Cloudflare status: There were multiple "DNS delays" and "Cloudflare API service issues" in the past few hours, which might have an effect on your installation.

Also check this Downloads fail for files more than 1Gb if download speed is less than 8MB/sec and it may help to resolve your issue.

No, CloudFlare only offers that kind of customization on Enterprise plans.

Veera Nagireddy
  • 1,656
  • 1
  • 3
  • 12
  • I'm on windows so I cannot use `time` you mentioned, also I'm not suing GCP. – Immutable Jan 08 '23 at 16:56
  • I'm using https://docs.docker.com/registry/ from distribution. Is there any whey to check if Cloudflare is an issue on windows ? – Immutable Jan 08 '23 at 16:57
  • can you provide error screen shots or logs? – Veera Nagireddy Jan 09 '23 at 02:54
  • Yup I mainly get two types of log https://imgur.com/a/0IiYJjZ - blobl unknown and the rror authorizing context – Immutable Jan 09 '23 at 05:32
  • Check token expiration, please go through the [link](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/19867) for more info. – Veera Nagireddy Jan 09 '23 at 07:12
  • I'm not using gitlab registy. I'm using standard docker registy that is in distribution. I just checked documentation for configuration, and seems no such option exists there. – Immutable Jan 09 '23 at 07:50
  • Does not really help me I cannot overwrite that time, and upload stops at around 2m mark so it does not reach 5m token expiry date. Look at answer from @BMitch his thing did the trick, but I would still like to figure out if I can fix this without using regctl. My guess is cloudflare. – Immutable Jan 09 '23 at 18:35
  • Answer edited, please check for more info. – Veera Nagireddy Jan 10 '23 at 06:09
  • I will try when I get home after work and let you know – Immutable Jan 10 '23 at 06:18