Jenkins + Docker + Github-hook을 이용하여 CI / CD 구축

김종찬·2023년 2월 23일
0

배포

목록 보기
1/1

Jenkins를 이용해 CI/CD 구축을 하며 삽질한 내용 정리

CI/CD를 통해 build 와 test, 배포까지 자동화를 구축하여 실무에서 사용한다고 익히 알고만 있었지 실제로 그 infra를 구현해본적이 없어 내게 크게 와닿지 않아 이참에 뿌리뽑고자 직접 CI/CD infra를 구축해보았다. 우선은 CI/CD 구축하기 앞서 정말 많은 레퍼런스, 블로그를 적어도 6시간 이상 본 것같다...너무 다양한 방법과 구축이 나와 솔직히 보면볼수록 더 헛갈렸다. 그중 내가 사용해보고 싶었던 infra를 찾게 되어 그에 관련한 많은 레퍼런스를 찾아보았다. 우선 내가 선택한 컨셉은 아래의 이미지와 같다.

이 시나리오를 요약하자면 네줄로 간단히 요약하자면
1) github project repo에 code를 push한다.
2) github-webhook을 이용하여 jenkins 서버에 spring project를 build한다.
3) build한 jar 를 docker를 이용하여 image를 생성하여 docker hub에 push한다.
4) 운영 server에서 docker hub의 image를 pull 하여 배포한다.

우선 CI/CD infra를 구축하며 느낀점을 말하면 일단은 셋팅이 너무 힘들었다...정말 코딩할때랑은 약간 다른 느낌 두번째로 새로운 Jenkins에서 사용되는 pipeline 문법이 익숙치 않아 거기서도 많이 해맸던것 같다. 파이프라인이라 하면 말 그대로 파이프를 따라 실행되는 느낌이다. -> 미리 지정해놓은 단계별 script를 따라 가공처리 되는 느낌을 받았다.(단계별로 뭐가 진행되어야하는지 알고리즘?? 스트림??처럼 머리로는 알겠는데 표현을 처음 접하는 명령어들이 많아 힘들었다.) 많이 막힐때는 직접 서버에 들어가서 빌드하고싶다..라고생각까지.... 우여곡절 끝에 수동 빌드를 통해 정상적으로 빌드가 되었을때, 그리고 push만 했는데 자동으로 buid - 배포까지 되었을때 기분은 정말 너무 좋았다.. 아래 요거 녹색불 보기위해 정말 많이...

이번 정리장에서는 infra를 구축하기 위한 핵심 key-word만 써내려가는 식으로 정리하겠습니다. 해당 키워드로 너무나 좋은 기술블로그와 레퍼런스 참조가능 생각나지 않을때 해당 키워드만 쏙쏙 검색하는식으로 써내려가겠습니다.

젠킨스 세팅

  • 우선 프리티어 인스턴스 서버를 두개 생성해야한다. 하나는 Jenkins(git clone, build, test, docker-image)를 위한서버 다른하나는 배포서버(배포서버는 그냥 프리티어로 생성), jenkins는 약간의 성능을 증가 시켜주어야한다. 안그러면 서버가 계속 죽어버린다.

  • 각각의 인스턴스에 도커를 설치해 주어야한다.

sudo yum -y upgrade

도커 설치
sudo yum -y install docker

도커 버젼 확인
docker -v

도커 시작
sudo service docker start

도커 그룹에 사용자 추가 -> docker가 그룹명, ec2-user가 사용자명
sudo usermod -aG docker ec2-user 
  • 젠킨스가 운용될 서버는 메모리 증설

  • docker 명령어를 통해 jenkins pull

  • jenkins에서 실행될 docker.sh 작성

  • docerk jenkins server run을 이용해 해당포트 번호로 url로 이동 첫화면에 비밀번호는 cli를 통해 jenkins 컨테이너에 접속하여 확인할수있다.

sudo docker exec -it jenkins bash
cat /var/jenkins_home/secrets/initialAdminPassword

아이디를 생성후 로그인 하였다면 본격적으로 젠킨스 셋팅과, 환경 변수, credentials 셋팅을 해줘야한다.


1) 플러그인 셋팅(why? 빌드, 배포서버에서의 .sh 카피 등 자동으로 부수적인 것들을 실행하기위해 그냥 처음부터 같이 넣어줬으면 안되나 생각하기도함..무거워져서 그런가? 아무튼 설치)

왼쪽 목록에 젠킨스관리 click -> 플러그인 관리 click하면 아래와 같이 보인다.

infra구축에 필요한 플러그인 설치목록

  • gradle
  • github integration
  • post build task
  • publish over ssh
  • pipeline
  • docker
    나는 기본적으로 이정도 설치했던것 같다. 추가적으로 필요한것들은 생기면 진행하면서 설치

2) Credentials 셋팅 (why? 깃허브, 도커허브, 토큰과 같은 아이디와 비밀번호를 이곳에서 넣어놔 추후에pipeline을 통해 script 진행시 해당하는것들에 접근하기 위해서)

왼쪽 목록에 젠킨스관리 click -> 중간에 manage credentials 클릭
global add 를 클릭하여 깃허브 아이디 비밀번호, 토큰, 토커허브 아이디 비밀번호 등등을 넣어주면된다. 간단함 github token -> secret text를 이용


3) SSH Servers 세팅 (why? -> 마찬가지로 pipeline에서 운영서버에 접근하기위해서-우리도 인스턴스서버에 접속했을때 키를 들고 들어갔던 원리랑 똑같은것 같다.)

  • 2<-에서 설정했던 킷허브 토큰(secret text) Credentials 설정

  • ssh key 설정 인스턴스 실행서 aws에서 주었던 키값을 넣어준다.Key 확인하여 넣어준다.

cat 키위치

cat ~/.ssh/xxxxxx.pem

  • 운영서버 IP를 넣어준다.

4) github-webhook 셋팅 (why? 우리가 code를 project repo에 push하면 이것을 감지하고 젠킨스에 알려줘 CI/CD해라 라고 알리기위해 이것을 설정안하면 둘과의 연관관계가 없기때문에 백날 푸쉬해봤자 젠킨스는 알길이 없다~)

CI/CD 하고자하는 repo - settings에 들어가 Webhooks click

URL은 http://JenkinsEC2_IP/github-webhook/ <-- 마지막에 github-webhook/은 필수

여기까지가 Jenkins의 기본 셋팅입니다.

남은셋팅은 1) 프로젝트에서 파일 내에서의 sh 작성,2) jenkins에서의 pipeline 셋팅


프로젝트내 셋팅

1) 프로젝트 내에서 쉘 스크립트 작성(why?-> 운영서버로이 파일을 보내어 실행되어야할 scrpit를 미리 작성해놓아 이 쉘 스크립트를 읽고 실행하게 하기 위해서)


위에서부터 보자면

  • 만약 lunch라는 컨테이너가 실행중이라면 실행중인 lunch컨테이너를 멈추고 해당 컨테이너 삭제

  • 이미지 삭제 // pull을 하기전 clean하게 비워주는 전초단계라고 생각하면 되겠다.

  • 이제 깨끗해졌으니 docker pull을 이용해 해당 이미지를 받아온다

  • 받아온 이미지를 이용하여 포트포워딩을 통하여 lunch라는 이름을 부여하여 컨테이너 실행

  • 불필요한 이미지들 삭제

자세한 도커 사용명령어는 Docker정리본 참고바랍니다.

2) Dockerfile 생성

여기까지가 프로젝트내에서의 셋팅입니다 이제 마지막으로 pipeline을 셋팅하면 됩니다.


Jenkins project 셋팅

이제 깃허브에서 프로젝트를 클론하고 빌드하고 이미지하고,넘겨주고, 배포하고하는 pipeline을 셋팅하면 끝입니다.

1) 새로운 아이템 생성

젠킨스 메인페이지 왼쪽 목차에 새로운 Item click하면 Freestyle과, Pipeline 둘 중 하나로 할수있는데 차이점을 말하자면 Freestyle은 기본적인 틀을 제공하고 거기에 맞춰 넣는 식으로 프로세스를 짜서 조금 간편하게 할수있다. 단점 간편한만큼 커스터마이징이 힘들고 제한적인 사항이 많다.. 작은프로젝트 내에서는 큰 Freestyle을 사용해도 무방할것같다. Pipeline 진입장벽이 다소있다. 그러나 역시 어려운만큼 많은 것들을 할 수있다. 커스터마이징이 가능하고, 다수의 형상관리 레포짓토리와 연계하여 사용가능. 역시 어려우니 많은것들을 할수있다. 여기서는 Pipeline에 대해서 설명하겠다. 개인적인 생각으로 Freestyle project로 먼저 해보고 Pipeline으로 마이그레이션하는 식으로 하시면 조금더 접근하기 괜찮은것 같다는것다.

이미지를 하나씩 보며 설명해보겠습니다.(젠킨스에서 똑같이 위에서부터 아래로 해당 이미지가 보일겁니다.)

  • Github project url을 지정해줍시다.

  • 빌드 트리거 체크 -> 깃헙훅을 이용하여 하기로 우리 시나리오에서 했으므로 깃헙 훅 체크

  • 파이프라인 작성 -> pipeline syntax를 통하여 이제부터 내가 위에서부터 실행하고자 하는 스크립트를 작성해주면된다. 작성에 앞서 간단한 pipeline syntax을 가볍게..보시는것도 좋아보입니다.

여기서는 제가 간단하게 작성한 script를 보도록 하겠습니다.

pipeline {
    agent any
    
    environment { 
        repository = "whdcks420/lunch"  //docker hub id와 repository 이름
        DOCKERHUB_CREDENTIALS = credentials('docker-hub') // jenkins에 등록해 놓은 docker hub credentials 이름
        dockerImage = '' 
    }
  
    stages {
        stage('Git Clone') {
            steps {
                git branch: 'master', url: 'https://github.com/bellCold/slack-lunch-migaraion.git'
            }
        }
        
        stage('Build') {
            steps {
                dir("./") {
                    sh "./gradlew clean build --stacktrace"
                }
            }
        }
        
        stage('Build-image') { 
            steps { 
                script { 
                    sh "docker build -t whdcks420/lunch:3.0 ."
                }
            } 
        }
        
        stage('Login') {
            steps {
                sh 'echo $DOCKERHUB_CREDENTIALS_PSW | docker login -u $DOCKERHUB_CREDENTIALS_USR --password-stdin'
            }
        }
        stage('Docker Push') { 
          steps { 
              script {
                sh 'docker push whdcks420/lunch:3.0' //docker push
              } 
          }
        } 
        
        stage('Cleaning up') { 
            steps { 
              sh "docker rmi whdcks420/lunch:3.0" // docker image 제거
              }
        }
        
        stage('SSH transfer') {
            steps {
                sshPublisher(
                    continueOnError: false, failOnError: true,
                    publishers: [
                        sshPublisherDesc(
                            configName: "ec2-deploy",//Jenkins 시스템 정보에 사전 입력한 서버 ID
                            verbose: true,
                            transfers: [
                                sshTransfer(
                                    sourceFiles: "scripts/deploy.sh", //전송할 파일
                                    removePrefix: "scripts", //파일에서 삭제할 경로가 있다면 작성
                                    execCommand: """echo $DOCKERHUB_CREDENTIALS_PSW | docker login -u $DOCKERHUB_CREDENTIALS_USR --password-stdin
                                    sh deploy.sh""" //원격지에서 실행할 커맨드
                                    )
                            ]
                        )
                    ]
                )
            }
        }
        
    }
}

우선 우리가 맨위에 보여진 이미지를 토대로 내용을 다시한번 간략히 보면서 스크립트를 어떤 순서에 또 무엇을 작성해야할지 생각해봅시다.(마치 알고리즘(?) 순서대로 스크립트를 읽는다라고 생각하면됩니다.)

1) 해당 project repo를 clone하여 가져온다.
2) 가져온 repo를 빌드한다.(-jar file 생성)
3) docker build를 통해 이미지를 생성한다.
4) docker hub에 로그인한다.
5) docker push 한다.
6) 운영서버에 위에서 미리 작성해놓은 쉘스크립트를 읽기록 시킨다.(도커에 로그인해서 ,pull해서 실행)


이 모든것들, 명령어 설정, 기타등등을 전부 기억하는건 제 생각에는 조금 힘들지않나 생각합니다. 한번 구축해보고 해당 흐름들만 인지하고 핵심적인 내용들만 필요할때 검색해보면 괜찮을것같습니다.

여기까지가 Jenkins와 docker를 이용하여 CI/CD를 구축하는 방법에 대해 알아보았습니다.

profile
봄이 오길

0개의 댓글