Registry: add rate limiting configuration

What does this MR do?

Registry: add rate limiting configuration

Changelog: added

Related to https://gitlab.com/gitlab-org/container-registry/-/issues/1226+.

Testing

  1. You'll need an accessible Redis instance. You can apply the following:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:latest
        ports:
        - containerPort: 6379
        env:
        - name: REDIS_PASSWORD
          value: YourPassword
        command:
        - sh
        - -c
        - |
          echo "user default on >${REDIS_PASSWORD} ~* +@all allchannels" > /tmp/redis.conf
          redis-server /tmp/redis.conf
---
apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis
  1. Create a secret with the matching password set as REDIS_PASSWORD above
kubectl create secret generic gitlab-registry-redis-password --from-literal=password=YourPassword
  1. Add the following config to your values.yml. You'll need the registry v4.22.0-gitlab or above.
registry:
  image:
    tag: v4.22.0-gitlab
  rateLimiter:
    enabled: true
    limiters:
      - name: global_rate_limit
        description: "Global IP rate limit"
        log_only: false
        match:
          type: IP
        precedence: 10
        limit:
          rate: 1
          period: "second"
          burst: 2
        action:
          warn_threshold: 0.7
          warn_action: "log"
          hard_action: "block"
    
  redis:
    rateLimiting:
      enabled: true
      # host: 'redis'
      host: 'redis.default.svc'
      password:
        enabled: true
        secret: gitlab-registry-redis-password
        key: password
  1. Upgrade your cluster and wait for the registry to start.
  2. Verify you are being rate-limited given the above configuration of 1 request per second, with a burst of 2. The first 3 requests (rate + burst) should pass, but the fourth one should be rate limited:
for i in {0..3}; curl -L -i "https://registry.gl-charts.jaimartin.dev/v2/"
HTTP/2 401
date: Fri, 23 May 2025 17:04:53 GMT
content-type: application/json
content-length: 87
docker-distribution-api-version: registry/2.0
www-authenticate: Bearer realm="https://gitlab.gl-charts.jaimartin.dev/jwt/auth",service="container_registry"
x-content-type-options: nosniff
x-ratelimit-remaining: 1
strict-transport-security: max-age=63072000
referrer-policy: strict-origin-when-cross-origin

{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}
HTTP/2 401
date: Fri, 23 May 2025 17:04:53 GMT
content-type: application/json
content-length: 87
docker-distribution-api-version: registry/2.0
www-authenticate: Bearer realm="https://gitlab.gl-charts.jaimartin.dev/jwt/auth",service="container_registry"
x-content-type-options: nosniff
x-ratelimit-remaining: 0
strict-transport-security: max-age=63072000
referrer-policy: strict-origin-when-cross-origin

{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}
HTTP/2 401
date: Fri, 23 May 2025 17:04:54 GMT
content-type: application/json
content-length: 87
docker-distribution-api-version: registry/2.0
www-authenticate: Bearer realm="https://gitlab.gl-charts.jaimartin.dev/jwt/auth",service="container_registry"
x-content-type-options: nosniff
x-ratelimit-remaining: 1
strict-transport-security: max-age=63072000
referrer-policy: strict-origin-when-cross-origin

{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}
HTTP/2 429
date: Fri, 23 May 2025 17:04:54 GMT
content-type: application/json
content-length: 158
docker-distribution-api-version: registry/2.0
retry-after: 0.068590
x-ratelimit-percentage: 100.00
x-ratelimit-remaining: 0
x-ratelimit-warning: true
strict-transport-security: max-age=63072000
referrer-policy: strict-origin-when-cross-origin

{"errors":[{"code":"TOOMANYREQUESTS","message":"too many requests","detail":{"ip":"10.0.128.172","limit":"ip","remaining":"0","retry_after":"68.589985ms"}}]}

You can also verify the header responses such as x-ratelimit-remaining

Author checklist

For general guidance, please follow our Contributing guide.

Required

For anything in this list which will not be completed, please provide a reason in the MR discussion.

  • Merge Request Title and Description are up to date, accurate, and descriptive.
  • MR targeting the appropriate branch.
  • MR has a green pipeline.
  • Documentation created/updated.
  • Tests added/updated, and test plan for scenarios not covered by automated tests.
  • Equivalent MR/issue for omnibus-gitlab opened.

Reviewers checklist

Edited by Clemens Beck

Merge request reports

Loading
Loading