---
title: "Spegel: Peer-to-Peer Image Distribution for Kubernetes"
description: Every node pulling the same image from Docker Hub separately is slow, wasteful, and risks rate limiting. Spegel fixes this with peer-to-peer image distribution - hands-on walkthrough included.
image: https://hepapi.com/hubfs/spegel-kubernetes-peer-to-peer-image-distribution.webp
---

[Skip to content](https://hepapi.com/blog/spegel-peer-to-peer-image-distribution-for-kubernetes#main-content)

[![hepapi-logo](https://hepapi.com/hubfs/hepapi-logo.svg)](https://hepapi.com/)

- [About Us](https://hepapi.com/about-us)
  
  Show submenu for About Us 
  
    - [Career](https://hepapi.com/career)
- [Services](https://hepapi.com/services)
  
  Show submenu for Services 
  
    - [Cloud Services](https://hepapi.com/cloud-services)
      
      Show submenu for Cloud Services 
      
          - [AWS Lambda](https://hepapi.com/services/aws-lambda)
          - [Amazon Relational Database Service](https://hepapi.com/services/aws-rds)
          - [AWS Elastic Kubernetes Service (EKS)](https://hepapi.com/aws-elastic-kubernetes-service-eks)
          - [AWS WAF](https://hepapi.com/services/aws-waf)
    - [DevOps Services](https://hepapi.com/services/devops)
    - [Enterprise AI Solutions](https://hepapi.com/services/enterprise-ai-solutions)
      
      Show submenu for Enterprise AI Solutions 
      
          - [Sandbox](https://hepapi.com/services/enterprise-ai-solutions/sandbox)
    - [Software QA Services](https://hepapi.com/services/software-qa)
      
      Show submenu for Software QA Services 
      
          - [TMS](https://hepapi.com/partnerships/tms)
    - [Application Modernization](https://hepapi.com/services/application-modernization)
- [Partnerships](https://hepapi.com/partnerships)
  
  Show submenu for Partnerships 
  
    - [AWS](https://hepapi.com/partnerships/aws)
    - [Suse Rancher](https://hepapi.com/partnerships/suse-rancher)
    - [SonarQube](https://hepapi.com/partnerships/sonarqube)
    - [Dynatrace](https://hepapi.com/partnerships/dynatrace)
    - [Testrail](https://hepapi.com/partnerships/testrail)
- Resources
  
  Show submenu for Resources 
  
    - [Knowledge Hub](https://hepapi.github.io/knowledge-hub/)
    - [Blog](https://hepapi.com/blog)

Open main navigation

Close main navigation

- [About Us](https://hepapi.com/about-us)
  
  Show submenu for About Us 
  
    - [Career](https://hepapi.com/career)
- [Services](https://hepapi.com/services)
  
  Show submenu for Services 
  
    - [Cloud Services](https://hepapi.com/cloud-services)
      
      Show submenu for Cloud Services 
      
          - [AWS Lambda](https://hepapi.com/services/aws-lambda)
          - [Amazon Relational Database Service](https://hepapi.com/services/aws-rds)
          - [AWS Elastic Kubernetes Service (EKS)](https://hepapi.com/aws-elastic-kubernetes-service-eks)
          - [AWS WAF](https://hepapi.com/services/aws-waf)
    - [DevOps Services](https://hepapi.com/services/devops)
    - [Enterprise AI Solutions](https://hepapi.com/services/enterprise-ai-solutions)
      
      Show submenu for Enterprise AI Solutions 
      
          - [Sandbox](https://hepapi.com/services/enterprise-ai-solutions/sandbox)
    - [Software QA Services](https://hepapi.com/services/software-qa)
      
      Show submenu for Software QA Services 
      
          - [TMS](https://hepapi.com/partnerships/tms)
    - [Application Modernization](https://hepapi.com/services/application-modernization)
- [Partnerships](https://hepapi.com/partnerships)
  
  Show submenu for Partnerships 
  
    - [AWS](https://hepapi.com/partnerships/aws)
    - [Suse Rancher](https://hepapi.com/partnerships/suse-rancher)
    - [SonarQube](https://hepapi.com/partnerships/sonarqube)
    - [Dynatrace](https://hepapi.com/partnerships/dynatrace)
    - [Testrail](https://hepapi.com/partnerships/testrail)
- Resources
  
  Show submenu for Resources 
  
    - [Knowledge Hub](https://hepapi.github.io/knowledge-hub/)
    - [Blog](https://hepapi.com/blog)
- [Contact us](https://hepapi.com/contact-us)

[Contact us](https://hepapi.com/contact-us)

[All posts](https://hepapi.com/blog/all)

 October 5, 2026

# Spegel: Peer-to-Peer Image Distribution for Kubernetes

![Picture of Erdem Doğanay](https://hepapi.com/hs-fs/hubfs/751055d8-d8e1-4c24-9b24-3ee1424d734a.jpg?width=50&name=751055d8-d8e1-4c24-9b24-3ee1424d734a.jpg)    Erdem Doğanay  ·   3 minute read

Spegel (Swedish for "mirror") is an open-source tool that enables peer-to-peer sharing of container images across Kubernetes nodes.

**Problem:** Normally, each node pulls the necessary image independently from Docker Hub or another registry. If the same image is deployed across 10 nodes, it will be downloaded externally 10 times.

**Solution:** Spegel runs as a DaemonSet on every node and behaves like a local OCI registry. When a node requests an image:

- It first checks the other nodes in the cluster
- If another node already has the image, it retrieves it from that node
- If no node has the image, it falls back to the upstream registry

 

#### Why Use Spegel?

Instead of each node downloading the same image from an external registry, only the first download is required. Subsequent requests can be served by other nodes in the cluster.

Some of the key benefits include:

- Reduced external registry traffic by eliminating repeated image downloads.
- Faster application deployments, especially during rolling updates and cluster autoscaling.
- Lower risk of Docker Hub rate limiting because far fewer requests go to external registries.
- Improved performance in air-gapped or bandwidth-constrained scenarios, allowing images to be distributed across nodes without internet connectivity.
- More efficient onboarding of new nodes, allowing them to retrieve existing images from peers instead of downloading everything again.
- Better bandwidth utilization by keeping image transfers inside the cluster whenever possible.

For clusters with frequent deployments or many worker nodes, Spegel can significantly reduce network usage while improving deployment speed and overall resilience.

 

#### Creating the Kind Cluster

```
# kind-config.yaml
apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
containerdConfigPatches:
- |-
  [plugins."io.containerd.grpc.v1.cri".registry]
    config_path = "/etc/containerd/certs.d"
  [plugins."io.containerd.grpc.v1.cri".containerd]
    discard_unpacked_layers = false
  [plugins."io.containerd.metadata.v1.bolt"]
    content_sharing_policy = "isolated"
nodes:
- role: control-plane
- role: worker
```

**Important settings:**

- config\_path - Directory where Spegel writes its mirror configuration
- discard\_unpacked\_layers = false - Required for Spegel to serve image layers to peer nodes
- content\_sharing\_policy = "isolated" - Ensures that each namespace has its own dedicated content store

```
kind create cluster --config kind-config.yaml
```

 

#### Installing Spegel

```
helm upgrade --create-namespace --namespace spegel \
  --install spegel oci://ghcr.io/spegel-org/helm-charts/spegel \
  --set service.registry.hostPort=30021 \
  --set spegel.logLevel=debug
```

*Note: service.registry.hostPort=30021 - In a Kind environment, this ensures that the hostPort matches the nodePort. Without it, the generated containerd mirror configuration contains an incorrect port.*

Verify that the pods are running. You should see one pod on each node:

```
kubectl get pods -n spegel -o wide --watch
```

**Expected output:**

```
NAME           READY   STATUS    NODE
spegel-xxxxx   1/1     Running   kind-spegel-demo-control-plane
spegel-yyyyy   1/1     Running   kind-spegel-demo-worker
```

 

#### Configuration Verification

When Spegel is installed, it creates /etc/containerd/certs.d/\_default/hosts.toml on every node. This file instructs containerd to send all registry requests to Spegel first.

```
docker exec kind-worker cat /etc/containerd/certs.d/_default/hosts.toml
```

**Expected output:**

```
[host.'http://192.168.97.3:30021']
capabilities = ['pull', 'resolve']
dial_timeout = '200ms'
```

**Testing Access to Spegel**

```
docker exec kind-worker curl -v http://192.168.97.3:30021/v2/
```

You should receive HTTP/1.1 200 OK.

 

#### Pointing hosts.toml to the Control Plane

First, retrieve the node IP addresses:

```
kubectl get nodes -o wide
```

Then update the worker's hosts.toml to point to the control-plane IP (replace 192.168.97.2 with your own control-plane IP):

```
docker exec kind-worker bash -c 'cat > /etc/containerd/certs.d/_default/hosts.toml << EOF
[host."http://192.168.97.2:30021"]
  capabilities = ["pull", "resolve"]
  dial_timeout = "5s"
  response_header_timeout = "5s"
EOF'
```

Restart containerd:

```
docker exec kind-worker systemctl restart containerd
sleep 5
```

 

#### Prepare the Demo Environment

**Step 1: Pull the image onto the control-plane**

```
docker exec kind-control-plane crictl pull docker.io/library/nginx:1.27.4
```

**Step 2: Create a tag that exists only on the control-plane node**

```
docker exec kind-control-plane \
  ctr -n k8s.io images tag \
  docker.io/library/nginx:1.27.4 \
  docker.io/library/nginx-spegel-test:latest
```

**Step 3: Verify that the tag does not exist on the worker**

```
docker exec kind-worker crictl img list | grep nginx-spegel-test
# No output should be returned
```

**Step 4: Monitor the control-plane logs**

```
kubectl logs -n spegel \
  $(kubectl get pod -n spegel -o jsonpath='{.items[?(@.spec.nodeName=="kind-control-plane")].metadata.name}') \
  -c registry -f | jq
```

Check podCIDR assignments:

```
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.podCIDR}{"\n"}{end}'
```

Access the Spegel debug web interface:

```
kubectl --namespace spegel port-forward spegel-cjq69 9090
# Then open: http://localhost:9090/debug/web/
```

**Step 5: Pull the tagged image onto the worker**

```
docker exec kind-worker crictl pull docker.io/library/nginx-spegel-test:latest
```

 

#### Log Analysis

After the pull completes, the Spegel pod running on the control-plane produces the following logs:

```
{
  "path": "/v2/library/nginx-spegel-test/manifests/latest",
  "status": 200,
  "method": "HEAD",
  "ip": "10.244.1.2",
  "handler": "manifest",
  "registry": "docker.io"
}
{
  "path": "/v2/library/nginx-spegel-test/blobs/sha256:16c9c4a8e9...",
  "status": 200,
  "method": "GET",
  "latency": "47.574305ms",
  "ip": "10.244.0.1",
  "handler": "blob",
  "registry": "docker.io"
}
```

**How do we interpret these logs?**

These logs show that the image request came from the worker node and that the Spegel instance on the control plane handled it successfully.

- ip (10.244.x.x) - The request originated from the worker node.
- handler (manifest / blob) - Spegel served both the image manifest and the image layers.
- status (200) - The request was completed successfully.
- registry (docker.io) - The image belongs to the Docker Hub registry.

**Conclusion:** The worker node pulled nginx-spegel-test:latest directly from the Spegel instance on the control plane instead of Docker Hub. No request was sent to Docker Hub.

```
Worker Node
  └── crictl pull nginx-spegel-test:latest
        └── containerd
              └── hosts.toml → Redirect to the Spegel endpoint (192.168.97.2:30021)
                    └── Spegel (control-plane) → served the manifest and blobs
                          (No request was sent to Docker Hub)
```

Share: [facebook-f icon](http://www.facebook.com/share.php?u=https://hepapi.com/blog/spegel-peer-to-peer-image-distribution-for-kubernetes) [linkedin-in icon](http://www.linkedin.com/shareArticle?mini=true&url=https://hepapi.com/blog/spegel-peer-to-peer-image-distribution-for-kubernetes) [twitter icon](https://twitter.com/intent/tweet?url=https://hepapi.com/blog/spegel-peer-to-peer-image-distribution-for-kubernetes) [envelope icon](mailto:?body=https://hepapi.com/blog/spegel-peer-to-peer-image-distribution-for-kubernetes)

[![hepapi-logo-light](https://hepapi.com/hubfs/hepapi-logo-light.svg "hepapi-logo-light")](https://hepapi.com/)

[![telcoset-group-company](https://hepapi.com/hs-fs/hubfs/telcoset-group-company.png?width=120&height=36&name=telcoset-group-company.png "telcoset-group-company")](https://telcoset.com.tr/)

Transforming Enterprises with Innovative DevOps, QA, and AI Solutions

[linkedin-in icon](https://www.linkedin.com/company/hepapi) [Follow us on Facebook](mailto:info@hepapi.com)

**Company**

[About](https://hepapi.com/about-us)[Career](https://hepapi.com/career)

[Services](https://hepapi.com/services)

[Partnerships](https://hepapi.com/partnerships)

[Contact Us](https://hepapi.com/contact-us)

[Privacy Policy](https://hepapi.com/privacy-policy)  
[Cookie Policy](https://hepapi.com/cookie-policy)

[Terms & Conditions](https://hepapi.com/terms-and-conditions)

**Resources**

[Blog](https://hepapi.com/blog)

[Knowledge Hub](https://hepapi.github.io/knowledge-hub/)

 

Copyright © 2026, Hepapi Software LTD.

```json
{
  "@context" : "https://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Erdem Doğanay",
    "url" : "https://hepapi.com/blog/author/erdem-doğanay"
  },
  "dateModified" : "2026-10-05T09:21:45.143Z",
  "datePublished" : "2026-10-05T09:21:45.000Z",
  "headline" : "Spegel: Peer-to-Peer Image Distribution for Kubernetes",
  "image" : [ "https://hepapi.com/hubfs/spegel-kubernetes-peer-to-peer-image-distribution.webp" ],
  "mainEntityOfPage" : {
    "@id" : "https://hepapi.com/blog/spegel-peer-to-peer-image-distribution-for-kubernetes",
    "@type" : "WebPage"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "url" : "https://hepapi.com/hubfs/hepapi-logo.svg"
    },
    "name" : "Hepapi Teknoloji Anonim Sirketi"
  }
}
```