เริ่มต้นเขียน CI/CD กับ Gitlab10 February 2019DevOps

เริ่มต้นเขียน CI/CD กับ Gitlab

หลังจากที่คราวก่อนได้โม้เกี่ยวกับ gitlab ไปแล้วว่าทำไมทีมผมจึงใช้งานมัน โดยประโยชน์ของมันหลักๆ ที่ผมชอบก็คือ รองรับการเขียน CICD ตั้งแต่การใช้งานฟรีเลย ฉะนั้นแล้วพวกเรามาทำ CICD กันเถอะ

CICD  คืออะไร

CICD ย่อมาจาก Continuous integration and continuous delivery ผมขออธิบายแบบสั้นๆ ก็คือการทำให้โปรเจ็คของเราทำงานแบบอัตโนมัติทั้งหมด ตั้งแต่การ run unitest, build, packing ไปจน deploy หรือใครจะมี flow แบบอื่นก็แล้วแต่จะใส่เข้าไป

สิ่งที่ต้องรู้

ก่อนที่จะเริ่มเขียน gitlab ci กันผมอยากให้ทุกคนต้องใช้ git และ docker เป็นก่อนนะ และเข้าใจการทำงานของ Container ด้วย เพราะการทำพวกระบบ CICD เราจะใช้ docker เข้าช่วย หากใครไม่รู้ ก็ไปรู้ซะ…

สมัคร gitlab ก่อนเลย

แน่ละจะใช้ของเขาก็สมัครของเขาด้วยเพื่อจะได้ใช้งานได้ https://gitlab.com/users/sign_in#register-pane สมัครเลยมันฟรี!!!

สร้าง Project ขึ้นมาหนึ่งอัน

ใน gitlab จะใช้คำว่า project แทน repository

สร้างไฟล์ .gitlab-ci.yml

ให้เราสร้างไฟล์ .gitlab-ci.yml ไว้ที่ root project ซึ่งทุกครั้งที่เรา push ขึ้นมา gitlab จะมาอ่านไฟล์นี้ทุกครั้ง

ผมจะขอยกตัวอย่างการเขียนจาก https://gitlab.com/twin-opensource/laravel-nginx-phpfpm-k8s/blob/master/.gitlab-ci.yml ทุกคนสามารถโหลด project นี้ไปทดสอบได้

Ref: https://area51.twinsynergy.co.th/structure-laravel5-nginx-phpfpm-k8s/

Stages

stages:
  - build
  - test
  - release
  - deploy

stages เป็นการกำหนด flow การทำงานของ pipeline นี้ให้กับ job ต่างๆ โดยมันจะเรียงตามลำดับที่เราได้กำหนดไว้ เช่น

  1. เริ่มต้นคือ build ถ้าสำเร็จมันก็จะไปที่ test และถ้าใน build นั้นมีหลาย jobs มันก็จะทำงานพร้อมกันเป็นแบบ parallel
  2. ถ้า jobs ทั้งหมดใน build ทำงานสำเร็จทั้งหมด test ถึงจะทำงานต่อ
  3. ถ้า jobs ทั้งหมดใน test ทำงานสำเร็จทั้งหมด release ถึงจะทำงานต่อ
  4. ถ้า jobs ทั้งหมดใน release ทำงานสำเร็จทั้งหมด deploy ถึงจะทำงานต่อ
  5. ถ้า jobs ทั้งหมดใน deploy ทำงานสำเร็จทั้งหมด ก็คือจบ pipeline มันจะขึ้นว่า success
กำหนด 2 stage ชื่อ build และ release
กำหนด 2 stage ชื่อ build และ release

Job

job คือการกำหนดว่าจะให้ทำอะไรใน stage นั้นๆ เช่น

job1:
  script: "execute-script-for-job1"

job2:
  script: "execute-script-for-job2"

โดยภายใน job จะมีค่ากำหนดเพิ่มเติมอีกเช่น image, before_script, script เป็นต้น

npm:
  stage: build
  image: node:10-alpine
  before_script:
    - apk add --no-cache --update make gcc g++ libc-dev libpng-dev automake autoconf libtool
  script:
    - cd laravel/
    - '[ -f package-lock.json ] && rm package-lock.json'
    - npm install
    - npm run prod
  cache:
    key: cache-node
    paths:
      - laravel/node_modules/
      - laravel/public/
  only:
    - master

ตัวอย่างข้างบนคือ job ที่ชื่อว่า npm โดยค่าอื่นๆ มีดังนี้

  • stage คือการบอกว่า job นี้อยู่ใน stage ไหน
  • image กำหนด docker image มาใช้งานโดยมันจะเอามาจาก hub.docker.com
  • before_script ก่อนเริ่ม script ให้มันทำอะไร โดยเราสามารถใส่คำสั่ง command ของ docker image ที่เลือกมาจาก image ได้ เช่นในตัวอย่างผมให้มันติดตั้ง make gcc g++ libc-dev libpng-dev automake autoconf libtool เพื่อไว้เตรียมตัวติดตั้ง packet ต่างๆ ของ node
  • script เป็นการกำหนดคำสั่ง command ให้มันทำอะไร
  • cache เราสามารถให้มัน cache ไฟล์หรือโฟล์เดอร์ไว้ เพื่อนำไปใช้งานใน job อื่นต่อ เช่นในตัวอย่างผมทำการ cache โฟล์เดอร์ laravel/node_modules/ และ laravel/public/ และตั้งชื่อ cache นี้ว่า cache-node
  • only เป็นการกำหนดว่าให้ job นี้ทำงานเฉพาะ branch หรือ tag ชื่อ master นั้นหมายความว่าเมื่อไรก็ตามที่ผมทำการ push code หรือ merge request เข้าไปยัง branch master หรือสร้าง tag ชื่อ master ไป job นี้จะถูกทำงานทันที

การดึง cache มาใช้งาน

จากโค็ดด้านบนผมได้ทำการ cache ไฟล์ชื่อ cache-node ใน job npm ไว้แล้ว คราวนี้เรามาดูวิธีการให้ job ที่เราต้องการดึง cache ชุดนี้มาใช้

release-nginx:
  stage: release
  image: docker:latest
  services:
    - docker:dind
  cache:
    key: cache-node
    paths:
      - laravel/public/
    policy: pull
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build --pull -t $CI_REGISTRY_IMAGE:nginx -f Dockerfile-nginx .
    - docker push $CI_REGISTRY_IMAGE:nginx
  only:
    - master

ที่นี่เรามาดูในส่วนของ cache จากโค็ดชุดนี้กัน มันจะมี policy เพิ่มขึ้นเป็นการกำหนดว่า job นี้จะให้มันทำการ pull หรือดึงข้อมูลมาจาก cache ที่ชื่อว่า cache-node ทุกครั้งก่อนทำการ script

และเรายังสามารถเลือกได้ว่าจะให้เอาเฉพาะไฟล์ หรือโฟล์เดอร์ไหนมา ซึ่งในตอนแรกผมผมทำการ cache โฟล์เดอร์ laravel/node_modules/ และ laravel/public/ ไว้ แต่เวลา pull ลงมาผมเลือกเฉพาะ laravel/public/

เพียงเท่านี้เราก็สามารถเขียน pipeline ให้กับโปรเจ็คของเราได้แล้วง่ายๆ ซึ่งในบทความต่อๆ ผมจะบอกวิธีการใช้งาน .gitlab-ci.yml เพิ่มเติม

ก่อนหน้า
ถัดไป