WHY GITLAB-CI

WHY GITLAB-CI

vs Jenkins

ABOUT JENKINS

The powerful CI system

Framework

  • 延展性 (成堆的Plugin)
  • 所有配置都可以在 Jenkins 上做完
  • 自由度爆表 (sheeeellscript!)
  • 報表

WHY GITLAB-CI

其實只是想偷懶

(簡單一點世界和平)

  • 懶人包整合 gitlab
  • 所有動作都可以寫 yml 完成 (不負責發言)
  • 維護上相對簡單

.gitlab-ci.yml

Configuration of your jobs

起手式 → stages


stages:
  - prepare
  - lint
  - test
  - build
  - package
  - deploy

stages 中會有哪些  job


stages:
  - prepare
  - lint
  - test
  - build
  - package
  - deploy
app:installing_dependencies:
  image: $NODE_IMAGE
  stage: prepare
  script:
    - cd app/
    - npm install
  retry: 2
  artifacts:
    paths:
      - app/node_modules

crawler:installing_dependencies:
  image: $NODE_IMAGE
  stage: prepare
  script:
    - cd crawler/
    - npm install
  retry: 2
  artifacts:
    paths:
      - crawler/node_modules

share:installing_dependencies:
  image: $NODE_IMAGE
  stage: prepare
  script:
    - cd share/
    - npm install
  retry: 2
  artifacts:
    paths:
      - share/node_modules
variables:
  NODE_IMAGE: node:10.13.0

Okay, it looks good

BUT...

app:installing_dependencies:
  image: $NODE_IMAGE
  stage: prepare
  script:
    - cd app/
    - npm install
  retry: 2
  artifacts:
    paths:
      - app/node_modules

crawler:installing_dependencies:
  image: $NODE_IMAGE
  stage: prepare
  script:
    - cd crawler/
    - npm install
  retry: 2
  artifacts:
    paths:
      - crawler/node_modules

share:installing_dependencies:
  image: $NODE_IMAGE
  stage: prepare
  script:
    - cd share/
    - npm install
  retry: 2
  artifacts:
    paths:
      - share/node_modules

artifacts 實際上...?

app:ensure_the_code_quality:
  image: $NODE_IMAGE
  stage: lint
  dependencies:
    - app:installing_dependencies
  script:
    - cd app/
    - npm run lint
  allow_failure: true

Everything goes right

UNTIL...

Build the docker image

app:docker-build:
  stage: package
  dependencies:
    - build_static_assets
  script:
    - echo $VERSION > app/version
    - docker build -f app/Dockerfile -t $APP_GCR:$VERSION .
    - docker push $APP_GCR:$VERSION
  only:
    - tags
  variables:
    NODE_ENV: production
    VERSION: $CI_COMMIT_TAG

Yeah! You're good to go, kid!

WAIT

gitlab-runner 是 base on docker...

那在 docker 內跑 docker...

Docker in Docker

HOW?

Docker in Docker

Yeah! Hold on......WAAAAT!?

Docker in Docker

Docker in Docker

總的來說,還得補一些東西上去 - 1

 [[runners]]
   url = "https://gitlab.com/"
   token = TOKEN
   executor = "docker"
   [runners.docker]
     tls_verify = false
     image = "docker:stable"
     privileged = true
     disable_cache = false
     volumes = ["/cache"]
   [runners.cache]
     Insecure = false

首先得在 gitlab runner 加上 privileged flag

Docker in Docker

總的來說,還得補一些東西上去 - 2A

app:docker-build:
  image: docker:stable
  stage: package
  dependencies:
    - build_static_assets
  services:
    - docker:dind
  script:
    - echo $VERSION > app/version
    - docker build -f app/Dockerfile -t $APP_GCR:$VERSION .
    - docker push $APP_GCR:$VERSION
  only:
    - tags
  variables:
    NODE_ENV: production
    VERSION: $CI_COMMIT_TAG
    DOCKER_HOST: tcp://docker:2375/
    DOCKER_DRIVER: overlay2

然後在你的 gitlab-ci.yml 加上需要的 variable

以及引用服務 dind

Docker in Docker

總的來說,還得補一些東西上去 - 2A+

 variables:
   # When using dind service we need to instruct docker, to talk with the
   # daemon started inside of the service. The daemon is available with
   # a network connection instead of the default /var/run/docker.sock socket.
   #
   # The 'docker' hostname is the alias of the service container as described at
   # https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services
   #
   # Note that if you're using Kubernetes executor, the variable should be set to
   # tcp://localhost:2375 because of how Kubernetes executor connects services
   # to the job container
   DOCKER_HOST: tcp://docker:2375/
   # When using dind, it's wise to use the overlayfs driver for
   # improved performance.
   DOCKER_DRIVER: overlay2

DOCKER_HOST 用來讓 docker 知道 service deamon 在哪裡

DOCKER_DRIVER 則是用來改善效能

Docker in Docker

總的來說,還得補一些東西上去 - 2B

 [[runners]]
   url = "https://gitlab.com/"
   token = REGISTRATION_TOKEN
   executor = "docker"
   [runners.docker]
     tls_verify = false
     image = "docker:stable"
     privileged = false
     disable_cache = false
     volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
   [runners.cache]
     Insecure = false

或是另一個方式,掛上自己,但是會有造成所有 container 都會是 runner 的兄弟,而不是 runner 的子節點

在官方文件上有提到這種方式只適用於極少情況

Docker in Docker

app:docker-build:
  image: docker:stable
  stage: package
  dependencies:
    - build_static_assets
  services:
    - docker:dind
  script:
    - echo $VERSION > app/version
    - docker build -f app/Dockerfile -t $APP_GCR:$VERSION .
    - docker push $APP_GCR:$VERSION
  only:
    - tags
  variables:
    NODE_ENV: production
    VERSION: $CI_COMMIT_TAG
    DOCKER_HOST: tcp://docker:2375/
    DOCKER_DRIVER: overlay2

HOW?

CREDENTIAL??

I need google cloud sdk...

I don't wanna create any credential files...

And support docker in docker...

Text

app:docker-build:
  image: mtpeak/google-cloud-sdk-with-kubectl:docker
  stage: package
  dependencies:
    - build_static_assets
  services:
    - docker:dind
  before_script:
    - gcloud auth configure-docker -q
  script:
    - echo $VERSION > app/version
    - gsutil cp -r app/.nuxt/dist gs://$ASSETS_GCS_BUCKET_NAME/$VERSION
    - docker build -f app/Dockerfile -t $APP_GCR:$VERSION .
    - docker push $APP_GCR:$VERSION
  only:
    - tags
  variables:
    NODE_ENV: production
    VERSION: $CI_COMMIT_TAG
    DOCKER_HOST: tcp://docker:2375/
    DOCKER_DRIVER: overlay2

Yeah! You're good to go, kid!

  • docker build 可維護性
  • runner executor with docker-machine => scalable + 不用想 credential 該怎麼丟 (等等,我好像沒講到 executor 設定相關)
  • gitlab-ci.yml 易讀好學外加很多參數可以用,不需要寫 script 拿值
  • 無痛整合 gitlab 

Wrap it up

  • 準備個 slack bot 做 production deploy confirm (build 完後在 slack 確認才做 k8s update)
  • 整理 cache 讓流程可以跑快一點
  • 搬家到 DRONE

The next...

Introduce the gitlab-CI

By Calvin Huang

Introduce the gitlab-CI

  • 1,653