โหมดมืด
บทที่ 18 — Deployment (Canary + Blue-Green + Feature Flag + GitOps)
← บทที่ 17: Service Mesh | สารบัญ | บทที่ 19: Polyglot Example →
📖 ศัพท์บทนี้ (อ่านก่อนเริ่ม):
- canary (คะ-แน-รี่ = นกขมิ้น) — มาจาก idiom "canary in the coal mine" (เหมืองถ่านหิน — คนงานเหมืองพานกขมิ้นลงไปเช็คก๊าซพิษก่อนคนเข้า) — ในที่นี้ = "ทดสอบกับ user ส่วนน้อยก่อน"
- progressive delivery — แนวคิดส่ง release แบบค่อยเป็นค่อยไป (ปล่อยให้ user ทีละกลุ่ม + watch metric)
- progressive rollout — action จริงของการปล่อยเป็นขั้น รวมทุก strategy ที่ค่อยเป็นค่อยไป (canary + feature flag + blue-green)
- Feature Flag (ธงเปิด-ปิด feature) — config ที่เปิด/ปิด feature ได้โดยไม่ต้อง deploy ใหม่
- kill switch (สวิตช์ดับฉุกเฉิน) — feature flag พิเศษที่ปิด feature ทันทีเมื่อเกิดปัญหา
- GitOps (กิต-อ๊อปส์) — pattern ที่ใช้ Git เป็น "แหล่งความจริงเดียว" ของ infrastructure: เขียน YAML ใน Git → tool sync เข้า cluster อัตโนมัติ
- Argo CD (อา-โก ซี-ดี) — GitOps controller ของ Intuit (ตอนนี้ CNCF graduated)
- Flux (ฟลักซ์) — GitOps controller ของ Weaveworks (CNCF graduated)
- Kargo (คาร์-โก) — tool promote artifact ข้าม stage (dev → staging → prod)
- immutable infrastructure (infra ที่เปลี่ยนไม่ได้) — ห้าม SSH ไปแก้ pod ที่รันอยู่; ถ้าต้องแก้ ให้ build image ใหม่แล้ว deploy ใหม่
- CNCF (ซี-เอ็น-ซี-เอฟ = Cloud Native Computing Foundation) — องค์กรที่ดูแล open-source project สำคัญ เช่น Kubernetes, Prometheus, Jaeger, Argo CD, Flux — project ที่ "CNCF graduated" หมายถึงผ่านการ review ว่า production-ready และ community แข็งแกร่ง
- shift left (เลื่อนซ้าย) — idiom DevOps: เลื่อน activity ตรวจสอบ ทดสอบ security ให้เกิดเร็วขึ้นใน pipeline (ซ้ายของ pipeline = ใกล้ dev มากขึ้น) — เช่น แทนที่จะ scan security ตอน deploy (ปลาย pipeline) ให้ scan code ตอน dev commit (ต้น pipeline) = shift left
TL;DR: บทนี้ตอบ "deploy หลาย service ต่อวันแบบไม่ทำ user เห็น downtime" — Rolling Update / Blue-Green / Canary (Argo Rollouts + analysis), Feature Flag (OpenFeature CNCF), GitOps (Argo CD + Flux), Kargo multi-stage promotion. ข้ามได้ถ้า: ตั้ง progressive delivery (= ส่ง release แบบค่อยเป็นค่อยไป) + feature flag + GitOps เป็นนิสัย
เมื่ออัพเดต app — ถ้า restart พร้อมกันทุก instance จะเกิด downtime; deployment strategy คือวิธีเปลี่ยนเวอร์ชันโดยไม่หยุดให้ user เห็น แต่ละแบบมี trade-off ระหว่าง ความเร็ว / ความเสี่ยง / resource ที่ใช้ บทนี้สอน 4 strategy หลักและ tooling รอบ ๆ
ใน monolith — deploy 1 ครั้งทั้งแอป ใน microservices — deploy หลาย service / วัน → ต้อง safe + fast + observable
อัพเดต 2026: K8s 1.33 เป็น baseline (Helm chart pin ทุกตัว), Argo CD / Flux = GitOps controller มาตรฐาน, Argo Rollouts + Flagger เป็นมาตรฐาน progressive delivery, OpenFeature (CNCF) กลายเป็น vendor-neutral standard ของ feature flag, Kargo สำหรับ multi-stage promotion, CloudNativePG สำหรับ Postgres on K8s, Strimzi operator สำหรับ Kafka on K8s, RabbitMQ Cluster Operator สำหรับ RabbitMQ
ใช้เวลา 3-4 ชั่วโมง
Part 1: Deployment Strategies
1.1 Rolling Update (default K8s)
text
v1: [pod1] [pod2] [pod3] [pod4]
Step 1: kill pod1 (kill = สั่ง pod หยุดทำงาน), start v2 pod1'
v1: [ ] [pod2] [pod3] [pod4]
v2: [pod1']
Step 2: kill pod2 ...
...
Done:
v2: [pod1'] [pod2'] [pod3'] [pod4']✅ ง่าย, K8s default ❌ ทุก traffic ผสมระหว่าง v1+v2 ระหว่าง rollout — ถ้า v2 buggy ก็เปื้อน
1.2 Blue-Green
Blue-Green รัน 2 เวอร์ชันคู่กัน — Blue (เก่า) รับ traffic จริง 100% ส่วน Green (ใหม่) deploy ไว้ทดสอบเงียบ ๆ พอมั่นใจก็สลับ traffic ไป Green แบบทันที (atomic) ข้อดีคือ rollback เร็วมาก (สลับกลับ) แต่ต้องใช้ resource สองเท่า:
📝 Convention: Blue = production ปัจจุบัน, Green = version ใหม่ที่กำลังทดสอบ · ชื่อสีไม่มีความหมายตรง ๆ — แค่จำว่า "Blue คือเก่า/รัน, Green คือใหม่/รอ" และหลังสลับแล้วบทบาทก็สลับด้วย (Green กลายเป็น production, Blue กลายเป็น standby)
text
v1 (Blue): running, receiving 100% traffic
v2 (Green): deployed, no traffic, test internally
Switch traffic Blue → Green (atomic):
v2 (Green): 100% traffic
v1 (Blue): standby for rollback✅ Instant rollback (switch กลับ) ✅ Test v2 fully ก่อน switch ❌ ต้องใช้ resource × 2
1.3 Canary
Canary ปล่อยเวอร์ชันใหม่ให้ traffic ส่วนน้อยก่อน (เช่น 10%) แล้วเฝ้าดู metric (error rate, latency) ถ้าดีก็ค่อย ๆ เพิ่มสัดส่วนจนครบ — จำกัด "blast radius" ถ้า v2 มีบั๊กก็กระทบแค่ส่วนน้อย แลกกับ rollout ที่ช้ากว่า:
text
v1: 90% traffic
v2: 10% traffic ← canary
↓ monitor metrics (error rate, latency)
↓ ถ้า OK → ค่อย ๆ เพิ่ม %
v2: 25%, 50%, 75%, 100%✅ Limited blast radius ✅ Catch bug ก่อน 100% ❌ Slower rollout (1-24 hr)
1.4 Feature Flag
Feature flag แยก "deploy" ออกจาก "release" — deploy โค้ดใหม่ขึ้นทุก pod แต่ปิด feature ไว้ แล้วค่อยเปิดให้ user ทีละกลุ่มผ่าน config (ไม่ต้อง deploy ใหม่) ข้อดีคือมี kill switch ปิดทันทีได้ และทุก stage ใช้ binary เดียวกัน:
text
v2 deployed ทุก pod แต่ feature ปิด
Toggle feature on 1% user
Monitor
Toggle on 100%✅ Deploy + release แยก (deploy ไม่ release) ✅ Kill switch ทันที ✅ Same binary across stage
Part 2: Implementation
2.1 Rolling Update K8s
วิธี deploy default ของ K8s คือ rolling update — ค่อย ๆ แทน pod เก่าด้วยใหม่ทีละตัว โดยรอ readiness probe ผ่านก่อนค่อย kill ตัวเก่า (maxUnavailable: 0 = ไม่ให้มี downtime) ได้ zero-downtime โดยไม่ต้องใช้ resource สองเท่า:
yaml
apiVersion: apps/v1
kind: Deployment
metadata: { name: orders }
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # extra pod during update
maxUnavailable: 0 # downtime tolerance
template:
spec:
containers:
- name: app
image: orders:v2
readinessProbe:
httpGet: { path: /actuator/health/readiness, port: 8080 }
initialDelaySeconds: 5
periodSeconds: 5K8s wait readiness → ค่อย kill v1 pod
📎 readinessProbe คืออะไร — K8s ใช้เช็คว่า pod พร้อมรับ traffic หรือยัง · ดูรายละเอียดที่ discovery-and-config.md §4
⚠️ Trade-off
maxSurge: 1+maxUnavailable: 0+replicas: 4: ระหว่าง update จะมี 5 pod ชั่วครู่ (4 + 1 extra) → ต้องการ resource headroom บน node · ถ้า node capacity ตึง อาจมี pod pending รอ schedule · ถ้า resource จำกัด ลดmaxSurgeเป็น25%หรือยอมmaxUnavailable: 1แทน
2.2 Blue-Green ด้วย K8s Service
ทำ Blue-Green บน K8s ได้ง่าย ๆ ด้วย label + Service selector — deploy 2 ชุด (blue/green) แล้วให้ Service ชี้ไป color เดียว สลับเวอร์ชันแค่ patch selector ของ Service (atomic) traffic จะย้ายไป green ทันที rollback ก็ patch กลับ:
yaml
# Both deployments
apiVersion: apps/v1
kind: Deployment
metadata: { name: orders-blue }
spec:
selector: { matchLabels: { app: orders, color: blue } }
template: { metadata: { labels: { app: orders, color: blue } } ... }
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: orders-green }
spec:
selector: { matchLabels: { app: orders, color: green } }
template: { metadata: { labels: { app: orders, color: green } } ... }
---
# Service selects blue
apiVersion: v1
kind: Service
metadata: { name: orders }
spec:
selector: { app: orders, color: blue }
ports: [{ port: 8080 }]Switch:
bash
kubectl patch service orders -p '{"spec":{"selector":{"color":"green"}}}'→ atomic switch
2.3 Canary ด้วย Argo Rollouts
💡 Argo Rollouts คืออะไร — เครื่องมือ install แยก (ไม่ได้มากับ K8s) ที่เพิ่มความสามารถ progressive delivery ให้ K8s โดยใช้ CRD (Custom Resource Definition = ประเภท object ใหม่ที่เราสร้างเพิ่มใน K8s) แทน Deployment ปกติ · K8s Deployment ปกติทำ canary แบบ fine-grained (กำหนด % traffic ตาม step) ไม่ได้ Argo Rollouts จึงเข้ามาเติมส่วนนี้
K8s Deployment ปกติทำ canary ไม่ได้ดี — Argo Rollouts เป็น CRD ที่เพิ่มความสามารถนี้: กำหนด step การเพิ่ม % traffic, หยุดรอ (pause) ให้คนดู metric หรือ auto-analyze แล้วเดินหน้า/rollback อัตโนมัติ (ถ้ายังไม่คุ้น K8s Deployment resource พื้นฐาน ดู kubernetes/02-deployments.md ก่อน):
yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata: { name: orders }
spec:
replicas: 10
strategy:
canary:
canaryService: orders-canary
stableService: orders-stable
trafficRouting:
istio:
virtualServices:
- name: orders
routes: [primary]
steps:
- setWeight: 10
- pause: { duration: 5m }
- analysis:
templates:
- templateName: error-rate-check
- setWeight: 25
- pause: { duration: 10m }
- analysis: ...
- setWeight: 50
- pause: { duration: 10m }
- setWeight: 100Analysis template:
yaml
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata: { name: error-rate-check }
spec:
metrics:
- name: error-rate
provider:
prometheus:
address: http://prometheus:9090
# ⚠️ ชื่อ metric ขึ้นกับ stack:
# - Spring Boot / Micrometer: http_server_requests_seconds_count (status label: "status")
# - Generic Prometheus client: http_requests_total
# ⚠️ "service" label = common tag — ไม่ใช่ default Micrometer label
# ต้องเพิ่มเองใน application.yml:
# management.metrics.tags.service=orders
# ตัวอย่างนี้ใช้ Spring Boot (ตรงกับบท observability/02)
query: |
sum(rate(http_server_requests_seconds_count{service="orders-canary",status=~"5.."}[5m]))
/ sum(rate(http_server_requests_seconds_count{service="orders-canary"}[5m]) or vector(1))
successCondition: result < 0.01→ Auto rollback ถ้า error rate > 1%
⚠️ ระวัง traffic = 0 ระหว่าง analysis (canary เพิ่งเริ่ม หรืออยู่ระหว่าง pause step) — ถ้าไม่มี request เข้ามาเลยในช่วง 5 นาทีนั้น ตัวหารจะเป็น 0 → Prometheus คืนค่า no data/NaN แทนที่จะเป็นตัวเลข ซึ่ง
successConditionเทียบกับ NaN ได้ผลไม่แน่นอน (Argo Rollouts อาจ error แทนที่จะ pass/fail ปกติ) — ตัวอย่างข้างบนใส่or vector(1)กันหารด้วยศูนย์ไว้แล้ว แต่ควรพิจารณาเพิ่มเงื่อนไข minimum sample size (เช่นcount() >= N) ก่อนเชื่อผลลัพธ์ด้วย
2.4 Canary ผ่าน Istio
ถ้ามี service mesh อยู่แล้วก็ทำ canary ได้โดยไม่ต้องมี Argo — กำหนด weight ของ traffic ระหว่าง subset v1/v2 ใน VirtualService แล้วค่อย ๆ ปรับสัดส่วนทีละ step ข้อดีคือควบคุม traffic ได้ละเอียดที่ระดับ network:
yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata: { name: orders }
spec:
hosts: [orders]
http:
- route:
- destination: { host: orders, subset: v1 }
weight: 90
- destination: { host: orders, subset: v2 }
weight: 10ปรับ weight ทีละ step
2.5 Feature Flag — OpenFeature standard (CNCF, 2026)
ปัญหา: provider lock-in (LaunchDarkly, Unleash, Flagsmith — แต่ละเจ้า API ต่างกัน)
OpenFeature (CNCF Incubating, 2023) = spec กลาง + SDK ทุกภาษา → swap provider ไม่ต้องแก้ code
java
// pom.xml — เช็ค Maven Central ก่อนใช้ (เวอร์ชันด้านล่างคือ pinned baseline 2026)
// <dependency>dev.openfeature:sdk:1.13.0</dependency>
// <dependency>dev.openfeature.contrib.providers:flagd:0.8.9</dependency>
OpenFeatureAPI.getInstance().setProviderAndWait(new FlagdProvider());
Client client = OpenFeatureAPI.getInstance().getClient();
public void checkout(User user) {
EvaluationContext ctx = new MutableContext(user.id())
.add("country", user.country())
.add("plan", user.plan());
if (client.getBooleanValue("new-payment-flow", false, ctx)) {
newCheckout();
} else {
oldCheckout();
}
}ตัว provider เปลี่ยนได้: flagd (open source), LaunchDarkly, Unleash, ConfigCat, Flagsmith
ตัวอย่าง flagd config (GitOps-friendly, store ใน K8s ConfigMap)
json
{
"flags": {
"new-payment-flow": {
"state": "ENABLED",
"variants": { "on": true, "off": false },
"defaultVariant": "off",
"targeting": {
"if": [
{ "in": [{ "var": "country" }, ["TH", "VN"]] },
"on",
{ "fractional": [
{ "var": "userId" },
[["on", 10], ["off", 90]]
]
}
]
}
}
}
}→ Targeting rule + percentage rollout, อ่านได้ทุก SDK ภาษา
Part 3: Database Migration
3.1 ปัญหา
ระหว่าง rolling update — v1 + v2 รันพร้อมกัน ถ้า v2 ใช้ schema ใหม่ที่ v1 ไม่รู้ → v1 พัง
3.2 Expand-Contract Pattern
เคล็ดลับเปลี่ยน schema โดยไม่ทำ app พังคือทำเป็นขั้น (expand-contract) — ขั้น expand เพิ่มของใหม่แบบเข้ากับของเก่าได้ (add column), ให้ v2 เขียนทั้งเก่า+ใหม่, backfill, แล้วค่อย contract (ลบของเก่า) ทุกขั้น v1 และ v2 ต้องรันร่วมกันได้:
3.3 Tools
มีเครื่องมือช่วยจัดการ migration — Flyway/Liquibase ดูแล versioning ของ schema (รัน migration ตามลำดับ, track ว่ารันถึงไหน) ส่วน gh-ost/pg-online-schema-change ช่วย ALTER ตารางใหญ่โดยไม่ lock:
- Flyway / Liquibase — migration
- gh-ost / pt-online-schema-change — MySQL online schema
- pg-online-schema-change — Postgres
Part 4: GitOps
4.1 หลักการ
GitOps ใช้ Git เป็น "แหล่งความจริงเดียว" ของทั้ง config และ deployment — คนแก้สถานะระบบผ่านการ commit เข้า git แล้วมี controller (Argo CD/Flux) คอยซิงค์ให้ cluster ตรงกับ git เสมอ ได้ audit trail, rollback, drift detection ฟรีจาก git:
"Git = single source of truth ของ infrastructure + deployment"
4.2 Argo CD
Argo CD เป็น GitOps controller ยอดนิยม — นิยาม Application ที่ชี้ไป git repo + path แล้วเปิด automated sync (prune + selfHeal) จากนั้นทุกการเปลี่ยน manifest ใน git จะถูก apply เข้า cluster อัตโนมัติ และ revert การแก้มือที่หลุดจาก git:
yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata: { name: orders }
spec:
source:
repoURL: https://github.com/acme/k8s-config
path: orders
targetRevision: HEAD
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true→ ทุก change ใน k8s-config/orders/*.yaml = auto apply
4.3 Benefits
ประโยชน์ของ GitOps ส่วนใหญ่ได้มาจากการที่ git เป็นแหล่งความจริง — audit trail คือ git history, rollback คือ git revert, multi-cluster คือ folder ต่อ env, และ controller คอย detect/heal drift ให้ ทำให้สถานะระบบโปร่งใสและย้อนกลับได้เสมอ:
- Audit trail = git history
- Rollback = git revert
- Multi-cluster = same git, different env folder
- Drift detection = controller compares
- Self-healing = revert manual change
4.4 Repo Structure
โครงสร้าง repo GitOps ที่นิยมคือแยก base (นิยามร่วม) ออกจาก environments (ค่าเฉพาะ dev/staging/prod) แล้วใช้ Kustomize/Helm overlay ค่าต่าง — แก้ base ทีเดียวมีผลทุก env ส่วนค่าเฉพาะ env แยกชัด ลดการ copy-paste:
text
acme/k8s-config/
├── base/ (shared definitions)
│ ├── orders/
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ └── ...
├── environments/
│ ├── dev/
│ │ └── orders/kustomization.yaml
│ ├── staging/
│ └── production/
└── apps/
└── orders-app.yaml (Argo CD Application)Use Kustomize หรือ Helm เพื่อ template
Part 5: Progressive Delivery
5.1 Tools เทียบกัน
| Argo Rollouts | Flagger | Spinnaker | |
|---|---|---|---|
| Ecosystem | Argo (CNCF graduated) | Flux (CNCF graduated) | Netflix OSS |
| Traffic routing | Istio, NGINX, ALB, SMI, Gateway API | Istio, Linkerd, Contour, Gloo, NGINX, Gateway API | Many |
| Strategy | Canary, BlueGreen | Canary, A/B, BlueGreen, Mirror | All |
| Analysis | Prometheus, Datadog, NewRelic, CloudWatch, Web | Same + Slack notifications | Same + many |
| K8s native | ✅ CRD | ✅ CRD | ❌ separate service |
| Setup ง่าย | ★★★★ | ★★★★ | ★★ |
คำแนะนำ 2026:
- ใช้ Argo CD แล้ว → ใช้ Argo Rollouts
- ใช้ Flux → ใช้ Flagger
- Spinnaker = legacy, ไม่แนะนำเริ่มใหม่
5.2 Flagger ตัวอย่าง (Flux/Linkerd users)
Flagger ทำ progressive delivery สำหรับฝั่ง Flux/Linkerd — นิยาม Canary ที่ผูกกับ Deployment แล้วมันจะค่อย ๆ เพิ่ม weight ตาม step วิเคราะห์ metric (success rate, latency) ทุกช่วง ถ้าเกิน threshold ก็ rollback อัตโนมัติ ทำให้ deploy ปลอดภัยโดยไม่ต้องเฝ้าเอง:
yaml
apiVersion: flagger.app/v1beta1
kind: Canary
metadata: { name: orders }
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: orders
progressDeadlineSeconds: 600
service:
port: 8080
targetPort: 8080
gateways: [public-gateway]
analysis:
interval: 1m
threshold: 5 # max fail ก่อน rollback
maxWeight: 50
stepWeight: 10
metrics:
- name: request-success-rate
thresholdRange: { min: 99 }
interval: 1m
- name: request-duration
thresholdRange: { max: 500 }
interval: 1m
webhooks:
- name: load-test
url: http://loadtester/
metadata: { cmd: "hey -z 1m -q 10 -c 2 http://orders-canary:8080/" }→ ทุก deploy: weight 10% → analyze → +10% → ... → ครบ 50% promote เป็น 100%
5.3 🆕 Kargo (multi-stage promotion, GA 2024)
ใน GitOps ปกติ dev/staging/prod คือ folder แยกใน repo — เมื่ออยากอัปเดต prod ต้องเปิด PR ไปแต่ละ folder แล้ว merge เอง ถ้ามี 10 service และ 3 env = เปิด PR เยอะมาก Kargo ทำให้กระบวนการ "ส่ง version ใหม่จาก dev → staging → prod" เป็นอัตโนมัติ + verify ทุกขั้น:
ปัญหา GitOps แบบดั้งเดิม: promote dev → staging → prod ทำด้วยมือ (PR หลายตัว)
Kargo = orchestrator ของ promotion ข้าม env (สร้างโดย Akuity ทีมเดียวกับ Argo)
yaml
apiVersion: kargo.akuity.io/v1alpha1
kind: Stage
metadata: { name: prod, namespace: orders }
spec:
subscriptions:
upstreamStages: [{ name: staging }] # promote มาจาก staging
promotionMechanisms:
gitRepoUpdates:
- repoURL: https://github.com/acme/k8s-config
writeBranch: main
kustomize:
images:
- image: ghcr.io/acme/orders
path: environments/prod
argoCDAppUpdates:
- appName: orders-prod
appNamespace: argocd
verification:
analysisTemplates: [{ name: smoke-test }]→ "Freight" (= image + manifest version) ไหลผ่าน Stage อัตโนมัติ + verify ทุกขั้น
Part 5.5: 🆕 Knative Serverless (Scale-to-Zero + Function Deployment)
Knative = K8s extension ที่ให้ "serverless experience" — auto-scale (รวม scale-to-zero), event-driven deployment
CNCF Incubating, ปี 2024 เป็น standard ของ "serverless บน K8s ของตัวเอง" (vs vendor lock AWS Lambda / GCP Cloud Run)
5.5.1 Knative มี 2 ส่วน
Knative แบ่งเป็น 2 ส่วนที่ใช้แยกกันได้ — Serving (auto-scale workload รวมถึง scale-to-zero, จัดการ revision/traffic split) และ Eventing (trigger แบบ event-driven ด้วย CloudEvents) เลือกใช้เฉพาะส่วนที่ต้องการได้:
| Component | ทำอะไร |
|---|---|
| Knative Serving | Auto-scale workload (รวม scale-to-zero), traffic split, revision management |
| Knative Eventing | Event-driven trigger (CloudEvents native), broker, subscription |
5.5.2 ทำไม Knative
Knative แก้ความเจ็บปวดหลายอย่างของ K8s ปกติ — HPA scale ลงถึง 0 ไม่ได้ (idle workload เปลือง CPU ตลอด), canary ต้องตั้งเครื่องมือเพิ่ม, event-driven ต้อง subscribe broker เอง Knative ให้ scale-to-zero, traffic split และ event trigger มาในตัว:
text
ก่อน Knative:
- HPA scale 1 → N (ไม่เคยลด 0) → idle workload เปลือง CPU
- Canary ต้อง Argo Rollouts + Service config
- Event-driven ต้อง subscribe Kafka เอง
ด้วย Knative:
- Service ไม่มี request → scale 0 → auto-up เมื่อ request เข้า (~1 sec cold start)
- Built-in traffic split ระดับ revision
- HTTP trigger จาก CloudEvents5.5.3 Knative Service ตัวอย่าง
yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata: { name: orders }
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/minScale: "0" # scale-to-zero
autoscaling.knative.dev/maxScale: "100"
# default metric = "concurrency" → target = 100 concurrent req / pod
# ถ้าอยาก target แบบ request-per-second ให้เพิ่ม:
# autoscaling.knative.dev/metric: "rps"
autoscaling.knative.dev/target: "100" # ค่านี้คือค่าที่เรากำหนดเองในตัวอย่างนี้ ไม่ใช่ default ที่ Knative ตั้งมาให้อัตโนมัติถ้าไม่ใส่ annotation (ตรวจสอบพฤติกรรม default ล่าสุดจาก Knative Serving docs ก่อนใช้จริง)
spec:
containers:
- image: ghcr.io/acme/orders:v1.2.3
resources: { requests: { cpu: 100m, memory: 128Mi } }
traffic:
- revisionName: orders-v1
percent: 90
- revisionName: orders-v2
percent: 10 # canary built-in!
tag: canary # available at canary.orders.svc.cluster.localความสามารถที่ได้ฟรี:
- HTTPS endpoint อัตโนมัติ (Let's Encrypt integration)
- Scale 0 → N → 0 ตาม traffic (KPA — Knative Pod Autoscaler — เร็วกว่า HPA)
- Revision history (เก็บ N versions, rollback ง่าย)
- Traffic splitting + canary
- mTLS ถ้าใช้กับ Istio/Linkerd
5.5.4 Knative Eventing — CloudEvents Trigger
Knative Eventing ทำให้ deploy service แบบ event-driven ได้ง่าย — Broker เป็น router ของ event, Trigger คือ "ฟัง event type นี้แล้วเรียก service นี้" เมื่อมี CloudEvents เข้าตรง filter Knative จะ POST ไปยัง service ให้เอง (และ scale up จาก 0 ถ้าจำเป็น):
yaml
# Broker = event router
apiVersion: eventing.knative.dev/v1
kind: Broker
metadata: { name: default }
spec:
config:
apiVersion: v1
kind: ConfigMap
name: kafka-broker-config
---
# Trigger = ฟัง event แล้วเรียก service
apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata: { name: orders-on-payment }
spec:
broker: default
filter:
attributes:
type: com.acme.payment.captured # CloudEvents type
source: /payment-service
subscriber:
ref:
apiVersion: serving.knative.dev/v1
kind: Service
name: orders # call orders service→ Event เข้าตรงตาม filter → Knative call HTTP POST ไป service พร้อม CloudEvents binary header
5.5.5 ใช้เมื่อ vs ไม่ใช้
✅ ใช้ Knative เมื่อ:
- Workload spiky (peak 10x average) — scale-to-zero ประหยัด
- Function-style services (รับ event → process → return)
- ต้องการ "managed Lambda" บน K8s ของตัวเอง (no vendor lock)
- Multi-cloud — Knative รันได้ทุก K8s (vs Cloud Run = GCP only)
❌ ไม่ใช้เมื่อ:
- Stateful service (databases, in-memory cache)
- Low-latency p99 (cold start ~1-3 sec)
- Long-running background worker (ใช้ Job/CronJob ดีกว่า)
- ทีมไม่มี K8s expert (ดูแล Knative + Istio ยาก)
5.5.6 Knative vs Cloud Run vs AWS Lambda
| Knative (self-host) | Cloud Run | AWS Lambda | |
|---|---|---|---|
| Vendor | None | GCP | AWS |
| Container support | ✅ | ✅ | ✅ (Lambda Container) |
| Scale-to-zero | ✅ | ✅ | ✅ |
| Cold start | ~1-3s (warm pool ลดได้) | ~1s | ~100-500ms |
| Multi-cloud | ✅ (K8s) | ❌ | ❌ |
| Event source | CloudEvents broker | Eventarc | EventBridge |
| Cost | infra cost | per-request | per-request |
| Max runtime | unlimited | 60 min | 15 min |
| Best for | K8s-native shop | quick deploy on GCP | serverless purist on AWS |
Part 5.6: 🆕 Backstage — Internal Developer Platform (IDP)
Backstage = Open-source IDP (Spotify, donated to CNCF 2020, Incubating)
ปี 2024-2026 เป็น enterprise standard สำหรับบริษัทที่มี 50+ services — แก้ปัญหา "ไม่มีใครรู้ว่ามี service อะไรบ้าง + ใครเป็นเจ้าของ"
5.6.1 ปัญหาที่ Backstage แก้
พอองค์กรมี service เป็นร้อย ๆ ตัว ความวุ่นวายเชิงองค์กรจะตามมา — ไม่มีใครรู้ว่ามี service อะไรบ้าง ใครเป็นเจ้าของ ใคร depend ใคร doc กระจัดกระจาย Backstage แก้ด้วยการรวมทุกอย่างไว้ที่ portal เดียว:
เมื่อบริษัทโตจาก 5 service → 500 service:
text
- ไม่รู้ว่ามี service อะไรบ้าง — ทีมใหม่ search GitHub 2 ชม.
- ไม่รู้ว่าใครเป็นเจ้าของ — service ตาย ตอน 3am ไม่มีใครรับสาย
- ไม่รู้ว่า service A depend on B — ปิด B = พัง 10 service โดยไม่รู้
- ทุกทีม "สร้าง template" ต่างกัน — onboard engineer ใหม่ 2 สัปดาห์
- Doc กระจาย — บน Confluence, Notion, GitHub README, Slack messages
- Cost ไม่รู้ — ใครจ่าย AWS bill ของ team X?5.6.2 4 Pillars ของ Backstage
1. Service Catalog
yaml
# catalog-info.yaml (commit ใน repo ของแต่ละ service)
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: orders-service
description: Handles order placement and tracking
annotations:
github.com/project-slug: acme/orders-service
pagerduty.com/service-id: PXXXXX
grafana/dashboard-selector: "tag in [orders]"
spec:
type: service
lifecycle: production
owner: team-commerce
system: ecommerce
dependsOn:
- component:default/payment-service
- component:default/inventory-service
- resource:default/orders-db
providesApis:
- orders-api
consumesApis:
- payment-api→ Auto-discover ผ่าน GitHub/GitLab org → render เป็น service catalog ที่ search ได้
2. Software Templates (Scaffolder)
yaml
# scaffolder-templates/spring-boot-microservice/template.yaml
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: spring-boot-microservice
title: Spring Boot Microservice
spec:
parameters:
- title: Service info
properties:
name: { type: string, title: Service name }
team: { type: string, title: Owner team }
steps:
- id: fetch
action: fetch:template
input:
url: ./skeleton # template repo
values:
name: ${{ parameters.name }}
team: ${{ parameters.team }}
- id: publish
action: publish:github
input:
repoUrl: github.com?owner=acme&repo=${{ parameters.name }}
- id: register
action: catalog:register
input:
repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }}
catalogInfoPath: /catalog-info.yaml→ Engineer คลิก "Create Spring Boot Service" → Backstage:
- Clone template
- Replace variables
- สร้าง GitHub repo + push code
- Setup CI/CD
- Register ใน service catalog
- Add to team
ขั้นตอนที่เคยใช้ 2 สัปดาห์ → 10 นาที
3. TechDocs (Documentation-as-Code)
markdown
<!-- docs/index.md ใน repo ของ service -->
# Orders Service
## Overview
...
## Architecture
yaml
# catalog-info.yaml
metadata:
annotations:
backstage.io/techdocs-ref: dir:.→ Backstage build MkDocs จาก markdown ใน repo → serve ใน portal → Doc อยู่กับ code → ไม่ stale
4. Plugins Ecosystem
| Plugin | ทำอะไร |
|---|---|
| GitHub Actions | Show CI status + trigger build |
| PagerDuty / Opsgenie | On-call + incident |
| Grafana / Datadog | Embed dashboards |
| Kubernetes | Pod/deployment status |
| ArgoCD | Deployment status + sync |
| Sentry | Error tracking |
| SonarQube | Code quality |
| Cost (AWS/GCP) | Team cost breakdown |
| Tech Radar | Approved tech list |
→ 1 portal เห็นทุกอย่าง — ไม่ต้องเปิด 10 tabs
5.6.3 Architecture
Backstage ประกอบด้วย portal (React) ที่แสดง catalog/template/docs, backend (Node) ที่เก็บข้อมูล catalog ใน Postgres, และ plugin จำนวนมากที่ดึงข้อมูลจากระบบภายนอก (GitHub, K8s, ArgoCD, Grafana) มารวมในที่เดียว:
5.6.4 Adoption Pattern
อย่าพยายาม onboard ทุก service พร้อมกัน — Backstage ได้ผลดีเมื่อค่อย ๆ ขยาย: ตั้ง backend ก่อน, import service สำคัญ, ทำ template ตัวแรก, เพิ่ม plugin ทีละตัว แล้วสุดท้ายบังคับให้ service ใหม่ต้องมี catalog-info.yaml:
Week 1-2: Setup Backstage backend + Postgres
Week 3-4: Import 10 critical service ผ่าน catalog-info.yaml
Week 5-6: ทำ 1 software template (เช่น "new microservice")
Week 7-8: Integrate GitHub Actions + ArgoCD plugin
Week 9-12: Onboard ทุก service ใหม่ผ่าน template
Month 4+: Add TechDocs + ArgoCD + Grafana plugin
Month 6: "ห้าม merge ไม่มี catalog-info.yaml"5.6.5 ใช้ vs ไม่ใช้
✅ ใช้ Backstage เมื่อ:
- บริษัท 50+ services
- มี Platform team อย่างน้อย 2 คน full-time
- Onboarding engineer ใหม่ใช้เวลานาน
- Service discovery ใช้เวลามาก
- ต้องการ "developer experience" เป็น culture
❌ ไม่ใช้เมื่อ:
- < 20 services (overhead ไม่คุ้ม)
- ไม่มี Platform team (Backstage ต้อง maintain)
- Org structure เปลี่ยนบ่อย (catalog stale ตลอด)
5.6.6 Alternatives ปี 2026
| Tool | จุดเด่น | License |
|---|---|---|
| Backstage (CNCF) | Plugin ecosystem ใหญ่สุด, customizable | Apache 2.0 |
| Port | SaaS, no-code workflow, faster setup | Commercial |
| Humanitec | Platform Orchestrator (เน้น app config) | Commercial |
| Cortex | SaaS, scorecards/maturity tracking | Commercial |
| OpsLevel | SaaS, similar to Cortex | Commercial |
| Roadie | Managed Backstage (no infra) | Commercial |
💡 เริ่มยังไง: ลอง demo.backstage.io ดูก่อน. ถ้าใช่ →
npx @backstage/create-appแล้วลอง POC 1 สัปดาห์
5.6.7 ตัวอย่าง Production
Backstage ไม่ใช่ของทดลอง — บริษัทใหญ่ที่มี engineer หลักพันใช้จริงใน production (Spotify ผู้สร้างเอง, Netflix, Expedia, American Airlines ฯลฯ) เป็นหลักฐานว่า pattern IDP นี้ scale ได้จริงในองค์กรขนาดใหญ่:
text
✅ Spotify — สร้าง Backstage (5000+ engineers)
✅ Netflix — ใช้ + custom plugins
✅ Expedia, American Airlines, Box, Roblox — production
✅ HelloFresh, LinkedIn — adoptionPart 6: CI/CD Pipeline
text
1. PR opened:
- Run unit + integration tests
- Run security scans (deps, image, SAST)
- Run lint + style
- Build artifact + image
- Deploy to ephemeral test env
- Run e2e
- Review approval
2. Merge to main:
- Build image, tag latest + git sha
- Push registry
- Update manifest in k8s-config repo (PR or auto-commit)
- Argo CD picks up → deploy dev
3. Promote to staging:
- Manual or auto trigger
- Update staging manifest
- Argo CD applies
4. Promote to production:
- Approval gate
- Update production manifest
- Argo CD applies canary
- Auto analysis6.1 Tools
มีเครื่องมือ CI/CD ให้เลือกหลายแบบ — แบบ hosted ทั่วไป (GitHub Actions, GitLab CI, Jenkins) หรือแบบ K8s-native ที่รัน pipeline เป็น pod (Tekton, Drone) เลือกตาม ecosystem ที่ทีมใช้และว่าต้องการรัน pipeline ใน cluster หรือไม่:
- GitHub Actions / GitLab CI / Jenkins
- Tekton (K8s-native pipelines)
- Drone
Part 7: Versioning
7.1 Image Tag
การตั้ง tag ของ image สำคัญต่อความน่าเชื่อถือของ deployment — ใช้ tag ที่ระบุ version ชัดเจน (semver หรือ git sha) ที่ immutable กฎเหล็กคืออย่าใช้ latest ใน production เพราะ pod แต่ละตัวอาจได้คนละ version โดยไม่รู้ตัว และ rollback ไม่ได้:
text
orders:v1.2.3 # semver
orders:v1.2.3-abc1234 # semver + sha
orders:abc1234 # sha (immutable, recommended)⚠️ อย่าใช้ latest ใน production — ไม่รู้ version
7.2 API Versioning
ระหว่าง rolling — v1 + v2 รัน → API ต้อง backward compatible
หรือใช้ URL versioning:
text
/v1/orders → v1 service
/v2/orders → v2 servicePart 8: Multi-environment
text
dev — feature branch deployed
staging — main branch, integration test
prod — released versionsแต่ละ env ต่าง:
- Replica count
- Resource limit
- Database
- Feature flags
- Secret
ใช้ Kustomize overlay หรือ Helm values
Part 9: Rollback
9.1 K8s
K8s เก็บประวัติ revision ของ Deployment ไว้ จึง rollback กลับเวอร์ชันก่อนได้ทันทีด้วย kubectl rollout undo (หรือระบุ revision ที่ต้องการ) เหมาะกับกรณีฉุกเฉินที่ deploy ใหม่แล้วพัง:
bash
kubectl rollout undo deployment/orders
kubectl rollout history deployment/orders
kubectl rollout undo deployment/orders --to-revision=39.2 GitOps
ในโลก GitOps การ rollback คือการ revert git แล้วปล่อยให้ controller ซิงค์กลับ — ได้ความสอดคล้องว่า git = สถานะจริงเสมอ และ rollback ก็ถูกบันทึกเป็น commit (audit ได้) ไม่ใช่การแก้ cluster ด้วยมือที่หลุดจาก git:
bash
git revert <commit>
git push
# Argo CD apply9.3 Argo Rollouts
ถ้าใช้ Argo Rollouts ทำ canary ก็มีคำสั่งคุม rollout โดยตรง — abort หยุด+ย้อนกลับ canary ที่กำลังไป, promote เดินหน้าข้าม step, undo ย้อนเวอร์ชัน ทำให้ควบคุม progressive delivery ได้ละเอียดตอนเกิดปัญหา:
bash
kubectl argo rollouts abort orders
kubectl argo rollouts promote orders --skip-current-step
kubectl argo rollouts undo orders9.4 Database
⚠️ DB migration อาจ rollback ไม่ได้ — drop column, data lost → ใช้ expand-contract เสมอ
Part 10: Production Checklist
text
☐ Image immutable tag (git sha)
☐ Rolling update with maxUnavailable=0
☐ Readiness probe + graceful shutdown
☐ Canary deployment สำหรับ critical service
☐ Auto rollback on error rate spike
☐ Database migration backward compatible
☐ Feature flag for risky feature
☐ GitOps (Argo CD / Flux)
☐ CI/CD with tests + scans
☐ Multi-env (dev, staging, prod)
☐ Approval gate before prod
☐ Rollback procedure tested
☐ Image vulnerability scan
☐ SBOM generated
☐ Image signed (Cosign)
☐ Resource limits set
☐ HPA (auto-scale) configured
☐ Pod disruption budget
☐ Network policyPart 10.5: Production War Stories
🔥 Knight Capital (2012): bad deploy ทำขาดทุน $440M ใน 45 นาที
deploy ไป 7 server แต่ลืม 1 server → mixed code: server เก่ายังรัน flag เก่าในโค้ด (legacy trading flag ภายใน ไม่ใช่ feature flag แบบที่บทนี้สอน) ที่กลายเป็น "buy aggressively" → 4 ล้านออเดอร์ผิดใน 45 นาที → บริษัทล้มละลาย
Lesson:
- Zero manual deploy: ทุก deploy ผ่าน CI/CD เท่านั้น
- All-or-nothing: ใช้ deployment strategy ที่ atomic (Blue-Green/Canary) — ไม่ใช่ "deploy ทีละเครื่อง"
- Dead code = bomb: ลบ flag/code ที่เลิกใช้ทันที (อย่าทิ้ง flag เก่าไว้เป็นปี)
- Kill switch: ทุก deploy ใหญ่ต้องมี feature flag ที่ปิดได้ใน < 1 นาที
🔥 GitLab (2017): backup ไม่มี + db wiped ระหว่าง maintenance — สูญ 6 ชม. data
DBA พิมพ์ผิด rm -rf บน primary แทน replica → no recent backup ใช้งานได้ → restore จาก snapshot 6 ชม. ก่อน
Lesson:
- Test backup จริง (restore drill) — แค่ตั้ง schedule ไม่พอ
- ระวัง destructive command ใน production (sudo cooldown, 2-person rule)
- GitOps ช่วย — config drift ตรวจได้ทันที
🔥 Roblox (2021): 73-hour outage จาก rolling update ที่ rollback ไม่ได้
Root cause จริงตาม postmortem "Roblox Return to Service" (Jan 2022) = Consul performance degradation + bug ใน streaming detail logger ของ Consul ที่กดให้ leader election ไม่ stable → routing พัง → rollback แต่ระบบ caching cluster อยู่ใน state ที่ไม่รู้จัก → ต้อง rebuild ทั้ง cluster (อ่าน postmortem ฉบับเต็มใน Roblox Tech Blog)
Lesson:
- Test rollback ทุก deploy — ถ้า rollback ไม่ได้ deploy ก็ไม่ได้
- Stateful infrastructure (cache, DB) ต้อง backward-compat schema
- Progressive rollout (canary) ช่วยตรวจปัญหาก่อนกระทบ 100%
🔥 Atlassian (2022): script deploy ผิดทำลายข้อมูล ~775 site นาน 14 วัน
Script delete app ใช้ list "app to remove" — แต่อ่าน list ผิด field → delete site แทน app → ตาม public postmortem ของ Atlassian = ~775 customer sites หายทั้ง Jira/Confluence/Jira Service Management → restore manual ใช้เวลานานสุดถึง 14 วันสำหรับบาง tenant (auto-restore ไม่รองรับ multi-tenant scenario นี้)
Lesson:
- Destructive script ต้องมี dry-run + 2-person review
- Soft delete (tombstone) ไม่ใช่ hard delete
- DR plan ต้องครอบ "bug ของตัว ops tool"
Part 10.6: 📋 Cheat Sheet
เลือก deployment strategy
text
Stateless web/API → Rolling (K8s default)
Risky feature / new logic → Canary + auto-analysis
Major DB migration → Blue-Green + read replica switch
Cannot tolerate downtime → Blue-Green
Cost-constrained → Rolling + readiness gating
Multi-region → Cell-based + per-cell canaryProduction deployment checklist
yaml
# Deployment essentials
strategy:
type: RollingUpdate
rollingUpdate: { maxSurge: 25%, maxUnavailable: 0 } # ⚠️ % แบบนี้ปัดเศษต่างกันตาม replica count จริง — เช่น replicas=2 → 25% ปัดเป็น 1 pod extra = รัน 3 pod พร้อมกัน ต้องเช็คกับ replica count จริง + PodDisruptionBudget ด้านล่าง (minAvailable: 80%) ว่าไม่ชนกัน
progressDeadlineSeconds: 600 # fail rollout if exceeded
template:
spec:
terminationGracePeriodSeconds: 60 # let in-flight req finish
containers:
- name: app
image: ghcr.io/acme/orders@sha256:abc... # digest, not tag
readinessProbe: { httpGet: { path: /actuator/health/readiness, port: 8080 }, periodSeconds: 5 }
livenessProbe: { httpGet: { path: /actuator/health/liveness, port: 8080 }, periodSeconds: 10, failureThreshold: 3 }
# ⚠️ Spring Boot 3 / JVM อาจ warm นาน (60-120s) — ปรับ failureThreshold ให้ครอบ
# เช่น failureThreshold: 60 + periodSeconds: 5 = 5-นาที window
startupProbe: { httpGet: { path: /actuator/health/liveness, port: 8080 }, failureThreshold: 30, periodSeconds: 5 }
lifecycle:
preStop: { exec: { command: ["sh", "-c", "sleep 15"] } } # SIGTERM grace
resources:
requests: { cpu: 200m, memory: 256Mi }
limits: { cpu: 1000m, memory: 512Mi }
---
# PodDisruptionBudget — กัน K8s drain ตาย workload
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata: { name: orders }
spec:
minAvailable: 80%
selector: { matchLabels: { app: orders } }Image security baseline
bash
# 1. SBOM (Software Bill of Materials)
syft orders:v1.2.3 -o spdx-json > sbom.json
# 2. Vulnerability scan
trivy image --severity HIGH,CRITICAL --exit-code 1 orders:v1.2.3
# 3. Sign image (Sigstore Cosign)
cosign sign --key cosign.key ghcr.io/acme/orders:v1.2.3
# 4. Verify in admission controller (Kyverno/OPA)
cosign verify --key cosign.pub ghcr.io/acme/orders:v1.2.3Deployment commands
bash
# Argo Rollouts
kubectl argo rollouts get rollout orders --watch
kubectl argo rollouts pause orders
kubectl argo rollouts promote orders
kubectl argo rollouts abort orders
kubectl argo rollouts undo orders
# Flagger
kubectl describe canary orders
kubectl get events --field-selector involvedObject.kind=Canary
# Argo CD
argocd app sync orders --prune
argocd app rollback orders <revision>
argocd app diff orders
# Kargo
kargo promote --project=orders --stage=prod --freight=abc123Anti-pattern → Fix
| Anti-pattern | แก้ |
|---|---|
image: orders:latest | image digest (@sha256:...) หรือ git sha tag |
ไม่มี readinessProbe | เพิ่มทุก deploy + แยก liveness/readiness |
terminationGracePeriodSeconds: 30 (default) + slow drain | ตั้ง 60-120s + preStop sleep ก่อน SIGTERM |
Manual kubectl apply ใน prod | GitOps only — drift detection จับ |
| Feature flag ค้าง 6+ เดือน | Quarterly flag audit, set expirationDate ใน OpenFeature |
| ไม่ test rollback | DR drill ทุก quarter — ลอง rollback บน staging |
Part 11: Pitfalls
- Use
latesttag — ไม่รู้ version ที่ running - No readiness probe — pod รับ traffic ก่อนพร้อม
- No graceful shutdown — request drop ระหว่าง deploy
- Big bang DB migration — break rolling
- No rollback test — production fail → ไม่รู้จะกลับยังไง
- Manual kubectl in prod — drift จาก git
- No canary — bug ถึง 100% ทันที
- Feature flag เก่าค้าง — code dead branch
- Untracked feature flag — config drift
- No PodDisruptionBudget — K8s drain ตาย workload
Part 12: Checkpoint
- Rolling update vs Blue-Green vs Canary — แต่ละแบบเหมาะกับ workload แบบใด?
- Argo Rollouts ทำอะไรเพิ่มจาก K8s Deployment?
- Argo Rollouts vs Flagger — เลือกตอนไหน?
- GitOps คือ? Argo CD vs Flux เลือกอย่างไร?
- OpenFeature มาแก้ปัญหาอะไรของ feature flag เดิม?
- Kargo ใช้ทำอะไร? ต่างจาก Argo CD ยังไง?
- Expand-Contract DB migration ทำงานยังไง? ทำไมต้องมีอย่างน้อย 3 deploys?
- ทำไม
latestimage tag (และ tag ที่ mutable ได้) เป็นอันตราย? Image digest แก้ได้ยังไง? - Feature flag กับ deployment ต่างกันยังไง? Decouple deploy/release หมายความว่ายังไง?
- PodDisruptionBudget ทำอะไร? ตั้งเป็น
minAvailable: 100%ดีไหม? - Canary auto rollback ทำงานยังไง? ต้องมี metric อะไรบ้าง?
- Image signing (Cosign) + SBOM ป้องกัน supply chain attack ยังไง?
- จาก Knight Capital case — bug อะไรที่ทำให้บริษัทล้มละลาย? วิธีกัน?
terminationGracePeriodSecondsตั้งสั้นเกินไปจะเกิดอะไรขึ้น?
Part 13: สรุปบทนี้
- Rolling = K8s default, simple
- Blue-Green = atomic switch, fast rollback, × resource
- Canary = progressive %, auto analysis (Argo Rollouts หรือ Flagger)
- Feature Flag = decouple deploy/release → ใช้ OpenFeature (CNCF standard)
- GitOps = git = source of truth (Argo CD / Flux)
- 🆕 Kargo = multi-stage promotion (dev → staging → prod) อัตโนมัติ
- Expand-Contract = backward-compat DB migration
- CI/CD: test + SAST + SBOM + scan (Trivy) + sign (Cosign) + deploy
- Immutable image = digest (
@sha256:...) ดีกว่า tag - Production: canary + auto-rollback + readiness gate + PodDisruptionBudget
- Learn from outages: Knight Capital, GitLab, Roblox, Atlassian — รากเดียวกัน: test rollback, no manual deploy, kill switch
บทถัดไป (สุดท้าย!) — Polyglot Example — รวมทุกอย่างเป็นระบบจริง