Github Actions를 이용한 CI/CD환경 구축
- [ Backend ]/Infra
- 2022. 12. 28.
개요
CI/CD (Continuous Integration/Continuous Delivery, Continuous Deployment)란 애플리케이션 개발 단계를 자동화하여 애플리케이션을 짧은 주기로 고객에게 제공하는 절차를 말한다. 그 과정에서 코드를 병합하고 build/test하고 서버로 옮기는 과정이 반복되게 되는데, 이러한 반복 작업을 줄이는 것이 CI/CD이다.
CI: 지속적인 통합
CI는 애플리케이션 코드의 변경을 정기적으로 build/test하는 과정을 자동화한 것을 말한다. 즉 애플리케이션 코드의 새로운 변경사항이 자동으로 공유 리포지토리에 병합된다.
1. 개발자가 구현한 코드를 기존 코드와 병합한다.
2. 병합된 코드가 올바르게 동작하고 빌드되는지 검증한다.
3. 검증 결과 문제가 있다면 수정하고 다시 1로 돌아간다. 문제가 없다면 배포를 진행한다.
CD: 지속적인 제공, 지속적인 배포
CI를 거친 후 이어지는 CD는 지속적인 서비스 제공, 배포라는 두가지 의미를 가지는데, 지속적 제공은 CI에서 버그 테스트를 거친 유효한 코드를 운영서버에 release하고 운영팀에서 서버의 코드를 배포 가능하게 한 것을 말한다. 지속적인 배포는 이 배포 가능한 코드를 배포하여 릴리즈된 애플리케이션을 실행하는 것까지를 의미한다.
결과적으로 이러한 CI/CD의 도입은 개발자가 실수로 작업을 누락하는 것을 방지하고, 애플리케이션에 대한 빠른 피드백과 신뢰성 향상이라는 효과를 볼 수 있다. 배포한 프로젝트에서 문제가 발생하면 수정된 코드가 제대로 동작하는지 검증하기 위해서 반복되는 compile-build-test-deploy라는 과정들에서 나타나는 자원 소모를 최소화하고 실수를 방지하는 것이다.
시작
기존에 만들었던 코드를 github actions라는 툴을 이용하여 CI/CD환경을 구축해보자. github repository에 push/pr등의 이벤트가 발생할 시 github action workflow에 정의한 작업이 실행되고, s3버킷에 푸시한 후 ec2 인스턴스로 배포하는 것이 목표이다.
aws 계정을 생성하고 인스턴스를 만드는건 https://bcp0109.tistory.com/362 이걸 참고했고, 배포 과정은 https://bcp0109.tistory.com/363를 참고했다.
- 올해(2023) 초까지만 해도 Github Actions에서 IAM 계정을 만들고, ACCESS ID와 KEY를 사용하여 secret으로 저장한 다음 인증했는데, 이렇게 Permanent한 Key를 사용하는 대신 IAM Role을 사용하자(https://yeonfamily.tistory.com/27)
-> 왠지 모르겠는데 안됨.
서버 구축 참고
1. 서버 시간 설정
sudo rm /etc/localtime //기존 삭제
sudo ln -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime //링크파일 생성
sudo cat /etc/localtime //확인
2. codedeploy-agent 설치
$ sudo apt update
$ sudo apt install ruby-full
$ sudo apt install wget
$ cd /home/ubuntu
$ wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
$ chmod +x ./install
$ sudo ./install auto > /tmp/logfile
$ sudo service codedeploy-agent status
에러 해결
1. 권한문제: .pem파일에서 보안파일 권한 수정. (참고: https://rainbound.tistory.com/entry/%EC%9C%88%EB%8F%84%EC%9A%B0-ssh-%EC%97%B0%EA%B2%B0-%EC%97%90%EB%9F%ACpermissions-too-open%EB%93%B1)
2. 권한문제 2: administrator 말고 현재 windows 사용자(HOME)로 변환하니 문제 해결, 근데 혹시몰라서 인스턴스 종료하고 새로 만들어서 뭐가 해결책인지는 모르겠다.
3. EC2 인스턴스 연결 문제: ipconfig로 powershell의 ip를 받아 인스턴스 보안설정 내 인바운드 규칙 추가
4. CodeDeploy Agent 설치 문제
(sudo service codedeploy-agent status 안됨)
-> https://lemontia.tistory.com/1080등의 포스트를 보면 ruby를 깔면 되는것같은데 난 https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html 이거보고 따라했는데 안됨. sudo apt install ruby-full 을 했을때 이미 깔려있음(
)에도 불구하고 안되고, 그렇다고 sudo serivce codedeploy-agent start를 해도 위 사진처럼 Unit codedepoy-agent.service not found가 뜨는 것을 볼 수 있다. service라는 명령어가 리눅스의 /etc/init.d 디렉토리의 링크파일을 시작/종료/재시작 등을 하는 커맨드라고 하는데, /etc/init.d경로로 들어가보니 codedeploy-agent라는 링크파일이 존재하지 않는 것을 확인할 수 있었다. 왜 링크파일이 안생기는거지?
>> 일단 원인을 찾은것같다. ./install 출력결과를 stdout으로 받아보니
와 같이 나오는데, ruby 버전을 다운그레이드 시키라는 말 같아서 구글링해보니
https://repost.aws/questions/QUiTn6W075Ro-ZaV5xhLen9g/issue-in-the-installation-of-the-aws-code-deploy-agent-in-ec-2-instance-with-ami-ubuntu-server-22-04-lts 보면 ubuntu 22.04버전은 codedeploy에서 지원되지 않는듯함. 인스턴스 종료하고 다시 처음부터 시작해야 할듯 싶다. 아니면 루비 버전을 다운그레이드시켜서 해볼수 있을거 같긴 한데, 나중에 혹시 또 문제가 발생할지 걱정이 되긴해서 어떻게하는게 맞는지 고민이 좀 된다.
>> 일단 서비스 배포 공부가 목적이기 때문에 그대로 진행하면서 오류 해결해나가는걸로 했다.
일단 sudo apt purge ruby로 루비를 제거한다음(제대로 삭제된지는 모르겠음..) 하위버전을 다운받아보려 시도했다.
https://blog.francium.tech/setting-up-ruby-2-7-6-on-ubuntu-22-04-fdb9560715f7 참고해서
rvm쓰려는데 rvm이라는 커맨드가 존재하지 않음.
rvm 설치하기위해서 https://www.infracody.com/2022/06/install-ruby-rvm-on-centos-7-linux.html 이걸 따라했는데 또 오류가 발생.
rvm gpg key도 설치해주고
rvm 설치 스크립트도 다운받아서 실행하려는데
rvm이라는 커맨드가 존재하지 않는다는 오류 발생. 구글링 끝에 쉘을 껐다 키거나 rvm스크립트를 현재 쉘에 로드해줘야한다고 한다(https://smile2x.tistory.com/entry/RVMruby-version-manager-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0)
source ~/.rvm/scripts/rvm
으로 rvm 스크립트 로드후 예전 ruby버전 (나는 2.7.6) 설치
설치 오류도 계속 뜨고 나중에 또 문제발생할것같아 20.04버전으로 다시 깔기로함.
> 우분투 20.04버전으로 인스턴스 다시 생성해주니 codedeploy agent 설치 성공.
5. 배포 오류
github action에서 성공적으로 build까지는 마쳤는데, codedeploy를 통해서 배포하는 과정에서 오류가 생겼다.
> Codedeploy agent가 running되지 않았다는 소리 같은데.. 확인해보면 돌아가고 있다.
> 먼저 appspec.yml파일이 분리해놓은 브랜치에만 있고 master에는 없었던것이 문제다. action 테스트하면서 분리한 브랜치에만 작성하고 master에는 빠트려서 그런줄 알았는데 그건 아니었다. 이거 해결할수 있을련지 모르겠음. 에러메세지가 너무 애매해서 어디서 에러가 터진건지 모르겠어..
- 에러가 날만한 원인 생각 (BeforeInstall에서 문제가 발생)
0. BeforeInstall에서 오류가 발생했으므로 appspec.yml이나 start/stop.sh의 문제는 아니라고 생각.
1. codedeploy-agent 설치 오류
2. 버전 문제
- 시도해본 방법:
일단 로그를 보고(
tail -F /var/log/aws/codedeploy-agent/codedeploy-agent.log
)나오는 오류 해결 노력중
1. sudo vim /etc/init.d/codedeploy-agent로 가서 LANG값 export (
start() {
echo -n $"Starting $prog:"
export LANG="en_US.UTF-8"
cd $AGENT_ROOT
nohup $BIN start >/dev/null </dev/null 2>&1 # Try to start the server
exit $?
}
) ---> 실패
2. update-rc.d -f code ----> 반응X, 실패
3. codedeploy agent 최신버전으로 업데이트 ----> 이미 최신버전
sudo /opt/codedeploy-agent/bin/install auto
- 4,5참고: https://lemontia.tistory.com/1080
4. codedeploy의 역할이 인스턴스에 부여되어 있는지 확인 ----> 이미 되어있음
5. codedeploy의 agent가 띄워져있는지 확인(iam역할 재부여했으니 sudo service codedeploy-agent restart) -----> 실패
6. codedeploy관련 log 확인
tail -F /var/log/aws/codedeploy-agent/codedeploy-agent.log
-----> 다음과 같은 warning을 뱉음. (이거 보고 1번을 한것)
근데 codedeployagent github를보니 20년도 version에 해결된 이슈라고 나와있는데다가 최근 구글링 정보가 없어.
그래서 내가 위에 최신버전 업데이트를 해보려한건데 이것도 안되니깐..
-> appspec file specifies "0,0" as the version이라는 메세지를 봐서 버전 명시를 해줘야 하는것 같음
추가로 이런 INFO메세지들도 뱉음
7. 서버에 이미 폴더가 있으면 배포한것으로 인식? (https://velog.io/@dev_shu/%EC%84%9C%EB%B2%84-%EB%B0%B0%ED%8F%AC-%EC%97%90%EB%9F%AC)
files:destination의 폴더를 미리 만들어줬는데 이게 문제였을수도 있을거같음 --------> 실패
8. appspec.yml에 경로 오류가 있었음
script폴더 안에 .sh파일들이 있었는데 scripts/*.sh로 경로를 잡음 ----------> 이것도 실패
9. appspec.yml에서 version 빠트림
-> 최종적인 해결 방법은 이거였다. 위에서 해놓은것들도 도움을 주었긴 하겠지만
> 여차저차 로그의 도움을 받아서 해결.
- linux서버 환경변수 설정(https://jjig810906.tistory.com/62),(https://veneas.tistory.com/entry/Linux-%EB%A6%AC%EB%88%85%EC%8A%A4-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%84%A4%EC%A0%95)해주고 mysql연결 후 실행하면 정상적으로 실행된다.
배포과정 설계
> 서버를 띄울 ec2, 배포할 결과물을 저장할 s3, 배포를 도와줄 codedeploy 이 세가지의 aws 서비스를 사용한다.
1. Github Actions에서 push/pr되면 프로젝트 빌드 후 압축해서 s3에 push
2. codedeploy가 실행되어 appspec파일을 참고하여 ec2에 배포 명령
3. ec2에서 s3에 push되어있는 파일을 가져와서 스크립트 실행
추가사항
환경변수 설정
(추후에 yml자체를 업데이트하는 방법도 고려해보기)
https://jjig810906.tistory.com/62
데이터베이스 연동
https://blogshine.tistory.com/322
https://victorydntmd.tistory.com/337
sudo mysql -u root -p
sudo mysql -u root -p -h <endpoint>
mysql 초기세팅
https://blogshine.tistory.com/322
https://www.bddungsblog.com/2022/11/ubuntu-mysql-resolving-mysql-password.html
nohup으로 백그라운드 실행하기
https://gksdudrb922.tistory.com/155
https://velog.io/@merci/AWS-EC2-Spring-boot-%EB%B0%B0%ED%8F%AC
nohup java -jar exe.jar 1>log.out 2>err.out &
-> nohup 이후에는 exit명령어를 통해서 종료해야 한다.
cpu usage 100% 해결
https://kth990303.tistory.com/361
-> swap메모리 할당을 통해서 해결해주었다.
https://diary-developer.tistory.com/32
-> 2024) 이걸로 하자
rds 연동 오류
https://gksdudrb922.tistory.com/240
-> vpc관련 오류. 올해(2023) 초까지만 해도 됐는데 안되서 겨우 찾음
환경변수 미적용 오류
정말 갑작스럽게 발생한 오류이다.
서버 세팅하고 환경변수 적용 확인한뒤($echo) actions를 통해 배포했는데, application.yml의 server.port에 string("${SERVER_PORT}" 자체)가 들어왔다면서 오류가 떴다.
환경변수 세팅 다시해주고, 배포 다시해주고, 환경변수 설정 제대로됐나 확인하고, 터미널 껐다 키고 별짓 다해도 똑같은 오류가 떴는데, ec2서버를 껐다가 재부팅해주니 동작한다.
원인은 찾지 못함.
후기
블로그에 정리되어있는것들이 좀 있어서 보고 따라하는 식으로 시작했는데, 나타나는 에러들을 해결하기가 정말 쉽지 않다. 처음에는 일단 코드가 아니고 어떻게보면 그냥 프로그램 구동인데다, 스프링처럼 프로그램이 돌아가는 흐름이 익숙한 것도 아니다보니 어디서 문제가 터진건지 디버깅이 불가능하다는게 제일 힘들었다. 그래도 어찌 로그파일 위치를 찾고 로그를 구글링하다보니 해결할 수 있었다.
무엇보다 일단 오류가 자주 발생해서 시간이 너무 많이 걸렸다. mysql로딩하고 database 생성해주는데만 권한문제, 계정문제, 메모리사용과다로 서버다운, 소켓접근 불가오류, 존재하지 않는 명령어(세팅 다시해줘야함)등의 오류가 발생함.. 처음이라 많이 헤멘것같기는 하지만 여튼 github action을 이용해서 ci/cd환경을 구축해보았다.
'[ Backend ] > Infra' 카테고리의 다른 글
Spring + Kotlin + Elastic Stack으로 로깅시스템 구축해보기 (0) | 2024.01.08 |
---|---|
쿠버네티스(Kubernetes) 알아보기 (0) | 2023.08.06 |
Docker와 포트포워딩 (0) | 2023.07.17 |
도커(Docker) 알아보기 (0) | 2023.07.14 |
OAuth2.0를 이용한 카카오 로그인 구현하기 (0) | 2023.02.13 |