Jenkins - 2 ( Jenkins file 및 k8s 배포 )

HD.Y·2024년 2월 22일
0

한화시스템 BEYOND SW

목록 보기
57/58
post-thumbnail

Jenkins Freestyle 과 Pipeline

  • Jenkins의 Item 💡
    Jenkins에서 하나의 CI/CD 프로젝트를 구축하기 위해서는 아이템(Item)을 생성하여야 한다. 하나의 Jenkins 서버에 여러개의 아이템을 만들 수 있고, 각각의 아이템들은 개발자가 설정하는 것에 따라 다르게 동작한다.
    Jenkins에서 아이템을 만드는 방법은 대표적으로 FreeStylePipeline이 존재한다.

  • Freestyle vs Pipeline

    Freestyle

    장점 : 웹 기반의 GUI를 통해 여러 플러그인을 쉽게 사용할 수 있다.

    단점
     1) CI 파이프라인에 변경 사항을 만들기 위해서는 Jenkins에 로그인해서 각각의
       프리스타일 Job의 설정을 변경해야만 한다.

     2) CI/CD의 과정을 콘솔을 통해서만 확인할 수 있다.
     3) 각각의 과정들을 한번에 보기 어렵다.


    Pipeline

    장점
     1) 코드로 프로젝트 설정을 할 수 있어서 프리스타일과 다르게 Jenkins 웹에 직접
       접근하지 않아도 설정 변경이 가능하다. (웹을 통한 설정도 가능하다.)

     2) CI/CD 파이프라인 설정을 하나의 스크립트 파일(Jenkins file)로 프로그래밍을 통해
       할 수 있다.

     3) 일반 코드처럼 버전 관리가 가능하다.
     4) GUI를 통해 현재 어떤 과정을 진행중이고 평균적으로 얼마만큼의 시간이 걸렸는지
       통계와 피드백을 준다.

    단점 : 프리스타일과 다르게 스크립트를 짜야하는 번거로움이 있다. 즉, 파이프라인
           구축을 위해서는 스크립트 문법을 학습하여야 한다.


🙉 Jenkins Pipeline으로 프론트엔드 및 백엔드 서버 구축하기

  • 시작하기에 앞서, 지난 글에서 Freestyle 로 생성한 item 들의 구성에서
    소스 코드 관리를 None 으로 바꿔준다. ( 동일한 깃허브 레포지토리 사용 불가 )

  • 프론트엔드 서버 구축 💻

1. 새로운 Item 클릭 ➡ Pipeline 선택 후 OK


2. 파이프라인 구성 설정
  1) GitHub project 선택 후 레포지토리 주소 입력 ( 선택사항 )
  2) Build Triggers 에서 "GitHub hook trigger for GITScm polling" 선택
  3) Pipeline Script에 jenkins file 문법 의거 작성

pipeline {
   agent any

   stages {
       stage('git clone') {
               steps {
                       git branch: 'main', url: 'https://github.com/[깃허브 계정]/[레포지토리명]'
               }
       }
       stage('Install Dependencies') {
           steps {
               script {
                   sh 'npm install'
               }
           }
       }

       stage('Delete Exist file') {
           steps {
               script {
                   sh 'rm -rf /var/lib/jenkins/workspace/[파이프라인 이름]/dist'
               }
           }
       }

       stage('Build') {
           steps {
               script {
                   sh 'npm run build'
               }
           }
       }

       stage('Archive Dist') {
           steps {
               script {
                   // dist 디렉토리로 이동
                   dir('dist') {

                       // tar로 압축
                       sh 'tar -cvf dist.tar ./*'
                       
                       // 압축 파일을 상위 디렉토리로 이동
                       sh 'mv /var/lib/jenkins/workspace/[파이프라인 이름]/dist/dist.tar ../'
                   }
               }
           }
       }
       stage('SSH transfer') {
           steps {
               sshPublisher(
                   continueOnError: false, 
                   failOnError: true,
                   publishers: [
                       sshPublisherDesc(
                           configName: "test-server",    // SSH 서버 설정해둔 이름
                           verbose: true,
                           transfers: [
                               sshTransfer(
                                   sourceFiles: "dist.tar",
                                   remoteDirectory: "/usr/share/nginx/html/",
                                   execCommand: "tar -xvf /usr/share/nginx/html/dist.tar -C /usr/share/nginx/html/"
                               )
                           ]
                       )
                   ]
               )
           }
       }
   }
}

이전 글에서 Freestyle 로 생성 후 구성에서 설정했던 내용들을 코드로 적어주는 것이다.

"지금 빌드" 또는 VS Code에서 깃허브로 Push 해보면, 아래와 같이 각 단계 별로 결과를
  그림으로 보여준다. 따라서, 어느 단계에서 오류가 발생했는지 알기가 쉽다.


  • 백엔드 서버 구축 💻

1. 새로운 Item 클릭 ➡ Pipeline 선택 후 OK

2. 파이프라인 구성 설정
  1) GitHub project 선택 후 레포지토리 주소 입력 ( 선택사항 )
  2) Build Triggers 에서 "GitHub hook trigger for GITScm polling" 선택
  3) Pipeline Script에 jenkins file 문법 의거 작성

pipeline {
   agent any
   
   tools {
       maven "maven-3.9.5"   // 이전 글에서 설정해줬던 메이븐의 Name
   }

   stages {
       stage('git clone') {
           steps {
               git branch: 'main', url: 'https://github.com/[깃허브 계정명]/[레포지토리명]'
           }
       }
       
       stage('Build') {   // 메이븐 빌드
           steps {
               sh 'mvn -B -DskipTests clean package' 
           }
       }
              
       stage('SSH Transfer') {
           steps {
               script {
                   sshPublisher(
                       continueOnError: false, 
                       failOnError: true,
                       publishers: [
                           sshPublisherDesc(
                               configName: "test-server",    // SSH 서버 설정해둔 이름
                               verbose: true,
                               transfers: [
                                   sshTransfer(
                                       sourceFiles: "target/lonua-0.0.1-SNAPSHOT.jar",
                                       removePrefix: "target/",
                                       remoteDirectory: "/root/",
                                       execCommand: '''
export APP_PASSWORD=
export AWS_S3_ACCESS_KEY=
export AWS_S3_SECRET_KEY=
export BRAND_BUCKET=
export CLIENT_ID=
export EXPIRED_TIME=
export JWT_SECRET_KEY=
export MAIL_SENDER=
export MASTER=
export MASTER_PW=
export MASTER_URL=
export PORTONE_KEY=
export PORTONE_SECRETKEY=
export PRODUCT_BUCKET=
export PRODUCT_INTROD_BUCKET=
export REGION=
export REVIEW_BUCKET=
export SLAVE=
export SLAVE_PW=
export SLAVE_URL=

echo "PID Check..." >> /var/log/jenkins_spring.log
CURRENT_PID=$(netstat -anlp | grep 8080 | awk '{print $7}' | cut -d '/' -f1)

echo "Running PID: {$CURRENT_PID}" >> /var/log/jenkins_spring.log

if [ -z $CURRENT_PID ]; then
   echo "Project is not running" >> /var/log/jenkins_spring.log
else
   echo "Project Killing" >> /var/log/jenkins_spring.log
   kill -9 $CURRENT_PID
   sleep 3
fi
echo "Deploy Project...." >> /var/log/jenkins_test_spring.log
nohup java -jar /root/lonua-0.0.1-SNAPSHOT.jar >> /var/log/jenkins_spring.log 2>&1 &
'''
                                   )
                               ]
                           )
                       ]
                   )
               }
           }
       }
   }
}

실행 결과


🐮 Docker 설정하기

  • 플러그인 사용 안하는 경우

1. Jenkins 서버에 도커 설치 및 실행

  ➡ yum install -y yum-utils

  ➡ yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

  ➡ yum-config-manager --enable docker-ce-nightly

  ➡ yum-config-manager --enable docker-ce-test

  ➡ yum install -y docker-ce docker-ce-cli containerd.io --allowerasing

  ➡ systemctl restart docker


2. Jenkins 서버에서 권한 설정

  ➡ ls -l /var/run/docker.sock 해보면 권한이 root와 docker 그룹에게만 있다.

  ➡ 젠킨스 계정을 도커 그룹에 추가 : usermod -aG docker jenkins

  ➡ 도커 권한을 젠킨스로 변경 : chown root:jenkins /var/run/docker.sock


3. Jenkins 대시보드에서 도커 허브 계정 변수 설정

  1) Jenkins 관리 ➡ Credentials 클릭

  2) Domain의 (global) 클릭 ➡ Add Credentials 클릭

  3) username : 도커허브 계정 / password : 도커허브 패스워드

  4) ID : 변수 이름 임의로 지정


4. 사용 시 : 파이프라인 구성의 빌드 환경에서 User secret text(s) or file(s) 체크
 ➡ Add 클릭 후 Username and password (separated ) 클릭

  ➡ Username Variable : 변수이름 설정 // DOCKER_EMAIL

  ➡ Password Variable : 변수이름 설정 // DOCKER_PASSWORD

  ➡ Build Steps의 Execute shell 작성

            docker build --tag [도커허브 계정]/[도커허브 레포지토리명]:[버전] .
            docker login -u ${DOCKER_EMAIL} -p ${DOCKER_PASSWORD}
            docker push [도커허브 계정]/[도커허브 레포지토리명]:[버전]


  • 플러그인 사용하는 경우 ( 사용법은 k8s 배포 시 설명 예정 )

1. Jenkins 관리 ➡ Plugins ➡ Avaiable plugins 클릭 후 Docker 검색

2. Docker, Docker Commons, Docker Pipeline, docker-build-step 설치


🐸 Freestyle로 생성하여 k8s 배포하기 ( 도커 플러그인 사용 )

  • 사전 준비 필요 사항 : DB 디플로이먼트 생성
              ➡ ( 쿠버네티스로 3계층 아키텍처 구성하기 글 참고 )

  • master 노드에 대한 SSH 등록
    1) Jenkins 서버에서 등록 : ssh-copy-id root@[master노드 IP]
    2) Jenkins 관리 ➡ System ➡ Publish over SSH 에 master 노드 추가

  • 도커 플러그인 사용을 위한 설정
    Jenkins 관리 ➡ System ➡ Docker Builder에 URL 등록
    URL : unix:///var/run/docker.sock


  • 백엔드 서버 구성하기( data.sql 파일 포함 시켜놨음 / 도커 컴포즈 글 참고 )

1. 인텔리제이에서 Dockerfile 생성

FROM openjdk:11-jdk-slim-stretch
COPY ./target/lonua-0.0.1-SNAPSHOT.jar lonua-0.0.1-SNAPSHOT.jar
CMD ["java", "-jar", "/lonua-0.0.1-SNAPSHOT.jar"]

2. 인텔리제이에서 backend-deployment.yml 생성

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-deployment  // 디플로이먼트 이름 설정
spec:
  replicas: 2
  strategy:
    type: RollingUpdate     // 디플로이먼트 방식 지정
  minReadySeconds: 10
  selector:
    matchLabels:
      type: backend
  template:
    metadata:
      labels:
        type: backend
    spec:
      containers:
      - name: backend-container
        image: hyungdoyou/be:2.VERSION    // VERSION은 젠킨스에서 변수로 처리 예정
        envFrom:
          - configMapRef:
              name: backendconfig         // 백엔드 Config Map 이름 ( 미리 생성 해놔야 함 )
      terminationGracePeriodSeconds: 5

3. 파이프라인 구성하기

  1) 빌드 유발까지는 동일하다. ( 빌드 환경도 미체크 )

  2) Build Steps - 1 : Maven 빌드 추가


  3) Build Steps - 2 : 도커 이미지 빌드 추가

    ➡ Docker command : Create/build image 선택

    ➡ Build context folder : $WORKSPACE/

    ➡ Tag of the resulting docker image :
     [도커허브 계정명]/[레포지토리명]:[버전앞숫자지정].$BUILD_NUMBER


  3) Build Steps - 3 : 도커 허브 Push 추가
   ➡ Docker command : Push image 선택
   ➡ Name of the image to push : [도커허브 계정명]/[레포지토리명]
   ➡ Tag : [버전 앞 숫자].$BUILD_NUMBER
   ➡ Docker registry URL : https://hub.docker.com/
   ➡ Registry credentials : 생성한 docker-credential 선택


  4) 빌드 후 조치 작성
   ➡ SSH Server Name : 등록해둔 master 서버 선택
   ➡ Source files : backend-deployment.yml
   ➡ Remote directory : /root/
   ➡ Exec command

// 젠킨스 빌드 숫자로 VERSION 변수를 변경해주는 명령어
sed -i "s/VERSION/$BUILD_ID/g" /root/backend-deployment.yml  

// 디플로이먼트 실행 명령어
kubectl apply -f /root/backend-deployment.yml


4. 지금 빌드 또는 깃허브에 Push 후 k8s 대시보드에서 확인

5. k8s 대시보드에서 백엔드 서버 Service 생성

apiVersion: v1
kind: Service
metadata:
  name: backend-svc
spec:
  selector:
    type: backend
  ports:
  - port: 8080
    targetPort: 8080

  • 프론트엔드 서버 구성하기

1. VS Code에서 frontend-deployment.yml 작성

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-deployment
spec:
  replicas: 2
  strategy:
    type: RollingUpdate
  revisionHistoryLimit: 1
  selector:
    matchLabels:
      type: frontend
  template:
    metadata:
      labels:
        type: frontend
    spec:
      containers:
      - name: frontend-container
        image: [도커허브 계정명]/[레포지토리명]:[버전 앞 숫자].VERSION

2. 파이프라인 구성의 Build Step 및 빌드 후 조치는 아래와 같다.

  1) Build Step - 1


  2) Build Step - 2


  3) Build Step - 3


  4) 빌드 후 조치


3. k8s 대시보드에서 프론트엔드 서버 Service 생성

apiVersion: v1
kind: Service
metadata:
 name: frontend-svc
spec:
 selector:
   type: frontend
 ports:
  - port: 80
    targetPort: 80
 type: LoadBalancer

Slack Notification 설정하기

1. Slack 에서 새 워크스페이스 및 채널 생성

2. 채널 오른쪽 클릭 ➡ 채널 세부정보 보기 클릭

3. 통합에서 앱 추가 클릭

4. Incoming WebHooks 검색 후 설치

5. 채널에 포스트에서 원하는 채널 선택 후 "수신 웹후크 통합 앱 추가" 선택

  ➡ 웹후크 URL을 Jenkins 대시보드에서 등록할 예정


6. Jenkins 관리 ➡ Credentials ➡ (global) ➡ Add Credentials 클릭
 ➡ Secret Text 선택

 ➡ Secret에 위에서 나온 웹후그 URL의 https://hooks.slack.com/services/ 뒤부분을
   입력

 ➡ ID 입력 후 생성


7. Jenkins 관리 ➡ Plugins ➡ Slack Notification 플러그인 설치


8. 파이프라인 구성의 빌드 후 조치에 아래와 같이 설정 추가

  1) 기본 설정 전부 체크


  2) 고급 설정 전부 체크 ( Include Custom Message 제외 )

  3) Override url : https://hooks.slack.com/services/

  4) Credential : 위에서 생성한 slack-credential 선택

  5) Channel / member id : 알람받을 채널 이름 입력


9. GitHub Push 시 Slack의 채널에 아래와 같이 알림이 오는지 확인

profile
Backend Developer

0개의 댓글