프리티어로 인스턴스를 생성하는 방법은 이미 너무 많아 생략한다.
AMI로 리눅스2 사용했고 인스턴스에 하나의 탄력적 ip(Elastic Ip)는 무료이기 때문에 추가했다.
❗️ 주의할 점은 ip와 인스턴스가 연결되어 있지 않으면 요금이 청구되므로 인스턴스를 삭제하거나 중지할 때 탄력적 ip도 같이 삭제 할 것. !!
ssh -i "본인pemkey명.pem" instance-user-name@instance-public-dns-name
(인스턴스 대시보드 > '연결' > SSH 클라이언트'에 접속하면 편하게 명령어 복사할 수 있도록 되어있다!)
매번 ssh -i "본인pemkey명.pem" instance-user-name@instance-public-dns-name
를 입력하는 건 너무 귀찮은 일이다.
간편하게 ssh 호스트명
로 접속할 수 있도록 설정해보자!
$ cp pem키명.pem ~/.ssh/
$ chmod 600 pem키명.pem
나처럼 기존의 aws 계정 config파일이 존재하면 기존 config파일 밑에 작성하면 된다. 없으면 config파일 생성하여 하단에 있는 정보 작성하기
$ vi config
Host {호스트명 설정}
User ec2-user // 리눅스로 이미지를 만들었을 경우
HostName {퍼블릭 IPv4 주소|탄력적 IP 주소}
IdentityFile {pem키 파일 위치}
ec2는 AWS에서 제공해주는 가상의 컴퓨터이기 때문에 필요한 소프트웨어들을 설치해야한다. 나는 스프링 프로젝트를 배포할 예정이기 때문에 java와 git을 설치했다.
인스턴스에 사용하는 java 버전과 프로젝트 버전이 일치하는 것이 좋기 때문에 11 버전을 설치했다.
sudo amazon-linux-extras install -y java-openjdk11
java -version
sudo yum install git
git --version
처음부터 jenkins로 빌드 및 배포해도 되지만 프로젝트 배포는 처음이기 때문에 cicd 구축 전에 해당 인스턴스에 연습삼아 빌드 및 배포를 해봤다.
나는 팀원 깃허브에 생성된 레포를 fork해서 작업할 예정인데 ec2인스턴스에 프로젝트를 배포하는 경우 일반적으로 원본 레포지토리 주소를 사용해야하므로 팀원의 주소를 복사해서 사용했다.
git clone https://github.com/[]/[].git
yml파일은 보안상 git에 직접 올리는 것을 지양하기 때문에 직접 인스턴스에 yml 파일을 넣으면 된다.
vim application-deploy.yml
./gradlew test
빌드테스트에서 실패했다.
해당 오류를 찾아보니 @SpringBootTest 주석처리 혹은 테스트 경로에 설정 파일 만들어주면 된다고 한다.
우선 주석처리하고 main에 merge한 후 인스턴스에 프로젝트가 존재하는 경로에서 변경 사항이 있는 깃 내용을 pull 받는다.
$ git pull
그 후에 다시 빌드 테스트했더니 성공
$ ./gradlew clean build
빌드 성공 시, 프로젝트 폴더에 build/lib
내부에 들어가면 jar파일이 만들어져 있다.
$ nohup java -jar todoit-0.0.1-SNAPSHOT.jar
$ vim nohup.out
을 통해 로그를 볼 수 있다.
(오류 발생 시 오류내용도 볼 수 있다.)
http:// [탄력적ip주소] : 8080
위의 과정과 동일
위의 과정과 동일하게 git과 java도 인스턴스에 같이 설치해주자!
sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
sudo rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
sudo yum install jenkins
$ sudo service jenkins start
![](https://velog.velcdn.com/images/dlfrlwk![](https://velog.velcdn.com/images/dlfrlwkd/post/4222c345-82ba-4225-aef8-28f73322a3ab/image.png)
d/post/7a06ffe7-4580-4c8b-8430-1c6e039e0d98/image.png)
$ sudo cat /var/lib/jenkins/secrets/initialAdminPassword
플러그인 설치하고 회원가입까지 해주면 완료!
`깃허브 settings > developer settings > personal access token`에서 발행
`dashboard > Jenkins관리 > Configure System > github`
credentials 선택 > kind: secret text 선택 > secret창에 발행한 깃허브 토큰을 입력
test connection으로 정상 동작하는 거 확인 후 저장
item 생성 시 freestyle과 파이프라인을 선택해서 구축할 수 있다. 파이프라인으로 생성할 경우 빌드 배포 단계 등을 다양하게 커스텀할 수 있지만 배포가 이번이 처음이기 때문에 편하게 구축할 수 있는 freestyle로 선택했다.
new item > Free style project > General > Github Project Url 입력
(ex. https://github.com/[본인깃허브계정]/[레포명])
하단 소스코드 관리 > Git 선택 > Repository URL 입력
(ex. https://github.com.[본인깃허브계정]/[레포명].git)
username은 자유롭게 작성하면 된다.
id와 password는 깃허브 아이디와 비밀번호를 입력해야한다.
❗️Branches to build에서 master로 되어있는 값을 main으로 바꿔야한다.
이부분 생각 못했다가 계속 빌드 실패해서 쓸데없는 시간 보냈다 ㅜㅜ
빌드 성공!
깃에서 일어나는 특정 이벤트들을 (ex. push) jenkins에서 감지할 수 있도록 webhook을 설치한다.
(jenkins에서 감지 후 알아서 빌드해준다.)
[jenkins 주소]/github-webhook/
❗️자동리다이렉트 주소라 마지막 슬래쉬 까먹지 말고 꼭 붙일 것
application/json
선택
나머지는 default로 선택된 값 그대로 냅뒀다.
깃으로 push하고 main에 merge했을 경우 자동 빌드 성공!
(생략가능)
추가로 빌드 결과를 디스코드에 보내주기 위해 jenkins 플러그인에서 Discord Notifier을 설치한다.
Discord에서 채널 서버의 settings > Webhooks 링크를 복사한 후 하단 jenkins url에 넣어주기만 하면 된다.
지금까지의 빌드 성공은 일종의 빌드 테스트라고 보면 된다.
실제 배포를 위한 빌드단계를 추가적으로 jenkins에서 설정해줘야한다.
실제 빌드를 진행하게 되면 gradle 폴더가 생기고 내부에 jar파일이 생기게 된다.
나는 gradle로 build하기 때문에 gradle 플러그인을 따로 설치해줬다.
CI 구축이 끝났다.
이제 생성된 jar파일을 SSH를 통해 원격 서버 (스프링부트 인스턴스)에 보내주면 된다.
❗️ 스프링프로젝트 서버 aws 보안규칙 > 인바운드규칙에 jenkins server도 추가하는거 잊지말기
jenkins ssh에 접속하여 SSH Key를 생성한다.
id_rsa와 id_rsa.pub가 생겼다.
(pub = public 즉, 공개키)
3-1. Jenkins 관리 > 시스템 설정 > Publish Over SSH 접속
$ cat id_rsa
을 통해 출력할 수 있다. id_rsa값을 복사해서 key 부분에 붙여넣는다.
3-2. add SSH Servers
name: 사용할 ssh server name (자유롭게 설정)
hostname: 원격 서버 ip
username: 원격 서버 user name
Remote Directory: 원격서버에서 접속하여 작업할 디렉토리 (하위 디렉토리는 item 설정에서 사용할 수 있어 나는 기본 디렉토리만 적어놨다.
test configuration 눌러서 success 뜨면 된다.
따로 경로를 바꾸지 않았으면 jenkins 설치되어 있는 인스턴스 내부에서 /var/lib/jenkins/workspace
경로에 내 스프링 프로젝트가 있다.
(Jenkins 관리 > 시스템설정에서 홈디렉토리 확인 가능)
해당 경로가 기본 경로로 잡혀 있기 때문에 jar파일이 생성되는 하위 디렉토리만 작성해주면 된다.
젠킨스에서 접속한 원격 SSH에서 소스파일을 업로드 할 경로를 지정한다.
파일 전송 후 실행할 명령어 (배포스크립트)
스프링프로젝트 인스턴스 내부에 넣어줬다.
#/bin/bash
REPOSITORY=/home/ec2-user/app/deploy
echo "Start Spring Boot Application!"
CURRENT_PID=$(pgrep -f todoit.*.jar)
echo "$CURRENT_PID"
if [ -z $CURRENT_PID ]; then
echo ">현재 구동중인 어플리케이션이 없으므로 종료하지 않습니다."
else
echo "> kill -15 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
echo ">새 어플리케이션 배포"
JAR_NAME=$(ls -tr $REPOSITORY/ | grep jar | tail -n 1)
nohup java -jar $REPOSITORY/$JAR_NAME 2>&1 &
nohup: 터미널 세션이 끊겨도 프로세스가 종료되지 않도록 해줌
& : 백그라운드 실행
ERROR: Exception when publishing, exception message [Failed to connect and initialize SSH connection. Message: [Failed to connect session for config [aws-jenkins]. Message [Auth fail]]]
다시 ssh 설정부분 들어가보니 해당 오류가 떠있다.
jenkins.plugins.publish_over.BapPublisherException: Failed to connect and initialize SSH connection. Message: [Failed to connect session for config [aws-jenkins]. Message [Auth fail]]
분명 아까 test success 였는데 ㅜㅜ
jenkins에서 발급받은 id_rsa.pub를 원격서버 ssh에 접속하여 존재하는 aurthorized_keys 폴더 하단에 추가해줬다.
chmod 600 ~/.ssh/authorized_keys 600
블로그를 통해 해결했다 휴우
로그 보면 빌드 성공 후 실행 중인 스프링을 kill한 후 새로운 jar필드를 구동시키는 걸 확인할 수 있다.
근데 어떤 오류발생으로 cicd 성공과 별개로 jenkins 상태가 unstable하다.
ERROR: Exception when publishing, exception message [Exec timed out or was interrupted after 120,000 ms]
Build step 'Send build artifacts over SSH' changed build result to UNSTABLE
배포스크립트 하단에 >/dev/null
를 추가해줬다.
>
: 리다이렉션의 의미로써 화면에 출력되는 내용을 > 우측에 있는 파일로 전송
2>&1
: 파일디스크립터에서 0은 표준입력, 1은 표준출력, 2는 표준에러를 의미한다. 표준에러를 표준출력으로 즉, 화면에 표시한다는 의미
> /dev/null 2>&1
: 표준출력이 현재 화면에서 /dev/null(로그파일)로 바꼈으므로 에러내용을 화면에 출력하지 않고 로그파일 (/dev/null)로 보낸다는 의미
내 첫 빌드 배포 구축기 끝 !!
+) 회고 및 앞으로 수정할 내용
jenkins credential을 깃허브 계정(아이디, 비번)으로 했는데 이렇게 할 경우 보안상의 문제가 있을 수 있다고 들었다. ssh에서 비밀키 생성 후 수정할 것
현재 젠킨스 아이뎀을 freestyle로 구축했는데 pipeline학습 후 pipeline으로 구축해보기
현재 pr후 merge한 프로젝트 (main)을 젠킨스가 보고있는데 만약에 빌드 할 때 오류가 나면 다시 로컬에서 수정하고 push하고 main으로 merge한 후 빌드 결과를 기다려야한다. main으로 통합하기 전에 pr보낸거에 대한 빌드결과를 보고 성공시 merge할 수 있도록 수정하기.
(github pullrequest builder hook)
publish over ssh 플러그인 종료가 됐음에도 불구하고 처음 도전하는 cicd 구축이기에 현재 레퍼런스가 제일 많아 사용하게 됐다. 해당 플러그인 사용하지 않고 구축해보기
리눅스명령어.. 공부의 필요성을 느꼈다 !
https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html
https://jojoldu.tistory.com/263
https://bcp0109.tistory.com/356
https://genie247.tistory.com/entry/jenkins-server-연동-오류-해결
https://blogger.pe.kr/369