진짜 개발자
본문 바로가기

Software Engineering/CICD (jenkins, etc)

CICD - Jenkins와 CodeDeploy를 이용한 CICD 구축하기 - 2 (구축)

728x90
jenkins

 

https://galid1.tistory.com/746

위 포스팅에서 이어지는 글입니다.

 

 

이제부터 본격적으로 CICD 환경을 구축해보도록 하겠습니다.

 

 

  1. Application 구축
  2. Git Repository 생성
  3. S3 Bucket 생성
  4. EC2 및 로드밸런서 구축
  5. CodeDeploy 구축
  6. Jenkins 프로젝트 설정
  7. Git Hub WebHook 설정
  8. SNS, Lambda 구축 (Slack에 알림)

구축 순서는 위와 같습니다.

 

 

 

구축 전 팁

위의 log를 확인하며 구축합니다.

 

 

 

 

 

1. 간단한 Application 구축

Spring Boot 프로젝트를 만들고,

Spring Boot 프로젝트를 만들고, "/" 에 해당하는 Handler를 만듭니다.

 

LoadBalancer를 이용해 CodeDeploy로 부터 배포요청을 전달 받는경우, Application이 최종적으로 잘 동작하는지를 확인하는 Step이 존재합니다. 따라서, 80port에서 app을 동작시켜야 합니다. resources -> application.properties 에서 server.port=80 을 추가합니다.

 

보통의 경우, 테스트 코드를 작성하여, jenkins에서 통합시, 테스트 코드를 실행한뒤 빌드가 진행됩니다. 지금은 생략하도록 하겠습니다.

 

 

1.1 appspec.yml

codedeploy 에서 배포를 다루기 위해 필요한 appspec.yml 을 생성합니다. 배포 생명주기에 따라, 파일을 특정 디렉토리로 옮기거나, Shell Script를 실행하도록 명령할 수 있습니다.

 

appspec.yml

위와 같이 작성합니다.

 

! appspec.yml 파일 작성시 주의 할점

  • 파일의 이름은 EC2 배포 기준 꼭 appspec.yml 이이어어야 합니다.
  • appspec.yml은 번들링한 파일안의 최상단(root)에 위치해야 합니다.
  • appspec.yml의 이름 및 내부의 작성될 내용은 배포대상 컴퓨팅 플랫폼과 os에 따라 영향을 받으므로 아래의 링크를 통해 확인 후 작성해야합니다.

 

https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure.html

자세한 작성 방법은 위의 링크를 통해 알 수 있습니다.

 

 

1.2 Scripts

이제 배포 과정에서 실행될 Shell Script를 생성합니다.

 

kill_process.sh

이 스크립트는, 앱을 배포한뒤 실행전, 이미 실행중이던 프로세스를 종료하는 스크립트입니다.

 

remove_before.sh

find /opt/codedeploy-agent/deployment-root/배포디렉토리/* -maxdepth 0 -type 'd' | grep -v $(stat -c '%Y:%n' /opt/codedeploy-agent/deployment-root/배포디렉토리/* | sort -t: -n | tail -1 | cut -d: -f2- | cut -c 3-) | xargs rm -rf

- 가장 최근에 배포되었던 파일을 제외한 나머지 배포 파일들을 제거 합니다. , 배포디렉토리는 우선적으로 codedeploy에 의해 배포가 한번 진행 생성되는 파일이므로, 배포를 한번  진행해야 알 수 있습니다.


sudo rm -rf /home/ec2-user/*

- 이전 배포에서 생성된 파일을 제거합니다.

 

run_process.sh

이 스크립트는, 앱을 배포한뒤, 새로운 앱을 실행하기 위한 스크립트입니다.

>> /dev/null 2 > /dev/null < /dev/null &은 표준 입출력 표준에러를 /dev/null로 리다이렉트 함으로써, Codedeploy가 Process의 실행이 완료되었음을 알리기 위해 꼭 필요합니다.

 

 

 

2. Git Repository 생성



git repository를 생성한뒤, 위의 App을 Push합니다.

 

 

 

3. Bucket 생성

통합 및 빌드된 Appappspec.yml ,shellscript들이 함께 번들링된 파일이 업로드될 S3버킷을 생성합니다.

 


 

 

 

4. EC2 및 Load Balancer 구축

아키텍처에서 알 수 있듯이 총 3대의 EC2와 1개의 Load Balancer가 필요합니다.

 

 

1.1 Jenkins 서버 구축

Ec2 서비스에서, jenkins를 설치할 인스턴스를 시작합니다.

 

 

docker 설치

도커를 설치합니다.

 

 

jenkins 설치

docker는 항상 root계정에서 사용합니다.

 

docker를 이용해 32789포트를 노출하여 jenkins를 실행합니다,

 

브라우저에서, 주소창에 "Jenkins가 동작중인 server의 domain":32789 을 입력합니다. administartor password의 경로를 복사합니다.

 

백그라운드에서 동작중인 jenkins 컨테이너에 bash 셸을 실행하며 attach합니다.

 

관리자 비밀번호를 복사하여 브라우저에 붙혀넣어 설치를 진행합니다.

 

Suggested install을 클릭하여, 설치를 진행하면 다음과 같이 Jenkins 설치가 완료됩니다.

 

 

code deploy plugin 설치

jenkins에서 codedeploy로 hook을 하기 위해서는 별도의 plugin을 설치해야합니다.

 

jenkins 관리 -> 플러그인 관리로 이동합니다.

 

설치 가능 탭에서 codedeploy를 검색하여 AWS CodeDeploy Plugin for Jenkins 를 설치합니다. (저는 사전에 설치하여 설치된 플러그인 목록에 나타납니다.)

 

 

1.2 App Server 구축

조건

  1. java app을 실행하기 위한 jdk
  2. code deploy 작업을 위한 codedeploy agent
  3. S3에 접근 가능한 IAM Role
  4. 로드밸런서 구축을 위한 서로 다른 두 서브넷에 존재하는 EC2 2대

 

 

IAM Role 생성


IAM -> 역할 -> 역할만들기를 선택합니다

신뢰할수있는 유형의 개체에서 AWS 서비스 사용 사례에서 EC2를 선택합니다.

 

S3와 CodeDeploy에 접근할 수 있는 정책을 연결합니다.

 

 

첫번째 App Server 구축

AWS EC2 -> 인스턴스 시작을 클릭합니다.

 

AMI는 Amazon Linux 2 AMI를 선택하고, 인스턴스 유형은 어플리케이션에서 필요한 사양을 만족하는 유형을 선택합니다.

 

인스턴스 구성탭에서 2a서브넷을 선택합니다. 그리고 앞서 생성한 EC2를 위한 역할을 추가합니다.

 

 

하단으로 스크롤을 내리면 사용자데이터영역이 있습니다. 위의 내용을 복사 붙혀넣기 합니다.

 

CodeDeploy 구성에서 알아볼 수 있는 적절한 태그를 부여합니다.

 

보안 그룹에서는 80port 트래픽을 허용합니다.

 

 

 

두번째 App Server 구축

위와 모두 같은 방식으로 인스턴스를 생성하되 인스턴스 구성탭에서 이전 AppServer와는 다른 서브넷을 선택하여 생성합니다.

 

 

 

1.3 Load Balancer 구축

 

AWS EC2 Service -> 로드 밸런싱 -> 로드밸런서 탭의 로드 밸런서 생성을 클릭합니다.

 

Application Load Balancer를 선택합니다.

 

리스너 탭에서는 HTTP 프로토콜을 선택합니다.

가용영역 탭에서는, 앞서 생성한 두 인스턴스가 위치하는 가용영역 2개를 선택합니다.

 

보안 그룹 구성에서는, 기존에 생성했던 Http 포트를 허용하는 보안그룹을 선택합니다.

 

새 대상 그룹을 선택하고 적절한 이름을 부여합니다

대상 유형은 인스턴스로 지정한 뒤, 프로토콜에서는 HTTP를 선택합니다.

 

앞서 생성한 두개의 AppServer를 선택하고 등록된 항목에 추가합니다.

 

 

 

5. CodeDeploy 구축

자동 배포를 위한 CodeDeploy를 설정하도록 하겠습니다.

 

배포 구성 생성

AWS CodeDeploy -> 배포 -> 배포구성 -> 배포 구성 만들기를 클릭합니다.

 

배포구성은 배포과정에서 성공 실패 여부를 결정하는 규칙 셋을 의미합니다. 우리의 규칙은 배포과정에서 최소 1개의 인스턴스가 서비스 가능한 상태를 유지해야 합니다.

따라서, 적절한 이름을 부여하고, EC2/온프레미스, 숫자, 값에는 1을 입력합니다.

 

 

애플리케이션 생성

 

AWS CodeDeploy -> 배포 -> 애플리케이션 -> 애플리케이션 생성을 클릭합니다.

 

적절한 이름을 설정하고, EC2/온프레미스를 선택하고 생성을 완료합니다.

 

 

배포그룹 생성

배포그룹을 생성하기전, CodeDeploy에서 배포대상이 되는 EC2 사용하기 위해 IAM Role이 필요합니다.

 

AWS IAM -> 역할 -> 역할만들기를 클릭합니다.

 

유형의 개체에서 AWS 서비스를 선택하고,

사용 사례에서 CodeDeploy -> CodeDeploy를 선택합니다.

 

다시 AWS CodeDeploy 서비스로 돌아와, 배포 -> 애플리케이션 -> 생성한 애플리케이션을 선택합니다. 뒤이어 나타나는 화면에서, 배포그룹 -> 배포그룹 생성을 클릭합니다.

 

적절한 이름을 부여하고, 서비스 역할에서, 앞서 생성한 역할을 선택합니다.

 

배포 유형에서, 현재위치를 선택합니다

환경 구성에서는 Amazon EC2인스턴스에 체크한뒤, 앞서 생성한 2개의 App Server를 선택합니다.

 

배포구성에서 앞서 생성한 배포구성을 선택합니다.

로드밸런싱 활성화를 체크하고, Application LoadBalancer를 선택합니다. 대상 그룹은 앞서 생성한 Loadbalancer group을 선택합니다.

 

 

 

6. Jenkins 프로젝트 생성

이제 Code가 푸시되었을때, code를 다운받아, 테스트 및 빌드를 실행한 뒤, CodeDeploy에게 배포 요청을 진행할 Jenkins Project를 생성합니다.

 


새로운 Item -> FreeStyle Project를 생성합니다.

 

 

소스코드 관리 탭

소스코드 관리탭에서 git을 선택하고, 앞서 생성한 Repository의 주소를 기입합니다. Branches to build에는 jenkins project가 반응할 branch를 지정합니다.

 

 

빌드 유발 탭

빌드 유발 탭에서 GitHub hook trigger for GITScm polling을 체크합니다.

 

 

Build 탭

BootJar 테스크 실행하기

Build 탭에서, Gradle Wrapper 사용을 체크하고, Make Gradlew executable에 체크합니다.

Wrapper location에는 ${workspace}를 입력하고, Tasks에는 bootJar를 입력합니다.

 

 

이전에 존재하는 파일 제거하기

add build step을 누른뒤 execute shell을 클릭한뒤 위의 내용을 추가합니다. 이 스크립트는 바로 아래에서 추가될 파일이 존재하는 경우 File exist exception이 발생하는것을 방지하기위해 존재하는 파일을 제거하는 스크립트입니다.

 

Jar 파일 옮기기



마찬가지로 shell을 추가하여, 위의 내용을 추가합니다. 이 스크립트는 bootJar(빌드) 를 통해 생성된 파일을 옮기는 스크립트입니다.

 

파일 합축 후, S3에 업로드 한뒤, CodeDeploy에게 알리기

이제 한 곳에 모인 파일을 bundeling하여 S3에 업로드한뒤, CodeDeploy에게 알려야합니다.

 

우선 CodeDeploy에게 접근하기 위해서, IAM 사용자를 생성해야합니다. IAM Service -> 사용자 -> 사용자 추가를 클릭합니다.

 

적절한 이름을 입력한 뒤, 프로그래밍 방식 엑세스에 체크합니다.

 

CodeDeployFullAccess, AmazonS3FullAccess를 선택합니다.

 

 

 

빌드 후 조치 탭에서 Deploy an application to AWS CodeDeploy를 선택합니다.

 

 

위와 같이 Codedeploy, S3 정보를 입력합니다.

Include Files에는 $JENKINS_HOME/workspace 경로에서 번들링할 파일을 선택하는 란입니다.

Exclude Files는 반대로 제외할 파일을 선택하는 란입니다.

AWS Access Key, AWS Secret Key는 앞서 AWS IAM에서 생성한 User의 정보를 입력합니다.

디렉토리 포함시 Scripts/* 를 입력하면, 디렉토리가 같이 포함됩니다.

 

 

 

 

7. GitHub WebHook 추가

GitHub에 개발자가 code를 push하는 경우, Jenkins에게 hook을 하도록 설정을 하겠습니다.

 

github reposiory -> Settings -> Webhooks -> Add WebHook을 클릭합니다.

 

"jenkin가 동작중인 domain:port"/github-webhook/을 입력하고, ContentType은 application/json으로 변경합니다.

 

그림과 같이 표시되면 성공입니다.

 

 

 

 

8. Test

SNS, Lambda, Slack 연동은 다음 포스팅에서 다루기로 하고, 마지막으로 테스팅을 해보도록 하겠습니다.

 

 

8.1 Push

보통의 경우 Code Push를 개발자의 로컬에서 진행하지만, 테스트이므로, GitHub에서 바로 진행하도록 하겠습니다.

 

GitHub의 repo로 이동하여, 아무런 파일을 연뒤, 수정 버튼을 클릭합니다.

 

그후, 주석으로 내용을 바꾼뒤 커밋 메시지를 입력하고 커밋을 진행합니다.

 

 

8.2 Jenkins(CI) 확인

jenkins의 프로젝트로 이동하면, build가 진행중임을 알 수 있습니다.

 

 

8.3 S3 bucket 확인

jenkins에서 테스트 및 빌드 후, app과 appspec.yml, Scripts들이 번들링 되어 버킷에, 업로드 되었습니다.

 

 

8.4 Codedeploy 확인

AWS Codedeploy -> 배포 -> 배포탭을 확인하면, 배포내역을 확인할 수 있습니다.

 

 

8.5 브라우저 확인

로드밸런서의 주소로 요청합니다.