들어가며
오늘은 CI/CD에 관해서 공부하였습니다. 신입 공고에도 자주 등장하는 키워드라 늘 관심이 많았고, 실제로 강의를 결제한 경험이 있는 내용입니다(물론 강의를 듣진 않았지만 🤣). 그 중에서도 Jenkins를 활용해 예제 웹 애플리케이션을 배포해 보겠습니다.
CI/CD
Jenkins는 CI/CD의 대표적인 도구 중 하나로 먼저 CI/CD개념에 대해서 알아보겠습니다.
CI (Continuous Integraion)
CI는 2가지의 주요 특성을 통해 설명드릴 수 있습니다.
1. 코드 변경사항을 주기적으로 빈번하게 통합해야 한다.
이는 같은 저장소에서 버그 수정, 기능 구현 등의 코드가 수정되었을 때, 이 작업 단위를 작개 쪼개라는 의미와 동일합니다. 예를 들어 기능 A의 개발을 맡은 팀이 엄청난 속도로 코드를 구성해 나가는데 코드를 1주일이 넘게 통합하지 않았다면 방대한 코드 충돌을 경험하게 될것입니다. 즉, 여기서 중요한 부분은
작업을 작은 단위로 나누어서 주기적이고, 빈번한 통합
을 수행하는 것입니다.
2. 코드 통합을 위한 단계(빌드, 테스트, 머지)의 자동화
이는 코드의 변경사항이 자동으로 빌드가 되어서 변경 이후에도 빌드가 성공적으로 이루어지는지 확인이 되어야 함을 의미합니다. 또 이 변경된 코드로 인해 발생하는 문제점이 존재하는지 자동으로 테스트까지 이루어져야 합니다. GitHub를 통해 협업하는 개발자들을 예시로 개발자들은 하루에도 몇 번씩 PullRequest를 통해 코드를 검토하고 새로 적용한 기능이나 수정한 버그들을 통합할 것입니다. 여기서 통합되기 전 GitHub Action을 통해 push된 코드가 성공적인
빌드와 테스트 과정을 거친 코드만 통합
시킵니다.
CI의 장점
- 개발 생산성 향상
작업을 작은 단위로 쪼개 주기적이고, 빈번하게 통합을 하므로 머지에서 발생하는 문제점을 해결해 생산성을 높일 수 있습니다. - 문제점을 빠르게 발견
수정한 버그나 개발한 기능에 있어서 코드 통합 시, 빌드와 테스트 과정을 거치기 때문에 개발자는 문제가 있는 부분을 CI 도구를 통해 즉각적으로 피드백 받을 수 있습니다. - 코드 퀄리티 향상
모든 개발자가 CI를 지향하는 개발을 한다면 unit 테스트 코드를 포함시켜야 하고, 주기적으로 자신의 코드를 자동검증하게 되므로 코드의 퀄리티가 향상됩니다.
CD(Continuous Delivery 또는 Deployment)
Continuous Delivery
소프트웨어를 언제든 신뢰성 있게 배포할 수 있는 상태를 유지하는 것을 말합니다. 즉, 최종 배포 이전의 단계를 지속적으로 유지하고 최종 배포 과정 자체는 수동적으로 이루어질 수 있습니다.
Continuous Deployment
코드가 자동화된 테스트를 통과하면 자동으로 프로덕션 환경에 배포되는 것을 의미합니다. 이는, 개발자가 커밋한 코드가 자동으로 배포 단계까지 이어지는 것을 말합니다.
이렇듯 CD에서어 어떤 D를 채택하는지에 따라서 마지막 배포 과정까지 자동화를 하는지를 결정짓게 됩니다. 이는 각 기업마다 문화, 각각의 이유에 따라서 다르게 채택됩니다.
CD의 장점
- 빠른 시장 출시
CD를 통해 개발된 기능이나 수정 사항을 빠르게 사용자에게 제공할 수 있습니다. 이는 경쟁 우위를 확보하고, 시장 변화에 신속하게 대응하는 데 도움이 됩니다. - 높은 제품 품질
지속적인 테스팅과 자동화된 배포 과정은 버그를 조기에 발견하고 해결하는 데 도움을 줍니다. 이는 전반적인 소프트웨어 품질을 향상시킵니다. - 효율적인 피드백 루프
빈번하고 지속적인 배포는 사용자와의 피드백 루프를 단축시킵니다. 이를 통해 사용자의 요구와 시장의 변화를 더 잘 이해하고, 제품을 적절하게 조정할 수 있습니다. - 위험 감소
작고 지속적인 배포는 대규모 배포에서 발생할 수 있는 위험과 복잡성을 줄여줍니다. 문제가 발생할 경우 즉시 대응할 수 있으며, 영향도가 더 적습니다. - 개선된 개발자 생산성
배포 프로세스의 자동화는 개발자가 반복적이고 수동적인 작업에서 벗어나 더 창의적인 작업에 집중할 수 있게 해줍니다. - 더 나은 협업 및 통합
CI/CD 파이프라인은 개발, 테스팅, 운영 팀 간의 긴밀한 협업과 통합을 촉진합니다. 이는 프로세스의 투명성을 높이고, 팀 간의 장벽을 낮춥니다. - 비용 절감
효율적인 개발 프로세스와 자동화는 장기적으로 운영 비용을 절감하는 데 도움이 됩니다.
실습
1. Jenkins 기본
인스턴스
실습을 진행할 AWS EC2 인스턴스를 생성해 줍니다. 보통 인프라와 관련된 도구들을 세팅할 때, 보안성, 안정성, 표준성 등의 이유로 linux계열 운영체제를 사용하기 때문에 Ubuntu를 택했습니다. Jenkins의 download문서를 보면 최소한의 사양이 나와있습니다.
https://www.jenkins.io/doc/book/installing/linux/
이를 맞추기 위해 EC2 인스턴스의 사양을 t3.medium으로 맞추어 주었습니다. 이로인해 약간의 비용이 발생할 수 있습니다.
보안 그룹의 경우 SSH통신을 위한 ssh 통신, 웹 어플리케이션 배포를 위한 HTTP 통신, 또 배포한 어플리케이션이 외부에서 접근할 때 열어둔 포트를 허용해주는 사용자 지정 IPv4 포트를 열어줍니다.
저는 네트워크 적인 능숙하지 못해서 보안 그룹과 같은 설정에서 자주 오류를 접합니다. 이번 실습에서도 하나의 인스턴스에서 두 개의 어플리케이션(jenkins와 tomcat)을 동일한 포트를 통해 열어두었다가 뒤 늦게 실행한 tomcat 포트에 접근하지 못하는 오류를 맞이했습니다.
tocmat의 포트를 8080에서 8081로 변경한 뒤에도 보안 그룹에서 8081포트를 열어주지 않아 외부에서 8081 포트에 접근하지 못하는 오류를 접하였습니다. 이번 계기를 통해서 전보다는 더 보안 그룹과 포트에 대해서 이해하게 된거 같습니다.
이후 위 문서에서 LTS버전으로 Jenkins를 다운받아 줍니다. Jenkins가 실행 되었다면 사용중인 인스턴스의 IP 혹은 DNS + :8080을 통해 웹사이트로 접속해 줍니다. 그럼 아래와 같은 화면이 나오는데 이미지에 보이는 빨간 리소스를 sudo cat 명령어를 통해 출력시켜 비밀번호를 입력합니다.
이후 환경에 맞는 플러그인을 자동으로 설치해 주는 항목과 직접 세팅하는 항목이 있는데 저는 자동 설치 항목을 택했습니다. 다음 Jenkins의 사용자 설정은 개인에 맞게 설정해줍니다.
이렇게 연결된 젠킨스에 들어가면 대쉬보드에 다음과 같은 항목이 존재합니다.
Item
- Jenkins에서는 'Item'을 통해 다양한 작업(Job)을 생성하고 관리합니다. 여기에는 프로젝트 빌드, 테스트 및 배포와 같은 작업이 포함됩니다.
Jenkins 관리
- Jenkins 인스턴스의 전반적인 설정과 구성을 관리하는 섹션입니다. 시스템 설정, 플러그인 관리, 보안 설정 등을 포함합니다.
이제 아이템을 만들어 간단한 테스트를 진행해 보겠습니다.
item을 만들 때, 아래와 이미지와 같이 item의 이름과 작업환경을 지정해줄 수 있습니다. 간단한 테스트를 진행할 것이기 때문에 Freestyle project를 지정해줍니다. 그 밑에 Maven project는 원래 항목에 없지만 실습을 진행하기 위해 Jenkins 관리 메뉴에서 plugin 항목에 들어가 별도로 설치해준 것입니다.
이후 item의 세부 세팅을 하는 페이지로 넘어가는데 여러 설정들은 차차 알아가 보겠습니다. 실습을 하며 설정하는 부분만 알아보겠습니다.
아래 이미지에 보이는 Build Steps는 item을 빌드 했을 때, 이루어지는 행동들을 설계하는 설정입니다. Execute shell을 골라 Jenkins를 실행하고 있는 인스턴스에 텍스트 파일을 생성해주는 명령어를 입력해 주겠습니다.
이후 아래 화면에서 빌드를 통해 작업을 실행할 수 있습니다. 빌드가 성공적으로 이루어졌는지, 오류가 발생했다면 Console을 통해 log를 확인할 수도 있습니다. 뿐만 아니라 구성페이지에서는 이전에 설정한 item을 수정해줄 수 있습니다.
출력된 콘솔을 보면 jenkins의 workspace에 item의 이름과 함께 빌드 내용이 담긴 것을 알 수 있습니다.
실제 인스턴스에서 이를 조회해보면 다음과 같습니다.
2. Maven으로 빌드하기
빌드란, 개발자가 개발한 소스 코드와 기타 개발 에 필요한 파일들을 실행 가능한 소프트웨어로 변환하는 과정을 의미합니다. Maven은 빌드를 돕는 대표적인 도구입니다.
Jenkins 관리 > Plugins에 들어와 Available plugins 항목에서 Maven을 검색해 설치해 줍니다.
이후 새로운 item을 추가할 때, Maven project 요소가 추가된 것을 확인할 수 있습니다.
이번에 item에서 할 작업은 github 저장소에 기존에 존재하는 간단한 웹 어플리케이션을 빌드하고 실행하는 작업입니다.
소스 코드 관리 항목에서 Git을 선택 해주고, 저장소의 Clone using the web URL을 입력해 줍니다. Branch의 경우 각자 관리할 코드의 Branch 이름을 입력해 줍니다.
제가 가져온 저장소는 Java기반 Spring 어플리케이션이기 때문에 빌드 시 POM 설정을 해줍니다.
Goals and option의 clean package 설정의 경우 빌드 시 mvn clean package 명령어를 통해 target directory를 깔끔하게 정리하고(clean), 소스 코드를 컴파일, 테스트하여 jar 혹은 war파일로 패키징해(package) 배포 가능한 형태로 만들어주는 역할을 합니다.
POM
Project Object Model인 POM은 주로 Apache Maven 프로젝트 관리 도구에서 사용됩니다. POM은 프로젝트의 구조, 설정, 의존성 등을 정의하는 XML 파일pom.xml 형태로 제공됩니다.
POM의 주요 기능
- 프로젝트 구성: 프로젝트의 이름, 버전, URL 등의 기본정보를 정의합니다.
- 의존성 관리: 프로젝트가 필요로 하는 라이브러리와 그 버전을 지정합니다. Maven은 이 정보를 바탕으로 필요한 라이브러리를 자동으로 다운로드하고 관리합니다.
- 플러그인 관리: 빌드 과정에서 필요한 컴파일, 테스트, 패키징 등의 작업을 수행하기 위한 플러그인 설정을 포함합니다.
- 빌드 설정: 소스 코드 디렉토리, 출력 디렉토리, 빌드 스크립트 등 빌드 프로세스의 세부 사항을 설정합니다.
- 프로파일 관리: 다양한 빌드 환경인 개발, 테스트, 프로덕션 등에 맞춰 다른 설정을 적용할 수 있는 프로파일을 정의합니다.
- 프로젝트 관계: 다른 Maven 프로젝트와의 관계를 정의하여, 멀티 모듈 프로젝트의 구성과 관리를 용이하게 합니다.
POM의 중요성
- 표준화된 프로젝트 구조: Mavne과 POM을 사용함으로써 일관된 프로젝트 구조를 유지할 수 있어 개발자 간의 협업이 용이해집니다.
- 자동화된 빌드 프로세스: 의존성 관리, 빌드, 테스트 등을 자동화하여 개발 과정을 간소화하고 오류를 줄일 수 있습니다.
- 이식성: POM 설정에 따라 다양한 환경에서 동일한 빌드 결과를 얻을 수 있어, 프로젝트의 이식성이 높아집니다.
Maven과 POM은 Java 기반 프로젝트에서 널리 사용되며, 개발 프로세스의 효율성과 품질 관리에 크게 기여합니다.
이후 빌드 시 /var/lib/jenkins/workspace/maven-project/target
위치에 프로젝트의 빌드 파일들이 위치합니다.
3. WAS, tomcat으로 배포하기
이제 어플리케이션을 배포하기 위해서 인스턴스 환경에 웹 서버인 tomcat을 설치하여 jenkins를 이용해 배포해 보겠습니다.
Web Application Server
WAS는 웹 어플리케이션을 실행시키고 관리하는 데 사용되는 서버 소프트웨어 또는 하드웨어를 말합니다. Web Server와는 다르게, WAS는 동적인 컨텐츠를 처리하기 위해 데이터베이스 조회나 로직 처리 같은 서버 사이드 스크립트를 실행할 수 있습니다. 주요 기능으로는 웹 어플리케이션 실행 환경을 제공하고, 라이프 사이클을 관리합니다. 그 이외에 동적 컨텐츠 처리, 데이터베이스 연결 및 관리, 보안, 트랜잭션 관리를 통한 데이터 처리 일관성 유지 등의 역할을 합니다.
WAS를 사용하면 동적인 웹 페이지를 구성하고, 서버 자원을 효율적으로 관리, 보안 강화, 스케일링 성능 최적화, 응용 프로그램 분리 등의 이점을 얻을 수 있습니다. 이러한 WAS는 주로 Java기반 Java EE 표준을 수용하고 있지만 이를 따르지 않는 .NET이나 비 자바계열 Citrix 등 또한 존재합니다. 잘 알려진 WAS 도구들로는 Apache Tomcat, Resin, JRun, .NET, Jetty 등이 존재합니다.
Apache Tomcat
아파치는 Web Server의 역할을 하고, Tomcat은 WAS역할을 합니다. 즉, Client의 요청을 Web Server인 Apache를 거쳐 WAS Tomcat에서 db와 같은 동적인 데이터 처리를 통해 정적인 응답을 내보내고, 이를 다시 Apache를 거쳐 Client에 나타납니다.
이 과정에서 이루어지는 통신은 HTTP 통신으로 이루어집니다. Apache의 경우 정적인 파일(HTML, CSS, JavaScript)을 다루고, Tomcat은 Java EE 기반으로 만들어졌으며 JSP와 Servlet을 구동하기 위한 서블릿 컨테이너의 역할과 DB연결, 외부 어플리케이션과의 연결 등의 역할을 수행합니다.
이제 인스턴스에서 tomcat을 설치하여 웹 서버를 띄우고 어플리케이션을 배포해 보겠습니다. 아래는 ubuntu 20.04환경에서의 tomcat version 9 설치 방법입니다.
sudo apt update
해당 명령어를 통해 시스템 내부 패키지들을 최신화 해줍니다. 이는 최신화 되지 않은 패키지들의 의존성이 충돌하는 문제를 방지해 줍니다.sudo apt install tomcat9 tomcat9-admin
Ubuntu환경에서 tomcat version 9 설치 명령어입니다.ss -ltn
ss 명령어를 통해 tomcat 8080 기본 포트가 재대로 요청을 받는지 확인합니다.systemctl status tomcat9
tomcat 서버가 잘 동작하는지 확인합니다.
🚫 이슈
여기서 저는 간단한 실습 예제를 수행하기 때문에 하나의 인스턴스에서 Jenkins와 Tomcat서버를 둘 다 구동시켰습니다. tomcat 서버가 동작하는데 오류가 발생하였고, 문제를 분석해보니 미리 작동 중이던 Jenkins의 포트 번호도 8080으로 지정되었기 때문에 오류가 발생한 것이었습니다. 이에 tomcat의 포트 번호를 8081로 변경하여 문제를 해결하였습니다.
이제 Jenkins Item을 Tomcat 환경으로 설정하여 웹 어플리케이션을 배포해 보겠습니다. 먼저 Jenkins에 접속해 item을 구성해 보겠습니다.
- Jenkins 관리 > plugins > available plugins > container 검색 후 Deploy to container Plugin 설치
- item 생성 이름 입력 후 Maven project 선택
- 소스 코드 관리 항목
Git 체크 후 원하는 어플리케이션 저장소 url입력 (+ 원하는 Branch 저장소로 변경) - 빌드 유발 항목
Build whenever a SNAPSHOT dependency is built 설정 체크 - Build 항목
Root POM에 pom.xml 기입, Goals and options에 clean package 기입(Java 기반 Spring 어플리케이션이기 때문에) - Post Steps의 Run regardless of build result 항목을 활성화해 주면서 빌드 결과와 상관없이 빌드 내용을 기록하여 문제를 더 쉽게 발견하거나, 오류가 발생한 부분 이외의 작업을 수행시킬 수 있습니다.
- 빌드 후 조치 항목 구성
해당 항목은 어플리케이션을 빌드한 이후의 동작을 관리하는 항목으로 아래와 같은 설정을 통해서 빌드한 파일을 배포할 수 있습니다.
- WAR/EAR files: 빌드한 war(Spring프로젝트 이기 때문에)파일의 위치를 기입해 배포할 파일의 위치를 제공합니다.
- Contaiers
어플리케이션 배포를 컨테이너 환경을 통해 더 안정화된 배포를 진행합니다.- Credentials: 보안, 인증을 담당합니다.
- Tomcat URL: Tomcat서버의 URL로 저는 포트 충돌을 피하기 위해 8081로 설정을 변경해 주었습니다.
이제 Item을 생성 후 빌드하면 인스턴스에 빌드가 파일이 생성되고, 빌드 후 조치 설정에 맞게 생성된 파일을 Tomcat 서버에 배포하게 됩니다.
8081 포트로 접근하면 배포된 tomcat서버를 확인할 수 있습니다.
tomcat서버위에 배포한 war파일인 hello-world에 접근해보면 간단한 어플리케이션이지만 웹 서버에 배포된 모습을 볼 수 있습니다.
'개발 > 9oormthon 부트캠프 👨🏼🏫' 카테고리의 다른 글
[9oormthon] EC2에 ALB이용해서 Nginx 배포해보기 (0) | 2024.04.24 |
---|