การจัดการคอนเทนเนอร์และคลัสเตอร์ (Containers & Kubernetes)
5.4 การจัดการคอนเทนเนอร์และโฮสต์ (Docker & Kubernetes)
เพื่อรับประกันว่าสภาพแวดล้อมในการทดสอบตรงกับระบบงานจริง การห่อหุ้มสคริปต์ (Containerization) ช่วยคัดแยกไลบรารีและจำกัดทรัพยากรการรันอย่างมีระเบียบ
1. กลไกเคอร์เนลของ Docker: Namespaces, Cgroups, และการทำงานแบบ Copy-On-Write
ทฤษฎีและกลไกการทำงาน (How it works): เทคโนโลยีคอนเทนเนอร์ไม่ใช่การเปิดจำลองระบบ OS ทั้งหมด (Virtual Machine) แต่เป็นโปรเซสของระบบปฏิบัติการโฮสต์ปกติ ที่ถูกกักกันด้วยคุณสมบัติหลักของ Linux Kernel: - **Namespaces**: แยกมุมมองทรัพยากร เช่น โพรเซส (PID), เครือข่าย (NET), ดิสก์รูท (MNT) ไม่ให้มองเห็นกันข้ามคอนเทนเนอร์ - **Control Groups (Cgroups)**: ล็อกขีดจำกัดหน่วยประมวลผลและการใช้สิทธิ์หน่วยความจำแรม (เช่น ห้ามกินแรมเกิน 4GB) - **Copy-On-Write (CoW)**: โครงสร้างไฟล์เลเยอร์ย่อยที่ยอมให้อ่านและเขียนเฉพาะส่วนต่างของบล็อกดิสก์ ช่วยจำกัดขนาดไฟล์ภาพจำลองและสปีดการเปิดตู้คอนเทนเนอร์ได้รวดเร็ว
# Running a Docker container with strict CPU and RAM cgroup limits
docker run -d --name etl-worker-prod --memory="4g" --cpus="2" pipecraft/etl-runner:v1.0
Use Case ในชีวิตจริง (Real-world Scenario): ในเซิร์ฟเวอร์รันระบบท่อข้อมูลหลักของบริษัทที่มีแรมจำกัด 32GB การใช้ Docker ครอบท่อประมวลผลช่วยป้องกันไม่ให้สคริปต์ที่รันขัดข้องแย่งดึงหน่วยความจำจนดึงระบบความปลอดภัยอื่นล่ม
ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): ข้อมูลในคอนเทนเนอร์สูญหายเมื่อหยุดเครื่องเนื่องจากลักษณะจัดเก็บชั่วคราว (Ephemeral Storage) แก้ไขโดยผูกเส้นทางเชื่อมภายนอกเพื่อย้ายข้อมูลเขียนถาวรลงที่ตัวเก็บคลาวด์หรือไดรฟ์แชร์ภายนอก (Docker Volumes)
2. การออกแบบไฟล์คอนเทนเนอร์แบบ Multi-Stage เพื่อความปลอดภัยและมีขนาดไฟล์เล็ก
ทฤษฎีและกลไกการทำงาน (How it works): การสร้างไฟล์คอนเทนเนอร์ระดับระบบจริง (Production Image) ต้องการขนาดไฟล์ที่สั้นกระชับที่สุดและไม่มีเครื่องมือที่ไม่จำเป็นสำหรับการรัน (เช่น GCC, Curl) เพื่อปิดช่องทางแฮกเกอร์โจมตี แนวทางปฏิบัติที่ดีที่สุดคือดีไซน์คอนเทนเนอร์แบบ **Multi-Stage Build**: ในเลเยอร์แรกใช้ติดตั้งคอมไพล์ไลบรารีและเครื่องมือหนาแน่น พอมาเลเยอร์รันจริงจะดึงโคลนเฉพาะไบนารีและสคริปต์ที่บิวด์เรียบร้อยแล้วมาครอบรัน บนอิมเมจระบบปฏิบัติการขั้นพื้นฐานที่มีขนาดเล็กระดับเมกะไบต์ (เช่น Alpine หรือ Distroless)
# Production-ready Multi-Stage Dockerfile for a Python ETL job
# Stage 1: Build dependencies environment
FROM python:3.9-slim AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends gcc python3-dev
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# Stage 2: Clean execution runtime
FROM python:3.9-slim AS runner
WORKDIR /app
# Copy built packages from builder layer
COPY --from=builder /root/.local /root/.local
COPY etl_script.py .
ENV PATH=/root/.local/bin:$PATH
USER 10001
CMD ["python", "etl_script.py"]
Use Case ในชีวิตจริง (Real-world Scenario): อิมเมจวิเคราะห์ข้อมูลที่บิวด์ตามปกติมีขนาดเกือบ 1.2GB ย้ายมาเขียนจัดรูปโครงสร้าง Multi-Stage บีบย่นขนาดอิมเมจปลายทางเหลือเพียง 150MB ช่วยย่นระยะเวลาการดึงอิมเมจรันข้ามระบบ CI/CD ลงได้กว่าสิบเท่า
ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): สิทธิ์การประมวลผลไฟล์ภายในตู้ที่ใช้ root (`USER root`) ซึ่งหากโดนเจาะระบบ แฮกเกอร์จะสามารถควบคุมโฮสต์หลักได้ แก้ไขโดยการสถาปนารหัสสิทธิ์ใช้งานที่ไม่ใช่สิทธิ์แอดมิน (`USER 10001` หรือ `USER nobody`) ปลายทาง Dockerfile เสมอ
3. สถาปัตยกรรมกลุ่มเครื่อง Kubernetes: ส่วนควบคุม โหนดหลัก และโพรเซสทำงานของ Pod
ทฤษฎีและกลไกการทำงาน (How it works): **Kubernetes (K8s)** ทำหน้าที่ควบคุมสเกลคอนเทนเนอร์ระดับหมื่นตู้ขนานกัน แบ่งออกเป็น: - **Control Plane**: แกนกลางบริหารจราจร ประกอบด้วย `apiserver`, `scheduler` คอยแจกคิว และ `etcd` ฐานข้อมูลแชร์ความถูกต้องสถานะ - **Worker Nodes**: เครื่องประมวลผลจริงที่มีโฮสต์ `kubelet` คอยเปิดปิดตู้คอนเทนเนอร์ - **Pod**: หน่วยพื้นฐานขนาดเล็กที่สุด ครอบกลุ่มคอนเทนเนอร์ที่มีความจำเป็นใช้งานร่วมกัน
# Conceptual architecture of Kubernetes cluster node communication
[Control Plane (apiserver + scheduler + etcd)]
|
(Directs Node Kubelet)
|
v
[Worker Node (Kubelet + Container Runtime)]
├── Pod 1: [Container (Spark Executor)]
└── Pod 2: [Container (dbt Runner)]
Use Case ในชีวิตจริง (Real-world Scenario): เมื่อเกิดกรณีจ๊อบดึงสถิติตลาดหลักทรัพย์หยุดชะงักพังเสียหายกลางคืน K8s Control plane จะตรวจวิเคราะห์เจอโหมดพังและสั่งลบล้าง Pod ตัวที่เดี้ยง และตั้งจำสร้าง Pod ตัวใหม่ทดแทนที่โหนดอื่นอัตโนมัติ (Self-healing)
ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): การติดตั้งจ๊อบรันแต่ขาดการระบุแรมและความต้องการจำเพาะ ส่งผลให้ Pod รันกระจุกแย่งกินเครื่องเดียวกันจนเครื่อง Worker หลัก OOM พัง แก้ไขโดยกำหนดสเปคการจองทรัพยากร `resources.requests` และ `resources.limits` ในไฟล์ YAML ของ Pod
4. การจัดการจ๊อบกระจายศูนย์: คอนฟิกการทำงานด้วย K8s Jobs, CronJobs, และ ConfigMaps/Secrets
ทฤษฎีและกลไกการทำงาน (How it works): ต่างจากงานบริการ API ที่ต้องเปิดระบบค้างไว้ 24 ชั่วโมง งานข้อมูลประเภท ETL ต้องการรันจนจบภารกิจแล้วปิดตัวลง Kubernetes มีคอนเซ็ปต์: - **K8s Jobs**: รันตู้คอนเทนเนอร์ประมวลผลจนสำเร็จ (Completed) แล้วเคลียร์ปิดตัว - **CronJobs**: ตั้งเวลารัน Job ประจำคาบเวลา (เช่น รันทุก 4 ทุ่มตรง) - **ConfigMaps / Secrets**: สำหรับส่งตัวแปรสภาพแวดล้อมและรหัสลับฐานข้อมูลให้คอนเทนเนอร์โดยไม่ต้องฝังไปในไฟล์อิมเมจ
# Kubernetes CronJob YAML deployment template for daily ETL execution
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-sales-extractor
spec:
schedule: "0 22 * * *" # Runs every night at 10 PM
jobTemplate:
spec:
template:
spec:
containers:
- name: extractor
image: pipecraft/daily-loader:v1.3
envFrom:
- secretRef:
name: database-credentials-secret # Access keys kept out of code
restartPolicy: OnFailure
Use Case ในชีวิตจริง (Real-world Scenario): จ๊อบส่งสรุปอีเมลโปรโมชันไปหาลูกค้าทุกคืนเวลาตีสองตรง โดยดึงรหัสความลับผ่าน Kubernetes Secrets เพื่อต่อ API ของบริษัทส่งจดหมายได้อย่างปลอดภัย
ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): ปัญหาระบบงาน CronJob ค้างคาหาก Task เดิมยังประมวลผลไม่จบจนกระทั่งรอบเวลาถัดมารันชนกัน แก้ไขโดยปรับตั้งค่าคอนฟิก `concurrencyPolicy: Forbid` เพื่อยกเลิกรอบใหม่หากจ๊อบเก่ารันไม่จบ
5. การจัดสรรโควต้าทรัพยากรการประมวลผล และการปรับขนาดพื้นที่จัดเก็บแบบชั่วคราว
ทฤษฎีและกลไกการทำงาน (How it works): เพื่อคุมต้นทุนฮาร์ดแวร์ระบบ และค้ำประกันความเสถียรในคลัสเตอร์ขนาดใหญ่ Kubernetes เปิดโอกาสให้ผู้พัฒนาจัดระเบียบโควต้าการจัดสรร: - **Resource Quotas**: จำกัดพื้นที่หน่วยประมวลผลแรมและขนาด CPU สูงสุดในระดับ Namespace - **Ephemeral Storage Limits**: บังคับขอบเขตการเขียนข้อมูลล็อกและไฟล์ส่วนต่างชั่วคราวลงในระบบดิสก์โหนด เพื่อจำกัดการเกิดปัญหากล่องคอนเทนเนอร์ประมวลผลเขียนไฟล์ล็อกขยะบวมจนเครื่องโฮสต์หลักหน่วยจัดเก็บเต็ม
# Specifying storage bounds inside container resources template
resources:
requests:
memory: "2Gi"
cpu: "1000m"
ephemeral-storage: "1Gi"
limits:
memory: "4Gi"
cpu: "2000m"
ephemeral-storage: "2Gi" # Hard cap on temporary write disk space
Use Case ในชีวิตจริง (Real-world Scenario): จ๊อบสแกนวิเคราะห์ภาพผู้ใช้ที่มีบั๊กตัวลูปไม่ยอมเคลียร์และยิงเขียนภาพบันทึกพังดิสก์บวม ระบบ K8s ตรวจพบขนาด Ephemeral Storage เกิน 2GB ที่กำหนด และสั่งสกัดทำลาย Pod ทิ้ง เพื่อไม่ทำร้ายดิสก์เครื่องแม่ล่ม
ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): การจำกัดแรมต่ำเกินไปทำให้เกิดปัญหาสคริปต์พังและระเบิดทิ้งกลางคันด้วยสัญลักษณ์ `OOMKilled` แก้ไขโดยมอนิเตอร์ระดับกราฟการดึงทรัพยากรย้อนหลังเพื่อปรับสเปค Limits ให้เหมาะสมตามจริง
🛠️ Weekend Sandbox Challenge: Deploy Kubernetes Job for ETL Batch
โจทย์ปฏิบัติการ: จงเขียนสเปคไฟล์ Kubernetes Job YAML เพื่อสั่งเปิดรันตู้คอนเทนเนอร์ประมวลผลข้อมูลจนเสร็จสิ้น (Completed) โดยจำกัดหน่วยความจำและขีดเขียนข้อมูลลง S3
# etl-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: pipecraft-batch-etl
spec:
template:
spec:
containers:
- name: etl-runner
image: pipecraft/batch-etl-runner:latest
resources:
limits:
memory: "2Gi"
cpu: "1"
restartPolicy: OnFailure
💼 Senior Technical Interview Q&A
Q1: สถาปัตยกรรมตู้คอนเทนเนอร์ Docker แตกต่างจากการรันเครื่องเสมือน (VMs) เชิงความคุ้มค่าทรัพยากรอย่างไร และ Namespace ป้องกันอะไรในระบบ?
A1: เครื่องเสมือน VMs จะต้องโคลนจำลองระบบปฏิบัติการ (Guest OS) ขึ้นมาเปลืองแรมและใช้หน่วยเก็บดิสก์ขนาดใหญ่ ในขณะที่ Docker คอนเทนเนอร์ จะแชร์เคอร์เนลของเครื่องแม่ (Host OS) ตรงๆ โดยใช้ Namespace คอยคัดแยกขอบเขตมุมมองโพรเซสและเน็ตเวิร์กไม่ให้กวนกัน ประหยัดค่าแรม Compute อย่างมหาศาล
Q2: ระหว่าง Kubernetes Jobs และ CronJobs มีความสอดคล้องกับพฤติกรรมการใช้งานท่อส่งข้อมูลประเภท Batch ETL และ Streaming อย่างไร?
A2: Kubernetes Jobs รันโปรเซสจนเสร็จสิ้นแล้วจบการทำงาน เหมาะสมอย่างยิ่งสำหรับงานประมวลผล Batch ETL ประจำสัปดาห์หรือจ๊อบซ่อมประวัติ ส่วน CronJobs ทำหน้าที่ตามเวลารอบที่ตั้งไว้ ส่วนงาน Streaming แบบเรียลไทม์ ต้องการ Deployments ปกติที่ต้องรันค้าง 24 ชั่วโมง
🐳 Interactive Dockerfile Image Builder
Interactive Docker
เป้าหมาย: เติมคำสั่ง Dockerfile (เช่น FROM, COPY, CMD) เพื่อกำหนดสเปคแพ็กเกจโปรแกรม Python ETL Pipeline ให้รันบนคอนเทนเนอร์
ข้อดี / จุดเด่น & ข้อเสีย / ข้อควรระวัง
ข้อดี / จุดเด่น
- • รับประกันการรันของสคริปต์ประมวลผลข้อมูลได้สม่ำเสมอในทุกเครื่องระบบปฏิบัติการ
- • ง่ายต่อการทำ Auto-scaling ขยายจำนวนประมวลผลและกู้คืนงานเมื่อพังอัตโนมัติ
ข้อเสีย / ข้อควรระวัง
- • มีอัตราการเรียนรู้วิธีตั้งค่าและบริหารคลัสเตอร์ Kubernetes ที่ยากและซับซ้อนมาก
- • การจัดการพื้นที่ดิสก์จัดเก็บอิมเมจเก่าๆ อาจทำให้เซิร์ฟเวอร์เต็มได้หากไม่มีระบบเก็บกวาด
ปฏิบัติการจริง (Lab Practice)
แล็บ: เขียน Dockerfile และประกอบประกอบอิมเมจท่อข้อมูล
💡 คำแนะนำ & ทริกเด็ด
ในการเขียน Dockerfile ให้ระบุคำสั่งติดตั้ง Dependencies (เช่น RUN pip install) ไว้ตอนต้นก่อนคำสั่งก๊อปปี้โค้ด (COPY . .) เพื่อให้ Docker ช่วยทำ Cache เลเยอร์ติดตั้งห้องสมุด ช่วยย่นเวลาบิวด์อิมเมจในอนาคตเหลือเพียงหลักวินาที