บันทึกการทำ post-deployment check บน Azure Container Apps
ช่วงนี้ใน project จะเริ่มทำการพัฒนา CI/CD pipeline สำหรับ developer ทั้งองค์กรเพื่อ deploy application ขึ้น cloud อย่าง Microsoft Azure หนึ่งในจุดหมายของการ deploy คือ Azure Container Apps (ACA) เราได้พูดถึงพื้นฐานของ ACA ในบทความก่อนหน้าแล้ว แวะไปอ่านก่อนเพื่อที่จะได้อ่านบทความนี้อย่างเข้าใจเต็มที่
ปัญหาที่พบเจอ
ในระบบงานปัจจุบันใช้ Azure Bicep เป็น Infrastructure-as-a-Code ในการ deploy application ผ่าน ACA ด้วย Azure CLI
เมื่อคำสั่ง run ผ่านแล้วเราจะได้ผลลัพธ์หน้าตาประมาณนี้
แต่ในบางครั้งเราก็จะพบว่ามันก็จะเกิดกรณีที่ fail ขึ้นจากหลากหลายสาเหตุด้วยกัน เช่น
- Configure Ingress ไม่ถูกต้องเพราะเลือก target port ไม่ตรงกับ port ที่ application เปิดไว้
- Configure Docker image ไม่ถูกต้องทำให้ ACA ไม่สามารถไป pull ออกมาจาก Docker registry ได้
- Health probe (liveness, readiness, startup) ดัน fail เกิน threshold ที่กำหนดไว้
- การเรียกใช้ root access เพื่อ run คำสั่งใน container
- เกิด error ที่ไม่ได้ handle ไว้ทำให้ application exit ด้วย status code ที่ไม่ใช่ 0
ซึ่งในกรณีส่วนใหญ่ก็จะทำให้ผลลัพธ์ของการ run คำสั่งข้างบน fail ส่งผลให้ properties.provisioningState
เป็น Failed
นั่นเอง แต่ก็จะมีบางกรณีที่คำสั่งข้างบนผ่าน แต่ก็เข้าไปดูใน ACA revision management ปรากฎว่า revision ใหม่ที่เอาขึ้นไปดันมี properties.provisioningState
เป็น Failed
หรือค้างอยู่ที่ Provisioning
ซะงั้น
นั่นหมายความว่าเราควรจะต้องตรวจสอบเพิ่มว่า revision ใหม่ที่เอาขึ้นไปมี properties.provisioningState
เป็น Provisioned
ถึงจะยืนยันได้ว่าการ deploy นั้นเสร็จสมบูรณ์แล้ว ไม่งั้นมันจะเกิด CrashLoopBackOff ส่งผลให้ container ใน ACA ถูก scale down จนเป็น 0 เกิด downtime ขึ้นในระบบตามมา
วิธีแก้ปัญหา
ใน Azure CLI เราสามารถเรียกดูสถานะของ revision ได้ผ่านคำสั่ง az containerapp revision list
$ az config set extension.use_dynamic_install=yes_without_prompt # Install extension ให้อัตโนมัติ
$ az containerapp revision list -n "<your-aca-name>" -g "<your-resource-group>"
จะได้ผลลัพธ์ออกมาหน้าตาประมาณนี้
โดยที่สถานะที่เราต้องการจะอยู่ใน properties.provisioningState
ทีนี้เราสามารถใช้ --query
option ในการหยิบ key จาก response ที่เป็น JSON ได้เลย แล้วก็ตั้ง output เป็น tab-separated value (tsv) เอา
$ az containerapp revision list -n "<your-aca-name>" -g "<your-resource-group>" --query ".properties.provisioningState" -o tsv
จะได้ผลลัพธ์ออกมาหน้าตาประมาณนี้
Provisioned
ดังนั้นเราสามารถเขียน script เพื่อ run คำสั่งไป check สถานะจนกว่าจะเป็น Provisioned
หรือ Failed
ได้
แต่ปัญหาที่ตามมาก็คือคำสั่งนี้มันไม่รองรับกรณีที่มีหลาย revision ถึงแม้ revision mode จะเป็น Single
ก็ตาม เพราะว่า revision เก่าจะยังไม่ถูกลบจนกว่า revision ใหม่จะมีสถานะ เป็น Provisioned
ทำให้ผลลัพธ์มันออกมาเกิน 1 ค่า แล้วเราจะแก้ยังไงต่อ
Provisioned
Failed
สิ่งที่เราต้องทำคือเราต้องไปหยิบ revision ล่าสุดมาให้ได้ เพื่อให้ผลลัพธ์มันออกมาได้ 1 ค่าเท่านั้น เผอิญว่าตอนระบบเรา build Docker image จะใส่ tag เป็น build number ไว้ ทำให้เราสามารถ filter เอาเฉพาะ revision ที่มี Docker image tag ตรงกับ build number ได้โดยการแก้ไข --query
option เป็น
ซึ่ง syntax จะล้อตาม JMESPath query ในกรณีเราเลือกใช้ contains
function ในการ filter image tag เอา แน่นอนว่าเราจะได้ผลลัพธ์ 1 ค่าเพราะ build number จะไม่ซ้ำกันในคนละ build อยู่แล้ว ที่เหลือก็แค่ดึงสถานะออกมาผ่าน properties.provisioningState
key เป็นอันเสร็จสิ้น