ระบบ CI/CD และการเฝ้าระวังคุณภาพข้อมูล (CI/CD, Monitoring & Testing)
5.5 ระบบ CI/CD การทดสอบ และการเฝ้าระวังคุณภาพข้อมูล
ระบบ DataOps ที่สมบูรณ์ต้องมี CI/CD Pipeline ที่รันการทดสอบ Data Quality อัตโนมัติก่อน Deploy ร่วมกับระบบ Observability ด้วย Prometheus & Grafana เพื่อเฝ้าระวัง Metrics สำคัญตลอด 24 ชั่วโมง
- Step 1: Data Ingestion & Event Processing
- Step 2: Distributed Computation & State Management
- Step 3: Orchestration & Resource Allocation
1. CI/CD Pipeline & GitHub Actions Self-Hosted Runners
Learning Progression
- [BASIC] ปูพื้นฐานภาษาเข้าใจง่าย - เข้าใจคอนเซปต์ภาพรวมและการแก้ปัญหาเบื้องต้น
- [INTERMEDIATE] โค้ด/คอนฟิกไวยากรณ์จริง - การเขียนโค้ดเพื่อใช้งานจริงในระบบ
- [PROFESSIONAL] Under-the-hood & Performance/FinOps - กลไกเบื้องลึกและการรีดประสิทธิภาพ
Real-World Enterprise Scenario
เคสระบบการเงิน/Big Tech: การรองรับ Transaction จำนวนมหาศาลต่อวินาทีพร้อมประกัน Data Integrity สูงสุด โดยใช้สถาปัตยกรรมที่ยืดหยุ่นและการมอนิเตอร์ระดับสูง
ทฤษฎีและกลไกการทำงาน (How it works): การนำโค้ดขึ้นระบบต้องผ่านด่าน CI/CD อัตโนมัติ (เช่น รัน SQLFluff Linting หรือ Dry-Runs) ในองค์กรที่ต้องการความปลอดภัยสูงและห้ามโค้ดหรือข้อมูลไหลออกสู่อินเทอร์เน็ตสาธารณะ จะไม่ใช้เซิร์ฟเวอร์ CI กลางของ GitHub แต่จะติดตั้ง **GitHub Actions Self-Hosted Runners** ซึ่งเป็นเอเจนต์ที่รันอยู่บนเซิร์ฟเวอร์หรือ Kubernetes Cluster ภายใน VPC ของบริษัทเอง ทำให้สามารถเข้าถึงฐานข้อมูลภายในเพื่อรันเทสได้อย่างปลอดภัย
# GitHub Actions snippet configured for a Self-Hosted Runner
name: Data Pipeline CI (Internal)
on: [push, pull_request]
jobs:
lint-and-dryrun:
runs-on: [self-hosted, linux, data-eng-vpc] # Target internal runner
steps:
- uses: actions/checkout@v3
- name: Run SQLFluff and Dry Run against internal Dev DB
run: |
pip install sqlfluff
sqlfluff lint models/ --dialect bigquery
dbt compile --target dev # Communicates with DB inside private network
Use Case ในชีวิตจริง (Real-world Scenario): ธนาคารแห่งหนึ่งป้องกันไม่ให้เซิร์ฟเวอร์รันไทม์ของ GitHub เข้าถึงฐานข้อมูลลูกค้า การใช้ Self-Hosted Runner ช่วยให้ขั้นตอน CI สามารถยิง Dry-run เช็คความถูกต้องของสกีมากับฐานข้อมูลภายในได้โดยไม่ต้องเปิดพอร์ต Firewall สู่โลกภายนอก
ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): หาก Runner ตัวเดิมถูกใช้งานซ้ำๆ (Persistent) อาจมีไฟล์ขยะของเทสรอบก่อนหน้าตกค้างทำให้เทสพัง แก้ไขโดยใช้ Ephemeral Runners (เช่น ARC - Actions Runner Controller บน K8s) ที่จะสร้างและทำลายตัวเองทิ้งทุกครั้งที่รันจบ
2. ยุทธวิธีการส่งมอบข้อมูลแบบไร้รอยต่อ (Blue-Green Deployments)
ทฤษฎีและกลไกการทำงาน (How it works): เพื่อหลีกเลี่ยงตารางข้อมูลอ่านไม่ได้ระหว่างกำลังโหลด (Downtime) วิศวกรข้อมูลจะนำเทคนิค **Blue-Green Deployment** มาใช้: - **Blue Environment**: ตารางที่กำลังใช้งานจริงให้ Dashboard อ่าน - **Green Environment**: ตารางโคลนสเปคใหม่ที่กำลังถูกประมวลผลอยู่เบื้องหลัง เมื่อระบบ Green ประมวลผลและทดสอบ Data Quality ผ่าน จึงจะใช้คำสั่งสลับ View (Alias swapping) ชี้เป้าไปที่ Green ทันที (Zero Downtime)
-- SQL demonstrating seamless blue-green schema swapping via aliases
CREATE OR REPLACE VIEW analytical_marts.active_sales_mart AS
SELECT * FROM analytical_marts.sales_mart_green; -- Swap reference to updated green table
Use Case ในชีวิตจริง (Real-world Scenario): โมเดลคำนวณรายได้บริษัทต้องใช้เวลาประมวลผล 2 ชั่วโมง ทีมงานใช้เทคนิค Blue-Green รันโค้ดชุดใหม่ใส่ตาราง Green จนเสร็จ แล้วค่อยสลับ View ให้ผู้บริหารดู ทำให้ผู้บริหารไม่เคยเจอตารางที่ว่างเปล่าระหว่าง 2 ชั่วโมงนั้น
ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): การลบตาราง Blue ทิ้งทันทีอาจทำให้คิวรี่ที่กำลังทำงานอยู่ค้างและล้มเหลว (In-flight query failure) แก้ไขโดยหน่วงเวลารอ (Time-travel/Grace period) ประมาณ 30 นาทีก่อนจะ Drop ตาราง Blue ทิ้ง
3. Prometheus Metrics Collection & Grafana Alert Rules
ทฤษฎีและกลไกการทำงาน (How it works): การมอนิเตอร์ระดับแพลตฟอร์มใช้ **Prometheus** วิ่งดึง (Scrape) สถิติตัวชี้วัดการทำงาน (Metrics) เช่น CPU, RAM, Network I/O จากพอร์ตของแอปพลิเคชัน (เช่น Airflow statsd หรือ Spark exporter) ตามรอบเวลา จากนั้นนำข้อมูลไปสร้างแดชบอร์ดบน **Grafana** และเขียน **Alert Rules** ประเมินผลแบบเรียลไทม์ หากค่าพุ่งทะลุเกณฑ์ที่กำหนด Grafana จะส่งสัญญาณเตือน (Alert) ออกไปทันที
# Grafana Alerting Rule YAML snippet for high memory usage
apiVersion: 1
groups:
- orgId: 1
name: InfrastructureAlerts
rules:
- alert: SparkExecutorOOMWarning
expr: (process_resident_memory_bytes / system_total_memory_bytes) > 0.85
for: 5m
labels:
severity: warning
annotations:
summary: "Spark Executor {{ $labels.instance }} memory > 85%"
Use Case ในชีวิตจริง (Real-world Scenario): Grafana Alert Rule จับได้ว่า Kafka Broker ตัวหนึ่งมีการใช้งานดิสก์เกิน 85% ติดต่อกัน 5 นาที จึงยิงข้อความเตือนเข้า Slack ทีม Data Platform ก่อนที่ดิสก์จะเต็ม 100% จนระบบล่ม ทำให้ทีมขยายดิสก์ได้ทันเวลา
ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): ปัญหา Alert Spike หากตั้งเงื่อนไขไวไป (เช่น แรมเกิน 90% แค่ 1 วินาทีก็เตือนเลย) จะสร้างเสียงเตือนขยะ (Alert Fatigue) แก้ไขโดยกำหนดหน่วงเวลาประเมินด้วยคำสั่ง `for: 5m` ใน Alert Rule เพื่อกรอง Noise ออก
4. Data Observability & Data Drift / Concept Drift Alerting
ทฤษฎีและกลไกการทำงาน (How it works): แตกต่างจาก Hardware Monitoring ระบบ **Data Observability** จะตรวจสอบเนื้อหาข้อมูล (Data Health) - **Data Drift**: ข้อมูลต้นทางมีลักษณะทางสถิติเปลี่ยนไป (เช่น ค่าเฉลี่ยรายได้ลูกค้าจาก 50,000 พุ่งเป็น 200,000) - **Concept Drift**: พฤติกรรมเป้าหมายเปลี่ยนไปจนทำให้โมเดล ML ไม่แม่นยำเหมือนเดิม เครื่องมือประเมิน (เช่น Great Expectations หรือ Evidently) จะตรวจสอบค่าทางสถิติของข้อมูลทุกแบตช์ก่อนอนุญาตให้โมเดล ML ทำงานต่อ
# Python logic checking for Data Drift using evidently
from evidently.report import Report
from evidently.metric_preset import DataDriftPreset
def check_data_drift(reference_data, current_data):
report = Report(metrics=[DataDriftPreset()])
report.run(reference_data=reference_data, current_data=current_data)
if report.as_dict()["metrics"][0]["result"]["dataset_drift"]:
raise Exception("ALERT: Significant Data Drift Detected. Halting Model Inference.")
Use Case ในชีวิตจริง (Real-world Scenario): ในช่วงโปรโมชั่น 11.11 รูปแบบการซื้อของลูกค้าเปลี่ยนไปอย่างสิ้นเชิง (Concept Drift) ระบบ Observability จับความผิดปกติของสถิติกระจายตัวได้และหยุดการยิงคำสั่งซื้ออัตโนมัติ พร้อมส่งแจ้งเตือนให้ Data Scientist เข้ามาตรวจสอบโมเดล
ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): การรันตรวจเช็คทางสถิติกับข้อมูลขนาดเพตะไบต์ทุกครั้งจะใช้เวลานานและเปลืองค่าคอมพิวต์ แก้ไขโดยใช้การสุ่มตัวอย่าง (Statistical Sampling) หรือตรวจสอบเฉพาะฟิลด์ที่มีความสำคัญระดับวิกฤต (Critical features)
5. การวางโครงสร้างเตือนภัยอัตโนมัติ (PagerDuty & Slack Webhooks)
ทฤษฎีและกลไกการทำงาน (How it works): เมื่อเกิด Incident ระบบต้องมีกระบวนการรับมืออัตโนมัติ: - **Slack Webhooks**: ยิงข้อความที่มีบริบทครบถ้วน (เช่น ลิงก์ไปที่ Airflow Log, รหัส Error) ให้ทีมรับทราบ - **PagerDuty**: ระบบจัดการ On-Call สำหรับ Incident ร้ายแรง (Severity 1) ซึ่งจะส่ง SMS, โทรเข้ามือถือ หรือ Push Notification ปลุกวิศวกรเวรดึกให้ลุกขึ้นมาซ่อมระบบ
# Python script to send structured alerts to a Slack Webhook on pipeline failures
import requests
def send_pipeline_alert(webhook_url, job_name, error_message):
alert_payload = {
"text": f" *DATA PIPELINE INCIDENT DETECTED* ",
"attachments": [{
"color": "danger",
"fields": [
{"title": "Failed Job", "value": job_name, "short": True},
{"title": "Severity", "value": "CRITICAL / P1", "short": True},
{"title": "Error Stack", "value": error_message, "short": False}
]
}]
}
requests.post(webhook_url, json=alert_payload)
Use Case ในชีวิตจริง (Real-world Scenario): ท่อส่งสรุปรายงานเงินเดือนพังทลายเนื่องจากฐานข้อมูลธนาคารต้นทางตัดเน็ตเวิร์ก โครงสร้าง PagerDuty จะโทรหา On-Call วิศวกร และหากวิศวกรไม่รับสายภายใน 5 นาที (Escalation policy) ระบบจะโทรหาหัวหน้าทีมทันที
ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): การส่งแจ้งเตือน PagerDuty สำหรับเรื่องเล็กน้อย (เช่น งานดีเลย์ 5 นาที) จะทำให้วิศวกรเหนื่อยล้าจนละเลยการเตือน แก้ไขโดยกรอง Alert เฉพาะระดับ P1 (Critical) ให้ต่อตรงหา PagerDuty ส่วนระดับอื่นๆ ให้เข้าห้อง Slack ตามปกติ
Weekend Sandbox Challenge: Build a Data Quality Check in CI
โจทย์ปฏิบัติการ: จงเขียนไฟล์ GitHub Actions Workflow โดยใช้ Self-Hosted Runner ทำการรัน Data Quality Checks เพื่อป้องกันตรรกะข้อมูลเพี้ยนขึ้นโปรดักชัน
# .github/workflows/data_quality_ci.yml
name: Data Quality CI
on: [push]
jobs:
validate:
runs-on: [self-hosted, linux, data-eng-vpc]
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
- name: Run Data quality assertions
run: |
pip install great_expectations
python -m pytest tests/data_tests.py
Senior Technical Interview Q&A
Q1: Data Observability แตกต่างจากการตรวจสอบ Infrastructure Monitoring (Prometheus/Grafana) อย่างไร?
A1: Infrastructure Monitoring ตรวจสอบสุขภาพของ "ฮาร์ดแวร์และซอฟต์แวร์" (เช่น CPU, RAM, Disk I/O, Uptime) ในขณะที่ Data Observability เจาะลึกตรวจสอบสุขภาพของ "เนื้อหาข้อมูล" (Data Health) โดยตรง เช่น มี Data Drift ไหม, จำนวน Null Value พุ่งสูงผิดปกติหรือเปล่า, หรือโครงสร้าง Schema มีการแอบลบฟิลด์หรือไม่
Q2: การใช้ GitHub Actions Self-Hosted Runners มีความสำคัญต่อโปรเจกต์ Data Engineering ขององค์กรขนาดใหญ่อย่างไร?
A2: องค์กรใหญ่เช่นธนาคารมีนโยบายความปลอดภัยเข้มงวด (VPC, Firewalls) ห้ามนำฐานข้อมูลออกสู่อินเทอร์เน็ตสาธารณะ การใช้เซิร์ฟเวอร์รันไทม์มาตรฐานของ GitHub จะไม่สามารถเข้ามารัน Test หรือ Dry-run บนฐานข้อมูลภายในได้ การนำ Self-Hosted Runner มาติดตั้งภายใน VPC ขององค์กรเองทำให้ CI/CD สามารถเข้าถึงฐานข้อมูลได้อย่างปลอดภัย 100% ปราศจากความเสี่ยงข้อมูลรั่วไหล
ข้อดี / จุดเด่น & ข้อเสีย / ข้อควรระวัง
ข้อดี / จุดเด่น
- มั่นใจว่าโค้ดใหม่จะไม่ทำให้ระบบคลังข้อมูลและท่อประมวลผลข้อมูลหลักเสียหาย
- รู้ปัญหาเน็ตเวิร์กล่มหรือเครื่องเซิร์ฟเวอร์เต็มก่อนลูกค้าส่งข้อความแจ้งเตือน
ข้อเสีย / ข้อควรระวัง
- ต้องเขียนไฟล์การทดสอบเพิ่มและดูแลรักษาโครงสร้างทดสอบค่อนข้างบ่อย
- มีค่าใช้จ่ายเพิ่มเติมจากเวลาคำนวณการประมวลผลรันเครื่องรันระบบ CI/CD
ปฏิบัติการจริง (Lab Practice)
แล็บ: ตั้งค่าท่อทดสอบ GitHub Actions สำหรับโปรเจกต์ข้อมูล
วิธีรันแล็บปฏิบัติการบนเครื่องจริง (Local Terminal Execution Blueprint)
เนื่องจากปฏิบัติการ Data Engineering / DevOps ระดับสูงต้องรันบน Environment จริง ขั้นตอนด้านล่างนี้คือคำสั่งสำหรับนำไปรันบน Terminal / Docker ในเครื่องของคุณ:
mkdir -p pipecraft-lab && cd pipecraft-lab python3 -m venv venv && source venv/bin/activate pip install --upgrade pip pandas polars pytest requests
# Run execution pipeline test
python3 -c "
import polars as pl
print(' [PipeCraft Lab] Running local pipeline engine...')
df = pl.DataFrame({'id': [1, 2, 3], 'status': ['SUCCESS', 'SUCCESS', 'AUDITED']})
print(df)
"
# Verify clean execution exit status echo " PipeCraft Local Lab Execution Completed Successfully!"
💡 คำแนะนำ & ทริกเด็ด
ในการเฝ้าระวังระบบ ให้ตั้งสัญญาณเตือน (Alert Rule) บน Grafana สำหรับสถิติ Task Failures ของ Airflow ให้เตือนทันที เพื่อแก้ไขข้อขัดข้องก่อนที่ผู้ใช้งานธุรกิจจะเห็นรายงานแดชบอร์ดผิดพลาด