SiamCafe.net Blog
Technology

Libvirt KVM CDN Configuration

libvirt kvm cdn configuration
Libvirt KVM CDN Configuration | SiamCafe Blog
2025-11-02· อ. บอม — SiamCafe.net· 11,233 คำ

KVM CDN

Libvirt KVM CDN Configuration VM Provisioning Nginx Cache Reverse Proxy Edge Server GeoDNS Origin SSL Let's Encrypt Static Dynamic Content Delivery

CDN TypeTechnologyCostControlPerformanceเหมาะกับ
DIY (KVM+Nginx)Self-managedต่ำ (VM cost)เต็มที่ดีมากCustom needs
CloudflareManagedฟรี-$$$ปานกลางดีมากทั่วไป
CloudFrontAWS ManagedPay-per-useสูงดีมากAWS ecosystem
BunnyCDNManagedถูกมากปานกลางดีBudget friendly
Varnish+KVMSelf-managedต่ำเต็มที่ดีมากHigh traffic

KVM VM Setup

# === Libvirt KVM — Create Edge Cache VM ===

# Create VM with virt-install
# virt-install \
# --name edge-cache-sgp \
# --ram 4096 \
# --vcpus 2 \
# --disk path=/var/lib/libvirt/images/edge-sgp.qcow2, size=100 \
# --os-variant ubuntu22.04 \
# --network bridge=br0 \
# --graphics none \
# --console pty, target_type=serial \
# --location http://archive.ubuntu.com/ubuntu/dists/jammy/main/installer-amd64/ \
# --extra-args 'console=ttyS0,115200n8 serial'

# virsh commands
# virsh list --all # List all VMs
# virsh start edge-cache-sgp # Start VM
# virsh shutdown edge-cache-sgp # Graceful shutdown
# virsh snapshot-create-as edge-cache-sgp snap1 "Before config"
# virsh snapshot-list edge-cache-sgp
# virsh dominfo edge-cache-sgp # VM info

# Clone VM for other regions
# virt-clone \
# --original edge-cache-sgp \
# --name edge-cache-tok \
# --file /var/lib/libvirt/images/edge-tok.qcow2

# Network — Bridge Configuration
# cat /etc/netplan/01-bridge.yaml
# network:
# version: 2
# ethernets:
# ens3:
# dhcp4: false
# bridges:
# br0:
# interfaces: [ens3]
# addresses: [10.0.1.10/24]
# gateway4: 10.0.1.1
# nameservers:
# addresses: [8.8.8.8, 1.1.1.1]

from dataclasses import dataclass

@dataclass
class EdgeNode:
 name: str
 region: str
 ip: str
 vcpu: int
 ram_gb: int
 disk_gb: int
 status: str

nodes = [
 EdgeNode("edge-sgp", "Singapore", "103.x.x.10", 2, 4, 100, "Running"),
 EdgeNode("edge-tok", "Tokyo", "103.x.x.20", 2, 4, 100, "Running"),
 EdgeNode("edge-hkg", "Hong Kong", "103.x.x.30", 2, 4, 100, "Running"),
 EdgeNode("edge-bkk", "Bangkok", "103.x.x.40", 4, 8, 200, "Running"),
 EdgeNode("origin", "Bangkok DC", "10.0.1.100", 8, 16, 500, "Running"),
]

print("=== CDN Edge Nodes ===")
for n in nodes:
 print(f" [{n.name}] Region: {n.region} | IP: {n.ip}")
 print(f" CPU: {n.vcpu} | RAM: {n.ram_gb}GB | Disk: {n.disk_gb}GB | {n.status}")

Nginx Cache Config

# === Nginx CDN Cache Configuration ===

# /etc/nginx/nginx.conf
# proxy_cache_path /var/cache/nginx/cdn
# levels=1:2
# keys_zone=cdn_cache:100m
# max_size=50g
# inactive=7d
# use_temp_path=off;
#
# server {
# listen 443 ssl http2;
# server_name cdn.example.com;
#
# ssl_certificate /etc/letsencrypt/live/cdn.example.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/cdn.example.com/privkey.pem;
#
# # Static content — long cache
# location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2|svg|webp|mp4)$ {
# proxy_pass http://origin-server;
# proxy_cache cdn_cache;
# proxy_cache_valid 200 24h;
# proxy_cache_valid 404 1m;
# proxy_cache_key "$scheme$request_method$host$request_uri";
# proxy_cache_use_stale error timeout updating http_500 http_502;
# add_header X-Cache-Status $upstream_cache_status;
# add_header Cache-Control "public, max-age=86400";
# expires 24h;
# }
#
# # Dynamic content — short cache
# location /api/ {
# proxy_pass http://origin-server;
# proxy_cache cdn_cache;
# proxy_cache_valid 200 5m;
# proxy_cache_key "$scheme$request_method$host$request_uri$args";
# add_header X-Cache-Status $upstream_cache_status;
# }
#
# # Purge endpoint
# location /purge/ {
# allow 10.0.0.0/8;
# deny all;
# proxy_cache_purge cdn_cache "$scheme$request_method$host$uri";
# }
#
# # Health check
# location /health {
# return 200 "OK";
# add_header Content-Type text/plain;
# }
# }

@dataclass
class CacheRule:
 content_type: str
 pattern: str
 ttl: str
 cache_key: str
 stale_serve: bool

rules = [
 CacheRule("Images", "*.jpg *.png *.webp *.svg", "24h", "URI only", True),
 CacheRule("CSS/JS", "*.css *.js *.woff2", "24h (versioned)", "URI + query", True),
 CacheRule("HTML Pages", "*.html", "5m", "URI + cookies", True),
 CacheRule("API Response", "/api/*", "5m", "URI + args", False),
 CacheRule("Video", "*.mp4 *.webm", "7d", "URI only", True),
 CacheRule("No Cache", "/admin/* /auth/*", "0", "N/A", False),
]

print("\n=== Cache Rules ===")
for r in rules:
 stale = "Yes" if r.stale_serve else "No"
 print(f" [{r.content_type}] Pattern: {r.pattern}")
 print(f" TTL: {r.ttl} | Key: {r.cache_key} | Stale: {stale}")

DNS and Operations

# === GeoDNS and CDN Operations ===

# GeoDNS Configuration (PowerDNS / Route53)
# cdn.example.com → Edge by region
# Asia-Pacific → edge-sgp (103.x.x.10)
# Japan → edge-tok (103.x.x.20)
# Thailand → edge-bkk (103.x.x.40)
# Default → edge-sgp

# Health Check Script
# #!/bin/bash
# EDGES=("edge-sgp:103.x.x.10" "edge-tok:103.x.x.20" "edge-bkk:103.x.x.40")
# for edge in ""; do
# name=""
# ip=""
# status=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "https:///health")
# if [ "$status" != "200" ]; then
# echo "ALERT: $name ($ip) is DOWN (status: $status)"
# # Remove from DNS / send alert
# fi
# done

@dataclass
class CDNMetric:
 metric: str
 edge_sgp: str
 edge_tok: str
 edge_bkk: str
 origin: str

metrics = [
 CDNMetric("Cache Hit Rate", "92%", "89%", "95%", "N/A"),
 CDNMetric("Avg Response", "15ms", "18ms", "8ms", "45ms"),
 CDNMetric("Bandwidth", "2.5 Gbps", "1.8 Gbps", "4.2 Gbps", "0.8 Gbps"),
 CDNMetric("Requests/s", "12,000", "8,500", "18,000", "3,200"),
 CDNMetric("Disk Usage", "45/100GB", "38/100GB", "120/200GB", "N/A"),
 CDNMetric("Uptime (30d)", "99.99%", "99.98%", "99.99%", "99.95%"),
]

print("CDN Performance:")
for m in metrics:
 print(f" [{m.metric}]")
 print(f" SGP: {m.edge_sgp} | TOK: {m.edge_tok} | BKK: {m.edge_bkk} | Origin: {m.origin}")

ops_checklist = {
 "SSL Renewal": "certbot renew --deploy-hook 'nginx -s reload'",
 "Cache Purge": "curl -X PURGE https://cdn/purge/path/to/file",
 "Log Rotation": "logrotate /etc/logrotate.d/nginx daily",
 "Disk Monitor": "Alert when cache disk > 80%",
 "Origin Health": "Health check every 10s, failover to backup",
 "Snapshot": "virsh snapshot weekly for each edge VM",
}

print(f"\n\nOperations Checklist:")
for k, v in ops_checklist.items():
 print(f" [{k}]: {v}")

เคล็ดลับ

Libvirt KVM คืออะไร

API Library Virtualization KVM QEMU virsh virt-manager VM สร้าง ลบ Start Snapshot Live Migration Linux Kernel Hardware Virtualization ฟรี

CDN คืออะไร

Content Delivery Network กระจาย Content Edge Server ลด Latency Static Image CSS JS Video Dynamic Edge Computing Nginx Varnish Cloudflare

สร้าง CDN ด้วย KVM อย่างไร

VM Edge Cache แต่ละ Region Nginx Reverse Proxy Cache TTL Origin Server GeoDNS Route SSL Let's Encrypt Health Check Purge API

ตั้งค่า Nginx Cache อย่างไร

proxy_cache_path Disk proxy_cache_key proxy_cache_valid TTL X-Cache-Status HIT MISS proxy_cache_use_stale Origin Down Cache Size Purge

สรุป

Libvirt KVM CDN Configuration VM Edge Cache Nginx Reverse Proxy GeoDNS Origin SSL Cache Hit Rate Static Dynamic Content Delivery Production

📖 บทความที่เกี่ยวข้อง

Libvirt KVM 12 Factor Appอ่านบทความ → MetalLB Load Balancer CDN Configurationอ่านบทความ → Libvirt KVM Database Migrationอ่านบทความ → Libvirt KVM Multi-cloud Strategyอ่านบทความ → Libvirt KVM Code Review Best Practiceอ่านบทความ →

📚 ดูบทความทั้งหมด →