When a user connects to a website, the physical distance between them and the web hosting server affects the time it takes for the content to appear on the screen. In addition to reducing bandwidth consumption, the globally distributed network of data centers improves web page content delivery speed for users regardless of their location in relation to the main server.
To accomplish this, a caching system stores temporary copies of website files in the proxy server nearest to the user, speeding up the page load time.
But first we going to need some pre-requirements:
- create a directory for hosting our images ex. /home/root2/cdn-images and upload some images in it.

- create kubernetes secret with tls certificates for ingress to make it publicly available
kubectl create secret tls tls-certificate --namespace default --key certificate-key.key --cert cetificate.crt
- Create DNS A record pointing to your server , for ex. cdn.example.com
- Install ingress, you can check the guide here
- Optionally, add caching for ingress:
create manifest configmap.yaml, paste the content below and apply itapiVersion: v1 kind: ConfigMap metadata: name: ingress-nginx-controller namespace: default labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx data: proxy-connect-timeout: "10" proxy-read-timeout: "120" proxy-send-timeout: "120" http-snippet: "proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=static-cache:10m max_size=4g inactive=120m use_temp_path=off;"kubectl apply -f configmap.yaml
Now let’s deploy everything:
* modify externalIPs, change “YOUR public ip” with the actual adress.
apiVersion: v1
kind: ConfigMap
metadata:
name: cdn-config
data:
default.conf: |
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
location / {
proxy_read_timeout 150;
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: cdn
spec:
selector:
matchLabels:
app: cdn
replicas: 1
template:
metadata:
labels:
app: cdn
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: cdn-config
mountPath: /etc/nginx/conf.d/default.conf
subPath: default.conf
- name: cdn-images
mountPath: "/usr/share/nginx/html/"
volumes:
- name: cdn-config
configMap:
name: cdn-config
- name: cdn-images
persistentVolumeClaim:
claimName: cdn-images
---
apiVersion: v1
kind: Service
metadata:
name: cdn
spec:
selector:
app: cdn
ports:
- port: 80
targetPort: 80
externalIPs:
- YOUR public ip
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-cdn
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/proxy-body-size: 8m
nginx.ingress.kubernetes.io/proxy-buffering: "on"
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_cache static-cache;
proxy_cache_valid any 120m;
add_header X-Cache-Status $upstream_cache_status;
spec:
tls:
- hosts:
- cdn.example.com
secretName: tls-certificate
rules:
- host: cdn.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: cdn
port:
number: 80
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: cdn-images
spec:
storageClassName: manual
capacity:
storage: 4Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /home/root2/cdn-images/
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cdn-images
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi
kubectl apply -f cdn.yaml configmap/cdn-config created deployment.apps/cdn created service/cdn created ingress.networking.k8s.io/ingress-cdn created persistentvolume/cdn-images created persistentvolumeclaim/cdn-images created
That’s it, after couple of seconds our deployment is up.

It is accessible and caching

Our cdn.yaml manifest consists of Configmap, Deployment, Service, PersistentVolume, PersistentVolumeClaim.
In Configmap section we create simple default.conf file for nginx
In Deployment we configure VolumeMounts with Volumes where we add our Configmap and PersistentVolumeClaim
Service section to make it accessible
Ingress to make it publicly available, here we also add annotations for proxy caching
PersistentVolume and PersistentVolumeClaim for mounting our cdn-images folder, where we gonna host our images.
