CI/CD

Container Deployment using CI/CD

CI/CD คืออะไร

CICD ย่อมาจาก Continuous Integration and Continuous Delivery อธิบายแบบสั้น ๆ ก็คือการทำให้โปรเจ็คของเราทำงานแบบอัตโนมัติทั้งหมด ตั้งแต่การ Build, Test, Packing ไปจน Deploy หรือใครจะมี flow แบบอื่นก็แล้วแต่จะใส่เข้าไป ซึ่งจะช่วยให้ developer สะดวกสะบายมากยิ่งขึ้น

สำหรับใครที่ต้องการเรียนรู้เนื้อหาเกี่ยวกับ CI/CD มากขึ้น สามารถรับชมคอร์ส AtlasX DevOps ได้ที่นี่

Build Pipeline

ในส่วนของ Build pipeline ที่ทางทีม AtlasX ได้ setup ไว้จะเป็นไปตามรูปนี้

AtlasX DevSecOps Pipeline for Container
  1. Developer เขียนโค้ดแล้ว push ไปยัง GitLab repository
  2. Jenkins รับรู้ว่ามี code ใหม่ push เข้ามา และจะทำกระบวนการต่าง ๆ ที่อยู่ใน pipeline ซึ่งทำตั้งแต่สแกน code จนถึง build image และ scan image ด้วย trivy
  3. เมื่อ build และ scan สำเร็จ จะทำการ push image ไปยัง registry ที่กำหนดไว้
  4. จากนั้นก็ทำการ deploy container ด้วย Portainer ซึ่งสามารถทำได้ 2 รูปแบบคือ
    1. ดำเนินการด้วย Portainer โดยสามารถ Deploy ได้ผ่านทางหน้าเว็บ โดยติดต่อทีม technology เพื่อช่วยในการ deploy
    2. ใช้วิธีการ GitOps ซึ่งจะต้องมีการสร้าง repository สำหรับเก็บ manifest ของ Docker Compose และทำการ deploy ผ่านทาง Jenkins และ Portainer
  5. Portainer จะทำการ deploy container ตามที่กำหนดไว้ใน Docker Compose
  6. Docker จะทำการ pull image จาก registry มาใช้งาน ตาม tag ที่กำหนดเอาไว้

Using Jenkinsfile

  1. ติดต่อทีม AtlasX สำหรับการทำ CI/CD และ Gitlab webhooks
  2. ดาวน์โหลด Jenkinsfile สำหรับ Docker ที่หน้า Download จากนั้นนำมาแทนที่ไฟล์เก่า หรือตั้งชื่อใหม่ว่า Jenkinsfile_Docker
  3. แก้ไขคอนฟิกใน Jenkinsfile ให้เรียบร้อย
  4. สร้าง Branch ใหม่ชื่อ jenkins และ Checkout ไปที่ jenkins จากนั้นทำการ Push ไปยัง origin
  5. ยกถ้วยกาแฟขึ้นแล้วก็จิบ ☕️

Jenkinsfile Parameters

ParameterDescription
IMAGE_NAMEชื่อ container image ตาม standard คือ {registry}/{org}/{project}/{app_name} เช่น atlasx-registry.cdg.co.th/ptt/ngr-cc/webapp
IMAGE_TAGtag ของ image เช่น latest, v1.0, v1.1
PROJECT_KEYชื่อโปรเจกต์สำหรับระบุในรายงานของ SonarQube report และควรเป็นชื่อที่ไม่ซ้ำ (เช่น AtlasX.Web.Application).
PROJECT_VERSIONเวอร์ชั่นของโปรเจกต์ที่เอาไว้ระบุในรายงานของ SonarQube report
REGISTRY_URLUrl ของ Docker Registry ที่จะนำ image ไปเก็บ
BASE_HREFAngular base href เฉพาะ angular project

Best Practice

1. GitOps Approach

ในกระบวนการ deployment แนะนำให้สร้าง GitLab repository สำหรับเก็บไฟล์ manifest เช่น docker-compose.yml แยกจาก GitLab repository ของโปรเจ็ค เพื่อใช้งานสำหรับการ deploy เท่านั้น เนื่องจาก Docker เป็นการรัน container ขึ้นมาจาก image นั่นจึงเป็นเหตุผลที่ไม่จำเป็นต้องนำ source code ไปเก็บบน production server อีก

2. Use Environment Variable for Secret

ในการเก็บ config ต่าง ๆ ที่เกี่ยวกับ Credentials หรือ secret ต่าง ๆ ให้ใช้ Environment Variable แล้ว inject เข้าไปในไฟล์ docker-compose.yml แทนการเก็บไว้ในไฟล์ docker-compose.yml โดยตรง ซึ่งการเก็บ Environment Variable สามารถทำได้หลายวิธี ไม่ว่าจะเป็น

2.1 ใช้ไฟล์ .env

วิธีนี้ใช้งานได้ง่ายที่สุด สามารถเก็บไฟล์ไว้บนเครื่อง production ได้เลย แต่ห้ามนำไฟล์ .env ไปเก็บไว้บน GitLab repository ของโปรเจ็คเด็ดขาด (แนะนำให้เก็บเป็น example.env สำหรับกำหนด template)

2.2 ใช้ Secret Manager

Secret Manager เป็นวิธีการเก็บ secret ไว้บน server ที่มีความปลอดภัยสูง สามารถกำหนดสิทธิ์การเข้าถึง secret ได้ รวมถึงข้อมูลรั่วไหลได้ยากขึ้น ซึ่งทางทีม AtlasX ได้นำ HashiCorp Vault มาใช้เป็น Secret Manager ในการเก็บ secret ของโปรเจ็ค ซึ่งสามารถเข้าถึง secret ได้ผ่าน API หรือ CLI ที่มีการเข้ารหัสแล้ว และสามารถกำหนดสิทธิ์การเข้าถึงได้