16.8 Infrastructure evolution
บทนี้วางแผนการวิวัฒนาการของ infrastructure ควบคู่กับการแยก service ใน Wave 2-3
สถานะปัจจุบัน
┌─────────────────────┐
│ Internet │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Nginx (reverse │
│ proxy, SSL term) │
└──────────┬──────────┘
│
┌─────────────────────────┼──────────────────────────┐
│ │ │
┌───────▼────────┐ ┌─────────▼─────────┐ ┌─────────▼────────┐
│ vtrc-api │ │ vtrc-web │ │ vtrc-rc-backoffice│
│ (Docker) │ │ (Nginx static) │ │ (Nginx static) │
└───────┬────────┘ └───────────────────┘ └──────────────────┘
│
├──► MariaDB (on-prem)
├──► Redis (on-prem)
├──► cu-central-api (Docker) ← live bridge ผ่าน END_POINT_CENTRALIZE / _AUTH
├──► LDAP / AD
└──► centralize-api (Docker, isolated; caller จาก vtrc-api ยังไม่ยืนยัน)จุดอ่อนของสถานะปัจจุบัน
- ไม่มี monitoring (ดู Volume 13.11)
- ไม่มี log aggregation
- network_mode: host ในบาง container
- ไม่มี health check
- deploy ด้วยมือ (manual docker pull)
- SSL ต่ออายุด้วยมือ
เป้าหมายเมื่อสิ้นสุด modernization
┌─────────────────────────────────┐
│ Cloudflare / CDN │
│ (DDoS protection, WAF, cache) │
└────────────────┬────────────────┘
│
┌────────────────▼────────────────┐
│ Nginx / Caddy (TLS auto-renew) │
│ + rate limit + circuit breaker │
└────────────────┬────────────────┘
│
┌────────────────▼────────────────┐
│ Internal API gateway / │
│ service mesh lite (Traefik) │
└────────────────┬────────────────┘
│
┌──────────────────┬─────────────┼──────────────┬──────────────────┐
│ │ │ │ │
┌──────▼─────┐ ┌───────▼─────┐ ┌────▼─────┐ ┌─────▼──────┐ ┌────────▼─────┐
│ identity │ │ leave │ │ payroll │ │ welfare │ │ document- │
│ service │ │ service │ │ service │ │ service │ │ renderer │
└──────┬─────┘ └─────────────┘ └──────────┘ └────────────┘ └──────────────┘
│
├──► MariaDB (managed หรือ on-prem HA)
├──► Redis (managed หรือ on-prem HA)
├──► event bus (Redis Streams หรือ Kafka)
├──► observability stack (Prometheus, Loki, Tempo)
└──► secret manager (Vault, GCP Secret Manager)ระยะการพัฒนา
ระยะ 1 · Wave 0 (สัปดาห์ที่ 1-2)
เป้าหมาย: ลด Critical risk โดยไม่เปลี่ยน architecture
งาน infrastructure:
- ปิด phpMyAdmin (debt PERF-7)
- ตั้ง uptime monitor (UptimeRobot)
- ตั้ง disk alert ที่ 80%
- backup script + ทดสอบ restore
ระยะ 2 · Wave 1 (เดือนที่ 1-3)
เป้าหมาย: observability พื้นฐาน + CI/CD
2.1 · Centralized logging
deploy Loki + Promtail + Grafana บน VM ใหม่:
# docker-compose.logging.yml
services:
loki:
image: grafana/loki:2.9.0
ports: ['3100:3100']
promtail:
image: grafana/promtail:2.9.0
volumes:
- /var/log:/var/log:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- ./promtail.yml:/etc/promtail/config.yml:ro
grafana:
image: grafana/grafana:10.0.0
ports: ['3001:3000']promtail เก็บ log จาก Docker container และ Nginx ส่งไป Loki ดูใน Grafana
2.2 · Monitoring + alerting
Prometheus + Grafana สำหรับ metric:
services:
prometheus:
image: prom/prometheus:v2.45.0
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
ports: ['9090:9090']
node-exporter:
image: prom/node-exporter:v1.6.0
ports: ['9100:9100']
# ติดตั้ง redis_exporter, mysqld_exporterAlert rule ขั้นต่ำ:
- CPU > 80% นาน 5 นาที
- Disk > 80%
- Service down (scrape fail)
- Error rate > 1%
- Memory > 90%
ส่ง alert ไป LINE Notify หรือ Slack
2.3 · CI/CD สำหรับ 5 repos
Bitbucket Pipelines สำหรับทุก repo (ตอนนี้มีแค่ vtrc-api, vtrc-web):
# bitbucket-pipelines.yml (สำหรับ backend service)
pipelines:
branches:
main:
- step:
name: Lint + Test
services: [docker]
script:
- npm ci
- npm run lint
- npm test
- step:
name: Build image
services: [docker]
script:
- docker build -t $IMAGE_NAME .
- docker push $REGISTRY/$IMAGE_NAME
- step:
name: Deploy to UAT
deployment: uat
trigger: manual
script:
- ssh $UAT_HOST "docker pull $REGISTRY/$IMAGE_NAME && docker-compose up -d"2.4 · Health endpoint ทุก service
app.get('/health', async (req, res) => {
try {
await db.authenticate();
await redis.ping();
res.json({ status: 'ok', db: true, redis: true });
} catch (err) {
res.status(503).json({ status: 'fail', error: err.message });
}
});docker-compose healthcheck:
services:
vtrc-api:
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:8081/health']
interval: 30s
timeout: 10s
retries: 3ระยะ 3 · Wave 2 (เดือนที่ 4-15)
เป้าหมาย: infrastructure สำหรับ multi-service
3.1 · Internal network + service discovery
ปัจจุบัน container คุยกันผ่าน network_mode: host (debt PERF-7) — ไม่ปลอดภัยและทำให้สับสน
เปลี่ยนเป็น Docker network ที่กำหนด:
# docker-compose.yml
networks:
vtrc-net:
driver: bridge
services:
vtrc-api:
networks: [vtrc-net]
# ไม่มี network_mode: host อีก
redis:
networks: [vtrc-net]ใช้ Docker DNS — service อ้างชื่อกันได้โดยตรง (redis:6379, vtrc-api:8081)
3.2 · Service registry (ถ้าจำเป็น)
ถ้าจำนวน service เพิ่มเป็น 5+ ตัว พิจารณาใช้:
- Traefik (recommended) — auto-discover Docker container, ทำ TLS, load balance
- Consul (heavyweight กว่า)
ตัวอย่าง Traefik สำหรับ internal routing:
services:
traefik:
image: traefik:v2.10
command:
- --providers.docker=true
- --providers.docker.exposedbydefault=false
ports: ['80:80', '443:443', '8080:8080']
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro3.3 · Event bus
เมื่อ bounded context เริ่มแยก และต้องการ async communication:
ตัวเลือก:
| ตัวเลือก | ข้อดี | ข้อเสีย |
|---|---|---|
| Redis Streams (recommended) | ใช้ Redis ที่มี, simple, ไม่ต้องการ infra ใหม่ | throughput จำกัด, persistence ไม่ดีเท่า Kafka |
| Kafka | throughput สูง, persistence ดี | infra ซับซ้อน, overkill สำหรับ VTRC |
| RabbitMQ | feature ครบ, message routing | อีก service ต้องดูแล |
ใช้ Redis Streams ก่อน ค่อยพิจารณา Kafka ถ้า volume สูง
3.4 · Secret management
ปัจจุบัน secret อยู่ใน .env บน host — ไม่ดี (debt SEC-3, SEC-4, SEC-11)
ตัวเลือก:
| ตัวเลือก | เหมาะกับ |
|---|---|
| GCP Secret Manager (recommended ถ้ามี GCP) | cloud-native, integrate กับ Bitbucket Pipelines |
| HashiCorp Vault (self-hosted) | on-prem, feature ครบ |
| Docker secrets (basic) | เริ่มต้น, ดีกว่า .env |
3.5 · Database HA
ปัจจุบัน MariaDB บน host เดียว — SPOF
ตัวเลือก:
| ตัวเลือก | เหมาะกับ |
|---|---|
| MariaDB Galera Cluster (3 node) | on-prem, sync replication |
| Cloud SQL / RDS (ถ้าย้าย cloud) | managed, auto-backup |
| Primary-replica (basic) | ลด risk น้อยสุด |
ระยะ 4 · Wave 3 (เดือนที่ 7-21)
4.1 · CDN + WAF
วาง Cloudflare ด้านหน้า:
- DDoS protection
- WAF rule
- Static asset cache
- SSL terminate (ลดภาระ Nginx)
4.2 · Kubernetes (พิจารณ์)
เมื่อ service เพิ่มเป็น 7+ ตัว และทีมพร้อม — พิจารณา K8s
หรือใช้ Docker Swarm ที่เรียนรู้ง่ายกว่า
4.3 · Distributed tracing
ติดตั้ง Tempo (หรือ Jaeger) เพื่อ trace request ข้าม service
ลำดับความสำคัญของ infrastructure debt
| Debt | Priority | Effort | Wave |
|---|---|---|---|
| ไม่มี monitoring | สูงมาก | 1 สัปดาห์ | 0 (or 1 ต้น) |
network_mode: host | สูง | 2-3 วัน | 1 |
| ไม่มี health check | สูง | 1-2 วัน | 1 |
| ไม่มี log aggregation | สูง | 1 สัปดาห์ | 1 |
| SSL ต่ออายุด้วยมือ | ปานกลาง | 1 วัน | 1 |
| CI/CD ไม่ครบ | สูง | 1 สัปดาห์ | 1 |
| ไม่มี secret manager | ปานกลาง | 1 สัปดาห์ | 2 |
| ไม่มี event bus | ปานกลาง | 1 สัปดาห์ | 2 |
| DB ไม่ HA | ปานกลาง | หลายสัปดาห์ | 2 |
| ไม่มี CDN/WAF | ต่ำ | 1 วัน | 3 |
| ไม่มี K8s | ต่ำ | หลายเดือน | 3 (optional) |
ข้อควรระวัง
1. อย่าย้ายของทุกอย่างไป cloud ในครั้งเดียว
VTRC มีข้อมูลประชากรและข้อมูลการเงิน — การย้ายไป cloud อาจมี compliance issue (PDPA, ม.ม. ที่เกี่ยวข้อง) พิจารณา hybrid (เก็บ DB on-prem, compute cloud หรือ cluster)
2. observability ก่อน complexity
อย่าเพิ่ม service mesh / K8s ก่อนทีมจะสามารถ debug บน Docker compose ได้คล่อง
3. แต่ละ infrastructure change ต้องมี rollback
ย้ายจาก Docker Compose → K8s ต้องสามารถ rollback ได้ (เก็บ Compose file ไว้)
สรุป
Infrastructure evolution ค่อย ๆ เป็น:
- Wave 0: แกด Critical + ตั้ง monitor พื้นฐาน
- Wave 1: observability + CI/CD + health check
- Wave 2: multi-service network + event bus + secret manager
- Wave 3: CDN/WAF + (optional) K8s
บทถัดไปจะครอบคลุม risk management ของ modernization ทั้งหมด