📖 Table of Contents
해당 포스팅은 아래의 시리즈로 구성되어 있습니다. 시리즈대로 포스팅을 읽어주세요 💚
- Teamcity 를 사용한 Build Process 구성 방법
- Teamcity로 Docker Container Image를 ECR로 Push 하는 방법
- ECS Fargate 에서 Datadog을 연결하는 방법
안녕하세요! 올디브에서 Back-end 업무를 맡은 코코리 입니다.
현재 올디브에서 진행하고 있는 다양한 프로젝트에서 신규, 결함 건들을 개발하고 이를 사용자에게 제공하기 위해 코드를 통합하고 배포하는 과정을 진행하고 있습니다. 이 과정이 모두 잘 알고 계신 CI/CD인데요! 올디브는 기존에 Jenkins로 올리브영 온라인몰 CI/CD를 구성하고 자동화했습니다.
그런데 최근 올디브에서 Teamcity를 사용해 Build Process를 구성하게 되었는데요! 오늘은 왜 새로운 Build Process를 구성했는지에 대한 설명과 많은 CI/CD Tool 중에 왜 Teamcity를 선택했는지 그리고 어떻게 Build Process를 구성했는지에 대해 설명해 드리고자 합니다.
그런데 왜 Build Process 롤 새로 구성하나요?
현재 올디브에서는 Back-end/Front-end 분리 작업을 진행하고 있습니다.
(스포아닌 스포이지만 Back-end는 Spring Boot + Kotlin으로 Front-end는 React, Next.js의 기술 스택을 사용하여 분리하고 있습니다.)
프로젝트를 분리하면서 당연히 CI/CD도 어떻게 구성할지 어떤 Tool을 쓸지 고민했습니다. 이 과정에서 기존의 CI/CD의 불편함을 해소하기 위해 Docker를 도입하기로 결정했습니다. (가령 롤백이라던가,, 롤백이요)
Docker를 사용하기로 결정하고 CI/CD Tool을 어떤 것을 사용할까 고민하며 Jenkins와 Teamcity를 테스트해 보았습니다.
Jenkins
위에서 설명드린 것과 같이 기존 올리브영 온라인몰은 Jenkins로 CI/CD를 진행했습니다. 하지만 기존 프로젝트에서 Jenkins로 CI/CD 를 진행하며 겪었던 불편함과 Docker를 셋팅을 하며 생긴 여러 문제점들이 있었습니다.
Plugin 관련 이슈
Jenkins는 다양한 Plugin을 제공하는 장점이 있습니다. 하지만 Docker Container에서 작업을 진행하며 Plugin 을 설치할때마다 재시작를 해야한다는 난관에 부딪혔습니다. 운영 상에 Plugin 에 문제가 있어 이를 제거하고 다시 배포를 해야한다고 가정한다면, 재시작을 위해 기다리는 시간이 있다면 참으로 난감하겠지요?
또한 현재 올디브는 OnPremise 서버를 사용하는데요. 이렇다보니 Plugin 설치를 할때마다 방화벽을 뚫어야하는 아찔한 상황도 있었습니다.
Docker container 실행 문제
또한 Docker container 실행 시 간헐적으로 프리징 현상이 있었습니다. 쉽게 설명하면 Job이 실행되고 종료가 되지 않는 현상이었습니다.
기존에도 Jenkins를 이용했지만 서버의 제약적인 환경과 Docker와의 궁합이 좋지 않다고 판단했습니다.
Teamcity
편리한 사용자 인터페이스
러닝커브가 있곘지만 UI가 예쁘고 (이게 가장 큰 이유입니다) 사용하기가 편리했습니다.
프로그래밍 언어 를 이용한 CI/CD 구성
Back-end 기술 스택이 Kotlin 이다 보니 올디브의 몇몇 개발자분들은 Kotlin 언어에 익숙합니다.
따라서 Kotlin Script 언어를 사용하여 CI/CD 구성을 Customizing 했습니다.
Reference 가 부족한 점이 단점이긴 하지만 사내에서 Confluence 를 통해 해당 부분을 문서화하며 CI/CD 를 구성했습니다.
Container 친화적 환경
Teamcity 자체에서 Docker를 쉽게 연동해주었기 때문에 사내 서버의 제약적인 부분을 해결 할 수 있었습니다. 그러나 Jenkins 보다 라이브러리 Pool 이 다양하지 않다는 점은 아쉽긴 합니다.
이외에도 자동화 파이프 라인 구성, 클라우드 통합 등 다양한 이점이 있습니다.
조금 늦긴 했지만, 사내에 Container 서비스를 도입해 운영하는 입장에서 컨테이너 서비스를 이용하지 않는 기존 시스템의 빌드 프로세스에 영향을 미치지 않고 MSA 서비스들의 독립적인 구성을 위해 Teamcity를 최종적으로 CI/CD Tool로 결정하게 되었습니다.
Teamcity 를 사용한 Build Process 구성
그렇다면 본격적으로 구성 방법에 대해 설명드리겠습니다.
설치는 Docker를 이용해 진행하였고, Agent는 3개까지 라이선스 구매 없이 운영 가능해 다음과 같이 2대의 OnPremise Instance에서 구성했습니다.
Teamcity Server 설치
먼저 Teamcity Server를 설치해야하는데요, package download 없이 docker cli를 이용해 실행했습니다. Command 실행 이전에 docker network 구성을 해야 합니다. 여기서는 teamcity 라는 network를 구성했습니다.
docker run -it --name teamcity-server --network="teamcity" -u 0 -e TEAMCITY_SERVER_MEM_OPTS="-Xmx2g -XX:MaxPermSize=270m -XX:ReservedCodeCacheSize=350m" -v /data/teamcity:/data/teamcity_server/datadir -v /data/logs:/opt/teamcity/logs -p 8111:8111 -d hub.oliveyoung.co.kr/infra/teamcity:latest
설치 대상 인스턴스가 Private Network라서 Official 이미지를 커스터마이징 해 올리브영 내부 Container Registry로 Push 했습니다. 내부 Registry는 harbor로 구성했는데, 추후 포스팅에서 설치 및 운영방법을 공유해 드리겠습니다.
환경변수는 동일하니 참고 부탁드립니다. 8111 은 고유 포트번호입니다. DNS 설정시 8111로 접근해야하는데 80으로 접근해 사용하시려면 Port Mapping 을 변경하면 됩니다.
Teamcity Agent 실행
다음 Teamcity Agent 실행입니다. 구성에서 안내드린대로 Teamcity Server 역할로 실행할 Instance에 1 Agent 를 아래 설치합니다.
docker run -it --name teamcity-agent -e SERVER_URL="http://<ContainerName>:8111" -e DOCKER_IN_DOCKER=start --user root --privileged --network="teamcity" -v /var/run/docker.sock:/var/run/docker.sock -v /data/opt/buildagent/work:/opt/buildagent/work -v /data/opt/buildagent/temp:/opt/buildagent/temp -v /data/opt/buildagent/tools:/opt/buildagent/tools -v /data/opt/buildagent/plugins:/opt/buildagent/plugins -v /data/opt/buildagent/system:/opt/buildagent/system -d hub.oliveyoung.co.kr/infra/teamcity-agent:latest
Server Url에 이전에 Server 로 실행할 Container 이름을 넣으면 됩니다.
Agent Instance 설치
다음은 Agent Instance에 Agent를 설치하는 Command 입니다.
docker run -it --name teamcity-agent -e SERVER_URL="http://<server_IP>:8111" -e DOCKER_IN_DOCKER=start --user root --privileged --network="teamcity" -v /var/run/docker.sock:/var/run/docker.sock -v /data/opt/buildagent/work:/opt/buildagent/work -v /data/opt/buildagent/temp:/opt/buildagent/temp -v /data/opt/buildagent/tools:/opt/buildagent/tools -v /data/opt/buildagent/plugins:/opt/buildagent/plugins -v /data/opt/buildagent/system:/opt/buildagent/system -d hub.oliveyoung.co.kr/infra/teamcity-agent:latest
설치가 완료되면 Agent 메뉴에서 Authorize 버튼을 클릭해 연결을 수행합니다.
Teamcity Good Potin
위와 같이 Teamcity로 Build Process를 구성하고 나서 경험한 장점들은 아래와 같습니다.
Build Step Arrange : Step을 정의하고 실행 순서와 조건을 정렬 후 운영 가능
Build Step Definition : Kotlin Script를 이용한 타 시스템 연동 및 Customizing
Build Step Integration : Plugin 설치 없이 사용할 수 있는 Container Service
마무리
여전히 CI/CD를 개선하고 자동화해야하는 부분은 많습니다. 이를 위해 올디브도 더 나은 방법은 없는지 찾고 있습니다! 다음 글에서 소개드린 Docker, Teamcity 운영 방법 등 더 자세한 내용 그리고 예전보다 무엇이 나아졌는지 설명드리도록 하겠습니다. 그럼 다음에 만나요~!