Jenkins
개념
- 지속적 통합 & 배포를 위한 워크플로우 제어에 사용되는 툴
- 자바 기반의 오픈소스 -> 자바와 친화성이 높음
- 아파치 톰캣처럼 서블릿 컨테이너 내부에서 실행되는 서버 시스템
- 파이프라인이라고 부르는 스크립트 작성 -> 각 빌드 단계마다 세부적으로 젠킨스의 태스크 정의 가능
- 다양한 플러그인 연동 제공
- Build Plugins : Maven, Ant, Gradle …
- VCS Plugins : Git, SVN …
- Languages Plugins : Java, Python, Node.js …
- github action 과 함께 CI/CD 툴로 많이 거론 됨
- 간단한 비교 요약
- 워크플로우 예시
- 최신 코드 가져오기 : 개발을 위해 중앙 코드 리포지터리에서 로컬 시스템으로 애플리케이션의 최신 코드를 가져옴
- 단위 테스트 구현과 실행 : 코드 작성 전 단위 테스트 케이스를 먼저 작성
- 코드 개발 : 실패한 테스트 케이스를 성공으로 바꾸면서 코드 개발
- 단위 테스트 케이스 재실행 : 단위 테스트 케이스 실행 시 통과(성공!)
- 코드 푸시와 병합 : 개발 소스 코드를 중앙 리포지터리로 푸시하고, 코드 병합
- 코드 병합 후 컴파일 : 변경 함수 코드가 병함되면 전체 애플리케이션이 컴파일된다
- 병합된 코드에서 테스트 실행 : 개별 테스트뿐만 아니라 전체 통합 테스트를 실행하여 문제 없는지 확인
- 아티팩트 배포 : 애플리케이션을 빌드하고, 애플리케이션 서버의 프로덕션 환경에 배포
- 배포 애플리케이션의 E-E 테스트 실행 : 셀레늄 Selenium과 같은 User Interface 자동화 도구를 통해 애플리케이션의 전체 워크플로가 정상 동작하는지 확인하는 종단간 End-to-End 테스트를 실행.
실습
설치 및 설정
자바 설치 및 환경 변수 설정
# 실습 편리를 위해서 root 계정 전환
sudo su -
# Add required dependencies for the jenkins package
# https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/amazon-linux-install.html
sudo yum install fontconfig java-17-amazon-corretto -y
java -version
alternatives --display java
JAVA_HOME=/usr/lib/jvm/java-17-amazon-corretto.x86_64
echo $JAVA_HOME
젠킨스 설치
# 젠킨스 설치
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
sudo yum upgrade
sudo yum install jenkins -y
sudo systemctl daemon-reload
sudo systemctl enable jenkins && sudo systemctl start jenkins # 다소 시간 걸림
sudo systemctl status jenkins
# 초기 암호 확인
sudo systemctl status jenkins
cat /var/lib/jenkins/secrets/initialAdminPassword
# 접속 주소 확인
curl -s ipinfo.io/ip | awk '{ print "Jenkins = http://"$1":8080" }'
설치 완료 되면 초창기 로그인 화면이 뜸
아까 cat 이하로 확인했던 암호로 입장
install
유저설정
주소 같은지 확인
대시보드 설명
구성에 대해 간략히 설명
item
- 작업 최소단위, job
- 종류
- 프로젝트 : 가장 기본적인 job 세팅
- 파이프라인 : 스크립트로 미리 정의된 템플릿 프로세스들로 job 실행
사람
- 계정 관련한 설정
젠킨스 관리
- 전역적인 설정
- tool 등을 설정 할 수 있음
실습
tool 설정 : 자바 JDK 를 사용하도록 path 지정 > save
item 생성 > 프로젝트
빌드 설정
빌드
확인
빌드에 변경 사항 추가하기 > 지금 빌드
변경 된 부분 확인
젠킨스 설치된 ec2 에서 프로젝트 위치 확인
#
find / -name First-Project
# 프로젝트(job, item) 별 작업 공간 확인
tree /var/lib/jenkins/workspace/First-Project
Jenkins with Docker
젠킨스에서 도커를 사용하는 방법
사전 준비
젠킨스 유저로 도커 사용하도록 설정 > 젠킨스 유저 전
# jenkins 유저로 docker 사용 가능하게 설정
grep -i jenkins /etc/passwd
usermod -s /bin/bash jenkins
grep -i jenkins /etc/passwd
# jenkins 유저 전환
su - jenkins
whoami
pwd
docker info
exit
su - jenkins 로 jenkins 사용자 로그인 후 기본적인 명렁어 확인했으나 docker 정보의 경우 권한 에러 발생
-> 권한 줘야함(666은 모든 사용자에게 읽기쓰기 오픈함 주의)
chmod 666 /var/run/docker.sock
usermod -aG docker jenkins
# Jeknins 유저로 확인
su - jenkins
docker info
# Dockerhub로 로그인 하기
docker login
Username: <자신의 계정명>
Password: <자신의 암호>
# myweb:v2.0.0 컨테이너 이미지 생성을 위한 Dockerfile 준비
# 실습을 위한 디렉터리 생성 및 이동
mkdir -p ~/myweb2 && cd ~/myweb2
# Dockerfile 파일 생성
vi Dockerfile
FROM ubuntu:20.04
ENV TZ=Asia/Seoul VERSION=2.0.0 NICK=peachdo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
sed -i 's/archive.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list && \
sed -i 's/security.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list && \
apt-get update && apt-get install -y apache2 figlet && \
echo "$NICK Web Server $VERSION<br>" > /var/www/html/index.html && \
echo "<pre>" >> /var/www/html/index.html && \
figlet AEWS Study >> /var/www/html/index.html && \
echo "</pre>" >> /var/www/html/index.html
EXPOSE 80
CMD ["usr/sbin/apache2ctl", "-DFOREGROUND"]
# 모니터링
watch -d 'docker images; echo; docker ps'
-----------
# (참고) 이미지 빌드
docker build -t myweb:v2.0.0 -f /var/lib/jenkins/myweb2/Dockerfile
# (참고) 컨테이너 실행
docker run -d -p 80:80 --rm --name myweb myweb:v2.0.0
젠킨스에서 Docker-Project 생성 & 빌드 스텝 설정
# build step
cd /var/lib/jenkins/myweb2
docker build -t myweb:v2.0.0 .
# add build step
docker run -d -p 80:80 --rm --name myweb myweb:v2.0.0
빌드 > 콘솔 출력
터미널에서 도커 이미지 빌드 할 때 봤던 로그들 확인
터미널에서 docker images 확인 & 이미지가 실행되는지 확인
Github 저장소 연결
실습용 레포지토리 포크
https://github.com/gasida/aews-cicd
프로젝트 생성
파라미터 string 추가 > VERSION & NICK
소스코드 관리(Source Code Management) 설정
additional behaviours 에서 sparse checkout path 를 1로 설정
build trigger 에서 poll scm 에 schedule '*****' 추가
+) poll scm
- 웹훅을 사용하지 않아도 빌드를 유발 시키기 위한 옵션
- 형상관리 서버를 주기적으로 감시하여 변경된 사항이 존재할때 빌드를 수행하는 설정
build step 설정
cd /var/lib/jenkins/myweb2
rm -rf Dockerfile
wget https://raw.githubusercontent.com/$NICK/aews-cicd/main/1/Dockerfile
docker build -t myweb:$VERSION .
docker run -d -p 80:80 --rm --name myweb myweb:$VERSION
Github 레포에서 1/Dockerfile 수정 후 커밋 > 트리거 발동
젠킨스에서 확인
노란 부분에서 어떤 커밋을 반영해서 돌아갔는지 보임
실패한 부분
Dockerfile 경로를 못찾음 -> 동일하게 Execute shell 수정
파이프라인
이론
위에 실습이 프로젝트에 관한 것이었다면, 지금 항목은 파이프라인에 관한 것
- 파이프라인 장점
- 코드 : 애플리케이션 CI/CD 프로세스를 코드 형식으로 작성할 수 있고, 해당 코드를 중앙 리포지터리에 저장하여 팀원과 공유 및 작업 가능
- 내구성 : 젠킨스 서비스가 의도적으로 또는 우발적으로 재시작되더라도 문제없이 유지됨
- 일시 중지 가능 : 파이프라인을 실행하는 도중 사람의 승인이나 입력을 기다리기 위해 중단하거나 기다리는 것이 가능
- 다양성 : 분기나 반복, 병렬 처리와 같은 다양한 CI/CD 요구 사항을 지원
- 파이프라인 용어
- 파이프라인 : 전체 빌드 프로세스를 정의하는 코드.
- node : 파이프라인을 실행하는 시스템.
- stage : 특정 단계에서 수행되는 작업들의 정의.
- step : 파이프라인의 특정 단계에서 수행되는 단일 작업을 의미
- 파이프라인 3가지 구성 형태
- Pipeline script : 일반적인 방식으로 Jenkins 파이프라인을 생성하여 Shell Script를 직접 생성하여 빌드하는 방식
- Pipeline script from SCM : 사전 작성한 JenkinsFile을 형상관리 저장소에 보관하고, 빌드 시작 시 파이프라인 프로젝트에서 호출 실행하는 방식
- Blue Ocean : 젠킨스 ui 로 관리하면 자동으로 jenkinsfile이 생성, 실행
- 구문 형태
- 선언형 : 쉽게 작성 가능, 최근 문법이고 젠킨스에서 권장하는 방법, step 필수!
예제)
pipeline {
agent any # Execute this Pipeline or any of its stages, on any available agent.
stages {
stage('Build') { # Defines the "Build" stage.
steps {
// # Perform some steps related to the "Build" stage.
}
}
stage('Test') {
steps {
//
}
}
stage('Deploy') {
steps {
//
}
}
}
}
- 스크립트형 : 커스텀 작업에 용이, 복잡하여 난이도가 높음, step은 필수 아님
예제 )
node { # Execute this Pipeline or any of its stages, on any available agent.
stage('Build') { # Defines the "Build" stage. stage blocks are optional in Scripted Pipeline syntax. However, implementing stage blocks in a Scripted Pipeline provides clearer visualization of each stage's subset of tasks/steps in the Jenkins UI.
// # Perform some steps related to the "Build" stage.
}
stage('Test') {
//
}
stage('Deploy') {
//
}
}
실습 : 파이프라인 w. script
파이프라인 아이템 생성
스크립트로 정의
pipeline {
agent any
stages {
stage('정보 확인') {
steps {
echo 'Hello World'
sh 'java -version'
}
}
stage('가라 배포') {
steps {
echo "Deployed successfully!";
}
}
}
}
스크립트 자리에 내용 바꿔보기 > echo 동작 확인
pipeline {
agent any
environment {
STUDYNAME = 'AEWS'
}
stages {
stage('연습') {
environment {
mykey = 'abcd'
}
steps {
echo "${STUDYNAME}";
sh 'echo ${mykey}'
}
}
}
}
maven 수정 테스트
pipeline {
agent any
tools {
maven 'maven_3.8.7'
}
stages {
stage('Example') {
steps {
sh 'mvn --version'
}
}
}
}
ui 상에선 아래 부분 수정하는 것
step 항목에 넣을 수 있도록 도와주는 문법 변환기
실습 : 파이프라인 SCM
파이프라인 아이템 생성
scm 으로 설정
실습 : secret text
관리 → Credentials → + Add Credentials → Secret text : Usename(root), Password(qwe123), ID(vmsshpw)
실습 : secret files
kube config 파일을 자신의 PC에 복사 → Jenkins Web에 Secret files 등록
scp root@<작업용EC2_공인IP>:/root/.kube/config .
# 아래 확인을 위해 모니터링
watch -d kubectl get pod
pipeline {
agent any
environment {
MY_KUBECONFIG = credentials('k8sconfig')
}
stages {
stage('remote k8s api') {
steps {
sh("kubectl --kubeconfig $MY_KUBECONFIG get pods -A")
sh("kubectl --kubeconfig $MY_KUBECONFIG run nginx --image nginx --port=80")
}
}
}
}
Jenkins → Credentials → Add → Secret file : File(업로드), ID(k8sconfig)
Jenkins with k8s
사전 준비 : 젠킨스에서 k8s 를 사용 할 수 있도록 설정
# jenkins 사용자에서 아래 작업 진행
whoami
mkdir ~/.kube
# root 계정에서 아래 복사 실행
cp ~/.kube/config /var/lib/jenkins/.kube/config
chown jenkins:jenkins /var/lib/jenkins/.kube/config
# jenkins 사용자에서 aws eks 사용(sts 호출 등)을 위한 자격증명 설정
aws configure
AWS Access Key ID [None]: ###
AWS Secret Access Key [None]: ###
Default region name [None]: ap-northeast-2
# jenkins 사용자에서 kubectl 명령어 사용 확인
kubectl get pods -A
파이프라인으로 디플로이먼트/서비스 배포
yaml 파일 수정 : 도커 이미지 수정 작업
k8s-1 아이템 생성
파이프라인 스크립트
pipeline {
agent any
tools {
jdk 'jdk-17'
}
environment {
DOCKERHUB_USERNAME = 'gasida'
GITHUB_URL = 'https://github.com/<본인 깃헙id>/aews-cicd.git'
// deployment-svc.yaml -> image: <도커 허브id>/myweb:v1.0.0
DIR_NUM = '3'
}
stages {
stage('Container Build') {
steps {
// 릴리즈파일 체크아웃
checkout scmGit(branches: [[name: '*/main']],
extensions: [[$class: 'SparseCheckoutPaths',
sparseCheckoutPaths: [[path: "/${DIR_NUM}"]]]],
userRemoteConfigs: [[url: "${GITHUB_URL}"]])
// 컨테이너 빌드 및 업로드
sh "docker build -t ${DOCKERHUB_USERNAME}/myweb:v1.0.0 ./${DIR_NUM}"
sh "docker push ${DOCKERHUB_USERNAME}/myweb:v1.0.0"
}
}
stage('K8S Deploy') {
steps {
sh "kubectl apply -f ./${DIR_NUM}/deploy/deployment-svc.yaml"
}
}
}
}
확인
접속 테스트를 위한 파드 생성
# 배포
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: netpod
labels:
app: pod
spec:
containers:
- name: netshoot-pod
image: nicolaka/netshoot
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
배포 및 확인
#
kubectl exec -it netpod -- curl myweb:8080
kubectl exec -it netpod -- curl myweb:8080 | grep Web
while true; do kubectl exec -it netpod -- curl myweb:8080 | grep Web; echo; done
# 작업공간 확인
tree /var/lib/jenkins/workspace/k8s-1
cat /var/lib/jenkins/workspace/k8s-1/Dockerfile
참고 자료
'Infra & DevOps > CICD' 카테고리의 다른 글
[ArgoCD] ArgoCD 설치 및 실습 (0) | 2024.04.20 |
---|