본문 바로가기

메가존 클라우드 2기 교육/실무 특화

CI / CD - Jenkins, Gti Lab

CI/CD 파이프라인이란?

 CI/CD 파이프라인은 새 버전의 소프트웨어를 제공하기 위해 수행해야 할 일련의 단계이다. 지속적 통합/지속적 배포(CI/CD) 파이프라인은 DevOps 또는 사이트 신뢰성 엔지니어(SRE) 방식을 통해 더 효과적으로 소프트웨어를 제공하는 데 초점을 맞춘 방법이다.

 CD/CD 파이프라인은 특히 통합 및 테스트 단계와 제공 및 배포 단계에서 모니터링 및 자동호라르 도입하여 애플리케이션 개발 프로세스를 개선한다. CD/CD 파이프라인의 각 단계를 수동으로 실행할 수도 있지만, CD/CD 파이프라인의 진가는 자동화할 때 드러난다

 Ci/CD 파이프라인의 단계는 각기 다른 태스크 하위 집합으로 이루어져 있는데, 이를 파이프라인 단계(pipeline stage)라고 부른다. 일반적인 파이프라인 단계는 다음과 같다.

  • 빌드(Build) - 애플리케이션을 컴파일하는 단계
  • 테스트(Test) - 코드를 테스트하는 단계. 이 단계를 자동화하여 시간과 수고를 줄일 수 있다.
  • 릴리스(Release) - 애플리케이션을 리포지토리에 제공하는 단계
  • 배포(Deploy) - 코드를 프로덕션에 배포하는 단계 (최종 운영 환경)
  • 검증 및 컴플라이언스(Validation & compliance) - 빌드 검증 단계는 해당 조직의 필요에 따라 결정된다. Clair와 같은 이미지 보안 스캔 툴을 사용하여 알려진 취약점(CVE)과 비교하는 방법으로 이미지의 품질을 보장할 수 있다.

Git과 GitHub 개념 및 환경 설정

 Git이란 소스코드를 효과적으로 관리하기 위해 개발된 '분산형 버전 관리 시스템'이다. 원래는 Linux 소스코드를 관리할 목적으로 개발되었다. Git에서는 소스 코드가 변경된 이력을 쉽게 확인할 수 있고, 특정 시점에 저장된 버전과 비교하거나 특정 시점으로 되돌아갈 수(롤백)도 있다. 또 내가 올리려는 파일이 누군가 편집한 내용과 충돌한다면, 서버에 업로드 할 때 경고 메시지가 발생된다.

 GitHub란 파일이나 폴더를 저장해 두는 곳이다. 그런데 Git 저장소가 제공하는 좋은 점 중 하나는 파일이 변경 이력 별로 구분되어 저장된다는 점이다. 비슷한 파일이라도 실제 내용 일부 문구가 서로 다르면 다른 파일로 인식하기 때문에 파일을 변경 사항 별로 구분해 저장할 수 있다.

 


Jenkins이란?

 Jenkins는 지속적 통합(continuous integration, CI)과 지속적 배포(continuous delivery, CD)를 위한 대표적인 도구이다. 빌드, 테스트, 배포 프로세스를 자동화하여 소프트웨어 품질과 개발 생산성을 높일 수 있다.


편리한 설정

웹 기반의 콘솔로 다양한 인증 기반과 결합이 가능하며 권한 관리 기능을 통해 안전한 빌드/배포 환경을 구축할 수 있다. 수많은 플러그인을 사용하여 자동화할 수 있어 반복되는 작업을 줄일 수 있다. 빌드/배포의 결과에 대해 통지 받을 수 있는 설정이 간편하고 다양한 채널을 통해 빠르게 피드백을 받을 수 있다.


안정적인 빌드/배포 환경

소스 버전 관리 툴(SVC)과 연동하여 코드 변경을 감지(Poll)하고, 자동화 테스트를 포함한 빌드를 수행하여 소프트웨어 품질을 향상시킬 수 있다. 자동화 테스트에는 코딩 표준 준수 여부 체크, 유닛 테스트, 통합 테스트 등을 설정할 수 있고 테스트 결과에 대한 피드백을 받아 잠재적인 오류를 사전에 예방할 수 있다. 빌드 결과물을 지속적으로 배포하도록 설정하여 개발 프로세스 전체를 자동화할 수 있다.


다양한 활용 및 손쉬운 확장

Jenkins는 많이 사용 되고 있는 오픈 소스 소프트웨어로 문서화가 잘 되어 있다. 빌드/배포 이외에도 스케쥴링을 이용한 배치 작업에도 활용되는 등 다양한 적용 사례들을 참고할 수 있다. 플러그 인을 직접 개발하여 기능을 확장하는 것도 가능하다. 네이버 클라우드 플랫폼에서 제공하는 다른 Dev Tools 상품들과도 쉽게 통합할 수 있다.

 


Git 설치


Git

Git을 활용한 GitHub에 소스코드 Push

## GitBash 접속
# 테스트 용 폴더 생성 후 파일 생성.
mkdir git-test && cd $_
echo "Hello World" >  README.txt

# Git 로컬 저장소를 생성, .git 디렉토리가 생성됨
git init

# 버전 관리를 위해 내 정보 설정
git config --global user.email "test@example.com"
git config --global user.name "kyounggu"

# 파일을 스테이지에 올리는 명령어, 스테이징 영역은 커밋할 준비가 된 변경 내용이 로컬 저장소에 기록되기 전에 대기하는 장소
git add README.txt

# Git 상태 확인
git status

# commit. 변경 사항을 로컬 저장소에 저장하는 명령어
git commit -m "add site"

# log 확인
git log
'ls -al'로 나오는 숨김 폴더 '.git'이 Git 로컬 저장소이다.

'Git status'

'Git commit'

'Git Log'. 버전관리에 쓰일 commit hash가 나온다.

# README.txt 업데이트 후 git status 확인
echo "Aloha" >> README.txt
cat README.txt
git add README.txt
git status

# 변경사항 commit 후 git log 확인
git commit -m "add upadate"
git log

 


새로운 로그가 생겼다. 이를 이용해 버전별로 구분이 가능. (롤백이 쉬움)

# commit hash의 시점으로 이동
git checkout [commit hash]

# 이전 시점으로 이동
git checkout -
checkout을 통해 Aloha가 없던 시점으로 돌아왔다.

이전 시점으로 이동해서 Aloha가 다시 생겼다.

GitHub 원격저장소 커밋

GitHub에서 리포지토리 생성.
# git 리포지토리 연결
git remote add origin https://github.com/kyounggudev/test-dev

# 연결된 리포지토리의 master 브랜치에 push(업로드)
git push origin master
처음 'push'를 하면 로그인 창이 뜬다.

GitHub의 'Settings' - 'Developer settings' - 'Tokens' - 'Generate new token'을 클릭

'repo'만 체크하고 Generate

생성된 토큰을 복사.

토큰으로 로그인.

push 명령어가 진행된다.

리포지토리에 업로드 된 것을 확인할 수 있다.

윈도우의 경우에는 '자격 증명 관리자'에 자격 증명 정보가 남는다. 이를 삭제하거나 편집할 수도 있다.

 


GitHub 원격저장소의 커밋을 로컬저장소에 내려받기

테스트용 VM 생성.
## 생성한 VM에서
# 자동완성 설치
yum install -y bash-completion

# git 설치
yum install -y git

# git 리포지토리 내려받기
git clone https://github.com/kyounggudev/test-dev.git
cd test-dev/

# 버전 관리를 위해 내 정보 설정
git config --global user.email "test@centos.com"
git config --global user.name "centos"

# README.txt 확인
cat README.txt

# 현재 경로의 모든 것을 add
git add . 

# git status

# commit
git commit -m "add list"

# 로그 확인
git log

# master 브랜치에 push 
git push origin master
README.txt 확인. 내려받기가 정상적으로 이루어진 것을 알 수 있다.

README.txt이 modified 됐다.

커밋을 해서 새로운 로그가 생겼다.

push를 하면 'git 아이디'와 '토큰 키'를 입력해줘야한다.

원격저장소의 새로운 커밋을 로컬저장소에 갱신하기

# cat README.txt

# 리포지토리의 matser 브랜치 pull
git pull origin master

# cat README.txt
pull을 하여 새로운 커밋을 반영할 수 있다.

 


Git Lab

Git Lab 설치

# Git Lab 패키지 Set up
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash

# Git Lab CE 설치 (아이피 입력)
EXTERNAL_URL="http://192.168.2.206" yum install -y gitlab-ce

# 패스워드 수정
cat /etc/gitlab/initial_root_password

해당 경로(git으로 내려받은 리포지토리 폴더)에 웹페이지 파일을 올린다.
# 웹 사이트 파일 업로드
git add .
git commit -m "change site"
git push origin master

Git Lab 접속

# gitlab이 설치한 인스턴스에 방화벽 설정
firewall-cmd --permanent --add-service=http
firewall-cmd --reload

# git lab의 root 계정 패스워드 확인
cat /etc/gitlab/initial_root_password
root의 패스워드 확인.
gitlab이 설치된 아이피로 접속하고 로그인.

 

 

패스워드 변경.

Git Lab 새 프로젝트 생성



프로젝트 생성 완료.

Git을 활용한 GitLab에 소스코드 Push

## git bash에서
# gitlab-test 폴더 생성 후 이동
cd
mkdir gitlab-test && cd $_
만든 폴더에 웹사이트 파일을 넣는다.

# init
git init

# 인적사항에 적힐 사용자 정보 입력
git config --global user.email "gitlab-test@example.com"
git config --global user.name "kyounggu"

# commit
git add .
git commit -m "new gitlab site"

GitLab 원격저장소 커밋

Cline with HTTP 주소 복사.
# 복사한 주소를 이용하여 Gitlab과 http 연결
git remote add origin http://192.168.2.206/root/my-dev.git

# Gitlab에 업로드
git push origin master
첫 push에는 로그인 인증을 해준다.

master 브랜치에 push가 된 것을 확인할 수 있다.

GitLab 원격저장소의 커밋을 로컬저장소에 내려받기

'my-dev'의 Clone with HTTP 주소를 복사.
# 로컬 저장소(VM)에 복사한 주소로 내려받기
cd
git clone http://192.168.2.206/root/my-dev.git

# 처음엔 main 브랜치이므로 아무것도 없다. 업로드한 master 브랜치로 checkout
git checkout master

# 사용자 정보 입력
git config --global user.email "gitlab-test@example.com"
git config --global user.name "kyounggu"

master 브랜치로 변경해야 업로드한 파일이 보인다.

'git init'을 하지 않았는데 '.git'폴더인 로컬 저장소가 생겼다. clone을 하면서 자동으로 생긴 것이다.

# 웹 사이트 소스코드 수정
vi index.html
//
사진처럼 이름 변경
//

# add
git add index.html

# commit
git commit -m "add my-dev"

# push (gitlab 아이디 패스워드 입력)
git push origin master

git push

원격저장소의 새로운 커밋을 로컬저장소에 갱신하기 

## git bash에서
# 갱신 전 index.html 확인 
vi index.html

# pull(갱신)
git pull origin master

# 갱신 후 index.html 확인
vi README.txt
갱신 전
갱신 후

원격 저장소 마이그레이션(Github에서 Gitlab으로 마이그레이션)

새로운 프로젝트 생성.
# github의 test-dev 리포지토리를 git-migration 폴더에 내려받기 ('--mirror': 리포지토리 복제)
cd
mkdir git-migration
git clone --mirror https://github.com/kyounggudev/test-dev.git git-migration

# 내려받은 리포지토리를 gitlab에 push
cd git-migration/
git push -uf http://192.168.2.206/root/my-gitlab.git --all
gitlab에 push 완료.

 이렇게 리포지토리를 이동하는 것을 통해 원격 저장소에 migration을 할 수 있다.

 

 


Jenkins

Jenkins-server 인스턴스 생성

#!/bin/bash
timedatectl set-timezone Aisa/Seoult
yum install -y httpd git
systemctl enable --now httpd
cd /var/www/html
git clone https://github.com/kyounggudev/test-dev.git
mv test-dev/* .
생성된 인스턴스의 퍼블릭 아이피로 접속.

jenkins-server의 아이피를 Route53의 레코드에 추가해준다.

젠킨스 설치

# root 계정으로 전환
sudo su -

# 시간
timedatectl set-timezone Asia/Seoul

# 업데이트
yum update -y

# 젠킨스 패키지 내려받기
wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo

# 공식 주소인지 키를 이용해 확인
rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key

# 아마존 리눅스 전용 epel 설치 (퍼블릭하게 사용하기 위함.)
amazon-linux-extras install epel -y

# 자바 설치
amazon-linux-extras install -y java-openjdk11

# 젠킨스 설치
yum install -y jenkins
systemctl enable --now jenkins

젠킨스는 8080포트로 접근하므로 인스턴스의 보안 그룹에 8080포트를 열어준다.

젠킨스 접속

# 초기 패스워드 확인
cat /var/lib/jenkins/secrets/initialAdminPassword

8080포트로 접속

플러그인 설치 없이 'x' 클릭

'Start using Jenkins' 클릭

'설정' 클릭

스크롤을 눌러서 비밀번호 변경.

 젠킨스 대시보드 

'Create a job' 클릭

이름을 정하고 'Freestyle project'를 클릭하고 'OK'

'Execute shell'을 통해 젠킨스 터미널에 접속하지 않아도, 빌드 시 Web UI에서 해당 명령어의 출력을 볼 수 있다.

'지금 빌드' 클릭

빌드가 성공하면 좌측 하단에 목록이 뜬다. '#1' 클릭

'Console Output'을 보면 위에서 넣었던 쉘 명령어의 출력을 볼 수 있다.

다시 'Configure' - 'Build Steps'에 내용을 추가.

다시 빌드하여 출력을 확인하면 추가한 내용의 출력이 추가된 것을 확인할 수 있다.

 


 

젠킨스에 깃허브 리포지토리 가져오기

새 리포지토리 생성.

# 실습에 사용할 리포지토리를 가져오기
mkdir git-migration
git clone --mirror https://github.com/hali-linux/hello-world.git git-migration

# 가져온 리포지토리를 자신의 Github에 Push
cd git-migration/
git push -uf [새로 생성한 자신의 리포지토리 주소].git --all
다른 사람의 리포지토리를 마이그레이션

Jenkins에서 Git 플러그인 설치

Tools에서 git과 관련된 명령어를 사용하도록 이름 설정

새로운 아이템 추가.

소스 코드 관리에 리포지토리 주소 기입

빌드를 하고난 후의 콘솔 출력.

이번엔 Test-dev의 주소 복사.

젠킨스에서 새로운 아이템 생성.

test-dev 리포지토리 주소 기입.

빌드 후, 콘솔 출력 모습

# 젠킨스 작업공간 확인
ls /var/lib/jenkins/workspace/
CLI 창에서도 젠킨스에 아이템이 생성된 것을 확인

 


 

 

Maven 설치

(자바 기반 프로젝트의 빌드, 패키징, 의존성 관리 등을 자동화하기 위한 도구)

## 젠킨스 서버 CLI에서
# maven 설치
cd /opt
wget https://dlcdn.apache.org/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz
tar -xvzf apache-maven-3.8.8-bin.tar.gz
mv apache-maven-3.8.8 maven
ls maven/bin

# 자바가 설치된 경로 확인
cd ~
find / -name java-11*

# 
vi .bash_profile
// JAVA_HOME에 확인한 자바 설치 경로를 붙여넣기
M2_HOME=/opt/maven
M2=/opt/maven/bin
JAVA_HOME=/usr/lib/jvm/java-11-openjdk-11.0.19.0.7-1.amzn2.0.1.x86_64

# User specific environment and startup programs

PATH=$PATH:$HOME/bin:$JAVA_HOME:$M2_HOME:$M2
//

# 변경한 설정 적용
source .bash_profile

# 메이븐 명령어 사용 가능한지 확인
mvn -v

jvm이 포함된 경로를 확인.

JAVA_HOME에 확인한 자바 설치 경로를 붙여넣기


젠킨스에서 'Maven Integration' 플러그인 설치

Tools에서 JDK 추가. 경로는 위에서 확인한 자바 경로 입력
Maven도 추가. 'mvn -v' 명령어를 통해 이름과 경로를 확인.

새로운 아이템 추가. Maven project 선택

GitHub의 레포지토리 주소 기입
clean install: 빌드하며 나온 결과물 중에서 불필요한 것을 정리, 제거하며 설치

빌드 후, 콘솔 출력

빌드되어 만들어진 파일인 'war'파일이 존재한다. (패키징)

Tomcat 서버 설치

VPC는 jenkins 서버와 같은 VPC로 해주고, '2c' 가용영역을 선택.

tomcat 서버를 레코드에 추가

# 인스턴스 세팅
sudo su -
timedatectl set-timezone Asia/Seoul
yum update -y
hostnamectl set-hostname tomcat-server

# 자바 섳치
amazon-linux-extras install -y java-openjdk11

# Tomcat 설치
cd /opt
wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.76/bin/apache-tomcat-9.0.76.tar.gz
tar -xvzf apache-tomcat-9.0.76.tar.gz
mv apache-tomcat-9.0.76 tomcat

# Tomcat 기동
cd tomcat/bin/
./startup.sh
8080포트(톰캣 포트)로 접속.
Manager App에 접속하면 권한이 없어서 Eeny 된다.

## 권한을 허용하기 위해 다음 과정 진행
# 수정할 context 확인
cd /opt/tomcat
find / -name context.xml

# host-manger에 있는 context 수정
vi /opt/tomcat/webapps/host-manager/META-INF/context.xml
//  톰캣 터미널 안에서만 자기자신 허용을 주석 처리
<!--  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> -->
//

# manager에 있는 context 수정
vi /opt/tomcat/webapps/manager/META-INF/context.xml
// 똑같이 주석 처리
<!--  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> -->
//

# 셧 다운으로 종료하고 다시 시작해서 수정 사항 적용 
cd bin/
./shutdown.sh
./startup.sh
주석 처리.

주석 처리.

수정 사항을 적용하고 다시 'Manager App' 에 접속하면 로그인 창이 뜬다.
# Tomcat 사용자 정보와 권한 수정
vi /opt/tomcat/conf/tomcat-users.xml
//
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-jmx"/>
<role rolename="manager-status"/>
<user username="admin" password="kosa0220" roles="manager-gui, manager-script, manager-jmx, manager-status"/>
<user username="deployer" password="kosa0220" roles="manager-script"/>
<user username="tomcat" password="kosa0220" roles="manager-gui"/>
//

# 링크를 걸어준다. (어디서든 사용 가능)
ln -s /opt/tomcat/bin/startup.sh /usr/local/bin/tomcatup
ln -s /opt/tomcat/bin/shutdown.sh /usr/local/bin/tomcatdown

# Tomcat 종료, 시작
tomcatdown
tomcatup


admin으로 로그인.

Tomcat와 Jenkins 통합

Jenkins에서 'Deploy to container' 플러그인 설치

credentials 추가.
젠킨스가 Tomcat에 접속할 수 있는 정보를 얻게됨.

새 아이템 추가. (Maven Proejct)

GitHub의 리포지토리 주소와 생성한 Credentilas 입력
clean install
**/*.war: 모든 경로(**/)에 있는 모든 이름의 war파일(*.war)

빌드 성공.

빌드에 성공하면 Tomcat 웹 애플리케이션 매니저에 '/wdbapp'이 생긴다.

회원가입 창이 뜨는데, 예시로 만든 페이지여서 제대로 작동되진 않는다(404 에러)

Git 소스 업데이트 (윈도우)

 해당 페이지의 소스코드를 수정해본다.

# git에서 내려받기
mkdir deploy && cd $_
git clone https://github.com/kyounggudev/hello-world.git

# master 브랜치로 이동
git checkout master

# webapp의 index.jsp 파일 수정
cd hello-world/webapp/src/main/webapp/
vi index.jsp
//
"Thankyou, Happy Learning 2023!!!"를 원한느 문장으로 수정
//

# 수정한 소스 코드 push
git add index.jsp
git commit -m "Hello World!!!"
git push origin master

Tomcat과 연결된 아이템에서 다시 빌드

톰캣 서버에 소스 코드 변경 사항이 반영된다. 이처럼 개발자들이 소스코드를 수정하면 이를 젠킨스를 통해 반영할 수 있다.

자동화 

빌드 유발에서 Poll SCM 체크.&nbsp;'Poll SCM': 주기적으로 Github를 확인.

# 다시 index.jsp를 수정
vi index.jsp
//
원하는 문장으로 수정
//

# Github에 push
git add index.jsp
git commit -m "Poll SCM Test"
git push origin master

빌드를 하지 않아도 자동으로 갱신된다.

이제 예시 페이지를 교체해본다.

# 잠시 백업
mv index.jsp index.jsp.bak

 

기존 페이지는 잠시 보관하고 새로운 페이지로 교체

# Github에 push
git add .
git commit -m "two-rabbit"
git push origin master
조금 기다리면 페이지가 교체된다.