CI/CD Handbook
CI/CD 0 → Hero จาก commit สู่ production อัตโนมัติ — pipeline, jobs, artifacts, matrix, secrets, กลยุทธ์ deploy, rollback และความปลอดภัย แบบไม่ผูกเครื่องมือ
สารบัญ
- LEVEL 0 · ปูพื้นจากศูนย์
- 01CI/CD คืออะไร & ทำไมต้องมี
- 02แบบจำลองความคิดหลัก
- LEVEL 1 · พื้นฐานที่ใช้จริง
- 03Pipeline แรกของคุณ
- 04Jobs · Steps · Runners
- 05Build · Test · Lint — สามเสาหลักของ CI
- LEVEL 2 · ระดับกลาง
- 06Artifacts & Caching
- 07Matrix & การขนานงาน
- 08Secrets & ตัวแปร
- LEVEL 3 · เข้าสู่ CD
- 09CI → CD: Delivery vs Deployment
- 10Environments & การ Deploy
- 11กลยุทธ์ Deploy & Rollback
- LEVEL 4 · ระดับเทพ
- 12ความปลอดภัยของ Pipeline
- 13Runners & ความเร็วของ Pipeline
- 14เทียบแพลตฟอร์ม & บทสรุป
เข้าใจ CI/CD 0 → Hero — จาก commit สู่ production อัตโนมัติ (CI/CD Handbook · 14 บท · 5 ระดับ) · เล่มต่อจาก Git 0 → Hero — พาคุณจากคนไม่เคยตั้ง pipeline ไปจนออกแบบสายการส่งมอบซอฟต์แวร์ที่อัตโนมัติ ปลอดภัย และเชื่อถือได้ เน้นแนวคิดและเหตุผลที่ไม่ผูกกับเครื่องมือใดเครื่องมือหนึ่ง พร้อมตัวอย่าง YAML จริงและเทียบหลายแพลตฟอร์ม
- ต่อจาก: Git 0 → Hero
- เวลาอ่าน: ~90 นาที
- ภาษา: ไทย พร้อมไดอะแกรม
LEVEL 0 · ปูพื้นจากศูนย์
CI/CD คืออะไร & ทำไมต้องมี#
ในเล่ม Git คุณเรียนวิธีบันทึกและรวมโค้ดของหลายคนเข้าด้วยกัน แต่มีคำถามที่ค้างอยู่: หลังจาก git push แล้ว ใครเป็นคนตรวจว่าโค้ดที่เพิ่งรวมเข้ามายัง build ได้ เทสต์ผ่าน และไม่ทำของเดิมพัง? ถ้าคำตอบคือ "คนในทีมต้องมานั่งตรวจเองทุกครั้ง" นั่นคือจุดที่ทุกอย่างเริ่มช้าและพลาดง่าย CI/CD คือการยกงานตรวจสอบและส่งมอบทั้งหมดนั้นให้ เครื่องทำอัตโนมัติทุกครั้งที่โค้ดเปลี่ยน
ตัวย่อสองชุดนี้แยกเป็นสองเรื่องที่ต่อเนื่องกัน:
- CI — Continuous Integration (การรวมโค้ดอย่างต่อเนื่อง): รวมงานของทุกคนเข้าสายหลักบ่อย ๆ แล้วให้ระบบ build + test อัตโนมัติทันที เพื่อจับปัญหาให้เร็วที่สุด
- CD — Continuous Delivery / Deployment (การส่งมอบ/ปล่อยขึ้นใช้งานอย่างต่อเนื่อง): เมื่อโค้ดผ่าน CI แล้ว ก็ แพ็กและส่งขึ้นไปใช้งานจริงอัตโนมัติ หรือเตรียมให้พร้อมกดปล่อยได้ทันที
1.1 ปัญหาที่ CI เกิดมาเพื่อแก้ — "integration hell"
ลองนึกถึงทีมที่แต่ละคนแยกไปเขียนฟีเจอร์ของตัวเองคนละ branch เป็นเวลาหนึ่งเดือน โดยไม่รวมกลับเลย พอถึงวันรวม (integrate) ทุกคนพบว่าโค้ดชนกันเต็มไปหมด สมมติฐานไม่ตรงกัน ของที่เคยทำงานกลับพัง — ต้องเสียเวลาเป็นสัปดาห์แก้ "วันรวมร่าง" นี้คือสิ่งที่เรียกว่า integration hell
CI พลิกปัญหานี้ด้วยหลักง่าย ๆ ข้อเดียว: ถ้าการรวมเจ็บ ก็รวมให้บ่อยขึ้นจนมันไม่เจ็บ รวมวันละหลายครั้ง ทีละนิด แล้วให้เครื่องตรวจทุกครั้ง ปัญหาจะถูกจับตั้งแต่ยังเล็กและรู้ทันทีว่าเกิดจาก commit ไหน
1.2 หัวใจคือ "วงจรป้อนกลับที่สั้น"
คุณค่าที่แท้จริงของ CI/CD ไม่ใช่ "ความอัตโนมัติ" เอง แต่คือ ความเร็วของวงจรป้อนกลับ (feedback loop) — ระยะเวลาตั้งแต่คุณเขียนโค้ดผิด จนถึงตอนที่มีคน/อะไรบางอย่างบอกคุณว่ามันผิด ยิ่งวงจรนี้สั้น ค่าแก้ยิ่งถูก เพราะคุณยังจำได้ว่าเพิ่งแก้อะไรไป และบั๊กยังไม่ทันแพร่ไปไหน
| บั๊กถูกจับเมื่อ | ค่าใช้จ่ายในการแก้ |
|---|---|
| ตอนเขียน (ในเครื่องตัวเอง) | แทบฟรี — แก้ทันที |
| ตอน CI รันหลัง push (ไม่กี่นาทีต่อมา) | ถูก — ยังจำ context ได้ |
| ตอน reviewer หรือ QA เจอ (วันต่อมา) | ปานกลาง — ต้องวนกลับมาคิดใหม่ |
| ตอนลูกค้าเจอบน production | แพงที่สุด — กระทบจริง + เร่งแก้ |
CI/CD คือเครื่องจักรที่ดัน "จุดที่จับบั๊กได้" ให้ขยับขึ้นไปบนสุดของตารางนี้ให้มากที่สุด
🧭 CI/CD ต่อยอดจาก Git โดยตรง — ทุกอย่างในเล่มนี้เริ่มทำงานจากเหตุการณ์ใน Git ที่คุณเรียนมาแล้ว —
git pushและการเปิด Pull Request คือ "ทริกเกอร์" ที่ปลุก pipeline ให้ตื่นขึ้นมาทำงาน ถ้ายังไม่แม่นเรื่อง branch กับ PR แนะนำให้ทบทวนบทที่ 4–5 และ 10 ของเล่ม Git ก่อน
✅ สรุปบทที่ 1 — CI = รวมโค้ดบ่อย ๆ แล้วให้เครื่อง build+test ทุกครั้ง · CD = ส่ง/ปล่อยขึ้นใช้งานอัตโนมัติเมื่อผ่าน CI · เกิดมาเพื่อฆ่า "integration hell" ด้วยการรวมถี่จนไม่เจ็บ · หัวใจคือ วงจรป้อนกลับที่สั้น — จับบั๊กยิ่งเร็ว ยิ่งถูก · pipeline ถูกปลุกโดยเหตุการณ์ใน Git เช่น push และ PR
แบบจำลองความคิดหลัก#
บทนี้สำคัญที่สุดในเล่ม เช่นเดียวกับบทที่ 2 ของเล่ม Git ถ้าคุณเข้าใจสองแนวคิดต่อไปนี้ — กายวิภาคของ pipeline และ เส้นแบ่งสามระดับของ CI/CD — รายละเอียด YAML ที่เหลือทั้งเล่มจะกลายเป็นเรื่องเดาได้ ไม่ใช่เรื่องท่องจำ
2.1 Pipeline คือสายพานประกอบอัตโนมัติ
แก่นของ CI/CD คือ pipeline — ชุดขั้นตอนที่ทำงานเรียงต่อกันโดยอัตโนมัติเมื่อมีเหตุการณ์มากระตุ้น มองมันเป็นสายพานในโรงงาน: โค้ดดิบเข้าทางหนึ่ง ผ่านสถานีตรวจและประกอบทีละสถานี แล้วออกอีกทางเป็นซอฟต์แวร์ที่พร้อมใช้งาน ทุกแพลตฟอร์ม (GitHub Actions, GitLab CI, Jenkins, CircleCI) ใช้คำศัพท์ต่างกันแต่โครงสร้างเดียวกันนี้เสมอ:
event ปลุก → workflow (ทั้ง pipeline) → ประกอบด้วยหลาย job (รันขนานกันได้ แต่ละอันบน runner ของตัวเอง) → แต่ละ job มีหลาย step ที่รันเรียงกันบนเครื่องเดียวจำลำดับชั้นนี้ไว้ให้แม่น เพราะมันคือโครงของทุกอย่าง:
| ชั้น | คืออะไร | กฎสำคัญ |
|---|---|---|
| Event (trigger) | เหตุการณ์ที่ปลุก pipeline | push, PR, tag, ตามเวลา, กดเอง |
| Workflow / Pipeline | ทั้งกระบวนการ เขียนไว้ในไฟล์ YAML | หนึ่งไฟล์ = หนึ่ง pipeline |
| Job | กลุ่มงานที่รันบนเครื่องหนึ่งเครื่อง | หลาย job รันขนานกันโดยปริยาย |
| Step | คำสั่งย่อยในแต่ละ job | step รันเรียงกัน แชร์พื้นที่ทำงาน |
| Runner | เครื่อง (จริง/เสมือน) ที่รัน job | เริ่มสะอาดทุกครั้ง ไม่มีของค้าง |
2.2 เส้นแบ่งสามระดับ: Integration → Delivery → Deployment
คนสับสน "CD" มากที่สุด เพราะมันย่อได้สองคำที่ต่างกัน ความจริงคือมันคือ สามขั้นที่ซ้อนกันเป็นชั้น ๆ แต่ละขั้นเพิ่มความอัตโนมัติขึ้นไปอีกระดับ:
เส้นแบ่งที่ต้องจำให้ขึ้นใจ: Continuous Delivery = ระบบทำให้ "พร้อมปล่อย" อัตโนมัติ แต่การกดปล่อยจริงเป็นการตัดสินใจของคน ส่วน Continuous Deployment = ตัดมนุษย์ออกจากสมการ ผ่าน CI/ทดสอบเมื่อไรก็ขึ้น production เมื่อนั้นทันที ทีมส่วนใหญ่เริ่มจาก Delivery แล้วค่อยขยับไป Deployment เมื่อความเชื่อมั่นในชุดทดสอบสูงพอ (ลงลึกในบทที่ 9)
2.3 หลักการที่อยู่เบื้องหลังทั้งหมด
ก่อนลงรายละเอียด จำหลักสามข้อนี้ไว้ มันคือ "ทำไม" ที่อยู่ใต้ทุกคำสั่งในเล่ม:
- ทำซ้ำได้เสมอ (reproducible) — pipeline เริ่มจากเครื่องสะอาดทุกครั้ง สิ่งที่ผ่านบน CI ต้องผ่านเหมือนกันไม่ว่าใครรัน "มันรันได้บนเครื่องผม" จึงไม่ใช่ข้ออ้างอีกต่อไป
- เร็วเข้าไว้ (fast feedback) — pipeline ที่ใช้เวลา 40 นาทีคือ pipeline ที่ไม่มีใครรอดู ความเร็วคือฟีเจอร์
- ล้มให้ดัง (fail loud) — เมื่อมีอะไรพัง ต้องหยุดและแจ้งทันที ไม่ใช่ปล่อยผ่านเงียบ ๆ แล้วให้ของเสียไหลขึ้น production
✅ สรุปบทที่ 2 — pipeline = สายพานอัตโนมัติ มีลำดับชั้น event → workflow → job (ขนาน) → step (เรียง) บน runner · CI/CD คือสามชั้นซ้อนกัน: Integration (build+test) ⊂ Delivery (พร้อมปล่อย กดเอง) ⊂ Deployment (ขึ้น prod อัตโนมัติ) · เส้นแบ่ง Delivery/Deployment คือ "มีคนกดปุ่มไหม" · หลักการใต้ทุกอย่าง: ทำซ้ำได้ · เร็ว · ล้มให้ดัง
LEVEL 1 · พื้นฐานที่ใช้จริง
Pipeline แรกของคุณ#
ทฤษฎีพอแล้ว มาเขียน pipeline จริงกัน เราจะใช้ GitHub Actions เป็นตัวอย่างหลักตลอดเล่ม เพราะใกล้กับเล่ม Git ที่สุดและเริ่มฟรีได้ทันที แต่ทุกแนวคิดย้ายไปแพลตฟอร์มอื่นได้ (บทที่ 14 เทียบให้ครบ) — โครงสร้างเปลี่ยน แต่ความคิดเหมือนเดิม
3.1 ไฟล์เดียวที่ปลุกทุกอย่าง
ใน GitHub Actions คุณแค่สร้างไฟล์ YAML ไว้ในโฟลเดอร์ .github/workflows/ แล้ว push ขึ้นไป — GitHub จะเห็นและเริ่มรันให้เองทันที ไม่ต้องตั้งค่าเซิร์ฟเวอร์อะไรเลย นี่คือ pipeline ที่สมบูรณ์ที่สุดเท่าที่ใช้งานได้จริง:
# .github/workflows/ci.yml
name: CI
on: # เมื่อไรให้รัน — นี่คือ "trigger"
push:
branches: [main]
pull_request: # รันตอนเปิด/อัปเดต PR ด้วย
jobs:
test: # ชื่อ job (ตั้งเองได้)
runs-on: ubuntu-latest # รันบนเครื่อง Linux ที่ GitHub เตรียมให้
steps:
- uses: actions/checkout@v4 # 1. ดึงโค้ด repo ลงมาในเครื่อง runner
- uses: actions/setup-node@v4 # 2. ติดตั้ง Node.js
with:
node-version: 20
- run: npm ci # 3. ติดตั้ง dependencies
- run: npm test # 4. รันชุดทดสอบ — ถ้าพัง pipeline แดงทันที3.2 อ่าน YAML นี้ทีละชั้น
ทุกบรรทัดแมปกับลำดับชั้นในบทที่ 2 ตรง ๆ:
on:คือ event/trigger — บอกว่าให้ปลุก pipeline เมื่อ push เข้าmainหรือเมื่อมี PRjobs:ใต้นั้นคือรายการ job — ตอนนี้มีตัวเดียวชื่อtestruns-on:เลือก runner — เครื่องเปล่า ๆ ที่ GitHub สร้างใหม่ให้ทุกครั้งsteps:คือ step ที่รันเรียงจากบนลงล่าง มีสองแบบ:uses:เรียกใช้ "action" สำเร็จรูปที่คนอื่นเขียนไว้ และrun:สั่ง shell command ตรง ๆ
หัวใจอยู่ที่ step สุดท้าย: ถ้า npm test คืน exit code ไม่เป็นศูนย์ (เทสต์ตก) step นั้นล้มเหลว job ก็ล้มเหลว และ pipeline ขึ้นสถานะแดง — บน PR คุณจะเห็นเครื่องหมาย ✕ ทันที นี่แหละคือ "fail loud" ในทางปฏิบัติ
3.3 การเริ่มสะอาดทุกครั้งคือฟีเจอร์ ไม่ใช่บั๊ก
สังเกตว่าทำไมต้องมี checkout และ setup-node ทุกครั้ง — เพราะ runner เกิดใหม่จากศูนย์ทุกการรัน ไม่มีโค้ด ไม่มี Node ติดมาก่อน นี่คือสิ่งที่ทำให้ pipeline "ทำซ้ำได้": ไม่มีของค้างจากการรันก่อนหน้ามาปนเปื้อนผล สิ่งที่ผ่านวันนี้จะผ่านเหมือนกันในอีกหกเดือน
🧭 ลองเองได้ใน 2 นาที — เอา repo ที่มี
npm testอยู่แล้ว สร้างไฟล์.github/workflows/ci.ymlตามด้านบน แล้วgit add→commit→pushเปิดแท็บ Actions บน GitHub คุณจะเห็น pipeline เริ่มหมุนทันที — นี่คือ git push จากเล่มที่แล้ว ที่ตอนนี้ "เกิดอะไรต่อ" แล้วจริง ๆ
✅ สรุปบทที่ 3 — pipeline = ไฟล์ YAML ใน
.github/workflows/·on:กำหนด trigger,jobs:→steps:กำหนดงาน · step มีสองแบบuses:(action สำเร็จรูป) และrun:(คำสั่ง shell) · runner เริ่มสะอาดทุกครั้งจึงต้อง checkout/setup ใหม่ — ความสะอาดนี้คือรากของการทำซ้ำได้ · เทสต์ตก = exit code ไม่เป็นศูนย์ = pipeline แดง
Jobs · Steps · Runners#
บทที่แล้วมี job เดียว pipeline จริงมักมีหลาย job ที่ต้องประสานกัน เข้าใจกฎการทำงานร่วมของ job/step/runner แล้ว คุณจะออกแบบ pipeline ที่ทั้งเร็วและถูกต้องได้
4.1 กฎทองสองข้อ: job ขนาน · step เรียง
นี่คือจุดที่มือใหม่พลาดบ่อยที่สุด ขอย้ำให้ชัด:
- หลาย job รันขนานกันโดยปริยาย และแต่ละ job อยู่บน runner คนละเครื่อง สะอาดแยกกัน — job หนึ่งสร้างไฟล์ไว้ อีก job มองไม่เห็น เพราะคนละเครื่อง
- step ภายใน job เดียวกันรันเรียงกัน บนเครื่องเดียว และ แชร์พื้นที่ทำงาน (workspace) — step แรกติดตั้งของไว้ step ถัดไปใช้ได้ทันที
ผลที่ตามมาในทางปฏิบัติ: งานที่ต้อง "ส่งของต่อกัน" ให้ใส่เป็น step ใน job เดียว ส่วนงานที่อิสระต่อกัน (เช่น เทสต์ frontend กับ backend) ให้แยกเป็นคนละ job จะได้รันพร้อมกัน เร็วขึ้น
4.2 needs — บังคับลำดับเมื่อ job ต้องพึ่งกัน
บางที job ต้องรอกัน เช่น deploy ต้องรอ test ผ่านก่อน ใช้ needs: เพื่อสร้างความสัมพันธ์นั้น — มันเปลี่ยน job ที่เคยขนานให้กลายเป็นกราฟลำดับ (เหมือนสาย commit ในเล่ม Git):
lint กับ test ไม่พึ่งใครจึงรันพร้อมกัน · build ใส่ needs: [lint, test] จึงรอให้ทั้งสองผ่านก่อน · ถ้า job ที่ถูก needs ล้มเหลว job ที่รออยู่จะถูกข้าม (ไม่รัน) ทันทีjobs:
lint:
runs-on: ubuntu-latest
steps: [ ... รัน linter ... ]
test:
runs-on: ubuntu-latest
steps: [ ... รันเทสต์ ... ]
build:
needs: [lint, test] # รอ lint และ test ผ่านทั้งคู่ก่อน
runs-on: ubuntu-latest
steps: [ ... build โปรเจกต์ ... ]4.3 Runner — เครื่องที่ลงมือทำจริง
Runner คือเครื่อง (จริงหรือเสมือน) ที่รับ job ไปรันจริง มีสองแบบใหญ่ ๆ ซึ่งเราจะลงลึกในบทที่ 13:
- Hosted runner — แพลตฟอร์มเตรียมให้ (เช่น
ubuntu-latest,windows-latest) เกิดใหม่สะอาดทุกครั้ง ไม่ต้องดูแล เหมาะกับงานทั่วไป - Self-hosted runner — เครื่องของคุณเองที่ลงโปรแกรม runner ไว้ ใช้เมื่อต้องการฮาร์ดแวร์พิเศษ (GPU), เข้าถึงเครือข่ายภายใน, หรือคุมค่าใช้จ่าย
✅ สรุปบทที่ 4 — หลาย job รันขนานบน runner แยกเครื่องสะอาด · step ใน job เดียวรันเรียงและแชร์ workspace ·
needs:สร้างลำดับเมื่อ job ต้องพึ่งกัน และข้าม job ถัดไปถ้าตัวที่พึ่งล้ม · runner มี hosted (สะดวก) และ self-hosted (คุมเอง) ·needsคุมลำดับ ไม่ได้ส่งไฟล์ — ส่งไฟล์ข้าม job ต้องใช้ artifact
Build · Test · Lint — สามเสาหลักของ CI#
CI ที่ดีไม่ได้วัดที่ "มี pipeline" แต่วัดที่ "ตรวจอะไรบ้าง" สามเสาหลักต่อไปนี้คือด่านมาตรฐานที่ทุก pipeline ควรมี เรียงจากเร็ว/ถูกไปช้า/แพง เพื่อให้ "ล้มเร็ว" — ด่านที่ถูกที่สุดควรล้มก่อน
5.1 Lint — ด่านที่ถูกและเร็วที่สุด
Lint คือการตรวจรูปแบบและกลิ่นของโค้ดโดยไม่ต้องรัน เช่น ตัวแปรที่ประกาศแล้วไม่ใช้, การจัดรูปแบบไม่สม่ำเสมอ, รูปแบบที่เสี่ยงบั๊ก มันเร็วมาก (วินาที) จึงควรเป็นด่านแรก ๆ — ไม่มีเหตุผลที่จะปล่อยให้เทสต์ที่ใช้เวลา 5 นาทีรันไปก่อน ทั้งที่โค้ดมี syntax ผิดที่ lint จับได้ใน 3 วินาที
5.2 Test — หัวใจของ CI
เทสต์อัตโนมัติคือสิ่งที่ทำให้ CI มีความหมาย เพราะมันคือสิ่งที่ "ตอบแทนคุณ" ว่าการเปลี่ยนแปลงไม่ทำของเดิมพัง โดยทั่วไปแบ่งเป็นชั้น ๆ ตามต้นทุน/ความเร็ว เรียกว่า testing pyramid:
| ชั้น | ตรวจอะไร | ความเร็ว / จำนวน |
|---|---|---|
| Unit | ฟังก์ชัน/หน่วยเล็กที่สุด แยกเดี่ยว | เร็วมาก · มีเยอะที่สุด |
| Integration | หลายส่วนทำงานร่วมกัน (เช่น โค้ด + ฐานข้อมูล) | ปานกลาง · มีพอประมาณ |
| End-to-End (E2E) | ทั้งระบบเหมือนผู้ใช้จริงกดใช้งาน | ช้า/เปราะ · มีน้อยที่สุด |
หลักคือ มี unit test เยอะ ๆ (เร็ว ถูก) เป็นฐาน แล้วมี E2E น้อย ๆ (ช้า แพง) ไว้บนยอด pipeline ฉลาด ๆ จะรัน unit ก่อนเพื่อล้มเร็ว แล้วค่อยลงทุนรัน E2E เมื่อชั้นล่างผ่านแล้ว
5.3 Build — พิสูจน์ว่ามันประกอบเป็นของจริงได้
การ build (คอมไพล์/แพ็ก) ใน CI พิสูจน์ว่าโค้ดไม่ใช่แค่ "เทสต์ผ่าน" แต่ "ประกอบออกมาเป็น artifact ที่ deploy ได้จริง" สำหรับภาษาที่คอมไพล์ ขั้นนี้จับ type error และปัญหา dependency ได้ ส่วนงานยุคใหม่มักจบที่การสร้าง container image ที่จะถูกส่งต่อไป deploy ในฝั่ง CD
5.4 เชื่อม CI กลับเข้า Git: status check & branch protection
นี่คือจุดที่ CI กับ Git บรรจบกันอย่างทรงพลัง ผลของ pipeline (เขียว/แดง) จะแสดงเป็น status check บน Pull Request และคุณตั้ง branch protection ให้ main ได้ว่า "ห้าม merge PR เข้ามาถ้า CI ยังไม่เขียว" — เท่ากับเปลี่ยน "ควรรันเทสต์นะ" (วินัยที่คนลืม) ให้เป็น "ระบบไม่ยอมให้ผ่านถ้าเทสต์ตก" (กฎที่บังคับเอง)
🧭 ต่อจากบทที่ 10 ของเล่ม Git — จำ Pull Request ได้ไหม — branch protection คือสิ่งที่เปลี่ยน PR จาก "ที่ขอให้รีวิว" ให้กลายเป็น "ประตูที่มีด่านอัตโนมัติเฝ้า" ทีมจริงจังมักบังคับทั้งสองอย่าง: ต้องมีคนรีวิวอนุมัติ และ CI ต้องเขียว ถึงจะกดปุ่ม merge ได้
✅ สรุปบทที่ 5 — สามเสาหลัก เรียงจากถูก/เร็วไปแพง/ช้า: lint → test → build ให้ด่านถูกล้มก่อน · เทสต์เป็นพีระมิด: unit เยอะ (ฐาน) E2E น้อย (ยอด) · build พิสูจน์ว่าประกอบเป็น artifact จริงได้ · ผูก CI กลับเข้า Git ด้วย status check + branch protection เพื่อบังคับว่า "CI ไม่เขียว = merge ไม่ได้"
LEVEL 2 · ระดับกลาง
Artifacts & Caching#
สองคำนี้คือ "fetch กับ pull" แห่งโลก CI/CD — ฟังดูคล้ายกันจนคนสับสนตลอด แต่จุดประสงค์ต่างกันสิ้นเชิง เข้าใจเส้นแบ่งนี้แล้ว pipeline ของคุณจะทั้งเร็วขึ้นและส่งของต่อกันได้ถูกต้อง
6.1 Artifact — ผลงานที่ต้องส่งต่อ
จำกับดักจากบทที่ 4: job คนละเครื่อง ส่งไฟล์หากันเองไม่ได้ artifact คือสะพานนั้น — job build "upload" ผลลัพธ์ (เช่นโฟลเดอร์ dist/ หรือไฟล์ .jar) ขึ้นที่เก็บกลาง แล้ว job deploy "download" กลับลงมาใช้ artifact เป็น ของที่มีคุณค่า ต้องเก็บไว้ใช้ต่อ และมักดาวน์โหลดมาดูภายหลังได้ด้วย
# ใน job build — อัปโหลดผลลัพธ์
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
# ใน job deploy — ดาวน์โหลดกลับมา
- uses: actions/download-artifact@v4
with:
name: dist6.2 Cache — ความเร็วที่ทิ้งได้
การติดตั้ง dependencies (npm, pip, Maven) ซ้ำทุกครั้งเสียเวลามาก ทั้งที่มันแทบไม่เปลี่ยน cache แก้ตรงนี้: เก็บโฟลเดอร์ที่ "สร้างใหม่ได้" (เช่น node_modules/) ไว้ใช้ซ้ำในการรันครั้งหน้า ต่างจาก artifact ตรงที่ cache หายได้โดยไม่กระทบความถูกต้อง — แค่ทำให้ช้าลง pipeline ก็ยังรันได้เหมือนเดิม
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }} # key เปลี่ยนเมื่อ lock เปลี่ยนเคล็ดอยู่ที่ cache key: ผูกกับ hash ของไฟล์ lock — ถ้า dependencies ไม่เปลี่ยน key เดิม ใช้ cache เดิม เร็วปรู๊ด; ถ้า lock เปลี่ยน key เปลี่ยน CI สร้าง cache ใหม่ให้ ไม่มีทางใช้ของเก่าผิดเวอร์ชัน
| Artifact | Cache | |
|---|---|---|
| เพื่ออะไร | ส่งผลลัพธ์ข้าม job / เก็บไว้ดู | เร่งความเร็วด้วยการใช้ซ้ำ |
| ถ้าหายไป | pipeline พัง— เพราะ deploy ไม่มีของ | แค่ช้าลง — สร้างใหม่ได้ |
| ขอบเขต | ภายในการรันเดียว (ข้าม job) | ข้ามการรัน (ข้ามเวลา) |
✅ สรุปบทที่ 6 — artifact = ส่ง "ผลงานที่ต้องใช้ต่อ" ข้าม job (build→deploy) ถ้าหาย pipeline พัง · cache = เก็บ "ของที่สร้างใหม่ได้" (deps) ไว้ใช้ซ้ำข้ามการรันเพื่อความเร็ว ถ้าหายแค่ช้าลง · cache key ผูกกับ hash ของ lock file เพื่อกันใช้ของเก่าผิดเวอร์ชัน
Matrix & การขนานงาน#
ถ้าโปรแกรมของคุณต้องทำงานได้บน Node 18, 20 และ 22 ทั้งบน Linux และ Windows คุณจะเขียน job ซ้ำกัน 6 อันไหม? ไม่ต้อง — matrix คือเครื่องมือที่สร้างชุด job ขนานให้อัตโนมัติจากการประกาศมิติเพียงไม่กี่บรรทัด
7.1 Matrix — ทดสอบหลายมิติพร้อมกัน
jobs:
test:
strategy:
fail-fast: false # ช่องหนึ่งตก ไม่ยกเลิกช่องอื่น — เห็นภาพครบ
matrix:
node: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }} # แต่ละ job หยิบค่าจากช่องของตัวเอง
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}7.2 fail-fast — เห็นภาพครบ หรือ ประหยัดทรัพยากร
fail-fast: true (ค่าเริ่มต้น) หมายถึง "พอช่องใดช่องหนึ่งตก ให้ยกเลิกช่องที่เหลือทันที" — ประหยัดเวลา/เครื่อง เหมาะตอนแค่อยากรู้ว่า "ผ่านหรือไม่ผ่าน" ส่วน fail-fast: false ปล่อยให้ทุกช่องรันจบ เหมาะตอน debug เพราะคุณอยากเห็นว่า พังเฉพาะ Windows + Node 18 หรือพังทุกที่ — ข้อมูลนี้ชี้ต้นตอได้ทันที
7.3 ความเร็วรวมของ pipeline
เพราะ job ขนานกัน เวลารวมของ pipeline ไม่ใช่ผลบวกของทุก job แต่เท่ากับ เส้นทางที่ยาวที่สุด (critical path) เหมือนหลายคนช่วยกันทำงานพร้อมกัน งานเสร็จเมื่อคนที่ช้าที่สุดเสร็จ การออกแบบ pipeline ให้เร็วจึงเป็นเรื่องของ "แตกงานอิสระให้ขนานกันให้มากที่สุด แล้วไล่บีบ job ที่อยู่บนเส้นทางวิกฤต"
✅ สรุปบทที่ 7 — matrix ขยายมิติที่ประกาศ (เช่น node × os) เป็นชุด job ขนานอัตโนมัติ ครอบคลุมหลายสภาพแวดล้อมด้วยโค้ดครั้งเดียว ·
fail-fast: falseให้ทุกช่องรันจบเพื่อเห็นภาพครบตอน debug · เวลารวมของ pipeline = เส้นทางที่ยาวที่สุด ไม่ใช่ผลบวก — เร่งได้ด้วยการขนานงานอิสระ
Secrets & ตัวแปร#
pipeline ที่ deploy จริงต้องใช้ความลับ: รหัส API, token, รหัสฐานข้อมูล แต่ความลับเหล่านี้ ห้ามอยู่ในโค้ดเด็ดขาด เพราะทุกอย่างใน Git ถูกบันทึกถาวรและกระจายไปทุก clone (จำคำเตือนเรื่อง .env ในบทที่ 3 ของเล่ม Git ได้ไหม) บทนี้คือวิธีจัดการความลับให้ถูกต้อง
8.1 ตัวแปรกับความลับ — ต่างกันที่ "ความไว"
| Variable (ตัวแปรธรรมดา) | Secret (ความลับ) | |
|---|---|---|
| เก็บอะไร | ค่าที่ไม่ลับ เช่น ชื่อ environment, region, ระดับ log | ค่าที่รั่วไม่ได้ เช่น token, รหัสผ่าน, private key |
| มองเห็นไหม | เห็นในล็อกได้ตามปกติ | ถูก mask เป็น *** ในล็อกอัตโนมัติ |
| เก็บที่ไหน | ในไฟล์ YAML หรือ settings ก็ได้ | ใน secret store ของแพลตฟอร์มเท่านั้น |
8.2 ใช้ secret อย่างถูกวิธี
คุณตั้งค่า secret ไว้ใน settings ของ repo (ไม่ใช่ในไฟล์) แล้วอ้างถึงด้วยไวยากรณ์พิเศษ — ค่าจริงจะถูกฉีดเข้ามาตอนรันเท่านั้น และถูกปิดบังในล็อก:
steps:
- run: ./deploy.sh
env:
API_TOKEN: ${{ secrets.API_TOKEN }} # ดึงจาก secret store, mask อัตโนมัติ
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}กลไกการ mask สำคัญมาก: ต่อให้สคริปต์ของคุณเผลอ echo ค่า secret ออกมา แพลตฟอร์มจะแทนที่ด้วย *** ในล็อกให้ก่อนแสดง — เป็นตาข่ายกันพลาดชั้นสุดท้าย (แต่อย่าพึ่งมันแทนความระมัดระวัง)
8.3 ขอบเขตและการสืบทอด
แพลตฟอร์มสมัยใหม่ให้ตั้ง secret ได้หลายระดับ: ระดับ organization (ใช้ร่วมหลาย repo), ระดับ repo, และระดับ environment (เช่น secret ของ production แยกจาก staging — บทที่ 10) หลักคือ ให้สิทธิ์น้อยที่สุดเท่าที่จำเป็น: secret ของ production ไม่ควรเข้าถึงได้จาก pipeline ของ branch ทดลอง
✅ สรุปบทที่ 8 — ความลับห้ามอยู่ในโค้ด/Git เด็ดขาด · variable = ค่าไม่ลับ (เห็นในล็อกได้), secret = ค่าไว (mask เป็น
***อัตโนมัติ เก็บใน secret store) · อ้างด้วย${{ secrets.X }}ฉีดเข้าตอนรันเท่านั้น · ตั้ง secret หลายระดับและให้สิทธิ์น้อยที่สุด · ระวัง PR จาก fork เข้าถึง secret — ช่องโหว่ pwn request
LEVEL 3 · เข้าสู่ CD
CI → CD: Delivery vs Deployment#
ถึงครึ่งหลังของเล่ม — เราข้ามจาก "ตรวจว่าโค้ดดี" (CI) ไปสู่ "ส่งโค้ดขึ้นใช้งานจริง" (CD) บทนี้ปักหมุดเส้นแบ่งที่บทที่ 2 เกริ่นไว้ ให้ชัดถึงระดับปฏิบัติ เพราะการเลือกผิดระหว่าง Delivery กับ Deployment คือการเลือกระดับความเสี่ยงที่ทีมรับได้
9.1 เส้นแบ่งเดียว: ใครเป็นคนกดปุ่มขึ้น production
9.2 แล้วควรเลือกแบบไหน
| Continuous Delivery | Continuous Deployment | |
|---|---|---|
| การขึ้น prod | อัตโนมัติถึงประตู แล้วคนกดอนุมัติ | อัตโนมัติทั้งเส้น ไม่มีคนคั่น |
| ต้องการ | ความเชื่อมั่นปานกลาง + จังหวะที่คนคุม | ชุดทดสอบ + monitoring ที่เชื่อมั่นสูงมาก |
| เหมาะกับ | ระบบที่ปล่อยผิดแล้วกระทบหนัก, มีข้อบังคับ | เว็บ/บริการที่ปล่อยถี่ ๆ และ rollback ได้เร็ว |
| ความถี่ปล่อย | เมื่อทีมพร้อม (วัน/สัปดาห์) | หลายครั้งต่อวันได้ |
คำแนะนำเชิงปฏิบัติ: เริ่มที่ Continuous Delivery เกือบทุกครั้ง ปล่อยให้ pipeline เตรียมทุกอย่างให้พร้อมโดยอัตโนมัติ แต่คงปุ่มที่มนุษย์กดไว้ก่อน เมื่อคุณ deploy ด้วยปุ่มนั้นหลายสิบครั้งจนไม่เคยมีเซอร์ไพรส์ และมี monitoring/rollback ที่ไว้ใจได้ ค่อยตัดปุ่มออกเพื่อก้าวสู่ Continuous Deployment — การก้าวข้ามนี้ควรมาจากความเชื่อมั่นที่พิสูจน์แล้ว ไม่ใช่ความมักง่าย
9.3 สิ่งที่ทำให้ Deployment เต็มรูปแบบเป็นไปได้
การปล่อยขึ้น prod อัตโนมัติจะปลอดภัยก็ต่อเมื่อมีตาข่ายรองรับครบ: ชุดทดสอบครอบคลุมพอจะเชื่อได้, monitoring ที่จับได้ทันทีเมื่อ prod เริ่มเพี้ยน, ความสามารถ rollback อัตโนมัติเมื่อสุขภาพระบบตก (บทที่ 11), และกลยุทธ์ปล่อยที่จำกัดวงความเสียหาย (เช่น canary) ขาดตาข่ายเหล่านี้ Continuous Deployment ก็คือการวิ่งโดยไม่มีเบรก
✅ สรุปบทที่ 9 — Delivery และ Deployment ใช้ CI/build ชุดเดียวกัน ต่างกันที่ มี "ประตูอนุมัติของมนุษย์" ก่อนขึ้น prod หรือไม่ · Delivery = พร้อมเสมอ คนเลือกเวลาปล่อย, Deployment = ผ่าน CI แล้วขึ้นเอง · เริ่มที่ Delivery ก่อน แล้วค่อยขยับเมื่อความเชื่อมั่นพิสูจน์แล้ว · Deployment เต็มรูปต้องมี test + monitoring + rollback + กลยุทธ์ปล่อยรองรับ
Environments & การ Deploy#
"production" ไม่ใช่ที่เดียวที่โค้ดไป โค้ดเดินผ่านหลายสภาพแวดล้อม (environment) ก่อนถึงผู้ใช้จริง บทนี้คือวิธีจัดสภาพแวดล้อมเหล่านั้นให้เป็นทางเดินที่มีด่านป้องกัน
10.1 บันไดของ environment
staging ตั้งให้เหมือน prod มากที่สุดเพื่อจับปัญหาก่อนถึงผู้ใช้ · ประตูป้องกันคั่นก่อน prod- dev / preview — deploy อัตโนมัติทุก branch/PR ไว้ลองของ พังได้ ไม่กระทบใคร
- staging — ตั้งให้เหมือน production มากที่สุด (ข้อมูล โครงสร้าง การตั้งค่าใกล้เคียง) เพื่อจับปัญหาที่จะเกิดบนจริง ก่อนมันเกิดจริง
- production — ของจริง มีด่านป้องกันแน่นหนาที่สุด
10.2 Environment protection — ด่านก่อน production
แพลตฟอร์มให้ผูกกฎป้องกันกับแต่ละ environment สิ่งเหล่านี้คือ "ประตูอนุมัติ" จากบทที่ 9 ในรูปธรรม:
- required reviewers — ต้องมีคนที่กำหนดกดอนุมัติ ก่อน job ที่ deploy เข้า prod จะเริ่มทำงาน
- wait timer — หน่วงเวลาก่อน deploy ให้มีช่วงยกเลิกได้ทัน
- branch restriction — เฉพาะ
main(หรือ tag ที่กำหนด) เท่านั้นที่ deploy เข้า prod ได้ - scoped secrets — secret ของ prod ผูกกับ environment นี้ pipeline จาก branch อื่นแตะไม่ได้
jobs:
deploy-prod:
needs: build
runs-on: ubuntu-latest
environment: production # ผูกกับ environment "production" — กฎป้องกันมีผลทันที
steps:
- uses: actions/download-artifact@v4
with: {name: dist}
- run: ./deploy.sh production
env:
DEPLOY_KEY: ${{ secrets.PROD_DEPLOY_KEY }}เมื่อ job นี้ผูก environment: production ที่มี required reviewer แล้ว มันจะ หยุดรอ ที่หน้า Actions จนกว่าจะมีคนกดอนุมัติ — นี่แหละคือ "ปุ่มที่มนุษย์กด" ในบทที่ 9 ที่ทำงานจริง
🧭 ทำไม staging ต้องเหมือน prod — บั๊กที่แพงที่สุดคือบั๊กที่ "โผล่เฉพาะบน prod" — มักเกิดเพราะ staging ต่างจาก prod (เวอร์ชัน, ข้อมูล, ตัวแปร) ยิ่ง staging เหมือน prod เท่าไร โอกาสที่ prod จะเซอร์ไพรส์ยิ่งน้อยลงเท่านั้น ลงทุนทำ staging ให้เหมือนคุ้มเสมอ
✅ สรุปบทที่ 10 — โค้ดไต่บันได dev → staging → production · staging ตั้งให้เหมือน prod เพื่อจับบั๊กก่อนถึงผู้ใช้ · ผูก job กับ
environment:เพื่อเปิดกฎป้องกัน: required reviewer, wait timer, branch restriction, scoped secret · job ที่ผูก environment ที่ต้องอนุมัติจะหยุดรอคนกด — ปุ่มของบทที่ 9 ในทางปฏิบัติ
กลยุทธ์ Deploy & Rollback#
"deploy" ไม่ได้มีแบบเดียว วิธีที่คุณเปลี่ยนจากเวอร์ชันเก่าเป็นใหม่บน production กำหนดว่า ถ้าเวอร์ชันใหม่มีปัญหา จะมีผู้ใช้กี่คนที่เจอ และคุณถอยกลับได้เร็วแค่ไหน นี่คือหัวใจของ CD ที่ปลอดภัย
11.1 สี่กลยุทธ์หลัก
| กลยุทธ์ | ทำอย่างไร | แลกอะไร |
|---|---|---|
| Recreate | ดับเวอร์ชันเก่าทั้งหมด แล้วเปิดใหม่ | ง่ายสุด แต่มีช่วง downtime |
| Rolling | ทยอยเปลี่ยนเครื่องทีละกลุ่ม | ไม่ดับ แต่ช่วงเปลี่ยนมีสองเวอร์ชันปนกัน |
| Blue-Green | ยกชุดใหม่ขึ้นคู่ขนาน แล้วสลับ traffic ทีเดียว | rollback ไวมาก แต่ใช้ทรัพยากร 2 เท่าชั่วคราว |
| Canary | ปล่อยให้ผู้ใช้ส่วนน้อยก่อน เฝ้าดู แล้วค่อยขยาย | จำกัดวงความเสียหายดีสุด แต่ซับซ้อนสุด |
11.2 Rollback — แผนถอยที่ต้องมีก่อนเดินหน้า
กฎเหล็กของ CD: อย่า deploy อะไรที่คุณถอยกลับไม่ได้ ความสามารถ rollback ที่เร็วและเชื่อถือได้ คือสิ่งที่ทำให้กล้าปล่อยบ่อย เพราะ "ปล่อยแล้วพัง" ไม่ใช่หายนะ แค่กด/รันถอยกลับเวอร์ชันก่อนหน้า Blue-Green ทำ rollback ได้แทบจะทันที (เสียบ router กลับ) ส่วนระบบที่ดีจะ rollback อัตโนมัติ เมื่อ health check หรือ metric หลังปล่อยตก โดยไม่ต้องรอคนสังเกต
✅ สรุปบทที่ 11 — สี่กลยุทธ์: recreate (ง่าย มี downtime), rolling (ทยอย ไม่ดับ), blue-green (ยกคู่ขนาน สลับ/ถอยไว), canary (ปล่อยทีละน้อย จำกัดวงดีสุด) · กฎเหล็ก: อย่า deploy สิ่งที่ถอยกลับไม่ได้ — rollback ที่ไว (อัตโนมัติยิ่งดี) คือเหตุผลที่กล้าปล่อยบ่อย · ทำ DB migration แบบเข้ากันได้สองทางเพื่อให้ถอยได้เสมอ
LEVEL 4 · ระดับเทพ
ความปลอดภัยของ Pipeline#
pipeline ของคุณมีกุญแจสู่ production มันจึงเป็น เป้าหมายการโจมตีชั้นดี — เจาะ pipeline ได้ เท่ากับเจาะทุกอย่างที่มันเข้าถึง บทนี้คือหลักการทำให้ pipeline แข็งแกร่ง ซึ่งเป็นทักษะที่แยกมือสมัครเล่นออกจากมืออาชีพ
12.1 Supply chain — โค้ดที่คุณไม่ได้เขียนแต่ให้สิทธิ์เต็ม
ทุก uses: someone/action@v4 คือการรันโค้ดของคนอื่นในสภาพแวดล้อมที่เข้าถึง secret ของคุณ ถ้าเจ้าของ action นั้นถูกแฮ็กหรือกลายเป็นคนร้าย เขารันอะไรใน pipeline คุณก็ได้ ป้องกันด้วย:
- ปักหมุดเป็น commit SHA ไม่ใช่ tag —
uses: actions/checkout@a1b2c3d...เพราะ tag อย่าง@v4ถูกย้ายไปชี้โค้ดร้ายได้ แต่ SHA ผูกกับเนื้อหาตายตัว (หลักการ SHA จากบทที่ 2 ของเล่ม Git ตรง ๆ) - ใช้เฉพาะ action ที่เชื่อถือได้ และตรวจก่อนอัปเกรด
- ล็อกเวอร์ชัน dependencies ด้วย lock file เสมอ
12.2 สิทธิ์น้อยที่สุด (least privilege)
โดยปริยาย token ของ pipeline มักได้สิทธิ์กว้างเกินจำเป็น จงหดให้เหลือเท่าที่ใช้จริง งานที่แค่รันเทสต์ไม่ควรมีสิทธิ์เขียน repo:
permissions:
contents: read # อ่านโค้ดได้พอ ไม่ให้สิทธิ์เขียนโดยไม่จำเป็นหลักคิด: ถ้า pipeline ถูกเจาะ ความเสียหายถูกจำกัดด้วยสิทธิ์ที่มันมี — ให้น้อย เสียหายน้อย
12.3 OIDC — เลิกเก็บกุญแจถาวร
วิธีเก่าคือเก็บ credential ระยะยาวของ cloud ไว้เป็น secret ซึ่งถ้ารั่วก็ใช้ได้ตลอดจนกว่าจะเพิกถอน วิธีใหม่คือ OIDC (OpenID Connect): pipeline แลก "ตัวตนที่ cloud เชื่อถือ" เป็น credential ชั่วคราวที่หมดอายุในไม่กี่นาที สำหรับการรันครั้งนั้นโดยเฉพาะ ไม่มีกุญแจถาวรให้รั่วอีกต่อไป — นี่คือมาตรฐานที่ทีมจริงจังขยับไปใช้
✅ สรุปบทที่ 12 — pipeline คือเป้าโจมตีเพราะถือกุญแจสู่ prod · ปักหมุด action ด้วย commit SHA ไม่ใช่ tag (ผูกเนื้อหาตายตัวเหมือน SHA ใน Git) · ให้ สิทธิ์น้อยที่สุด เพื่อจำกัดความเสียหายเมื่อถูกเจาะ · ใช้ OIDC แทน credential ถาวรเพื่อเลิกเก็บกุญแจที่รั่วได้ · กันโค้ดจาก fork ไม่ให้แตะ secret/สิทธิ์
Runners & ความเร็วของ Pipeline#
เมื่อทีมโตและ pipeline รันวันละหลายร้อยครั้ง สองเรื่องกลายเป็นปัญหาจริง: เครื่องที่รัน (runner) และเวลาที่ใช้ บทนี้คือมุมมองวิศวกรรมของการ scale CI/CD
13.1 Hosted vs Self-hosted — เลือกอย่างมีเหตุผล
| Hosted runner | Self-hosted runner | |
|---|---|---|
| ใครดูแล | แพลตฟอร์ม — เกิดใหม่สะอาดทุกครั้ง | คุณเอง — ติดตั้ง/อัปเดต/รักษาความปลอดภัย |
| เหมาะเมื่อ | งานทั่วไป เริ่มเร็ว ไม่อยากดูแล | ต้องการ GPU/ฮาร์ดแวร์พิเศษ, เข้าถึงเน็ตภายใน, คุมต้นทุนสเกลใหญ่ |
| ความเสี่ยง | ต่ำ | สูงถ้าใช้กับ public repo — โค้ดจาก PR อาจฝังตัวในเครื่องที่ใช้ซ้ำ |
13.2 ทำให้ pipeline เร็วขึ้น
pipeline ช้าคือ pipeline ที่บั่นทอนทุกคน เครื่องมือเร่งความเร็วเรียงตามผลที่ได้:
- ขนานงาน — แตก job อิสระให้รันพร้อมกัน (บทที่ 7) ลดเส้นทางวิกฤต
- cache — เลิกติดตั้ง dependencies ซ้ำ (บทที่ 6)
- ล้มเร็ว — เรียงด่านถูก/เร็ว (lint) ไว้หน้า ด่านแพง (E2E) ไว้หลัง (บทที่ 5)
- รันเฉพาะที่เปลี่ยน — ใน monorepo ใหญ่ ตรวจเฉพาะส่วนที่ถูกแก้ด้วย path filter แทนการรันทั้งหมด
- shallow clone —
git clone --depth 1ดึงแค่ commit ล่าสุด (ตรงกับบทที่ 15 ของเล่ม Git) ลดเวลา checkout repo ใหญ่
13.3 ทำ pipeline เป็นโค้ดที่ดูแลได้
เมื่อ workflow เยอะขึ้น มันก็คือโค้ดเบสอีกชุดที่ต้องดูแล หลีกเลี่ยงการก๊อป YAML ซ้ำไปมาด้วย reusable workflow และ composite action — แยกขั้นตอนที่ใช้ซ้ำออกเป็นชิ้นกลางแล้วเรียกใช้ เหมือนแยกฟังก์ชันในโค้ดทั่วไป pipeline ที่ดีถูกรีวิว เวอร์ชัน และรีแฟกเตอร์เหมือนโค้ด production
✅ สรุปบทที่ 13 — hosted runner สะดวกและสะอาดทุกครั้ง, self-hosted ใช้เมื่อต้องการฮาร์ดแวร์/เครือข่ายพิเศษ แต่ อันตรายกับ public repo — ใช้เป็น ephemeral และแยกเครือข่าย · เร่งความเร็ว: ขนานงาน + cache + ล้มเร็ว + รันเฉพาะที่เปลี่ยน + shallow clone · จัดการ workflow เป็นโค้ดด้วย reusable workflow/composite action
เทียบแพลตฟอร์ม & บทสรุป#
ตลอดเล่มเราใช้ GitHub Actions เป็นตัวอย่าง แต่ย้ำมาตลอดว่าแนวคิดข้ามแพลตฟอร์มได้ บทสุดท้ายนี้พิสูจน์คำกล่าวนั้น แล้วม้วนทุกอย่างกลับมาเป็นแก่นที่ถือกลับไปใช้ได้จริง
14.1 คำเดียวกัน คนละชื่อ
ทุกแพลตฟอร์มมีลำดับชั้นเดียวกับบทที่ 2 เปลี่ยนแค่คำศัพท์และรูปแบบไฟล์:
| แนวคิด | GitHub Actions | GitLab CI | Jenkins |
|---|---|---|---|
| ไฟล์นิยาม | .github/workflows/*.yml | .gitlab-ci.yml | Jenkinsfile |
| หน่วยรวม | workflow | pipeline | pipeline |
| กลุ่มงาน | job | job (จัดกลุ่มด้วย stage) | stage |
| เครื่องรัน | runner | runner | agent / node |
| ของสำเร็จรูป | action | template / include | plugin / shared library |
นี่คือเหตุผลที่เล่มนี้เน้น "แนวคิด" — เรียนกลไกหนึ่งครั้ง ย้ายแพลตฟอร์มเมื่อไรก็แค่เรียนคำศัพท์ใหม่ ไม่ต้องเรียนวิธีคิดใหม่ CircleCI, Azure Pipelines, Travis และอื่น ๆ ก็เข้าแม่พิมพ์เดียวกันนี้
14.2 หลักปฏิบัติที่ดี — รวมทั้งเล่ม
- เก็บ pipeline ไว้กับโค้ด (pipeline-as-code) เวอร์ชันคู่กัน รีวิวคู่กัน
- เร็วและล้มเร็ว — ด่านถูกอยู่หน้า ขนานงานให้มาก cache ให้พอ
- บังคับด้วยระบบ ไม่ใช่วินัย — branch protection ทำให้ "CI ไม่เขียว = merge ไม่ได้"
- เริ่มที่ Delivery คงปุ่มมนุษย์ไว้ก่อน แล้วค่อยขยับสู่ Deployment เมื่อความเชื่อมั่นพิสูจน์แล้ว
- ถอยได้เสมอ — ไม่ deploy สิ่งที่ rollback ไม่ได้ migration เข้ากันได้สองทาง
- ความปลอดภัยไม่ใช่ของเสริม — pin SHA, least privilege, OIDC, กันโค้ด fork แตะ secret
14.3 บทสรุปทั้งเล่ม — แก่นที่ถือกลับไป
ถ้าจำได้แค่ไม่กี่อย่างจากเล่มนี้ ขอให้เป็นสิ่งเหล่านี้ เพราะทุกเทคนิคงอกออกมาจากมัน:
- CI/CD มีค่าเพราะมัน ย่นวงจรป้อนกลับ — จับปัญหายิ่งเร็ว ยิ่งถูก
- ทุก pipeline คือ event → workflow → job (ขนาน) → step (เรียง) บน runner — โครงเดียวข้ามทุกเครื่องมือ
- CI/CD คือ สามชั้นซ้อนกัน Integration ⊂ Delivery ⊂ Deployment เส้นแบ่งคือ "มีคนกดปุ่มไหม"
- ความปลอดภัยและ ความสามารถถอยกลับ คือสิ่งที่ทำให้ "ปล่อยบ่อย" เป็นเรื่องกล้าทำ ไม่ใช่เรื่องเสี่ยง
- pipeline คือ โค้ด — เวอร์ชัน รีวิว และดูแลมันด้วยมาตรฐานเดียวกับโค้ด production
🧭 เส้นทางต่อจากนี้ — วิธีเก่งขึ้นจริงคือลงมือ: เอา repo ทดลองใส่
ci.ymlง่าย ๆ จากบทที่ 3 แล้วค่อย ๆ เติมทีละชั้น — เพิ่ม matrix, cache, แล้ว deploy ขึ้น environment ฟรีสักที่ จากนั้นลองพังมันดู (ทำเทสต์ให้ตก, ทำ deploy ให้ล้ม) เพื่อเห็นว่า fail loud กับ rollback ทำงานอย่างไร — pipeline ที่คุณเคยทำพังและกู้คืนเอง สอนได้ลึกกว่าทุกคู่มือ
✅ สรุปบทที่ 14 — ทุกแพลตฟอร์มใช้ลำดับชั้นเดียวกัน ต่างแค่คำศัพท์/ไฟล์ — เรียนแนวคิดครั้งเดียวย้ายได้หมด · หลักปฏิบัติ: pipeline-as-code, เร็ว+ล้มเร็ว, บังคับด้วยระบบ, เริ่มที่ Delivery, ถอยได้เสมอ, ความปลอดภัยมาก่อน · แก่น: ย่นวงจรป้อนกลับ · โครง event→job→step · สามชั้น CI/CD · ถอยได้+ปลอดภัย · pipeline คือโค้ด — เท่านี้คุณก็จาก 0 ถึง Hero ของ CI/CD แล้ว
— จบหลักสูตร —
CI/CD 0 → Hero — จาก commit สู่ production อัตโนมัติ · เล่มต่อจาก Git 0 → Hero · เขียนเป็นภาษาไทย พร้อมไดอะแกรมทุกหัวข้อ
วิธีใช้ให้คุ้ม: อ่านไล่ระดับ Level 0–1 ก่อนเพื่อจับแบบจำลองความคิด แล้วลงมือสร้าง pipeline จริงควบคู่ไปทีละบท · ตัวอย่างยึด GitHub Actions แต่ทุกแนวคิดย้ายไป GitLab CI / Jenkins / CircleCI ได้ (บทที่ 14)