목차

    개요

    Codestates PreProject 진행 시, Github Actions와 AWS Connector를 막아놔서 CI/CD를 쉽게 연결하기가 어려운 상황이 있었습니다. 수업 때 배웠던 내용이 적용이 안되어 당황스러웠지만 언제나 그렇듯이 답을 찾을 것입니다.

    Github 권한 중 Webhooks 기능은 열려 있는 것을 확인하여 Jenkins에 Webhooks로 신호를 보내 CI/CD를 진행하면 어떨까라는 생각이 들어 기록을 남기고자 합니다.

    이 내용이 다른 동기님들께도 도움이 되었으면 좋겠습니다.

     

    큰 흐름 설명

    시도했던 블로그들을 소개하기 전에 큰 흐름부터 설명하고 넘어가고자 합니다.

     

    1. AWS EC2에 Jenkins 설치 및 포트 오픈

    2. Github Webhooks로 main branch에 push 작업이 일어날 시 Jenkins에 알림을 보내도록 설정

    3. Jenkins Pipeline을 이용하여 빌드 작업 진행

    4. Jenkins Pipeline을 이용하여 EC2 내부에서 백그라운드로 빌드된 파일 실행

     

    위 순서대로 진행했습니다.

    작업한 순서대로 설명을 진행할 때, 제가 참고했던 블로그도 함께 소개드리겠습니다.

     

    Ubuntu에 Jenkins 설치할 때 참고한 블로그

    https://hyunmin1906.tistory.com/272

     

    [Ubuntu 20.04] 젠킨스(Jenkins) 설치 및 설정

    ■ Jenkins Jenkins는 Java로 빌드 된 오픈 소스 CI (Continuous Integration) 및 CD (Continuous Delivery) 도구이며, Jenkins는 기본적으로 소프트웨어 프로젝트를 빌드, 테스트 및 배포하기 위해서 사용한다. 또한 DevO

    hyunmin1906.tistory.com

     

    Jenkins 설치 후, EC2에 인바운드 규칙을 추가해야합니다.

    아래 블로그의 2번 내용인 EC2 인스턴스 접근 허용 포트 추가 내용을 참고하여 진행하였습니다.

    https://junhyunny.github.io/information/jenkins/jenkins-deploy-ec2-using-docker/

     

    젠킨스(Jenkins) 파이프라인 서비스 배포 on EC2 인스턴스

    <br /><br />

    junhyunny.github.io

     

    Github와 Jenkins 연결하기

    해당 과정에서 가장 많은 삽질을 진행하여 참고한 블로그와 제 코드를 함께 공유하겠습니다.

    https://velog.io/@sihyung92/%EC%9A%B0%EC%A0%A0%EA%B5%AC2%ED%8E%B8-%EC%A0%A0%ED%82%A8%EC%8A%A4-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%EB%B0%B0%ED%8F%AC-%EC%9E%90%EB%8F%99%ED%99%94#%EB%B9%8C%EB%93%9C%ED%95%98%EA%B8%B0

     

    [우젠구2편] 젠킨스 파이프라인을 활용한 배포 자동화

    지속적 배포를 할 수 있는 대표적인 오픈소스 툴, 젠킨스!서버 구성을 직접해야하는 단점이 있지만, 오랫동안 사랑받아온 만큼 레퍼런스도 다양하고 플러그인도 많이 제공합니다!오늘은 젠킨스

    velog.io

     

    우선 큰 뼈대는 위 블로그를 참고했습니다.

    위 블로그를 참고하여 완성한 최종 코드는 아래와 같습니다.

     

     

    stage는 내가 원하는 작업의 제목을 뜻한다고 이해하시면 됩니다.

     

    build 부분에서 steps 안에 있는 dir는 내가 빌드하고자하는 파일의 시작 폴더를 작성하시면 됩니다.

    저희 프로젝트 같은 경우 Frontend 작업 폴더는 client, Backend 작업 폴더는 server 폴더로 작성해두었기 때문에 dir('server')라 적어 두었습니다.

     

    sh는 쉘 명령어를 뜻합니다. 내부에 적힌 내용을 모두 쉘 명령어들입니다.

    echo build start는 쉘에 그냥 build start를 기록하기 위함입니다.

    sudo chmod +x ./gradlew는 gradlew를 실행파일로 인식하게 하기 위함입니다.

    sudo ./gradlew clean build는 빌드된 파일이 있다면 지우고 빌드하라는 명령어입니다.

     

    EC2 환경 내에서 위의 두 명령어는 sudo 권한이 있어야 실행이 되기 때문에 sudo를 작성해주었습니다.

     

    이슈 발생: Jenkins에 sudo를 사용하려면 권한이 없어서 안된다는 오류가 발생합니다.

    해결을 위한 참조 블로그

    https://labs.ssen.name/Server/Jenkins/Jenkins%EC%97%90%EC%84%9C%20sudo%20%EA%B6%8C%ED%95%9C%EC%9D%84%20%EC%8B%A4%ED%96%89%EC%8B%9C%ED%82%A4%EA%B8%B0.html

     

    이슈 발생: 메모리 문제로 빌드가 안된다.

     

    위와 같이 잘 설정해두었음에도 빌드가 안되는 문제가 발생하였습니다.

    직접 CLI 환경으로 접속하여 진행해봤는데도 진행이 안되는 문제가 발생하였습니다.

    오류가 발생하는 것이 아닌 진행이 너무 느린 것을 보아 메모리 문제라 예상했습니다.

     

    확인 결과 실제로 Jenkins가 메모리의 절반을 소비하고 있었고 무료 EC2를 사용하여 총 메모리가 1GB이기 때문에 문제가 발생한 것이었습니다.

     

    이슈 해결을 위한 참조 블로그.

    아래의 개인 블로그에서 스왑 파일 크기를 참고하였고 진팽 과정은 AWS 공식 사이트의 방식을 따랐습니다.

     

    https://blog.jiniworld.me/33

     

    [Jenkins] swap file 설정을 통한 메모리 누수문제 해결

    젠킨스를 이용하여 톰캣 또는 spring boot jar 앱을 실행시킬 때, 아래의 메시지를 출력하며 build fail이 될 때가 있습니다. OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000e0800000, 130023424, 0) failed;

    blog.jiniworld.me

    https://aws.amazon.com/ko/premiumsupport/knowledge-center/ec2-memory-swap-file/

     

    스왑 파일을 사용하여 Amazon EC2 인스턴스의 스왑 공간으로 메모리 할당

    Amazon Elastic Compute Cloud(Amazon EC2) 인스턴스에서 스왑 파일로 사용할 메모리를 할당하려고 합니다. 어떻게 해야 하나요?

    repost.aws

     

    스왑 메모리를 설정한 후에는 빌드가 무사히 진행됨을 확인하였습니다.

     

     

     

    빌드된 파일 배포 진행

    빌드가 모두 완료가 되었고 이제 배포만 자동화하면 되는 상황입니다.

    참고한 블로그는 아래의 블로그이고 해당 블로그를 참고해서 변경한 제 코드를 이용해 설명을 진행하겠습니다.

     

    https://pjh3749.tistory.com/261

     

    [Spring] Jenkins(젠킨스)를 활용한 스프링부트 앱 간단 배포하기

    젠킨스를 활용한 스프링부트 앱 배포 젠킨스란? 젠킨스란 소프트웨어 개발 시 지속적 통합 (Continuous Integration) 서비스를 제공하는 툴이다. 젠킨스의 공식 홈페이지를 가보자. 메인화면에 젠킨스

    pjh3749.tistory.com

     

    위 블로그에서 다른 것들은 보지 않고 아래의 스크립트 내용만 참고하였습니다.

     

     

    위 스크립트 내용을 참고해 제가 작성한 코드는 아래와 같습니다.

     

    마지막 끝에 있는 &는 꼭 추가해주셔야합니다.

     

    코드 설명을 드리자면

     

    위 코드는 저희가 빌드한 파일의 이름이 바뀌더라도 해당 이름을 파일명에서 따오는 명령어입니다.

     

    위 코드는 만약 저희가 앞서 빌드 후 실행한 jar 파일이 있다면 해당 Process ID를 찾아내는 명령어입니다.

     

    위 코드는 만약 우리가 앞서 빌드 후 실행한 jar 파일의 Process ID가 존재한다면 종료시키는 명령어입니다.

     

    위 코드는 우리가 빌드한 파일을 실행하는 명령어입니다.

    뒤에 작성한 >>는 앞에서 실행되는 내용을 뒤에 있는 파일에 쓰라는 내용입니다.

    Spring boot의 실행 내용을 로그로 기록하고 보기 위함입니다.

    가장 앞에 있는 nohup 명령어를 통해 세션과 연결을 종료해도 우리의 빌드된 파일은 실행이 종료되지 않을 것입니다.

    가장 마지막에 있는 & 연산자 덕분에 우리는 빌드된 파일을 백그라운드에서 돌릴 수 있게 됩니다.

     

    EC2 Jenkins 폴더에 해당 쉘 스크립트 파일을 만들었다면 Jenkins의 파이프라인을 수정해줍시다.

     

    위 내용은 stages 코드가 닫힌 시점부터 작성을 해줍니다.

    post는 빌드가 완료된 다음 어떤 작업을 진행할건지에 대한 코드입니다.

    always는 빌드가 성공하든 실패하든 항상 실행하라는 뜻입니다.

    success, failure 등 다양한 조건이 있지만 만약 main branch에 merge된 코드가 빌드에 실패한 경우를 대비해 항상 실행되도록 always를 설정하였습니다.

     

    sudo ./backend_deploy.sh를 통해 앞서 소개드린 쉘 스크립트 파일을 실행하도록하였습니다.

    이후 빌드를 진행하였고 메인 브랜치에 push를 진행하였을 때도 webhooks로 잘 진행됨을 확인하였습니다.