แผนการเรียนรู้
/

สัปดาห์ที่ 7: Continuous Delivery & Deployment Strategies

จาก Source Code สู่มือผู้ใช้งาน: กระบวนการส่งมอบซอฟต์แวร์อย่างต่อเนื่องและกลยุทธ์การ Deploy ที่ปลอดภัย

Agenda วันนี้

  • Concepts: Continuous Delivery vs. Continuous Deployment
  • Artifacts: ความสำคัญของ Artifact Management และ Container Registry
  • Release Management: การจัดการเวอร์ชันและการปล่อยซอฟต์แวร์
  • Strategies: กลยุทธ์การ Deploy (Rolling, Blue/Green, Canary)
  • GitOps: แนวคิดสมัยใหม่ในการจัดการ Deployment
DevOps Course: Week 7

ทบทวน: Continuous Integration (CI)

ก่อนจะส่งมอบ (Deliver) เราต้องมั่นใจว่าการรวมโค้ด (Integrate) สมบูรณ์แล้ว

Build

คอมไพล์โค้ด หรือสร้าง Docker Image

Test

Unit Test และ Integration Test ผ่านทั้งหมด

Artifact

ได้ชิ้นงาน (เช่น Docker Image) ที่พร้อมนำไปใช้งาน

"CI จบที่การได้ Artifact ที่ผ่านการทดสอบ... แต่ CD คือการนำ Artifact นั้นไปสู่ Environment ถัดไป"

Continuous Delivery คืออะไร?

แนวปฏิบัติในการพัฒนาซอฟต์แวร์ที่ทำให้โค้ดของเรา "พร้อมที่จะ Deploy" ไปยัง Production ได้ตลอดเวลา อย่างปลอดภัยและรวดเร็ว

  • ทุกการเปลี่ยนแปลงที่ผ่านการ Test จะถูกเตรียมพร้อมสำหรับการ Release
  • Key Concept: การ Deploy ไป Production ยังต้องใช้ "การตัดสินใจของมนุษย์" (Manual Approval) เพื่อกดปุ่มเริ่ม
  • เป้าหมายคือลดความเสี่ยง และทำให้การ Deploy เป็นเรื่องน่าเบื่อ (Boring is good)

ความแตกต่างที่สำคัญ (The Crucial Difference)

Most Enterprise

Continuous Delivery

✅ Automated Build & Test

✅ Deploy to Staging อัตโนมัติ

Manual Approval เพื่อไป Production

"ซอฟต์แวร์พร้อมเสมอ แต่เราเลือกเวลาปล่อยเอง"

Ultimate Goal

Continuous Deployment

✅ Automated Build & Test

✅ Deploy to Staging อัตโนมัติ

🚀 Automated Deploy ไป Production ทันที

"ถ้า Test ผ่าน ลูกค้าจะได้ใช้ฟีเจอร์ใหม่ทันที"

The CD Pipeline Structure

เส้นทางของโค้ดจากเครื่อง Developer สู่ Production Server

💻 Commit
⚙️ CI Build Unit Tests
📦 Artifact Docker Image
🚧 Staging Integration Test
🚀 Production Live Traffic

Reference: DevOps Pipeline

ทำไมต้องทำ Continuous Delivery?

⚡ Faster Time to Market

ส่งมอบฟีเจอร์ใหม่ถึงมือลูกค้าได้เร็วขึ้น ไม่ต้องรอนานเป็นเดือน

📉 Low Risk Releases

การปล่อยทีละนิด (Small Batches) ทำให้ความเสี่ยงต่ำ และแก้ปัญหาได้ง่ายกว่าการปล่อยก้อนใหญ่

🔄 Faster Feedback Loop

ได้รับฟีดแบ็คจากผู้ใช้จริงเร็วขึ้น เพื่อนำมาปรับปรุงผลิตภัณฑ์

🤖 Reliable Deployments

กระบวนการเป็นอัตโนมัติ ลด Human Error จากการ Deploy ด้วยมือ

Foundation: Infrastructure as Code (IaC)

ก่อนจะ Deploy แอปฯ เราต้องมีโครงสร้างพื้นฐานที่พร้อมและเหมือนกันทุก Environment

❌ ClickOps

การกดสร้าง Server ผ่านหน้าเว็บ Console

  • ทำซ้ำยาก (Non-repeatable)
  • เสี่ยงต่อ Human Error
  • ไม่มี Version Control

✅ Infrastructure as Code

การเขียน Code เพื่อกำหนดโครงสร้างระบบ (เช่น Terraform, Ansible)

  • ตรวจสอบย้อนหลังได้ (Audit Trail)
  • Environment เหมือนกันเป๊ะ (Consistency)
  • Disaster Recovery ได้เร็ว

Immutable Infrastructure

"Don't fix servers, replace them."

ในยุค Container เราจะไม่ SSH เข้าไปอัปเดตแพทช์หรือแก้โค้ดใน Server ที่รันอยู่

🚫 Mutable: อัปเดต v1 เป็น v2 บนเครื่องเดิม (เสี่ยงต่อ Configuration Drift)
Immutable: สร้าง Container v2 ใหม่ แล้วลบ v1 ทิ้ง

*Docker Image คือตัวอย่างที่ดีที่สุดของ Immutable Artifact

ความสำคัญของ Artifact Management

Artifact คือ "ของ" ที่ได้จากการ Build และพร้อมส่งมอบ (เช่น Docker Image, JAR file, Binary)

Build Once, Deploy Anywhere

เราควร Build Artifact แค่ครั้งเดียว ในขั้นตอน CI แล้วใช้ตัวเดิม Deploy ไปยังทุก Environment (Dev, QA, Prod)

Single Source of Truth

ถ้าเกิดปัญหาที่ Production เราต้องมั่นใจได้ว่า Image นั้นคือตัวเดียวกับที่ผ่านการเทสมาแล้ว

ที่เก็บ Artifact (Container Registry)

เปรียบเสมือน "โกดัง" เก็บสินค้าที่รอส่งออก

Docker Hub Docker Hub Public/Private
☁️ Azure ACR Enterprise Grade
🦊 GitLab Registry Built-in
Best Practice: ควรใช้ Private Registry สำหรับซอฟต์แวร์ขององค์กร เพื่อความปลอดภัยและการควบคุมสิทธิ์การเข้าถึง

การจัดการ Version (Tagging Strategy)

การตั้งชื่อ Tag ของ Docker Image มีผลต่อการทำ CD อย่างมาก

🚫 อย่าใช้ 'latest' ใน Production

เพราะเราจะไม่รู้เลยว่า 'latest' ตอนนี้คือเวอร์ชันไหนกันแน่ ทำให้ Rollback ยาก

✅ ใช้ Semantic Versioning หรือ Commit SHA

  • myapp:v1.0.2 (ชัดเจน, สื่อความหมาย)
  • myapp:git-a1b2c3d (ผูกกับ Source Code commit ได้แม่นยำ)

การจัดการ Configuration (12-Factor App)

"Code เดียวกัน แต่ Config ต่างกันตาม Environment"

เราไม่ควร Hardcode ค่า Database หรือ API Key ลงใน Docker Image แต่ควรส่งเข้าไปตอน Deploy ผ่าน Environment Variables

# Docker Compose Example

services:

  web:

    image: myapp:v1.0.0

    environment:

      - DB_HOST=${DB_HOST}

      - API_KEY=${API_KEY}

Chain of Custody (ห่วงโซ่ความคุ้มครอง)

ใน Enterprise CD ความปลอดภัยและการตรวจสอบย้อนกลับเป็นเรื่องสำคัญ

🔍 Traceability

รู้ว่า Artifact นี้มาจาก Commit ไหน, ใครเป็นคนเขียน, และผ่านการ Test อะไรมาบ้าง

🖊️ Image Signing

การเซ็น Digital Signature ให้กับ Image เพื่อยืนยันว่าไม่ได้ถูกแก้ไขระหว่างทาง (Supply Chain Security)

Release Management Process

Release ไม่ใช่แค่การ Copy ไฟล์ แต่คือกระบวนการ

1
Planning: กำหนดฟีเจอร์ที่จะปล่อยในเวอร์ชันถัดไป
2
Building & Versioning: สร้าง Artifact และติด Tag (SemVer)
3
Testing (Staging): ทดสอบในสภาพแวดล้อมเสมือนจริง (UAT)
4
Approval: การอนุมัติ (Gatekeeping) ก่อนขึ้น Production

Deployment Strategies

"จะเปลี่ยนของเก่าเป็นของใหม่ยังไง ให้ระบบไม่ล่ม และผู้ใช้ไม่บ่น?"

🔄

Rolling

ค่อยๆ เปลี่ยนทีละตัว

🔵🟢

Blue/Green

สลับขั้วทันที (Instant Switch)

🐤

Canary

ปล่อยให้กลุ่มเล็กๆ ลองก่อน

1. Recreate Strategy (Big Bang)

วิธีทำงาน: หยุดระบบเก่าทั้งหมด (Downtime) -> ลงของใหม่ -> เริ่มระบบใหม่

ข้อดี:

  • ง่ายที่สุด ไม่ต้องใช้ Tool ซับซ้อน
  • ไม่เปลืองทรัพยากร (ไม่ต้องรัน 2 เวอร์ชันพร้อมกัน)

ข้อเสีย:

  • Downtime: ระบบจะใช้งานไม่ได้ช่วงหนึ่ง
  • ไม่เหมาะกับ Business Critical App

2. Rolling Deployment

ค่อยๆ แทนที่ Instance เก่าด้วยของใหม่ ทีละส่วน (Incrementally)

v2
v1
v1

Step 1

v2
v2
v1

Step 2

v2
v2
v2

Complete

Zero Downtime: ผู้ใช้ยังใช้งานได้ตลอด

⚠️ Risk: จะมีช่วงเวลาที่ v1 และ v2 ทำงานพร้อมกัน (ต้องระวังเรื่อง Database/API compatibility)

3. Blue/Green Deployment

สร้าง Environment ใหม่ (Green) ให้สมบูรณ์ แล้วสลับ Traffic ไปทีเดียว

Blue (Current Live)

User Traffic ❌

Green (New Version)

User Traffic ✅

Instant Switch & Rollback: สลับไปมาได้ทันที ถ้ามีปัญหาก็สลับกลับ Blue ง่ายมาก

⚠️ Cost: เปลืองทรัพยากร 2 เท่า (ต้องมี Server รองรับทั้ง 2 environments)

4. Canary Deployment

"นกขมิ้นในเหมืองถ่านหิน" - ปล่อยให้ผู้ใช้กลุ่มเล็กๆ ลองก่อน

Users (100%)
v1 (Stable) - 90%
v2 - 10%

1. ปล่อย v2 ให้ User 10%

2. Monitor Error Rate / Performance

3. ถ้าดี -> ขยายเป็น 50% -> 100%

4. ถ้าพัง -> Rollback ทันที (ผู้ใช้ส่วนใหญ่ไม่ได้รับผลกระทบ)

Feature Flags (Decoupling Deploy from Release)

Deploy โค้ดไปแล้ว แต่ "ปิด" ฟีเจอร์ไว้ก่อน แล้วค่อย "เปิด" เมื่อพร้อม

if (features.isEnabled('new-checkout-ui')) {

  return <NewCheckout />;

} else {

  return <OldCheckout />;

}

✅ A/B Testing ได้ง่าย
✅ Kill Switch ปิดฟีเจอร์ทันทีถ้ามีบั๊ก

Zero Downtime: เป้าหมายสูงสุด

หัวใจสำคัญคือ Load Balancer และ Health Checks

1. Health Check: ระบบต้องรู้ว่า Container ตัวใหม่ "พร้อม" (Healthy) หรือยัง ก่อนจะส่ง Traffic ไปหา

2. Graceful Shutdown: Container ตัวเก่าต้องเคลียร์ Request ที่ค้างอยู่ให้จบก่อนจะดับไป

3. Database Migrations: ต้องระวังการแก้ Database ที่ทำให้เวอร์ชันเก่าพัง (Backward Compatibility)

เปรียบเทียบกลยุทธ์ (Comparison)

Strategy Zero Downtime Real User Testing Cost Rollback Duration
Recreate ❌ No ❌ No Lowest Slow
Rolling ✅ Yes ❌ No Low Slow
Blue/Green ✅ Yes ❌ No High (x2) Instant ⚡
Canary ✅ Yes ✅ Yes Low Fast

Modern CD: GitOps

ใช้ Git เป็น "Single Source of Truth" สำหรับ Infrastructure และ Application

🐱

Git Repo

(Manifests)

Sync 🔄
🐙

ArgoCD / Flux

(Controller)

☸️

Kubernetes

(Cluster)

แทนที่จะรันคำสั่ง kubectl apply เอง เราแค่แก้ไฟล์ใน Git แล้วระบบจะ Sync ให้เองอัตโนมัติ

เครื่องมือสำหรับ CD (Tools)

🐙

ArgoCD

GitOps tool สำหรับ Kubernetes ยอดนิยม

🤵

Jenkins

Classic tool ปรับแต่งได้เยอะ แต่ต้องดูแลเอง

☁️

Render / Vercel

Platform as a Service (PaaS) ที่รวม CD มาให้ในตัว ใช้ง่าย

🚀

GitHub Actions

ใช้ทำได้ทั้ง CI และ CD (Push Docker, Deploy to Cloud)

Security in CD Pipeline

ความปลอดภัยต้องอยู่ในทุกขั้นตอน ไม่ใช่แค่ตอนจบ

Image Scanning

สแกนหาช่องโหว่ (CVEs) ใน Docker Image ก่อนขึ้น Production (เช่นใช้ Trivy, Snyk)

Secret Management

ห้ามฝัง Password ใน Code/Image ให้ใช้ Vault หรือ Secret Manager ของ Cloud

Least Privilege

CD Tool ควรมีสิทธิ์เท่าที่จำเป็นในการ Deploy เท่านั้น

หลัง Deploy เสร็จ... จบไหม?

NO! เราต้องเฝ้าระวัง (Monitor) ทันที

📊

Metrics

CPU, RAM, Error Rate (Prometheus)

📝

Logs

บันทึกเหตุการณ์ (ELK, Loki)

🚨

Alerts

แจ้งเตือนเมื่อมีปัญหา (PagerDuty)

*ถ้า Deploy แล้ว Error Rate พุ่งสูง -> ต้อง Auto-Rollback ทันที

สรุปบทเรียน (Summary)

  • CD (Delivery) คือการทำให้พร้อม Deploy, CD (Deployment) คือการ Deploy อัตโนมัติ
  • Artifact ต้อง Build ครั้งเดียว (Immutable) แล้วใช้ตลอด Pipeline
  • Deployment Strategies (Rolling, Blue/Green, Canary) ช่วยลด Downtime และความเสี่ยง
  • Configuration ต้องแยกออกจาก Code (Environment Variables)
  • Security & Monitoring เป็นส่วนสำคัญของ CD Pipeline
💬

Q & A

มีคำถามเกี่ยวกับ Continuous Delivery หรือ Deployment Strategies ไหมครับ?

เตรียมตัวทำ Lab! 🧪

Next: Hands-on Deployment

ใน Lab ถัดไป เราจะนำโปรเจกต์ Django + React ที่ทำ CI ไว้แล้ว มาทำ CD (Continuous Deployment) ขึ้น Cloud จริงๆ

  • เราจะใช้ Render.com (PaaS) ในการ Deploy
  • เชื่อมต่อ GitHub Repo กับ Render
  • ตั้งค่า Environment Variables บน Cloud
  • ทดสอบแก้ไขโค้ดและดูมัน Deploy อัตโนมัติ (Automated Deployment)
สิ่งที่ต้องเตรียม: GitHub Account & Render Account

ขอบคุณครับ

See you in the Lab!

Lab: Continuous Deployment to Render 🚀

เรียนรู้วิธีการนำ Django Application ขึ้นสู่ระบบ Production จริงบนคลาวด์ของ Render.com

🎯 เป้าหมายของ Lab

  • ✅ เตรียมความพร้อมโค้ด Django สำหรับ Production (Gunicorn, Whitenoise)
  • ✅ สร้างและเชื่อมต่อฐานข้อมูล PostgreSQL บน Render
  • ✅ ตั้งค่า Web Service และ Automated Deployment (CD)
  • ✅ จัดการ Environment Variables และ Secrets อย่างปลอดภัย

Step 1: เตรียม Repository (Fork & Clone)

เราจะใช้โค้ดจาก Branch wk07 เป็นจุดเริ่มต้นในการ Deploy

# 1. ไปที่ GitHub และทำการ Fork Repository ต่อไปนี้ไปยังบัญชีของคุณ:

https://github.com/wichitpaulsombat/djrepo


# 2. ในเครื่องของคุณ ให้ Clone repo ที่เพิ่ง Fork มา (สลับไปที่ branch wk07)

$ git clone -b wk07 https://github.com/YOUR_GITHUB_USER/djrepo.git

$ cd djrepo

💡 ข้อสังเกต: โปรเจกต์นี้ได้รับการปรับแต่งค่าบางส่วนสำหรับ Render ไว้แล้ว เช่น การเพิ่มไลบรารีที่จำเป็นลงใน requirements.txt

Step 2: ทำความเข้าใจไฟล์สำคัญ (Build Script)

Render ต้องการคำสั่งในการ "Build" โปรเจกต์ เราจึงมักสร้างไฟล์ build.sh แยกไว้

# build.sh (ตรวจสอบว่ามีไฟล์นี้อยู่ในโปรเจกต์)

#!/usr/bin/env bash

# Exit on error

set -o errexit


# ติดตั้ง Dependencies

pip install -r requirements.txt


# รวบรวม Static Files (CSS, JS, Images)

python manage.py collectstatic --no-input


# อัปเดตโครงสร้างฐานข้อมูล

python manage.py migrate

Library ที่จำเป็น (ใน requirements.txt):

  • gunicorn : Web Server สำหรับรัน Django บน Production
  • psycopg2-binary : ตัวเชื่อมต่อฐานข้อมูล PostgreSQL
  • dj-database-url : ตัวแปลง String URL เป็นการตั้งค่า Database
  • whitenoise : ตัวช่วยเสิร์ฟ Static files

Step 3: สร้าง Database บน Render

1. เข้าไปที่ dashboard.render.com และ Sign in ด้วยบัญชี GitHub

2. กดปุ่ม New + และเลือก PostgreSQL

3. ตั้งค่าฐานข้อมูลดังนี้:

  • Name: djrepo-db (หรือชื่ออะไรก็ได้)
  • Region: Singapore (หรือโซนที่ใกล้คุณที่สุด)
  • PostgreSQL Version: 15 หรือ 16
  • Instance Type: Free (ใช้งานได้ฟรี)

4. กดปุ่ม Create Database

🔑 สำคัญ: เมื่อสร้างเสร็จแล้ว ให้คัดลอก Internal Database URL เก็บไว้ (เราจะใช้เชื่อมต่อกับ Web Service)

Step 4: สร้าง Web Service (เชื่อมโค้ด)

ตอนนี้เราจะนำโค้ดจาก GitHub มาวางบนเซิร์ฟเวอร์

1. กลับมาที่หน้า Dashboard หลัก กด New + แล้วเลือก Web Service

2. เลือก Build and deploy from a Git repository แล้วกด Next

3. กด Connect ที่ Repository djrepo ของคุณ

4. ตั้งค่า Web Service เบื้องต้น:

  • Name: djrepo-app (ชื่อเว็บของคุณ)
  • Region: Singapore (ควรเป็นที่เดียวกับ Database)
  • Branch: wk07 (ห้ามลืมเลือก branch นี้!)
  • Runtime: Python 3

Step 5: ตั้งค่า Build & Start Command

บอกให้ Render รู้ว่าต้องรันคำสั่งอะไรเพื่อเตรียมและเปิดใช้งานแอป

Build Command

ใส่คำสั่งเพื่อเรียกใช้สคริปต์ที่เราเตรียมไว้

./build.sh

Start Command

ใช้ Gunicorn เสิร์ฟแอปแทนรันเซิร์ฟเวอร์ของ Django

gunicorn mysite.wsgi:application
⚠️ ระวัง: ชื่อ mysite ใน Start Command ต้องตรงกับโฟลเดอร์ที่มีไฟล์ wsgi.py ในโปรเจกต์ของคุณ (ให้เช็คชื่อโปรเจกต์ในโค้ดอีกครั้ง หากตั้งชื่ออื่นให้เปลี่ยนตามนั้น)

Step 6: ตั้งค่า Environment Variables

เลื่อนลงมาที่หมวด Environment Variables และเพิ่มค่าต่างๆ ดังนี้ (กด Add Environment Variable):

DATABASE_URL = postgres://... (วาง Internal Database URL จาก Step 3)
SECRET_KEY = พิมพ์ข้อความสุ่มยาวๆ มั่วๆ ลงไป (ห้ามให้ใครรู้)
DEBUG = False # ปิดโหมด Debug บน Production เพื่อความปลอดภัย
PYTHON_VERSION = 3.11 # กำหนดเวอร์ชัน Python ให้ตรงกับตอนพัฒนา

เมื่อกรอกครบแล้ว ให้เลื่อนลงไปล่างสุดและกดปุ่ม Create Web Service

Step 7: ดูผลการ Deploy และ Logs

เมื่อกด Create แล้ว ระบบจะเริ่มกระบวนการ CI/CD ทันที

สิ่งที่ต้องสังเกตในหน้า Logs:

  1. ระบบกำลัง Clone repository และ Checkout branch wk07
  2. ระบบทำการรัน ./build.sh
  3. ดูว่า pip install ทำงานสำเร็จหรือไม่
  4. ดูว่า Database migrations สมบูรณ์หรือไม่ (Applying migrations...)
  5. สถานะสุดท้ายจะต้องขึ้นว่า ==> Your service is live 🎉
🌐 ถ้าสำเร็จ คุณสามารถคลิกที่ URL ด้านมุมซ้ายบน (เช่น https://djrepo-app.onrender.com) เพื่อดูเว็บไซต์ของคุณได้เลย!

Step 8: สร้างบัญชี Admin (Superuser)

ฐานข้อมูลบน Production เริ่มต้นจะว่างเปล่า เราต้องสร้าง Admin เพื่อเข้าหลังบ้าน

วิธีทำบน Render:

  1. ที่หน้า Dashboard ของ Web Service ให้คลิกแท็บ Shell
  2. รอสักครู่เพื่อให้ Terminal โหลด
  3. พิมพ์คำสั่งสร้าง Superuser
  4. กรอก Username, Email, และ Password

# พิมพ์คำสั่งนี้ในหน้า Shell

$ python manage.py createsuperuser


Username: admin

Email address: admin@example.com

Password:

Password (again):

Superuser created successfully.

🛠️ Troubleshooting (การแก้ปัญหา)

Build Failed (pip error)

สาเหตุ: พิมพ์ชื่อ Library ใน requirements.txt ผิด หรือเวอร์ชัน Python ไม่ตรงกัน

แก้: เช็ค Logs ให้ดีว่าตัวไหน Error และระบุ PYTHON_VERSION ให้ตรง

Database Connection Error

สาเหตุ: คัดลอก DATABASE_URL ผิด หรือใส่ External URL แทน Internal

แก้: กลับไปเช็คที่แท็บ Environment ให้แน่ใจว่าใช้ postgres://... ที่ถูกต้อง

เว็บพัง 500 Server Error

สาเหตุ: โค้ดมีบั๊ก หรือลืมตั้ง ALLOWED_HOSTS ใน Django settings

แก้: ถ้าในโปรเจกต์ตั้ง ALLOWED_HOSTS = ['*'] ไว้แล้ว ให้ไปเช็คหน้า Logs เพื่อดู Error จริงๆ ของ Django

เวทมนตร์แห่ง CD: Auto Deploy 🔄

Render ได้เชื่อมต่อกับ GitHub Repository ของคุณเรียบร้อยแล้ว

ทุกครั้งที่คุณมีการ git push การอัปเดตโค้ดขึ้นไปยัง Branch wk07 บน GitHub ของคุณ:

  • Render จะตรวจจับการเปลี่ยนแปลงโดยอัตโนมัติ (ผ่าน Webhook)
  • ทำการ Build ใหม่ (Zero-downtime deploy)
  • แอปพลิเคชันจะถูกอัปเดตโดยที่คุณไม่ต้องกดปุ่มใดๆ อีก!
🎉

ภารกิจสำเร็จ! การส่งงาน

รายละเอียดการส่งผลการทำ Lab:

  • URL ของเว็บไซต์: ส่งลิงก์ Render ของคุณ (เช่น https://djrepo-app.onrender.com)
  • Screenshots (จัดทำเป็น PDF):
    • หน้าเว็บของคุณที่ทำงานได้ปกติ (หน้าแรก)
    • หน้าเว็บ /admin ที่เข้าสู่ระบบด้วย Superuser แล้ว
    • หน้า Dashboard ของ Render ที่แสดงสถานะ Service เป็นสีเขียว (Live)