현재 참여하고 있는 프로젝트가 개발단계에서는 SVN을 사용하지만, 유지보수 단계에서는 GitLab을 기반으로 하여 CI/CD를 적용하여 작동될 예정이라고 한다. 그래서 SVN으로 관리 되던 프로젝트를 Git으로 마이그레이션하고, GitLab과 서버를 연결하여 자동으로 배포가 될 수 있는 환경을 구축해야 했습니다.
팀에서도 Jenkinson이나 Gitlab을 직접 사용해본 경험이 있는 분이 없었습니다. 해서 기본적인 관련 키워드를 공부하는 것부터 시작했습니다.
CI/CD에 대해서 좀더 깊이 살펴보았습니다.
Continous Intergration/Development의 약자인 CI/CD는 지속적이고 자동적으로 프로젝트를 배포하는 개발 방법을 의미합니다. 대표적인 프로그램으로는 Jenkinson과 GitLab이 있습니다. 기본적인 작동 방식은 VCS에 변화가 생겼을 때 자동적으로 이를 감지하여 소스를 자동으로 빌드한 후 Shell이니 docker 같은 Executor를 사용하여 서버를 컨트롤하고, 여러 명령어들을 사용하여 배포하게 됩니다.
브랜치를 통해서 관리 될 때 효용성이 매우 극대화 되는 것으로 보이는데 이는 Branch 개념을 잘 녹여낼 수 있기 때문입니다. 예를들어 개발계, 검증계, 운영계 브랜치를 만들고, 각각의 브랜치가 업데이트 될 때 해당되는 서버에도 자동으로 배포 되는 방법입니다. 이를 활용하여 소스의 변화를 즉각적이고, 편하게 배포하여 단계적이면서도 즉각적으로 배포할 수 있는 환경을 구축 할 수 있다.
SVN에서 GItLab으로의 마이그레이션은 어렵지 않지만 방법은 다양했습니다.
우선 이클립스 내장 svn과 git을 활용하여 SVN에서 파일을 체크아웃한 후 바로 Git으로 push하는 방법을 사용했습니다. 사내 환경이다 보니 외부에서 프로그램을 가져오는 것이 조심스러운데 이클립스와 플러그인은 이미 갖춰지는 툴이어서 편했습니다. 문제는 git 자체의 좀 더 세부적인 명령어들의 사용이 어려웠고, Git Clone을 하면 SVN으로 체크아웃 한 파일들이 제거되는 등 지속적으로 사용하기에는 어려움이 있었습니다.
외부에서 가져올 수 있는 오픈소스 프로그램입니다. 우선 외부에서 프로그램 자체를 가져오는 것이 조심스러워서 고민하다 사용하지 않았습니다.
여러 방법을 고민하다가 알게 된 것이 git에서 제공하는 git svn clone 명령어입니다. 여러 옵션들을 함께 제공하기 때문에 svn의 파일만 가져오는 것부터 커밋 데이터까지 모두 가져오는 것까지 다양한 방법을 제공합니다.
사용자 계정과 이메일이 중요한 git이기 떄문에 이를 별도의 .txt파일에 맵핑한 후 아래의 코드를 사용하여 마이크레이션 하면 됩니다.
git svn clone http://svnhost:port/저장소주소 —authors-file=users.txt —no-metadata
주의사항:
적용도중 계속 오류가 발생했습니다. 원인은 Users.txt 파일 있었습니다. 윈도우에서 작성할 시 line-ends 설정을 CR-LF(윈도우)에서 LF(Unix)로 변경해야 됩니다. git bash가 리눅스 기반 프로그램이기에 운영체제간 인코딩 문제로 인한 오류였습니다.
Https://grave32.tistory.com/43
간단하게 소스만 받아온다면
git svn clone 주소 -r HEAD
gitlab은 ci/cd에 최적화 되어있는 github라고 생각하면 되는 듯 합니다.
ci/cd를 관리하기 위한 gitlab-ci.yml을 사용하여 자동배포 스크립트를 작성하면 되고,
tag라는 개념으로 gitlab-runner가 설치되어있는 서버를 불러옵니다.
GitLab Runner를 서버에 설치하고 설정합니다.
사내 gitlab에서 docker환경으로 구성된 공유 Runner를 제공하였습니다. 그러나 해당 서버는 방화벽으로 인해 Maven Repository에 접근할 수 없게 설정 되어 있었습니다. 그래서, 공유 Runner 대신 개발 서버를 빌드 환경으로 사용하기로 하였습니다. 동일하게 외부 IP에 접근이 불가능하기 떄문에 offline mode로 maven를 설정하기로 하였습니다.
maven의 빌드과정을 잘 알지 못하여 어마무지한 삽질을 하였습니다.
mvn package 와 mvn install이 있는데 둘 다 동일하게 pom.xml을 참고하여 빌드를 진행합니다. 대신 차이점은 install의 경우 빌드 된 war/jar 파일을 다시 압축해제하여 제공한다고 생각하며 되는 듯 합니다. 처음에는 이 사실을 몰라 package 명령어를 사용한 후 unzip을 사용하여 압축해제하였습니다만 그럴 필요가 없는 부분이었습니다.
최종적으로는 혹시 있을 캐시가 걱정되어 clean을 적용하여 빌드하도록 하였습니다.
mvn clean insatll
Gitlab-runner에서는 비교적 최신 버전의 git과 Curl을 설치하도록 요구합니다. gir remote-https 명령어를 사용하기 위해서인데 CentOS의 경우 구버전이 기본으로 설치되어있어 발생하는 문제였습니다.
tar.gz파일을 다운로드 받을 수 잇었고, 이를 C 컴파일링을 하여 설치할 수 있었다. Curl의 최신버전 또한 필요했는데 7.74ver 이상의 경우 보안상 추가적으로 TLS 설정을 요구하여 7.70ver를 선택했다.
<주의사항>: C컴파일은 단순히 압축해제 같은 개념이 아닌 현재 운영체제에 환경 및 설치된 프로그램들을 모두 참고하여 컴파일 결과를 생성합니다. curl을 기준으로 git이 작동하기 때문에 curl을 먼저 설치를 모두 완료한 후, git을 설치해야 오류를 막을 수 있습니다. (어마무지한 땅굴을 팠습니다.)
.configure
make
make insatll
파일 복사시 디렉토리가 없어서 에러가 자꾸 발생했습니다. 순수 Mkdir의 경우 경로가 이미 있을 경우 에러를 발생시킵니다. -p 옵션을 사용하여 에러 발생을 막았습니다.
최종적으로 개발 검증 운영 배포에 성공했습니다. 이제 간헐적으로 나오는 오류를 수정하고, 라이센스를 별도로 관리하도록 스크립드를 일부 개선할 예정입니다.
tomcat stop 이후 배포를 완료한 후 tomcat start시 해당 과정의 진행이 너무 빠를 경우 tomcat stop이 완료 되지 않았는데 start를 하여 tomcat이 결과적으로 재시동 되지 못하는 문제가 발생하였습니다.
쉘 스크립트를 작성하여 해당 스크립트에서 제한 시간 안에 주기적으로 tomcat 포트의 존재를 확인하여 해당 포트가 제거 되었을 떄에 tomcat을 start하도록 만들었습니다.
<wait_until_dead.sh>
netstat | grep : <해당 포트
추가예정
Shell Script가 편해지니 이제 자동화가 눈에 보인다. 우선 git-svn 마이그레이션 과정을 bash shell 파일로 만들어서 원터치로 실행되도록 바꿨다. 이는 별도의 글에서 작성하겠다.
사실 CI/CD보다 리눅스의 여러 설정 및 권한 관리가 매우 어려웠습니다. 리눅스가 매우 익숙해진 느낌이 늘고 CLI도 더 부담 없게 느껴집니다. 권한과 관련된 rwx와 777도 이제 눈에 들어옵니다. rpm, yum, rm, zip, unizp, tar, root, su -, sudo, cp, cmod 등등 CLI에 명령어와 친해질 수 있어서 즐거웠습니다. 개인 개발용 노트북에 Arch linux기반인 Manjaro를 설치하여 사용하고 있었는데 이제 Terminal이 무섭지 않습니다.
또한 Docker를 잘 활용 할 수 있었다면 상당 부분 쉬워졌을지도 모르겠습니다. 결국 외부망을 사용 할 수 없기에 제약이 많았을지도 모르겠지만 말입니다.
클라우드 기반 서비스의 경우 was를 docker이미지로 만들어서 쿠버네티스로 관리한다고 하는데 당연히 사람이 하나하나 할 수 없는 수준의 일이니 자동화가 필수 일 것입니다. 나도 그 정도의 트래픽과 규모의 프로젝트를 경험하는 날이 오길 바래봅니다.
개발자를 돕는 개발자가 되고 싶은 요즘입니다. 설계와 환경구축으로 나와 함께 일하는 개발자가 더 몰입하고 집중 할 수 있는 환경을 제공하는 것 말입니다. 좋은 설계와 좋은 개발환경이 더 좋은 품질로 이어질 수 있다고 생각합니다.