CD Using Gitlab

MicroService 단위 어플리케이션의 지속적이고 빠른 배포와 안정적인 통합을 유지하기 위해 BXM Cloud Platform에서는 Gitlab Work Flow와 통합된 k8s cluster 환경단위 배포 전략을 제공합니다. 제안된 Work Flow에서는 Environments(Production k8s cluster | Stating k8s cluster | Development k8s cluster)와 프로젝트 branch를 mapping하여 Gitlab에서 제공하는 Merge Request Process, CI/CD Pipeline Process에 연계하여 배포 작업을 진행합니다.

Work Flow Model

BXM Cloud Platform Project의 통합/배포 프로세스는 Environment branches with Gitlab flow 모델을 기반으로 합니다. 배포 환경과 branch를 일치시키는 Flow Model을 이용하여 복잡성을 단순화합니다.

모델에서와 같이 프로젝트는 환경과 매핑되는 branch를 구성하고 특정 환경으로의 배포는 배포 시점에 대상 환경과 매핑된 branch의 자원을 베이스로 진행됩니다. 개발자원은 master branch에 지속적으로 통합되어야 하며 pre-production, production으로의 통합은 배포 시점에 단방향으로만 이루어지도록 합니다.

Continuous Delivery Example

  • Environments Branches: 프로젝트의 기본 protected branch는 배포 환경(k8s clusters)에 따라 아래 처럼 구성됩니다.

  • Gitlab CI/CD config: Gitlab Pipeline job은 아래 처럼 정의되며 프로젝트 생성시에 환경정보를 인용하여 자동으로 생성됩니다.

    image: java:8
    
    variables:
    KUBE_NAMESPACE: "default"
    DEVELOPMENT_CABUNDLE: DATA+OMITTED
    STAGING_CABUNDLE: DATA+OMITTED
    PRODUCTION_CABUNDLE: DATA+OMITTED
    ... ...
    
    stages:
    - build
    - development
    - staging
    - production
    
    before_script:
    - export GRADLE_USER_HOME=`pwd`/.gradle
    
    cache:
    paths:
    - .gradle/wrapper
    - .gradle/caches  
    
    build:
    stage: build
    script:
    - ./gradlew assemble
    only:
    - master
    
    test:
    stage: build
    script:
    - ./gradlew check
    only:
    - master
    
    deploy to development:
    stage: development
    before_script:
    - curl -L -o /usr/bin/kubectl $BLOB_STORE/kubectl --insecure && chmod +x /usr/bin/kubectl
    - curl -L -o /usr/bin/kubectl-blobstore $BLOB_STORE/kubectl-blobstore --insecure && chmod +x /usr/bin/kubectl-blobstore
    - curl -L -o /usr/bin/kubectl-apps $BLOB_STORE/kubectl-apps --insecure && chmod +x /usr/bin/kubectl-apps
    
    script:
    - ./gradlew assemble
    - |
      kubectl config set-cluster "$K8S_CLUSTER_GROUP/$CI_JOB_STAGE" --server="$DEVELOPMENT_APISERVER" \
      --certificate-authority="$(pwd)/kube.ca.pem" \
      --embed-certs=true
    - |
      kubectl config set-credentials "$K8S_CLUSTER_GROUP/$CI_JOB_STAGE/cfcr-admin" \
      --token="$DEVELOPMENT_CLUSTER_USER_TOKEN"
    - |
      kubectl config set-context "$CI_JOB_STAGE" \
      --cluster="$K8S_CLUSTER_GROUP/$CI_JOB_STAGE" \
      --user="$K8S_CLUSTER_GROUP/$CI_JOB_STAGE/cfcr-admin"
    - kubectl config use-context "$CI_JOB_STAGE"
    - kubectl config set-context --current --namespace="$KUBE_NAMESPACE"
    - kubectl apps push
    only:
    - master
    when: manual
    
    deploy to staging:
    stage: staging
    before_script:
    - curl -L -o /usr/bin/kubectl $BLOB_STORE/kubectl --insecure && chmod +x /usr/bin/kubectl
    - curl -L -o /usr/bin/kubectl-blobstore $BLOB_STORE/kubectl-blobstore --insecure && chmod +x /usr/bin/kubectl-blobstore
    - curl -L -o /usr/bin/kubectl-apps $BLOB_STORE/kubectl-apps --insecure && chmod +x /usr/bin/kubectl-apps
    
    script:
    - ./gradlew assemble
    - |
      kubectl config set-cluster "$K8S_CLUSTER_GROUP/$CI_JOB_STAGE" --server="$STAGING_APISERVER" \
      --certificate-authority="$(pwd)/kube.ca.pem" \
      --embed-certs=true
    - |
      kubectl config set-credentials "$K8S_CLUSTER_GROUP/$CI_JOB_STAGE/cfcr-admin" \
      --token="$STAGING_CLUSTER_USER_TOKEN"
    - |
      kubectl config set-context "$CI_JOB_STAGE" \
      --cluster="$K8S_CLUSTER_GROUP/$CI_JOB_STAGE" \
      --user="$K8S_CLUSTER_GROUP/$CI_JOB_STAGE/cfcr-admin"
    - kubectl config use-context "$CI_JOB_STAGE"
    - kubectl config set-context --current --namespace="$KUBE_NAMESPACE"
    - kubectl apps push
    only:
    - pre-production
    when: manual
    
    deploy to production:
    stage: production
    before_script:
    - curl -L -o /usr/bin/kubectl $BLOB_STORE/kubectl --insecure && chmod +x /usr/bin/kubectl
    - curl -L -o /usr/bin/kubectl-blobstore $BLOB_STORE/kubectl-blobstore --insecure && chmod +x /usr/bin/kubectl-blobstore
    - curl -L -o /usr/bin/kubectl-apps $BLOB_STORE/kubectl-apps --insecure && chmod +x /usr/bin/kubectl-apps
    
    script:
    - ./gradlew assemble
    - |
      kubectl config set-cluster "$K8S_CLUSTER_GROUP/$CI_JOB_STAGE" --server="$PRODUCTION_APISERVER" \
      --certificate-authority="$(pwd)/kube.ca.pem" \
      --embed-certs=true
    - |
      kubectl config set-credentials "$K8S_CLUSTER_GROUP/$CI_JOB_STAGE/cfcr-admin" \
      --token="$PRODUCTION_CLUSTER_USER_TOKEN"
    - |
      kubectl config set-context "$CI_JOB_STAGE" \
      --cluster="$K8S_CLUSTER_GROUP/$CI_JOB_STAGE" \
      --user="$K8S_CLUSTER_GROUP/$CI_JOB_STAGE/cfcr-admin"
    - kubectl config use-context "$CI_JOB_STAGE"
    - kubectl config set-context --current --namespace="$KUBE_NAMESPACE"
    - kubectl apps push
    only:
    - production
    when: manual
  • Deploy to Development k8s cluster: 배포 과정은 아래 메뉴를 이용하여 사용자 명령에 의해 진행됩니다.

  • Create Merge Request (master source to pre-production target) & Merge

  • Deploy to Staging k8s cluster: 배포 과정은 아래 메뉴를 이용하여 사용자 명령에 의해 진행됩니다.

  • Create Merge Request (master pre-production to production target) & Merge

  • Deploy to Production k8s cluster: 배포 과정은 아래 메뉴를 이용하여 사용자 명령에 의해 진행됩니다.