[CI/CD] Jenkins

황서희·2023년 3월 7일
0
post-thumbnail

Jenkins

공식 사이트

젠킨스는 구축, 테스트 및 배포와 관련된 소프트웨어 개발 부분을 자동화하여 지속적인 통합 및 지속적인 배포를 촉진하는 오픈소스 자동화 서버이다. Apache Tomcat과 같은 서블릿 컨테이너에서 실행되는 서버 기반 시스템이므로 Tomcat이 반드시 필요하다. CVS, Subversion, Git과 같은 버전 제어 도구를 지원한다. Ant, Maven 등 프로젝트와 쉘 스크립트 및 Windows 배치 명령을 실행한다.

젠킨스 2 특징

Pipeline-as-code 및 Jenkinsfile을 지원하는 새 젠킨스 버전이다.

  • Jenkinsfile
    CI/CD 파이프라인을 코드로 작성 가능하다. 이것을 Pipeline-as-code라고 한다.

  • DSL(Domain-Specific Language)
    도메인(영역)의 사양을 선언할 수 있는 언어이다. Scripted Pipeline과 Declarative Pipeline이 있다. Scripted Pipeline는 Groovy라는 언어를 사용해 작성하기가 까다롭기 때문에 Declarative Pipeline(선언적/서술적 파이프라인)을 자주 사용한다.

젠킨스를 세 가지 형태로 다운로드 받아 볼 것이다.

  1. 리눅스 패키지로 설치
  2. 도커에서 운영
  3. 쿠버네티스에서 운영 (최종)

젠킨스 인스턴스 생성 및 젠킨스 설치

EC2 인스턴스로 생성한다.

  1. 보안 그룹 설정
    SSH와 HTTP, TCP:8080을 열어둔다.

  2. t3.medium, 40gb 스토리지로 EC2 인스턴스를 생성한다.

ssh ubuntu@ip -i sh.pem #인스턴스 접속
sudo hostnamectl set-hostname jenkins
exec bash

젠킨스 설치 참고

젠킨스를 Java에서 사용하기 위해선 Java 11 혹은 Java 17 버전이 필요하다.

sudo apt update
sudo apt install openjdk-11-jdk #Java 11 설치
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo tee \
  /usr/share/keyrings/jenkins-keyring.asc > /dev/null
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
  https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
  /etc/apt/sources.list.d/jenkins.list > /dev/null #저장소 추가
sudo apt-get update
sudo apt-get install jenkins

내부적으로 Tomcat을 가지고 있고 war 파일로 만들어져 있는 것을 확인할 수 있다. 또한 8080으로 서비스를 하고 있다. public ip에 8080으로 접속하면 jenkins 접속을 확인할 수 있다.

젠킨스 초기 설정

젠킨스의 잠금을 풀어야 한다.

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

명령어를 치면 나오는 잠금 패스워드를 입력하면 잠금이 풀린다.

젠킨스의 가장 강력한 점은 플러그인이다. 젠킨스 플러그인 검색 사이트에서 플러그인을 검색할 수 있다. 이와 같이 선택적으로 플러그인들을 다운로드 받을 수도 있지만, Suggested 옵션을 사용해서 필수적인 플러그인을 자동으로 설치할 수도 있다.

플러그인 설치가 다 되고 관리자 계정을 만들면 젠킨스 초기 설정이 완료된다. 초기 설정을 완료하고 Start Using Jenkins를 클릭하면 젠킨스 초기 화면이 나온다.

젠킨스 프로젝트 생성

젠킨스에서는 Item 하나를 프로젝트라고 부른다. 이 프로젝트가 하나의 오토메이션(자동화)를 구성할 수 있게 해 주는 하나의 단위이다. Item 추가에서 Freestyle project를 지정한다. (주로 사용하게 되는 것은 Pipeline이다.) Item 하나를 간단하게 만들어 보자.

  • git repository 주소
  • branch specifier에 * /main으로 브랜치 설정
  • Build Steps에 echo "hello world" > hello.txt로 Command 설정
  • Apply를 누르고 저장한다.

생성한 프로젝트에서 지금 빌드 버튼을 누르면 지정한 프로젝트가 실행된다.

Build History에서 빌드 버전을 확인할 수 있다. 첫 실행이므로 #1로 나온다. #1를 클릭하고 Console Output을 누르면 빌드의 결과를 콘솔로 확인할 수 있다.

sudo -i -u jenkins #젠킨스 사용자로 전환. 젠킨스가 다운로드 될 때 자동으로 생성된다.
cd ~/workspace
cd ~/workspace/test_project #저장소 클론
cat hello.txt #빌드한 작업 결과 확인

이와 같이 지정한 작업을 사용자 대신 수행해준다. 따라서 어떤 명령어를 어떻게 수행할 것인가를 지정해 주면 실제로 과정을 자동으로 수행해 준다. 빌드도 조건을 지정함으로써 자동으로 빌드하게 할 수 있다.

결국 젠킨스를 실행할 때 중요한 것은 명령어를 어떻게 실행시킬 것이냐이다.

  • fork
    포크는 원래 "업스트림" 리포지토리와 코드 및 표시 유형 설정을 공유하는 새 리포지토리이다. 포크는 오픈 소스 프로젝트에서 또는 사용자가 업스트림 리포지토리에 대한 쓰기 액세스 권한이 없는 경우와 같이 업스트림 리포지토리에 다시 제안되기 전에 아이디어 또는 변경 내용을 반복하는 데 자주 사용된다.

Maven 빌드

Maven으로 빌드하기 위해 필요한 것은 패키지이다.

sudo apt install maven
mvn --version #버전 확인

jenkins의 build steps에서 mvn clean package를 입력한 후 빌드한다. 이 상태에서 Console Output을 클릭하면 실시간으로 빌드 현황을 확인할 수 있다.

작업 공간에서는 해당되는 디렉터리를 shell 창에 들어가지 않고도 확인할 수 있다.

플러그인으로 빌드하기

젠킨스의 강력한 점은 다양한 플러그인이라고 할 수 있다. 플러그인으로 빌드하기 위해선, 대시보드에서 Jenkins 관리 탭에 들어간다.

플러그인 관리를 클릭한다.

Available plugins에서 maven을 검색하면 Maven Integration을 확인할 수 있다. 클릭해서 선택해서 Install without restart를 클릭하면 Jenkins가 해당 플러그인과 의존성 플러그인을 설치한다. 설치되면 대시보드로 돌아가서, Global Tool Configuration을 클릭한다. 여기서 Global은 젠킨스 전체에서 사용한다는 듯이다.

Name에는 이름을, JAVA_HOME에는 자바가 설치된 홈 디렉터리를 입력하면 된다.

ls -l /etc/alternatives/java #자바 실제 홈 디렉토리 확인

Maven 역시 Name에는 이름을, MAVEN_HOME에는 자바가 설치된 홈 디렉터리를 입력하면 된다.

ls -l /etc/alternatives/maven #maven 실제 홈 디렉토리 확인

Apply 후 저장하면 글로벌 툴을 설정할 수 있다. 초기 화면으로 돌아와 Item 추가를 누르면, Maven Project가 추가되어 있다. Maven 플러그인을 설치했기 때문이다.

Git에는 내 저장소 주소와 main 브랜치를 작성해 준다. Build 부분이 달라지는데, maven은 pom.xml 로 빌드가 고정된다. Goals and options는 clean package로 지정해 주고 Apply 후 저장한다. 그리고 빌드하면 빌드가 완료됐을 때 target이 만들어진다.

Tomcat 서버에 배포하기

Jenkins가 설치되어 있는 인스턴스에 배포해도 되지만, Jenkins는 빌드하기 위한 시스템이므로 조금 더 현실적인 구성을 위해 배포용 Tomcat 서버를 따로 구성해서 배포한다. 보안 그룹은 Jenkins 인스턴스를 생성할 때와 같은 것으로 지정하고, t3.small과 8GB 스토리지로 생성해 준다.

ssh ubuntu@ip -i sh.pem #인스턴스 접속
sudo hostnamectl set-hostname tomcat
exec bash
sudo apt update && sudo apt install tomcat9 -y #tomcat 설치

SCP 명령으로 배포

Jenkins 서버와 Tomcat 서버는 VPC로 연결되어 있다. ssh로 서로 접속할 수도 있으므로, scp가 가능하다. Jenkins 서버에서 Tomcat 서버로 접속을 하려면 인증을 거쳐야 하는데, jenkins 서버에서 키를 만들고 tomcat 서버로 키를 배포해야 한다.

ssh-keygen
#ssh-copy-id ubuntu@ip #안된다. 키를 복사하려면 인증을 해야 하는데, 인증하는 방법이 맞지 않기 때문이다.

jenkins 인스턴스에서 생성한 공개 키가 tomcat 서버에 복사되어 있어야 하지만, 방금 만든 것이기 때문에 복사되어 있지 않아 인증할 수 없다. 따라서 유일하게 인증할 수 있는 방법은 authorized_keys 파일에 public key를 직접 복사 붙여넣기 해야 한다.

cat .ssh/id_rsa.pub #jenkins인스턴스에서 복사
vi .ssh/authorized_keys #tomcat 인스턴스에 붙여넣기
ssh ubuntu@ip #jenkins 인스턴스에서 ssh로 tomcat 인스턴스 접속
scp /var/lib/jenkins/workspace/maven_project/garget/hello-world.war ubuntu@private ip:/var/lib/tomcat9/webapps

Permission denied가 뜬다. webapps 디렉터리는 소유자인 tomcat에만 write 권한이 있기 때문이다. 따라서 소유자인 tomcat 그룹에 현재 사용자인 ubuntu 사용자를 넣어야 한다.

sudo usermod -aG tomcat $USER #tomcat 그룹에 현재 사용자를 넣는다.
scp /var/lib/jenkins/workspace/maven_project/garget/hello-world.war ubuntu@private ip:/var/lib/tomcat9/webapps #해결딤

tomcat 서버에서 확인하면 hello.war 파일이 있는 것을 확인할 수 있다.

cd /var/lib/tomcat9/webapps
ls

tomcat 서버 퍼블릭 ip의 8080으로 접속하면 웹 사이트를 확인할 수 있다.

Jenkins를 사용해서 배포

Jenkins를 이용하는 배포는 maven project를 통해 배포할 수 있다. post steps의 구성이 필요하다. post steps는 Run only if build succeeds의 Excute shell로 설정해 준다.

scp /var/lib/jenkins/workspace/maven_project/target/hello-world.war ubuntu@ip:/var/lib/tomcat9/webapps

Apply 후 저장하면 Build Failure가 된다. jenkins의 권한에서 실행해야 하는데 명령어 상으로는 ubuntu 사용자로 실행했으므로 jenkins가 톰캣 서버에 접근할 권한이 없기 때문이다. 해결하기 위해서는 jenkins 사용자에서 ssh 키를 만든 후 그 키를 사용해야 한다.

sudo -i -u jenkins #사용자 전환
ssh-keygen
cd .ssh
cat id_rsa.pub #키를 복사한다.
vi .ssh/authorized_keys #tomcat 서버에서 붙여넣기한다.

ubuntu 사용자는 위에서 설명한 것과 같이 톰캣 그룹에 속해있는 상태여야 한다. 쓰기 권한을 가져야 하기 때문이다.

Jenkins 시스템

  • 컨트롤러
    젠킨스 시스템의 핵심, 모든 설정/옵션/잡에 대해 관리, 다른 시스템에 설정되어 있지 않으면 잡을 실행하는 기본 노드, 가능하는 무거운 작업은 노드에서 실행한다.

  • 노드
    컨트롤러에 의해 관리되고 잡을 실행하기 위한 모든(컨트롤러/노드0 시스템, 에이전트가 설치되어 있어야 한다.

  • 에이전트
    컨트롤러에 연결하는 Java 클라이언트 프로그램/프로세스

  • 엑시큐터(Executor)
    잡을 실행하기 위한 슬롯, 에이전트의 스레드, 해당 노드에서 실행할 수 있는 동시 작업 수

Jenkins 글로벌 도구

Dashboard > Jenkins 관리 > Global Tool Configuration

컨트롤러나 노드에서 빌드에 필요한 도구 설정, 기본 도구 의외에 플러그인에 의해 추가할 수 있다.

JDK, Git, Gradle, Ant, Maven

Jenkins 플러그인

Dashboard > Jenkins 관리 > 플러그인 관리

컨트롤러에 설치되며 Jenkins의 기능을 향상시키는 수단이다. 빌드 관련 도구, 클라우드 공급자, 공급 도구로 나뉘어져 있다.

Jenkins 자격증명

Dashboard > Jenkins 관리 > Manage Credentials

Jenkins는 상호작용 할 수 있는 타사 사이트 및 애플리케이션을 위한 자격 증명을 구성할 수 있다. 자격 증명의 유형으로는 API token, Username and password, Secret file, ssh 등이 있다.

Jenkins-node 인스턴스 생성

Jenkins 컨트롤러에서 빌드하는 경우는 거의 없으므로 대부분은 노드 인스턴스를 따로 생성해서 빌드한다.빌드 용으로 사용할 노드이기 때문에 java와 maven이 필요하다.

sudo hostnamectl set-hostname jenkins-node
exec bash
sudo apt update && sudo apt install -y openjdk-11-jdk maven

jenkins 패키지를 직접 설치하는 것이 아니라 ssh 설치해서 노드로만 사용할 것이기 때문에 사용자를 따로 만들어준다. 딱히 정해져 있는 것은 아니지만 username 을 jenkins로 맞춰 주는 편이 편하다.

sudo username jenkins -d /var/lib/jenkins -m -s /bin/bash
sudo -i -u jenkins

mkdir .shh
cd .ssh/
vi authorized_keys #jenkins 인스턴스 jenkins 사용자의 id_rsa.pub의 내용을 붙여넣기한다.

jenkins 인스턴스에서 이제 jenkins-node로의 접속이 가능하다.

ssh jenkins@private ip

이 상태로 빌드를 실행하면 실패하는데, ssh가 pki 구조가 아니어서 제 3자가 공개키를 인증할 수 있는 구조가 아니기 때문이다. 따라서 처음에 직접 등록을 해야 한다. 이 절차는 jenkins-node 인스턴스에서 실행한다. 한 번만 실행해 주면, jenkins-node 안에 tomcat의 정보가 들어가 있으므로 다시 물어보지 않는다.

ssh ubuntu@private ip #tomcat에 접속, pingerprint에 yes라고 답한다.

해당 절차를 진행한 후 빌드하면 정상적으로 진행되는 것을 확인할 수 있다.

빌드를 자동으로 실행하기

빌드 시작 버튼을 누르지 않고 자동으로 빌드를 실행하는 방법은 다음과 같다.

빌드 유발(Trigger)에서 Poll SCM(Source Code Management)을 클릭한다.

schedule을 * * * * * 로 설정한다. 매 분마다 레포지토리에 새로운 커밋이 있는지 확인한다는 뜻이다. local desktop 에서 내용을 바꾼 후 자동으로 빌드를 진행하는지 확인한다.

vi src/main/webapp/WEB-INF/views/index.jsp #버전을 1.0.1로 수정
git add .
git commit -m "version: 1.0.1"
git push

Jenkins에서 프로젝트의 Git polling log나 Build History를 확인해 보면 저장소에 커밋된 내용을 자동으로 가져와 빌드를 진행하는 것을 확인할 수 있다.

profile
다 아는 건 아니어도 바라는 대로

0개의 댓글