[CI/CD 구축] AWS, Docker, GitLab을 사용하여 CI/CD 구축하기 3편(끝)

[이전글]

 

[CI/CD 구축] AWS, Docker, GitLab을 사용하여 CI/CD 구축하기 2편

[이전글] [CI/CD 구축] AWS, Docker, GitLab을 사용하여 CI/CD 구축하기 회사에서 프로젝트를 진행할 때, 각자의 소스 버전 관리 시스템(GitLab, GitHub 등)의 repository에 push만 진행하면 알아서 자동으로 서버

min-nine.tistory.com

 


브랜치 전략

기본 브랜치 세 개로 관리하고, 개발 브랜치는 master 브랜치에서 생성한 개발 브랜치에서 만 개발합니다.

 
브랜치명 용도 비고
master 기본브랜치 개발브랜치 생성하는 곳
staging 개발서버 배포브랜치  
production 배포 브랜치  
{협업툴 티켓 넘버}-{프로젝트명} 개발브랜치 REDMINE/JIRA-0001-PROJECT_A

 

브랜치 배포 전략

브랜치를 여러 개 사용하면서 배포 전략을 구상해 봤습니다. 비즈니스 로직 git repository와 이미지(image,css,js)폴더 git repository를 다르게 사용하고 있었기에, 두개를 아래와 같이 그려보며 배포 전략을 구상하였고, 그대로 적용하여 현 업무를 마무리 하였습니다.

 

CI/CD 구조도

(초안)

(수정안)

[staging]

staging 브랜치에서 push를 할 경우 runner로 묵여있는 서버에서 gitlab-ci.yml 파일의 스크립트를 읽어 미리 만들어 놓은 node 기반의 builder engine을 가동합니다. 이 engine의 역할은 비즈니스 로직을 최신화하여 docker를 띄워 application을 build 한 후에 tgz(압축파일)로 만들어 놓는 기능을 수행합니다.

 

staging 브랜치는 별도의 이벤트 handle 없이 바로 S3로 압축된 tgz 파일을 upload 한 후에 AWS CodeDeploy로 작업을 요청하면 사전에 만들어두었던 AWS CodeDeploy Application 및 그 하위 배포 그룹을 기반으로 S3 bucket에 저장되어 있는 tgz 파일을 맵핑되어있는 EC2 혹은 온프레미스 서버로 해제하여 배포하여 줍니다.

 

[production]

production 브랜치도 위와 마찬가지로 push를 할 경우 runner로 묵여있는 서버에서 gitlab-ci.yml 파일의 스크립트를 읽어 미리 만들어 놓은 node 기반의 builder engine을 가동합니다.

 

production 브랜치는 별도의 이벤트 handle이 필요하기 때문에 중간에 배포를 컨트롤하는 배포관리자(가칭) CMS를 만들어서 해당 배포 내용을 승인했을 경우 S3로 압축된 tgz 파일을 upload 한 후에 AWS CodeDeploy로 작업을 요청. 사전에 만들어두었던 AWS CodeDeploy Application 및 그 하위 배포 그룹을 기반으로 S3 bucket에 저장되어 있는 tgz 파일을 맵핑되어있는 EC2 혹은 온프레미스 서버로 해제하여 배포하여 줍니다

 

 

CI/CD 핵심 코드

staging, production 두 브랜치 모두 build를 해야 하기 때문에 build를 담당하는 stage에 2개의 브랜치를 합하여 넣어줍니다. 아래 코드는 build라는 stage를 만들어 staging, production 브랜치에서 push 할 경우 빌드 개념으로 아래 적혀있는 script의 내용을 tags에 있는 runner가 연동되어있는 서버에서 실행하겠다는 대충 그런 의미입니다.

# .gitlab-ci.yml (in project folder)

build-job:
  stage: build
  only:
    - staging
    - production
  script:
    - cd /home/mingyu/source/node/builder
    - node .
  tags:
    - project1_runner

실제 배포를 요청하는 스크립트는 아래와 같습니다. when: on_success를 사용하여 build-job이 성공적으로 끝났을 때 실행하게 하며, 각 브랜치마다 배포 방식을 다르게 하기로 정하였기 때문에 별도의 이벤트 handle을 하지 않은 staging 브랜치의 경우 미리 runner서버에 만들어 놓은 php laravel 기반의 배포 애플리케이션 command 명령어로 배포를 실행하게 합니다.

 

production의 경우 가칭 배포관리자에서 이벤트 handle을 시키게 하기 위해 DB에 커밋 정보 및 배포할 압축 file의 full path를 적어주기만 합니다. 이는 배포 관리자 형태로 만든 CMS에서 해당 배포 실행을 클릭할 경우 위의 배포 프로세스를 탈 수 있게 하기 위함입니다.

# .gitlab-ci.yml (in project folder)

deploy-staging:
  when: on_success
  stage: deploy
  only:
    - staging
  script:
    - cd /home/mingyu/source/laravel/deploy
    - ARCHIVE_DIRECTORY="tgz로 압축된 파일이 들어있는 폴더"
    - ARCHIVE_FILENAME="tgz로 압축된 파일 명"
    - php artisan deploy:s3_and_codedeploy "${CI_PROJECT_NAMESPACE}" "${CI_PROJECT_NAME}" "${ARCHIVE_DIRECTORY}/${ARCHIVE_FILENAME}"
  tags:
    - project1_runner

deploy-production:
  when: on_success
  stage: deploy
  only:
    - production
  script:
    - cd /home/mingyu/source/laravel/deploy
    - DEPLOY_INFO_FILEPATH="tgz로 압축된 파일 pull path"
    - php artisan store:add_commit_history "${DEPLOY_INFO_FILEPATH}"
  tags:
    - project1_runner

실제로 배포를 진행하는 laravel의 핵심 코드 기능은 아래처럼 구현하였습니다. AWS S3 Bucket으로 tgz파일이 잘 업로드된 후에 AWS CodeDeploy Action을 실행해야 했기 때문입니다.

<?php

namespace App\Console\Commands;

use Aws\CodeDeploy\CodeDeployClient;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;

class DeployS3AndCodedeploy extends Command
{

    protected $signature = 'deploy:s3_and_codedeploy {group} {name} {file}';
    
    protected $description = 's3랑 codedeploy action을 진행해보자';

    public function __construct()
    {
        parent::__construct();
    }

    public function handle()
    {
    	$path_s3 = $this->storeFileToS3();
        $this->actionCodeDeploy();
    }

    private function storeFileToS3()
    {
       // 작동 코드 ...
        return $save_path;
    }

    private function actionCodeDeploy()
    {
    	// 작동 코드 ...
        dump($result);
    }
}

 

코드를 다 올리지 않는 이유는 스스로도 부족하다고 생각하고, 본 게시글은 laravel로 deploy를 어떻게 구현했나, 혹은 node로 어떻게 build 해서 압축파일을 만드는 엔진을 만들었는가? 의 포스팅이 아니다. 전반적인 CI/CD를 어떤 흐름을 잡고 구성하는지에 대해 중점적으로 다루고 싶었다. 

 

이번 업무를 맡아서 진행하며 많은 것을 생각하고 배우고 익혔다. 웹 개발자로 살아오며 내가 해왔던 일들은 기획서를 보고 그대로 구현해내는 일이었고, 이번 CI/CD 구현 업무를 계기로 방식을 생각하고, 설계해보고 구현해보는 재미를 느꼈고 그에 대한 개발자로서 어떻게 성장해 나가야 할 지에 대한 새로운 길이 또 보였고 그와 동시에 아직도 한참 모자란 스스로가 보였다. 

 

좋은 계기가 된 것 같다.