DAY 01 Curriculum Standard v3.2
Step 01 – Step 06
Core Distributed System Architecture

Jenkins Controller & Agent

ผ่าโครงสร้างสมองกลจัดคิว (Controller) แยกขาดจากแรงงานลงมือรัน (Agent) ป้องกันระบบกลางล่มเมื่อเจอเวิร์กลามหนัก พร้อมเข้าใจ Failure Domain Isolation, Label Allocation และการเขียนสคริปต์ปลอดภัย

Pedagogy Rule
Human First
Hands-on Simulator
Queue Allocator
Day 1 Exam
15 MCQs (100%)
Architectural Motto

"Never Execute Heavy Builds on the Controller."

Controller คือจุดเปราะบางที่สุดของทั้งบริษัท (Single Point of Orchestration) การปล่อยให้โปรเจกต์คอมไพล์โค้ดบน Controller คือความเสี่ยงระดับวิกฤตที่วิศวกรระดับอาวุโสจะไม่ยอมให้เกิดขึ้น

Failure Domain Isolation

เมื่อ Agent พัง หรือหน่วยความจำหมด ดับแค่ Pod/Node นั้น แต่ Jenkins Web UI และคิวงานของทีมอื่นยังรันต่อไปได้ราบรื่น

DAY 01 SPECIFICATION READY TO COMMENCE
STEP 01

Introduced Topic & The Big Picture

Definition ในภาษามนุษย์

Jenkins คืออะไร และทำหน้าที่อะไรในระบบสากล?

Jenkins คือ "ผู้จัดการฝ่ายปฏิบัติการอัตโนมัติ" ของทีมพัฒนาซอฟต์แวร์ หน้าที่ของมันคือคอยเฝ้าดูคลังโค้ด (Git) เมื่อไหร่ก็ตามที่มีคนส่งโค้ดใหม่เข้ามา มันจะทำหน้าที่รับคำสั่ง แล้วกระจายงานให้เครื่องจักรลูกน้องไปรันเทสต์ คอมไพล์โค้ด และส่งระบบขึ้นเซิร์ฟเวอร์ โดยที่โปรแกรมเมอร์ไม่ต้องมานั่งเปิด Terminal รันคำสั่งทีละบรรทัดด้วยมืออีกต่อไป

Before (โลกที่ไม่มีสิ่งนี้) The Manual Era
  • รันบิลด์บนโน้ตบุ๊กตัวเอง: โปรแกรมเมอร์แต่ละคนมีสเปกเครื่อง เวอร์ชัน Java และเครื่องมือไม่เท่ากัน เจอปัญหาคลาสสิก "เครื่องฉันรันผ่าน ทำไมเครื่องเธอพัง"
  • เสียเวลาเฝ้าหน้าจอ: ต้องกดคอมไพล์แล้วนั่งรอครึ่งชั่วโมง ไม่สามารถไปทำงานอย่างอื่นได้
  • โยนไฟล์ขึ้นเซิร์ฟเวอร์ด้วยมือ: เสี่ยงต่อการลืมไฟล์บางตัว หรือก๊อปปี้ทับคอนฟิกที่สำคัญจนระบบจริงพัง
After (โลกที่มีสิ่งนี้) The Automated Era
  • Push แล้วจบ: นักพัฒนาแค่ git push โค้ดเข้า Repository แล้วสลับไปเขียนฟีเจอร์ถัดไปได้ทันที
  • มาตรฐานกลางเดียวกัน: โค้ดถูกส่งไปรันบน Agent ที่ติดตั้งสภาพแวดล้อมมาตรฐาน สะอาด ไร้ข้ออ้างเรื่องเครื่องส่วนบุคคล
  • รู้ผลความผิดพลาดทันที: ถ้ารันเทสต์ไม่ผ่าน Jenkins ยิงแจ้งเตือนกลับมาในแชตทีมทันทีภายใน 3 นาที
Anatomy & Components: ผ่าเครื่องในสถาปัตยกรรม 2 ขั้ว
Master-Worker Pattern
1. Jenkins Controller (สมองสั่งการ)
Brain
  • • หน้าที่หลัก: จัดคิวงาน (Build Queue), บันทึก Log, บริหารปลั๊กอิน, ให้บริการ Web UI
  • • เก็บข้อมูล: จัดเก็บข้อมูลทั้งหมดไว้ในไดเรกทอรี JENKINS_HOME (Job config, credentials, build history)
  • • กฎเหล็ก: ปิด Executor ให้เป็น 0 (ห้ามรันคำสั่งบิลด์หนักๆ บนนี้เด็ดขาด)
2. Jenkins Agent / Node (แรงงานภาคสนาม)
Worker
  • • หน้าที่หลัก: รันโปรแกรมจริง เช่น คำสั่ง Maven, Gradle, NPM, Docker build และ Test scripts
  • • การเชื่อมต่อ: เชื่อมต่อไปยัง Controller ผ่านช่องทาง SSH หรือ Inbound TCP Agent (Remoting/JNLP protocol)
  • • Label: ติดป้ายกำกับ (Label) เพื่อให้ Controller คัดเลือกงานส่งให้ตรงกับทักษะของเครื่อง
STEP 02

Everyday Mental Model & Intuition

ภาพจำในชีวิตประจำวัน: ระบบครัวภัตตาคารขนาดใหญ่ (The Commercial Kitchen)

หากคุณกำลังสงสัยว่าทำไมต้องแยก Controller กับ Agent ออกจากกัน ให้มองภาพเหมือนกับการบริหารจัดการในครัวระดับมิชลินสตาร์:

01
หัวหน้าเชฟ (Controller)

ยืนอยู่หน้ากระดานรับออเดอร์ คอยจัดคิวโพย ไม่ลงมือย่างสเต็กเอง เพราะถ้าหัวหน้าเชฟมัวแต่ก้มหน้าย่างเนื้อ แล้วกระทะไหม้ หัวหน้าเชฟจะดูออเดอร์โต๊ะอื่นไม่ได้อีกเลย ครัวพังทั้งร้าน

02
เชฟผู้ช่วยประจำเตา (Agents)

คนหนึ่งอยู่เตาย่างเนื้อ (Label: grill) คนหนึ่งอยู่สเตชันเตรียมสลัด (Label: cold-prep) รอรับโพยจากหัวหน้าเชฟมาทำ พอทำเสร็จก็ส่งจานขึ้นโต๊ะ

03
ใบสั่งอาหาร & สูตร (Jenkinsfile)

สูตรอาหารที่เขียนขั้นตอนชัดเจน: 1. ล้างผัก -> 2. ย่างเนื้อให้สุกระดับมีเดียมแรร์ -> 3. เช็ดจานให้สะอาดก่อนเสิร์ฟ ถ้าขั้นตอนไหนพัง ก็โยนทิ้งแล้วเริ่มใหม่

STEP 03

Real-World Engineering Context & War Story

Production War Story: วิกฤต Controller OOMKilled ล่ม 12 ชั่วโมง
SEV-1 OUTAGE

จุดเริ่มต้น: บริษัทสตาร์ตอัปแห่งหนึ่งเซ็ต Jenkins ติดตั้งบน VM ตัวเดียว โดยให้มี Executor จำนวน 10 ช่องบน Controller โดยตรง เพราะสะดวก ไม่ต้องเสียเวลาต่อ Agent ข้ามเครื่อง ทุกอย่างทำงานได้ราบรื่นมาตลอด 6 เดือนแรก

วันที่พังยับเยิน: วันศุกร์เวลา 16:30 น. ก่อนรีลีสเวอร์ชันใหญ่ ทีม Backend จำนวน 4 คนกดรัน Integration Tests ซึ่งต้องดาวน์โหลด Docker Container และกินแรม 6GB ต่อบิลด์พร้อมกัน 4 บิลด์

สิ่งที่เกิดขึ้น: Linux Kernel ของเซิร์ฟเวอร์ Controller เกิดสภาวะ Memory Exhausted ตัวกลไก Out-Of-Memory Killer (OOM Killer) สั่งยิงดับโปรเซส Java ของ Jenkins ทันที หน้าจอ Web UI ดับสนิท คิวงานของทีม Frontend, Mobile และ QA ค้างเติ่งทั้งบริษัท ข้อมูลไฟล์ Config บางส่วนบันทึกไม่สมบูรณ์จนเกิดความเสียหาย ทีม DevOps ต้องใช้เวลากู้คืนและไล่ตรวจ integrity ย้อนหลังนานกว่า 12 ชั่วโมง

หลักการแก้ปัญหาแบบ Senior DevOps: Failure Domain Isolation

ตั้งค่า # of executors = 0 บน Built-in Controller โหนด และสั่งงานทั้งหมดไปยัง Agent ภายนอกเท่านั้น หากการทดสอบกินแรมจนพัง เครื่องที่จะดับมีแค่ Agent ตัวนั้น Controller จะยังคงทำงาน ส่งการแจ้งเตือนกลับมาใน Slack ได้ตามปกติ และจัดคิวงานอื่นต่อได้ทันที

STEP 04

Hands-on Syntax Breakdown (ลงมือทำทีละก้าว 3 ระดับ)

LEVEL 01: SIMPLEST EXECUTION

รันบน Agent ตัวไหนก็ได้ที่ว่าง (agent any)

Syntax พื้นฐานสุด
pipeline {
    agent any  // สั่งให้ Controller มอบหมายงานให้ Agent ตัวใดก็ได้ในระบบที่มีคิวว่าง
    stages {
        stage('Hello') {
            steps {
                echo 'Hello, Jenkins Distributed System!'
            }
        }
    }
}

คำอธิบาย: เหมาะสำหรับการเริ่มต้นทดสอบไปป์ไลน์ แต่ในองค์กรที่มีโหนดหลากหลาย OS (Linux, Windows, macOS) การใช้ agent any อาจทำให้สคริปต์ Linux เผลอไปรันบนเครื่อง Windows จนพังได้

LEVEL 02: CONDITIONAL ROUTING

เจาะจง Agent ด้วยระบบ Label (agent { node { label '...' } })

Production Requirement
pipeline {
    agent {
        node {
            label 'linux-build-worker'  // บังคับให้ส่งงานเฉพาะโหนดที่มีป้ายกำกับตรงเป๊ะ
        }
    }
    stages {
        stage('Inspect Worker Node') {
            steps {
                echo "Build is safely executing on worker agent: ${env.NODE_NAME}"
                sh 'hostname && uname -a'  // รันคำสั่ง Shell บน OS ของ Agent
            }
        }
    }
}

คำอธิบาย: การใช้ label คือหัวใจของการจับคู่งาน ป้องกันไม่ให้คำสั่ง Shell Script หลุดไปรันผิดเครื่อง

LEVEL 03: PRODUCTION-GRADE

แยก Agent อิสระต่อ Stage พร้อม Clean Workspace (agent none)

Enterprise Standard
pipeline {
    agent none  // ปิดการจอง Agent ที่ระดับ Global บังคับให้แต่ละ Stage ต้องจองแยกกัน

    stages {
        stage('Backend Maven Build') {
            agent {
                node { label 'java21-maven-agent' }
            }
            steps {
                echo 'Building JAR binary...'
                sh 'mvn clean package -DskipTests'
            }
        }

        stage('Frontend NPM Build') {
            agent {
                node { label 'node20-frontend-agent' }
            }
            steps {
                echo 'Bundling React assets...'
                sh 'npm ci && npm run build'
            }
        }
    }

    post {
        always {
            cleanWs()  // ล้างขยะใน Workspace เสมอ ป้องกันปัญหาดิสก์เต็ม
        }
        failure {
            echo 'Build encountered critical error! Notifying channel...'
        }
    }
}

คำอธิบาย: การใช้ agent none ช่วยให้เครื่อง Maven ไม่ต้องถูกจองค้างไว้ตอนที่งานกำลังรันฝั่ง Frontend ส่งผลให้คืนเครื่องกลับสู่ Pool ได้รวดเร็วกว่า และคำสั่ง cleanWs() การันตีว่าดิสก์ของ Agent จะไม่มีวันเต็ม

STEP 05

Interactive Simulator: Node Matching & Queue Allocator

จำลองสถานการณ์: Controller รับ Job เข้าคิว และพยายามส่งต่อให้ Agent

ลองปรับค่า Requested Label ใน Pipeline แล้วกดปุ่ม "Trigger Build" เพื่อดูพฤติกรรมของ Build Queue และสถานะของ Node

Jenkins Controller Panel ONLINE
Controller Executors: 0 (Protected)

ตาม Best Practice ระดับโลก Controller ต้องปิด Executor เป็น 0 เพื่อป้องกัน OOM Crash

Registered Cluster Agents (Nodes) Ready for simulation
Agent-Linux-01 Linux x86_64
Labels: linux-heavy docker-build
IDLE
Agent-MacMini-02 macOS ARM64
Labels: macos-xcode ios
IDLE
[System] Jenkins cluster initialized. 2 agents connected.
[System] Controller # of executors: 0 (Isolated).
[System] Ready to match build requests.
STEP 06

Active Recall Deep-Dive Exam (15 MCQs)

Day 01 Composition: 15 Questions (100% Day 1 Content)
Score:
0 / 15
Answered: 0/15