Environment Variables & Parameters
เปลี่ยนไปป์ไลน์แบบตายตัว (Hardcoded) ให้เป็นระบบอัตโนมัติที่ยืดหยุ่น: เข้าใจความต่างระหว่าง env.* ตัวแปรระบบ, บล็อก environment ระดับ Global/Stage, และระบบรับค่าจากมนุษย์ด้วย parameters พร้อมกฎความปลอดภัย String Interpolation
"One Pipeline to Rule All Environments."
ไปป์ไลน์ที่ออกแบบอย่างถูกต้องจะต้องไม่มีการระบุ URL, ชื่อ Bucket หรือ Environment ปลายทางแบบฮาร์ดโค้ดแม้แต่บรรทัดเดียว ไฟล์ Jenkinsfile เดียวกันต้องสามารถนำไปรันได้ทั้ง Dev, Staging และ Production ผ่านตัวแปรอย่างปลอดภัย
ข้อสอบวันนี้มี 15 ข้อ ประกอบด้วยเนื้อหาใหม่ Day 3 จำนวน 9 ข้อ, ทบทวน Day 2 จำนวน 3 ข้อ, และทบทวนสถาปัตยกรรม Day 1 จำนวน 3 ข้อ
Introduced Topic & The Big Picture
Environment Variables และ Parameters คืออะไรในระบบ Jenkins?
Environment Variables คือ "ป้ายข้อมูลกลางที่แปะไว้ข้างโต๊ะทำงาน" ที่โปรแกรมเมอร์และระบบสามารถหยิบมาอ่านได้ตลอดเวลา (เช่น รอบนี้บิลด์ครั้งที่เท่าไหร่ หรือกำลังทำงานอยู่บนกิ่ง Git ไหน) ส่วน Parameters คือ "ช่องกรอกแบบสอบถามตอนสั่งเริ่มงาน" ที่อนุญาตให้มนุษย์เลือกหรือป้อนข้อมูลก่อนที่บิลด์จะเริ่มทำงาน เช่น เลือกว่าจะส่งไฟล์ขึ้นระบบ staging หรือ production
- สร้างไฟล์แยกตามสภาพแวดล้อม: ต้องมี
Jenkinsfile-dev,Jenkinsfile-staging,Jenkinsfile-prodสิ้นเปลืองเวลาดูแลรักษา - แก้ยากเมื่อ IP หรือโดเมนเปลี่ยน: ต้องเปิด Git Commit เพื่อเปลี่ยน URL ทุกครั้งที่เซิร์ฟเวอร์เปลี่ยน IP
- เสี่ยงกดยิงผิดเป้าหมาย: ไม่มีปุ่มยืนยันค่า ทำให้โค้ดทดลองเผลอส่งขึ้นระบบจริงได้ง่ายมาก
- Jenkinsfile เดียวใช้ได้ทุกที่: โค้ดดึงค่าคอนฟิกจากตัวแปร
envตามที่ถูกส่งเข้ามาแบบไดนามิก - มีหน้าต่างเลือกก่อนรัน (Build with Parameters): ให้ทีมเลือก Dropdown เลือกระดับความเร่งด่วน หรือระบุเลขเวอร์ชันที่จะปล่อยได้ผ่าน Web UI
- นำเข้า Metadata อัตโนมัติ: รู้เลขบิลด์ (
BUILD_NUMBER), กิ่งโค้ด (BRANCH_NAME) และชื่อโหนดคนรันโดยไม่ต้องพิมพ์เอง
Built-in env.*
ตัวแปรที่ Jenkins จัดเตรียมไว้ให้อัตโนมัติ เช่น env.BUILD_NUMBER, env.JOB_NAME, env.WORKSPACE
Global environment { }
บล็อกประกาศตัวแปรระดับบนสุดของไปป์ไลน์ ค่าตัวแปรจะส่งผ่านลงไปถึงทุก Stages และทุกคำสั่งในไฟล์
Stage-level environment
ตัวแปรที่มีผลเฉพาะใน Stage นั้นๆ เพื่อจำกัดขอบเขต (Scope) ไม่ให้รั่วไหลหรือตีกับสเตจอื่น
parameters { }
ฟิลด์รับค่าจากผู้ใช้ก่อนเริ่มรัน เช่น choice, string, booleanParam ถูกเรียกใช้ผ่าน params.NAME
Everyday Mental Model & Intuition
หากต้องการเห็นภาพความแตกต่างระหว่าง Pipeline ปกติ, Environment และ Parameters ให้จินตนาการถึง **ใบสั่งงาน (Work Order Form)**:
ข้อมูลที่พิมพ์มาจากโรงงาน (env.*)
บนกระดาษทุกแผ่นมีหมายเลขใบสั่งงาน วันที่พิมพ์ และชื่อโรงงานประทับไว้ให้อัตโนมัติ คนทำงานไม่ต้องมานั่งเขียนเอง และไม่สามารถแก้ไขหมายเลขนี้ได้
ช่องกากบาทเลือกของลูกค้า (parameters)
ก่อนส่งงานเข้าสายพาน ลูกค้าต้องติ๊กเลือกว่าต้องการจัดส่งแบบ "ด่วนพิเศษ" หรือ "ธรรมดา" และระบุรหัสไปรษณีย์ปลายทาง ซึ่งจะกำหนดพฤติกรรมของช่างในแต่ละจุด
ป้ายติดเครื่องมือประจำจุด (environment)
ช่างแผนกพ่นสีมีป้ายแปะไว้ว่า "สีที่ใช้: สีแดง" พอช่างหยิบสีมาพ่นก็ดูตามป้ายนี้ โดยไม่ต้องแก้ขั้นตอนการพ่นสีที่เป็นมาตรฐานสากล
Real-World Engineering Context & War Story
จุดเริ่มต้น: ทีมพัฒนาสร้างสคริปต์รัน Database Integration Test สำหรับล้างตารางทดสอบก่อนเริ่มเทสต์ แต่เนื่องจากความรีบเร่ง วิศวกรจึงฮาร์ดโค้ดค่า URL และชื่อฐานข้อมูลไว้ในสคริปต์: sh 'python reset_db.py --target db.internal.prod' โดยตั้งใจว่าจะแก้กลับเป็น staging ทีหลัง
วันที่พังยับเยิน: โค้ดนี้ถูก Commit เข้ากิ่งทดสอบ (feature/quick-fix) แล้วมีคนกดรันไปป์ไลน์โดยไม่ระวัง ปรากฏว่าสคริปต์ไปเชื่อมต่อกับ Production Database ตัวจริง และสั่งรัน DROP TABLE users, orders; ทันที ลูกค้ากว่า 200,000 รายไม่สามารถล็อกอินใช้งานได้ ระบบล่มกะทันหัน
สิ่งที่เกิดขึ้น: ทีมต้องสั่งปิดระบบชั่วคราวและกู้ข้อมูลย้อนหลังจาก Snapshot Backup เป็นเวลา 6 ชั่วโมง และสูญเสียธุรกรรมที่เกิดขึ้นใหม่ไปทั้งหมด
ห้ามฮาร์ดโค้ดชื่อเป้าหมายเด็ดขาด! ให้ใช้ parameters { choice(...) } เพื่อบังคับให้ผู้ใช้ต้องระบุ และในสคริปต์ต้องใช้เงื่อนไขตรวจสอบเสมอ เช่น หาก params.TARGET_ENV == 'production' จะต้องไม่อนุญาตให้รันคำสั่งรีเซ็ตข้อมูลเด็ดขาด
Hands-on Syntax Breakdown (ลงมือทำทีละก้าว 3 ระดับ)
การอ่านค่าตัวแปรระบบอัตโนมัติ (env.*)
pipeline { agent any stages { stage('Print System Metadata') { steps { // เรียกใช้ผ่าน String Interpolation ของ Groovy ด้วยเครื่องหมาย Double Quote ("") echo "Build Number: ${env.BUILD_NUMBER}" echo "Job Name: ${env.JOB_NAME}" echo "Workspace Path: ${env.WORKSPACE}" // ใน Shell Script สามารถเรียกตรงๆ ผ่าน $BUILD_NUMBER ได้ sh 'echo "Running inside Linux shell on build $BUILD_NUMBER"' } } } }
คำอธิบาย: สังเกตความแตกต่าง: หากใช้ Double Quotes (" ") Groovy จะทำการคำนวณค่าตัวแปรก่อนส่งให้ Shell แต่ถ้าใช้ Single Quote (' ') ตัวแปรจะถูกส่งไปให้ระบบปฏิบัติการ Linux ของ Agent ประเมินค่าเอง
การสร้าง Custom Environment ทั้งแบบ Global และ Stage-Scoped
pipeline { agent any // Global Environment: มีผลกับทุก Stage environment { APP_NAME = 'payment-service' RELEASE_VERSION = '2.4.0' } stages { stage('Compile') { steps { echo "Compiling ${env.APP_NAME} version ${env.RELEASE_VERSION}..." } } stage('Deploy to Staging') { // Stage-level Environment: มีผลเฉพาะใน Stage นี้เท่านั้น environment { TARGET_CLUSTER = 'k8s-staging-ap-southeast' } steps { echo "Deploying ${env.APP_NAME} to cluster: ${env.TARGET_CLUSTER}" } } } }
คำอธิบาย: ตัวแปร TARGET_CLUSTER จะสามารถเข้าถึงได้เฉพาะภายใน Stage "Deploy to Staging" เท่านั้น หากนำไปเรียกใช้ใน Stage อื่นค่าจะเป็น null
การรับพารามิเตอร์แบบคลิกเลือก (choice, string, boolean) พร้อมตรวจจับความปลอดภัย
pipeline { agent any parameters { choice( name: 'DEPLOY_ENV', choices: ['development', 'staging', 'production'], description: 'เลือกสิ่งแวดล้อมปลายทางที่ต้องการติดตั้ง' ) string( name: 'IMAGE_TAG', defaultValue: 'v1.0.0', description: 'Docker Image Tag ที่ผ่านการทดสอบแล้ว' ) booleanParam( name: 'RUN_SMOKE_TESTS', defaultValue: true, description: 'สั่งรัน Smoke Tests ทันทีหลังติดตั้งหรือไม่' ) } stages { stage('Deploy Artifact') { steps { // เรียกใช้ผ่าน params object echo "Deploying image [${params.IMAGE_TAG}] into target: [${params.DEPLOY_ENV}]" // Conditional check ตามพารามิเตอร์ script { if (params.DEPLOY_ENV == 'production') { echo 'CRITICAL: Production deployment detected. Enabling high-availability traffic drain.' } } } } } post { always { cleanWs() } } }
คำอธิบาย: เมื่อประกาศบล็อก parameters เสร็จสิ้น ในการรันครั้งถัดไป หน้าจอของ Jenkins จะเปลี่ยนปุ่ม "Build Now" ให้กลายเป็น "Build with Parameters" โดยอัตโนมัติ เพื่อให้ผู้ใช้เลือกตัวเลือกก่อนรัน
Interactive Simulator: Dynamic Parameter Injection Engine
จำลองสถานการณ์: ป้อนค่าพารามิเตอร์และดูผลกระทบต่อคำสั่ง Shell และ Logic ตรวจสอบ
ปรับแต่งค่าพารามิเตอร์ DEPLOY_ENV, IMAGE_TAG, และ RUN_SMOKE_TESTS ด้านล่าง จากนั้นกด "Trigger Build with Parameters" เพื่อดูการสร้างคำสั่ง Bash แบบไดนามิก
หากเปิดใช้งาน จะเพิ่ม Stage ย่อยสำหรับตรวจสอบ Health Check อัตโนมัติ