Skaffold Dev 12 Factor App
โดย อ.บอม กิตติทัศน์ | 28/03/2026 | SiamCafe.net Since 1997
Skaffold คืออะไร และแก้ปัญหาอะไร
Skaffold เป็น command-line tool จาก Google ที่ช่วย automate workflow ของ Kubernetes development ปัญหาที่ Skaffold แก้คือ feedback loop ที่ช้าในการพัฒนา Kubernetes application: ทุกครั้งที่แก้ code ต้องรัน docker build, docker push, kubectl apply, รอ pod restart ซึ่งใช้เวลาหลายนาที Skaffold ทำทุกอย่างนี้โดยอัตโนมัติและทำให้เร็วขึ้นมากด้วย file sync
Skaffold release ครั้งแรกโดย Google ในปี 2018 และกลายเป็น CNCF project ในปัจจุบัน ทำงานร่วมกับ builders หลายตัว (Docker, Buildpacks, Bazel, Jib สำหรับ Java) และ deployers หลายตัว (kubectl, Helm, Kustomize)
เนื้อหาเกี่ยวข้อง — Docker Compose V2 Team Productivity
12-Factor App Methodology คืออะไร
12-Factor App เป็น methodology สำหรับสร้าง software-as-a-service app ที่ scale ได้ดี เขียนโดย Adam Wiggins จาก Heroku เหมาะมากสำหรับ containerized applications บน Kubernetes
12 factors สรุปสั้นๆ: I. Codebase: หนึ่ง repo ต่อ app, II. Dependencies: ประกาศ explicit ทุก dependency, III. Config: เก็บ config ใน environment variables, IV. Backing services: ใช้ URL-based service ที่เปลี่ยนได้, V. Build/release/run: แยก stages ชัดเจน, VI. Processes: stateless, share-nothing processes, VII. Port binding: export services via port, VIII. Concurrency: scale ด้วย process model, IX. Disposability: fast startup/graceful shutdown, X. Dev/prod parity: ให้ environments เหมือนกันที่สุด, XI. Logs: stream logs เป็น stdout/stderr, XII. Admin processes: รัน admin tasks เป็น one-off processes
ติดตั้ง Skaffold
# Linux/Mac
curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64
sudo install skaffold /usr/local/bin/
skaffold version
# Windows (Chocolatey)
choco install skaffold
# macOS (Homebrew)
brew install skaffold
# ตรวจสอบ
skaffold version
skaffold.yaml: Configuration File พื้นฐาน
# skaffold.yaml - basic setup
apiVersion: skaffold/v4beta6
kind: Config
metadata:
name: my-app
build:
artifacts:
- image: gcr.io/my-project/my-app
docker:
dockerfile: Dockerfile
buildArgs:
APP_VERSION: "{{.VERSION}}"
sync:
# File sync: copy files ตรงเข้า container ไม่ต้อง rebuild
manual:
- src: "src/**/*.py"
dest: /app/src
- src: "templates/**"
dest: /app/templates
deploy:
kubectl:
manifests:
- k8s/*.yaml
portForward:
- resourceType: service
resourceName: my-app
port: 8000
localPort: 8000
profiles:
- name: dev
patches:
- op: replace
path: /build/artifacts/0/docker/dockerfile
value: Dockerfile.dev
- name: production
deploy:
helm:
releases:
- name: my-app
chartPath: charts/my-app
valuesFiles:
- values-production.yaml
Skaffold Workflow: Dev Loop
# Start dev loop - watch files และ auto-deploy
skaffold dev --profile dev
# ตัวเลือกที่มีประโยชน์
skaffold dev \
--profile dev \
--port-forward \
--cleanup=false \ # ไม่ cleanup resources เมื่อ exit
--tail # stream logs
# Build และ deploy ครั้งเดียว (ไม่ watch)
skaffold run --profile staging
# Debug mode - remote debugging
skaffold debug --profile dev
# Build only
skaffold build -t latest
# Render manifests only
skaffold render --profile production > final-manifests.yaml
12-Factor: Config ใน Environment Variables กับ Kubernetes
Factor III ของ 12-Factor คือ Config ต้องเก็บใน environment variables ไม่ใช่ hard-code ใน code Kubernetes รองรับด้วย ConfigMap และ Secret:
# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: "production"
APP_PORT: "8000"
LOG_LEVEL: "info"
DATABASE_HOST: "postgres-service"
DATABASE_PORT: "5432"
REDIS_HOST: "redis-service"
---
# k8s/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
stringData:
DATABASE_PASSWORD: "supersecretpassword"
SECRET_KEY: "production-secret-key"
API_KEY: "external-api-key"
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
spec:
containers:
- name: my-app
image: gcr.io/my-project/my-app
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: app-secrets
# 12-Factor IX: Disposability - graceful shutdown
lifecycle:
preStop:
exec:
command: ["sleep", "5"]
# 12-Factor IX: fast startup
startupProbe:
httpGet:
path: /health
port: 8000
failureThreshold: 30
periodSeconds: 2
เนื้อหาเกี่ยวข้อง — Ubuntu Server 2026
12-Factor: Logs เป็น Event Stream (Factor XI)
Factor XI กำหนดให้ app log ออกมาเป็น unbuffered stdout/stderr ไม่ควร write log ลง file ใน container เอง Kubernetes จะ collect logs เหล่านี้ผ่าน logging infrastructure:
# Python - 12-Factor logging setup
import logging
import sys
import json
class JSONFormatter(logging.Formatter):
def format(self, record):
log_obj = {
"timestamp": self.formatTime(record),
"level": record.levelname,
"message": record.getMessage(),
"module": record.module,
}
if record.exc_info:
log_obj["exception"] = self.formatException(record.exc_info)
return json.dumps(log_obj, ensure_ascii=False)
# Setup
handler = logging.StreamHandler(sys.stdout) # stdout ไม่ใช่ file
handler.setFormatter(JSONFormatter())
logging.basicConfig(handlers=[handler], level=logging.INFO)
logger = logging.getLogger(__name__)
logger.info("Application started", extra={"version": "1.0.0"})
# FastAPI app ที่ follow 12-Factor logging
from fastapi import FastAPI, Request
import logging, time, uuid
app = FastAPI()
logger = logging.getLogger(__name__)
@app.middleware("http")
async def log_requests(request: Request, call_next):
request_id = str(uuid.uuid4())[:8]
start = time.time()
response = await call_next(request)
duration = (time.time() - start) * 1000
logger.info(
"HTTP request",
extra={
"request_id": request_id,
"method": request.method,
"path": request.url.path,
"status": response.status_code,
"duration_ms": round(duration, 2),
}
)
return response
Skaffold กับ Helm Integration
Skaffold ทำงานร่วมกับ Helm ได้ดีมาก เหมาะสำหรับ production deployment ที่ต้องการ values ต่างกันในแต่ละ environment:
# skaffold.yaml พร้อม Helm
apiVersion: skaffold/v4beta6
kind: Config
build:
artifacts:
- image: my-registry/my-app
deploy:
helm:
releases:
- name: my-app
chartPath: charts/my-app
setValues:
image.repository: my-registry/my-app
image.tag: "{{.IMAGE_TAG}}"
valuesFiles:
- charts/my-app/values.yaml
profiles:
- name: staging
deploy:
helm:
releases:
- name: my-app
setValues:
replicaCount: 2
resources.requests.memory: 256Mi
valuesFiles:
- charts/my-app/values.yaml
- charts/my-app/values-staging.yaml
- name: production
deploy:
helm:
releases:
- name: my-app
setValues:
replicaCount: 5
autoscaling.enabled: true
resources.requests.memory: 512Mi
valuesFiles:
- charts/my-app/values.yaml
- charts/my-app/values-production.yaml
12-Factor: Dev/Prod Parity (Factor X)
Factor X คือ keep development, staging, production as similar as possible Skaffold ช่วยเรื่องนี้ด้วย profile system และ Kubernetes-native dev loop ทำให้ code รันใน environment เดียวกัน (Kubernetes) ตั้งแต่ development
แนวทางปฏิบัติสำหรับ dev/prod parity: ใช้ image เดิมในทุก environment เปลี่ยนแค่ configuration, ใช้ database engine เดียวกัน (ไม่ใช้ SQLite ใน dev กับ PostgreSQL ใน prod), ใช้ backing services เดียวกัน (Redis, Elasticsearch) แม้แต่ในการ dev ท้องถิ่น Kubernetes ด้วย minikube หรือ kind ช่วยเรื่องนี้ได้มาก
Skaffold Pipeline ใน CI/CD
# GitHub Actions กับ Skaffold
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: google-github-actions/setup-gcloud@v2
- name: Configure Docker
run: gcloud auth configure-docker
- name: Install Skaffold
run: |
curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64
sudo install skaffold /usr/local/bin/
- name: Configure kubectl
run: |
gcloud container clusters get-credentials my-cluster \
--zone asia-southeast1-a
- name: Deploy to staging
run: |
skaffold run \
--profile staging \
--tag ${{ github.sha }} \
--default-repo gcr.io/my-project
Skaffold File Sync: เร่งความเร็ว Dev Loop
File sync เป็น feature ที่ทำให้ Skaffold เหมาะมากสำหรับ development เมื่อแก้ไขไฟล์ที่กำหนดไว้ใน sync config Skaffold จะ copy ไฟล์เข้า container โดยตรงโดยไม่ต้อง rebuild image ทำให้ feedback loop จากหลายนาทีลดเหลือไม่กี่วินาที
# skaffold.yaml - sync config
build:
artifacts:
- image: my-app
docker:
dockerfile: Dockerfile
sync:
# Auto sync: ถ้า Dockerfile มี COPY src/ /app/src/
# Skaffold auto-detect sync paths
auto: {}
# หรือกำหนด manual
manual:
- src: "**/*.py"
dest: /app
- src: "static/**/*"
dest: /app/static
- src: "templates/**/*"
dest: /app/templates
# Infer จาก Dockerfile COPY instructions
infer:
- "**/*.py"
FAQ: Skaffold และ 12-Factor App
Q: Skaffold ต่างจาก Tilt อย่างไร?
A: ทั้งคู่แก้ปัญหา Kubernetes dev loop เหมือนกัน Skaffold เป็น Google project มี integration กับ GKE ดีกว่า Tilt มี Tiltfile ที่ยืดหยุ่นกว่าและรองรับ multi-service development ได้ดีกว่า เลือกตาม preference และ ecosystem ของทีม
Q: 12-Factor App ใช้ได้กับทุกภาษาไหม?
A: ใช่ 12-Factor App เป็น language-agnostic methodology ใช้ได้กับ Python, Node.js, Go, Java, Ruby ทุกภาษา หลักการสำคัญคือ design pattern ไม่ใช่ implementation specifics
Q: Skaffold รองรับ local Kubernetes อะไรบ้าง?
A: minikube, kind, k3s/k3d, Docker Desktop Kubernetes, MicroK8s ทุกตัว Skaffold auto-detect environment และปรับ behavior ให้เหมาะสม เช่น ไม่ push image เมื่อใช้ local registry
Skaffold กับ Local Kubernetes Development
การ setup local Kubernetes development environment ที่ดีด้วย Skaffold ต้องเลือก local cluster ที่เหมาะสม minikube เป็นตัวเลือก classic ที่รองรับ addons มากมาย kind (Kubernetes IN Docker) เหมาะมากสำหรับ CI/CD เพราะ boot เร็วมาก k3s/k3d เบาที่สุดและเหมาะสำหรับ resource-constrained environment
# Setup minikube สำหรับ Skaffold dev
minikube start --driver=docker --cpus=4 --memory=8192
minikube addons enable ingress
minikube addons enable metrics-server
# Skaffold auto-detect minikube และใช้ minikube docker daemon
eval $(minikube docker-env)
# รัน Skaffold dev
skaffold dev --profile dev
# Setup kind สำหรับ CI
kind create cluster --name dev-cluster
kubectl cluster-info --context kind-dev-cluster
Skaffold มีฟีเจอร์ skaffold init ที่ช่วย auto-generate skaffold.yaml จาก existing Dockerfiles และ Kubernetes manifests ในโปรเจค ทำให้เริ่มต้นง่ายมาก:
# Auto-generate skaffold.yaml
skaffold init --generate-manifests
# หรือให้ Skaffold analyze repo แล้วสร้าง config
skaffold init \
--XXenableJibInit \
--XXenableBuildpacksInit
12-Factor: Process Model และ Horizontal Scaling
Factor VIII ของ 12-Factor คือ Scale out via the process model หมายความว่า app ควรออกแบบให้ scale โดยการ run multiple processes แทนที่จะ scale up (เพิ่ม resource per instance) Kubernetes HorizontalPodAutoscaler (HPA) ทำ horizontal scaling อัตโนมัติ:
# k8s/hpa.yaml - Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleUp:
stabilizationWindowSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
12-Factor: Disposability (Factor IX) ใน Practice
Disposability หมายถึง processes ควร start ได้เร็วและ shutdown ได้อย่าง graceful ในทางปฏิบัติบน Kubernetes หมายความว่า pod ต้องรับ SIGTERM signal แล้วทำ graceful shutdown ภายใน terminationGracePeriodSeconds และไม่รับ request ใหม่หลังได้รับ SIGTERM
# Python FastAPI - graceful shutdown
import asyncio
import signal
from contextlib import asynccontextmanager
from fastapi import FastAPI
shutdown_event = asyncio.Event()
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
print("Starting up...")
yield
# Shutdown - handle gracefully
print("Shutting down...")
await asyncio.sleep(5) # drain in-flight requests
app = FastAPI(lifespan=lifespan)
# Handle SIGTERM
def handle_sigterm(signum, frame):
print("SIGTERM received, starting graceful shutdown")
shutdown_event.set()
signal.signal(signal.SIGTERM, handle_sigterm)
Skaffold Debugging: Remote Debug ใน Kubernetes Pod
หนึ่งในฟีเจอร์ที่ดีที่สุดของ Skaffold คือ skaffold debug ที่ช่วยให้ debug code ที่รันอยู่ใน Kubernetes pod ได้จาก local IDE:
# รัน debug mode
skaffold debug --profile dev
# Skaffold จะ:
# 1. Build image พร้อม debug support
# 2. Inject debug container ด้วย port forward
# 3. Python: ใช้ debugpy port 5678
# 4. Node.js: ใช้ --inspect port 9229
# 5. Java: ใช้ JDWP port 5005
# Dockerfile.dev - พร้อม debugpy
FROM python:3.12-slim
RUN pip install debugpy uvicorn fastapi
WORKDIR /app
COPY . .
# Debug mode: ใช้ debugpy เป็น wrapper
CMD ["python", "-m", "debugpy",
"--listen", "0.0.0.0:5678",
"--wait-for-client",
"-m", "uvicorn", "main:app",
"--host", "0.0.0.0", "--port", "8000"]
ใน VS Code เพิ่ม launch configuration:
{
"name": "Skaffold Remote Debug",
"type": "python",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}/src",
"remoteRoot": "/app/src"
}
]
}
สรุป Skaffold และ 12-Factor App
Skaffold และ 12-Factor App methodology เป็นเครื่องมือและหลักการที่ส่งเสริมกันอย่างดีเยี่ยม Skaffold ทำให้ inner development loop บน Kubernetes เร็วขึ้นอย่างมีนัยสำคัญ ในขณะที่ 12-Factor App ให้หลักการออกแบบที่ทำให้ application พร้อมสำหรับ cloud-native environment ตั้งแต่วันแรก
ทีม engineering ที่นำ Skaffold มาใช้ร่วมกับ 12-Factor principles จะได้ประโยชน์จาก: development environment ที่ consistent กับ production, feedback loop ที่เร็วขึ้น, deployment pipeline ที่ automated และ reproducible, และ application architecture ที่ scale และ operate ได้ง่ายใน Kubernetes
ดูข้อมูลเพิ่มเติมที่ SiamLanCard และ Siam2R | SiamCafe Book





