Skip to content

How to deploy and configure simple CDN server in Kubernetes

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.

In this tutorial we are going to deploy our own local CDN server for hosting image files.

But first we going to need some pre-requirements:

  1. create a directory for hosting our images ex. /home/root2/cdn-images and upload some images in it.
  2. 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
  3. Create DNS A record pointing to your server , for ex. cdn.example.com
  4. Install ingress, you can check the guide here
  5. Optionally, add caching for ingress:
    create manifest configmap.yaml, paste the content below and apply it

    apiVersion: 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, just copy and paste the manifest below:
* 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

Now let’s take a look on the content of our manifest

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.

 

Published inAutomationKubernetesLinuxNginx