[medium] Directory Structure and Installing Plugins in Jenkins
폴더 구조 정리 사이트 (https://yeongki.notion.site/Jenkins-3ccd5eaef5744d409a18d3dcbaf817a8?pvs=4)
1. 실습 환경 (Jenkins 설치)
visual studio code - icon 팩 설치
- vscode > extension > vscode-icons 설치 > Set File Icon Theme
Jenkins 설치 - docker
- 젠킨스에 대한 학습을 목표로하는 글이기 때문에 Docker를 통해 간단하게 배포하였습니다.
#!/bin/bash
# Update package index and install required packages for Docker
sudo yum update -y
sudo yum install -y tree
sudo yum install -y docker
# Start Docker service
sudo service docker start
# Add the current user to the docker group
sudo usermod -aG docker root
sudo usermod -aG docker ec2-user
# Restart Docker service to apply changes
sudo service docker restart
sudo docker run -d -p 8888:8080 -v ~/jenkins_home:/var/jenkins_home --name jenkins -u root jenkins/jenkins:lts
Jenkins 설치 - 초기 비밀번호
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
sudo cat ~/jenkins_home/secrets/initialAdminPassword
Jenkins 설치 - Plugin
Jenkins 설치 - First Admin User 정보 입력
jenkins_home 경로 확인하기
http://{jenkinsServerIP}:{port}/systemInfo
2. Jenkins Item
Jenkins Item 생성해보기
- Item : 젠킨스에서 사용하는 작업의 최소 단위
- Item 유형
Item유형 | 설명 |
Freestyle Project | - 가장 일반적인 유형으로, 스크립트, 환경 변수, 플러그인 등으로 자유롭게 조합해 빌드 프로세스 설정가능 - 웹페이지 UI 지원여부 : UI 통해 빌드 프로세스 설정 가능 - SCM(Source Code Management) 지원 여부 : Git, SVN 등 플러그인 & UI로 설정가능 - 빌드 후 조치 설정 : 빌드가 성공, 실패 후 추가 조치를 설정가능 |
Pipeline | 코드로 빌드 프로세스를 정의하는 유연하고 강력한 방법. Jenkinsfile에 파이프라인 구성을 작성하고 버전 관리할 수 있음. |
Multi-configuration project | 여러 하위 프로젝트를 관리하고 빌드하는 프로젝트. 여러 하위 프로젝트를 동시에 빌드하고 종속성을 관리하는 데 사용됨. |
다운스트림 프로젝트 | 다른 프로젝트가 성공적으로 완료될 때마다 실행되는 프로젝트. 주로 종속성 관리 및 연속적인 빌드 및 배포 프로세스를 구성하는 데 사용됨. |
Maven 프로젝트 | Apache Maven을 사용하여 Java 프로젝트를 빌드하는 프로젝트 유형. pom.xml 파일을 기반으로 빌드를 수행함. |
외부 Job | Jenkins 이외의 다른 CI/CD 도구나 외부 스크립트를 실행하는 데 사용되는 특별한 유형의 프로젝트. 주로 외부 시스템과의 통합에 사용됨. |
- 유형별로 각자 다른 포멧의 config.xml 파일이 생성됩니다.
Jenkins Item - Freesteyle
- 가장 일반적인 유형으로, 스크립트, 환경 변수, 플러그인 등으로 자유롭게 조합해 빌드 프로세스 설정가능
- 웹페이지 UI 지원여부 : UI 통해 빌드 프로세스 설정 가능
Jenkins Item - Pipeline
- 사이드 프로젝트시 Jenkins Pipeline(Declarative) 스크립트로 React, Spring을 CI하는 코드입니다.
pipeline {
agent any
environment{
REACT_APP_BACKEND_SERVER_SHOW='https://auth.XXXX.site'
REACT_APP_BACKEND_SERVER_PLAY='https://spring.XXXX.site'
REACT_APP_AWS_S3_REGION='ap-northeast-3'
REACT_APP_AWS_BUCKET_NAME='XXXX-devteam-02-s3-image'
REACT_APP_AWS_ACCESS_KEY_ID='AKIAX...........'
REACT_APP_AWS_SECRET_ACCESS_KEY='4uOJwAtK9.........'
REACT_APP_LAMBDA='https://XXXXXXXXX.execute-api.ap-northeast-3.amazonaws.com/v1/'
region='ap-northeast-3'
aws_credential='awscredentials'
file='./build'
bucket='XXXX-devteam-02-s3-image'
}
tools {nodejs "nodejs-16.10.0"}
stages {
stage('Clone') {
steps {
// Get some code from a GitHub repository
git branch: 'dev', credentialsId: 'github-Token', url: '<https://github.com/yeongki0944/mzc-quiz-front.git>'
}
}
stage('React npm install'){
steps {
sh 'npm install'
}
}
stage('React Build') {
steps {
withEnv([
'REACT_APP_BACKEND_SERVER_SHOW=https://auth.XXXX.site',
'REACT_APP_BACKEND_SERVER_PLAY=https://spring.XXXX.site',
'REACT_APP_AWS_S3_REGION=ap-northeast-3',
'REACT_APP_AWS_BUCKET_NAME=XXXX-devteam-02-s3-image',
'REACT_APP_AWS_ACCESS_KEY_ID=AKIAX...........',
'REACT_APP_AWS_SECRET_ACCESS_KEY=4uOJwAtK9.........',
'REACT_APP_LAMBDA=https://XXXXXXXXX.execute-api.ap-northeast-3.amazonaws.com/v1/'
]) {
sh "rm -rf ./build"
sh "DISABLE_ESLINT_PLUGIN=true npm run build"
sh "ls -al"
}
}
}
stage('S3 Upload'){
steps{
withAWS(region:"${region}", credentials:"${aws_credential}"){
s3Delete(bucket:"${bucket}", path:"/")
s3Upload(file:"${file}", bucket:"${bucket}", path:"")
}
}
}
}
}
pipeline {
agent any
environment{
// Git Env
GIT_URL = "https://github.com/XXXXXX/XXXXX-backend-play.git"
GIT_BRANCH = 'dev'
// AWS Default Env
AWS_ACCOUNT_ID="503237308475"
AWS_DEFAULT_REGION="ap-northeast-3"
AWS_CREDENTIAL='awscredentials'
// AWS ECR Env
IMAGE_NAME="XXXX-devteam-ecr-backend-play"
IMAGE_TAG="latest"
IMAGE="${IMAGE_NAME}:${IMAGE_TAG}"
ECR_URL="{AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${IMAGE_NAME}:${IMAGE_TAG}"
ECR_CREDENTIAL = "ecr:ap-northeast-3:awscredentials"
// ECS Env
// PROJECT_NAME="XXXX-backend-play" // Jenkins Project Name
CLUSTER_NAME="XXXX-devTeam-02-ECS-mquiz-Cluster"
SERVICE_NAME="XXXX-devTeam-02-ECS-Service-mquiz-play"
ECS_ClusterName='XXXX-devTeam-02-ECS-mquiz-Cluster'
ECS_ServiceName='XXXX-devTeam-02-ECS-Service-mquiz-play'
}
stages {
stage('Clone') {
steps {
// Get some code from a GitHub repository
git branch: GIT_BRANCH, credentialsId: 'github-Token', url: GIT_URL
}
} // end-Clone Stage
stage('gradlew Build'){
steps{
sh "chmod +x ./gradlew"
sh "./gradlew clean bootJar"
}
}// end-Gradle Build Stage
stage('Docker Build') {
steps{
script{
docker.build(IMAGE)
}
}
}// end-Docker Build Stage
stage('Docker Run') {
steps {
sh "docker ps -f name=$IMAGE_NAME -q | xargs -r docker container stop"
sh "docker container ls -a -fname=$IMAGE_NAME -q | xargs -r docker container rm"
sh """docker run \\\\
--name $IMAGE_NAME \\\\
-d \\\\
-p 8888:8080 \\\\
-e swgger.matcheingStrategy=ant_path_matcher \\\\
-e env-mongodb-uri=mongodb://root:root@13.208.214.29:27017 \\\\
-e env-mongodb-database=show \\\\
-e env-redis-host=XXXX-devteam-02-redis-cluster-001.ecmilg.0001.apn3.cache.amazonaws.com \\\\
-e env-redis-port=6379 \\\\
-e env-redis-password= \\\\
-e env-rabbitmq-host=b-b449c15f-8022-48b3-86a6-ade7a3c4c228.mq.ap-northeast-3.amazonaws.com \\\\
-e env-rabbitmq-port=5671 \\\\
-e env-rabbitmq-username=megaquiz \\\\
-e env-rabbitmq-password=cloudteam2!! \\\\
$IMAGE"""
}
}
stage('ECR Push'){
steps{
script{
docker.withRegistry(ECR_URL, ECR_CREDENTIAL){
docker.image(IMAGE).push()
}
}
}
}// end-ECR Push
stage('ECS Deploy'){
steps{
script{
withAWS(credentials:AWS_CREDENTIAL, region:AWS_DEFAULT_REGION) {
sh """
aws ecs update-service --region ${AWS_DEFAULT_REGION} --cluster ${ECS_ClusterName} --service ${ECS_ServiceName} --force-new-deployment
"""
}// end-withAWS
}// end-script
}// end-steps
} // end-ECS stage
} // end-stages
post{
always{
sh "docker rmi $IMAGE | true"
}
}
}// end-pipeline
3. Script vs Declarative
Script, Declarative 특징
- Script
- Groovy문법과 리눅스명령어를 기반으로 스크립트 코드를 작성하는 것
- 장점 - 복잡한 파이프라인을 설계할 수 있음
- 단점 - 구현이 복잡해짐 → 유지보수성 낮아짐
- Declarative
- 더 구조화돼 전통적 젠킨스 웹 폼과 유사하다.
- 문법 확인 및 에러 확인이 쉽다
- 반복적인 로직을 처리하기 프로그램적으로 처리하기 어려움
- 유연성이 적다
- 새로운 사용자가 배우기 쉬움
- 아래 동일한 내용에 대해 Script와 Declarative 두가지 스타일로 작성한 4장의 사진이 있습니다.
- 분석 포인트 1. script 방식은 작성하는 규칙이 존재하지 않음 > 코드를 작성하듯이 자유로운 스타일
- 분석 포인트 2. Declarative 방식은 4개 모두 일정한 패턴이 보임 > 구조화된 패턴이 존재
Declarative pipeline syntax 특징
- red box - 필수요소
- black box - 선택요소
Todo
#1 https://www.slideshare.net/StephenKing/declarative-jenkins-pipelines 해당 PPT 학습해보기
#2 Groovy DSL, Pipeline DSL에 대해 알아보기
4. Git, CSV의 코드를 Jenkins로 Clone하기
Git URL
# 실습에 사용할 Github
https://github.com/gasida/aews-cicd.git
https://github.com/nydiarra/springboot-jwt.git
jenkins_home/workspace/item이름 폴더 확인