Solving Docker Hub rate limits in Kubernetes with containerd registry mirrors

When running Kubernetes workloads in AWS EKS (or any other environment), you may encounter the Docker Hub rate limit error:

429 Too Many Requests – Server message: toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading

Why are Docker Hub rate limits a problem? Docker Hub imposes strict pull rate limits: authenticated users up to 40 pulls per hour; anonymous users up to 10 pulls per hour; no pull rate limits for only paid authenticated users

To check your current limit state, you need to get token first:

For anonymous pulls:

TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq -r .token)

For authenticated pulls:

TOKEN=$(curl --user 'username:password' "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq -r .token)

and then make a request to get headers

curl --head -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest

You should see the following headers (excerpt):


date: Sun, 26 Jan 2025 08:17:36 GMT
strict-transport-security: max-age=31536000
ratelimit-limit: 100;w=21600
ratelimit-remaining: 100;w=21600
docker-ratelimit-source: <hidden>

Possible solutions

  • DaemonSets that run predefined configuration of each your k8s node
  • For AWS-based clusters, EC2 Launch Template and it’s user data input
  • For AWS-based clusters, AWS Systems Manager and aws:runShellScript action
  • You can update the config manually, however, in most cases the cluster nodes have a short lifetime due to autoscaler (use the shell script from daemonset below, containerd service restart is not required)

In this guide, we will find out how to define DaemonSets in AWS EKS with containerd (containerd-1.7.11-1.amzn2.0.1.x86_64) and Kubernetes 1.30

  1. Check your containerd config at /etc/containerd/config.toml and make sure that the following is present config_path = "/etc/containerd/certs.d"
  2. Containerd registry host namespace configuration is stored at /etc/containerd/certs.d/hosts.toml
  3. The following manifest adds the required files and folders. Existing and future nodes will be automatically configured with the mirror by the DaemonSet. initContainer is used to update the node’s configuration, wait container is required to keep the DaemonSet active on nodes. Use taints and tolerations, change priority class or other fields to fit your requirements.
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    name: containerd-registry-mirror
    cluster: clustername
    otherlabel: labelvalue
  name: containerd-registry-mirror
spec:
  selector:
    matchLabels:
      name: containerd-registry-mirror
  template:
    metadata:
      labels:
        name: containerd-registry-mirror
    spec:
      nodeSelector:
        eks.amazonaws.com/nodegroup: poolname
      priorityClassName: system-node-critical
      initContainers:
      - image: alpine:3.21
        imagePullPolicy: IfNotPresent
        name: change-hosts-file-init
        command:
          - /bin/sh
          - -c
          - |
            #!/bin/sh
            set -euo pipefail
            TARGET="/etc/containerd/certs.d/docker.io" 
            cat << EOF > $TARGET/hosts.toml
            server = "https://registry-1.docker.io"

            [host."https://<your private registry>"]
              capabilities = ["pull", "resolve"]
            EOF
        resources:
          limits:
            cpu: 100m
            memory: 200Mi
          requests:
            cpu: 50m
            memory: 100Mi
        volumeMounts:
        - mountPath: /etc/containerd/certs.d/docker.io/
          name: docker-mirror
      containers:
      - name: wait
        image: registry.k8s.io/pause:3.9
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            cpu: 50m
            memory: 100Mi
          requests:
            cpu: 10m
            memory: 20Mi
      volumes:
      - name: docker-mirror
        hostPath:
          path: /etc/containerd/certs.d/docker.io/

5. Apply the manifest to your cluster:kubectl apply -f containerd-registry-mirror.yaml , and then monitor the DaemonSet status kubectl get daemonset containerd-registry-mirror -n kube-system

6. To double-check, ssh to the node and get the content of /etc/containerd/certs.d/docker.io/hosts.toml

7. If you need to setup default mirror for ALL registries, use the following path /etc/containerd/certs.d/_default/hosts.toml

Hope it’s helpful for someone faced with the same issue.

Got questions or need help? Drop a comment or share your experience

Have a smooth containerization!

Technical Review: Amazon Web Services in Action, Third Edition

Amazon Web Services (AWS) is a comprehensive and widely adopted cloud computing platform provided by Amazon.com. Launched in 2006, AWS offers a vast array of cloud services to help individuals, businesses, and organizations build and deploy applications, store data, and manage their IT infrastructure more efficiently. Moreover, AWS is the longest-running Magic Quadrant Leader, with Gartner naming AWS a Leader for the thirteenth consecutive year.

The full Gartner Report

It’s rare to encounter a DevOps or Cloud engineer who hasn’t engaged with AWS. Even if one specializes in Azure or GCP, familiarity with AWS is almost essential, at least in theory. Personally, having spent over two years working with AWS, I’ve found the platform to be both seamless and captivating.

It’s no wonder that AWS remains a frontrunner in the market. Therefore, it’s crucial to have access to quality learning resources for efficiently mastering AWS. For me, AWS in Action, 3rd edition stands out as the ideal choice.

I have read AWS in Action, 2nd edition and had a privilege to review the 3rd edition in September, 2022. The authors, brothers Andreas Wittig and Michael Wittig are cloud consultants focusing on Amazon Web Services with years of experience, covered all the core services in clear, plain language, including services such as AWS Lambda and CloudFormation.

The book is full of real-world examples and written for mid-level developers and SysOps/DevOps Engineers. The short list of services covered in the book: EC2, CloudFormation, CloudWatch, integration with Jenkins, S3, Glacier, EBS, EFS, RDS, DynamoDB, ECS, Fargate, ElastiCache, Elastic Load Balancing and Simple Queue Service

Click to see the table of contents
  • Part 1: Getting started
  • Chapter 1 What is Amazon Web Services?
  • Chapter 2 A Simple Example: WordPress in Fifteen Minutes

Part 2: Building virtual infrastructure of computers and networking

  • Chapter 3 Using Virtual machines: EC2
  • Chapter 4 Programming Your Infrastructure: The command line, SDKs and CloudFormation
  • Chapter 5 Securing Your System: IAM, security groups and VPC
  • Chapter 6 Automating Operational Tasks with Lambda
  • Part 3: storing data in the cloud
  • Chapter 7 Storing Your Objects: S3 and Glacier
  • Chapter 8 Storing on Hard Drives: EBS and instance store
  • Chapter 9 Sharing Data Volumes Between Machines: EFS
  • Chapter 10 Using a Relational Database Service: RDS
  • Chapter 11 Caching Data in Memory: ElastiCache
  • Chapter 12 Programming for the NoSQL Database Service: DynamoDB
  • Part 4: Architecting on AWS
  • Chapter 13 Achieving High Availability: Availability zones, auto-scaling and CloudWatch
  • Chapter 14 Decoupling Your Infrastructure: Elastic Load Balancing and Simple Queue Service
  • Chapter 15 Automating Deployment
  • Chapter 16 Designing for Fault Tolerance
  • Chapter 17 Scaling up and down: Auto-scaling and CloudWatch
  • Chapter 18 Building Modern Architectures for the Cloud: ECS and Fargate

Pay attention to Part 4: Architecting on AWS. This part will help you prevent outage of your applications running in AWS by implementing right architecture and set of tools. As a result, you will be able to design greenfield environments or plan migrations to AWS.

For DevOps and software engineers, services such as AWS Lambda, CodeDeploy, CloudFormation, HashiCorp’s Packer and integration of some services with Jenkins are also covered. So, you will be ready to automate your deployment after reading the book.

Overall, it’s highly recommended book to purchase. My favorite on AWS and, based on sales, it’s a bestseller in AWS category. Thanks Andreas Wittig and Michael Wittig for fundamental work and keeping the book up-to-date.