[jenkins] webhook CI /CD Pipeline 구축하기

ssongkim·2022년 1월 13일
0

jenkins

목록 보기
3/7
post-thumbnail
post-custom-banner

저번 시간에는freestyle project를 생성하여 webhook 이벤트 발생 시 CI까지만 구축해보았습니다.
이번 시간에는 pipeline 아이템을 생성하여 webhook이벤트 발생 시 빌드 유발을 하여 spring project의 CI / CD를 구축해보겠습니다.

만약 이전 게시글에서 넘어오시고 해당 프로젝트의 CD를 구축하고자 한다면 credential 등록, webhook 등록 단계는 이미 진행한거니 건너 띄어도 됩니다.

CI / CD 구축 단계

CI / CD 파이프라인 구축의 전체적인 흐름은 이와 같습니다.

CI / CD 구축 단계
1. jenkins가 리소스에 접근하는데 필요한 credentials 등록
2. 깃허브 레포지토리 webhook 설정
3. pipeline Item생성
4. 파이프라인 코드 작성

예상 CI / CD 구성도


이번 시간에는 젠킨스를 도커로 구동하고 젠킨스와 스프링 애플리케이션 배포를 하나의 서버에서 진행해보겠습니다. 여기서 좀만 응용하면 젠킨스와 배포를 별도의 서버에서, 혹은 배포를 클라우드에서 하는 것이 가능합니다.

1. 리소스 접근에 필요한 credential 등록하기

젠킨스는 단지 서버이기 때문에 배포에 필요한 각종 리소스(github repo접근, aws 리소스 접근, ssh 접근 등)에 접근하기 위한 중요 정보를 젠킨스가 가지고 있어야 합니다.
예를들어 aws ECS를 이용해 배포한다면 젠킨스는 ecs update cli 명령어를 실행할 수 있도록 관련 권한이 부여된 aws 액세스토큰과 시크릿액세스토큰 값을 가지고 있어야 파이프라인에서 명령어 실행이 가능할 것입니다.

이번 시간에는 젠킨스와 배포를 하나의 EC2인스턴스에서 진행하기 때문에 깃허브 레포지토리 접근 credential만 필요합니다.

github repository credential 등록

깃허브 레포지토리에 접근하기 위한 credential을 등록하겠습니다.
깃허브 계정의 액세스 토큰을 발급해 사용하는 방법이 있고 레포지토리 별로 SSH key를 등록해 사용하는 방법이 있습니다. 저희는 레포지토리 별로 SSH key를 등록하는 방법을 사용하겠습니다.

1. RSA 키 생성

ssh-keygen은 비대칭 암호화를 위해 private key, public key 쌍을 만드는 명령어입니다. repository와 젠킨스를 연동할 키를 생성해봅니다.
저는 이전에 도커를 이용해 젠킨스를 설치했었습니다 도커파일이 작성되어있는 해당 디렉토리에 키를 생성해서 보관하겠습니다. 키는 어디든 안전한 곳에다가 저장만 하면 됩니다.

cd ~/my-jenkins # 젠킨스 루트로 이동
mkdir ./.ssh #.ssh 폴더 생성

# 해당 폴더의 .ssh폴더에 키 생성
cd ~/my-jenkins
ssh-keygen -t rsa -f .ssh/my-jenkins-github-key


passphrase를 입력하라고 나오는데 권장 값은 10~30문자라고 합니다.

이와같이 개인키와 공개키가 생성됨을 확인할 수 있습니다.

2. 대상 Github Repository에 Deploy Key(SSH public key) 등록



앞서 생성한 키 중 public key를 레포지토리의 세팅 --> deploy keys --> Add deploy key를 눌러 등록해줍니다.

그럼 이렇게 등록됩니다.

3. Jenkins Credencials에 대상 레포지토리에 대한 SSH private key 등록

Jenkins 웹 대시보드로 이동한 뒤, Jenkins 관리 탭에서 Manage Credentials를 클릭합니다.


1. add key를 클릭하고 Kind를 SSH Username with private key로 정합니다.
2. 그리고 Scope를 Global로 설정한 뒤, ID를 아까 만들어준 RSA Key의 이름과 동일하게 설정합니다.
3. Enter Directly를 클릭하고 private key 내용을 그대로 붙여넣기 합니다.
4. RSA 키 생성 시 Passphrase를 입력했다면 마찬가지로 똑같이 입력해주어야합니다 입력 안했었으면 비워둡니다.

시작부터 끝까지 전부 복사 붙여넣기 해야합니다.

깃허브 레포지토리에 접근하기 위한 credential 등록을 해주었습니다.

aws리소스 접근 위한 credential 등록하기

  • 단순히 젠킨스가 aws 리소스에 접근하는 방법을 알려드리고자 작성합니다.
    이번 프로젝트에서는 등록할 필요가 없습니다!! 이번 단계를 건너띕니다.

만약 aws ECR, ECS와 같은 서비스를 젠킨스에서 사용하고자 한다면 젠킨스가 aws 리소스에 접근하여 명령어를 사용할 수 있도록 credential을 등록해야합니다.

1. aws 사용자 생성


aws IAM으로 들어가 jenkins가 사용할 사용자를 추가합니다. aws cli를 사용할 예정이므로 AWS 자격 증명 유형을 프로그래밍 방식 액세스로 선택합니다.

2. aws 사용자에 권한 부여


그 다음 aws 리소스 접근에 필요한 권한을 사용자에 부여합니다.

3. 액세스 키 발급


사용자를 생성하면 이와같이 액세스 키와 비밀 액세스 키가 발급됩니다.
이를 젠킨스가 활용할 수 있도록 Jenkins Credentials에 등록하여야 합니다.

4. 액세스 키 등록


젠킨스 관리 -> manage credentials -> add credentials를 누르고
secret text 타입으로 global scope를 주어 액세스 키와 비밀 액세스 키를 따로 등록합니다.

ID를 지정해주면 파이프라인에서는 이런 형태로 불러와 환경변수로 사용할 수 있습니다.

5. aws Credentials 등록


ID(유니크하게), Access Key, Secret Access Key를 등록하여 aws 계정을 사용할 수 있도록 합니다.

젠킨스가 필요로하는 credential을 등록하였습니다 이제 웹훅 설정을 하겠습니다.

2. Github repository Webhook 설정

웹훅은 깃허브 레포지토리에 변화가 발생한다면 깃허브에서 젠킨스로 이벤트가 생겼다고 알림을 보냅니다. 알려줄 때 사용하는 그 경로를 설정하는 작업을 깃허브 레포지토리에서 해주어야합니다.

깃허브 웹훅 추가

다시 Github repository로 가서 Setting -> Webhooks -> Add webhook 을 클릭합니다.

Webhooks이 발동될 Target URL 을 명시할 수 있고, 어떤 이벤트에 웹훅을 발동시킬 것인지 설정할 수 있습니다.
Payload URL 은 Github Webhook 이 발동되어 데이터를 전달할 URL을 의미하는데, 우리의 Jenkins의 Integration 으로 가야합니다.

URL을 위와 같이 EC2 인스턴스의 ip와 젠킨스로 연결되는 포트를 설정하고 /github-webhook/ 을 추가해줍니다.

그리고 push 이벤트를 감지하도록 체크하고 Add webhook을 눌러 웹훅을 추가합니다.

github integration 플러그인 설치


이와같이 뜨는 경우 우리는 깃허브->젠킨스로만 설정을 해주었지 젠킨스에서 웹훅을 받아주는 설정을 하지 않았기에 불이 들어오지 않는 것입니다. github integration 플러그인를 설치해주면 됩니다.

다시 Jenkins 대시보드로 돌아가서 Jenkins -> Dashboard -> Jenkins 관리 -> 플러그인 관리 -> 설치가능 으로 이동한 후 github integration 플러그인을 추가하고 Download now and install after restart를 눌러 재시작 시켜줍니다.

그럼 깃허브로 돌아가보면 웹훅 란에 체크표시로 바뀐 것을 확인할 수 있습니다.

젠킨스가 깃허브 레포지토리에 접근 가능하도록 credential 설정을 해주었고 github webhook 설정 작업을 통해 해당 레포지토리에 이벤트가 발생하면 젠킨스에 알림이 가도록 하였습니다.
이제 해당 레포지토리에서 webhook 이벤트가 날라오면 파이프라인을 작동하도록 CI / CD 파이프라인을 구성해보겠습니다.

3. pipeline 생성하기

1. pipeline item 추가


파이프라인을 클릭하고 이름을 지정해 OK를 누릅니다.

깃허브 레포지토리 경로를 넣고 Pipeline speed/durability는 Performance-optimized 로 설정합니다.
public repository인 경우 위 사진과 같이 http clone 경로를 사용해도 되지만 private repo인 경우 SSH clone 주소를 집어넣고 위에서 설정했던 SSH key를 지정하셔야 합니다.


Build Trigger를 Github hook trigger for GitScm Polling 으로 체크합니다.

2. 파이프라인 작성하기

파이프라인 코드를 작성합니다. 파이프라인 문법은 따로 다루도록 하겠습니다.

pipeline {
    agent any
    options {
        timeout(time: 1, unit: 'HOURS') // set timeout 1 hour
    }
    environment {
        REPOSITORY_CREDENTIAL_ID = 'laika-jenkins-github-key' // github repository credential name
        REPOSITORY_URL = 'https://github.com/Laika-kproejct/IoT-backend.git'
        TARGET_BRANCH = 'main'
        IMAGE_NAME = 'laika-backend'
        CONTAINER_NAME = 'laika-backend'
        PROFILE = 'dev'
    }
    stages{
        stage('init') {
            steps {
                echo 'init stage'
                sh '''
                docker rm -f $CONTAINER_NAME
                '''
                deleteDir()
            }
            post {
                success {
                    echo 'success init in pipeline'
                }
            }
        }
        stage('clone project') {
            steps {
                git url: "$REPOSITORY_URL",
                    branch: "$TARGET_BRANCH",
                    credentialsId: "$REPOSITORY_CREDENTIAL_ID"
                sh "ls -al"
            }
            post {
                success {
                    echo 'success clone project'
                }
                failure {
                    error 'fail clone project' // exit pipeline
                }
            }
        }
        stage('dockerizing by maven') {
            steps {
                sh '''
                ./mvnw spring-boot:build-image -DskipTests -Dspring-boot.build-image.imageName=$IMAGE_NAME
                '''
            }
            post {
                success {
                    echo 'success dockerizing by maven'
                }
                failure {
                    error 'fail dockerizing by maven' // exit pipeline
                }
            }
        }
        stage('deploy') {
            steps {
                sh 'docker run --name $CONTAINER_NAME -e "SPRING_PROFILES_ACTIVE=$PROFILE" -d -p 8080:8080 -t $IMAGE_NAME'
            }
            
            post {
                success {
                    echo 'success deploying laika spring project'
                }
                failure {
                    error 'fail deploying laika spring project' // exit pipeline
                }
            }
        }
        
    }

}

REPOSITORY_URL 환경변수의 경우 private repo일 때는 git clone 시 HTTPS가 아닌 SSH 주소를 기입하여야 합니다!

저희는 젠킨스와 배포를 하나의 서버에서 진행하기 때문에 deploy stage에서 직접 docker run을 해주었지만 만약 배포를 ECS에 했다면 오케스트레이션은 aws ECS가 담당하므로 ECR에 이미지 업로드 후 aws cli를 통해 update 명령어를 호출했을 것입니다.

docker build의 경우 maven 명령어를 사용하였습니다.
-DskipTests는 테스트 진행을 스킵한다는 메이븐 옵션입니다. 이걸 없애면 매 빌드마다 스프링 내에 정의한 테스트코드를 돌 것이고 테스트 실패 시 deploy되지 않을 것입니다.

만약 추가해야하는 git ignore된 시크릿파일이 있다면 파이프라인에서 따로 추가하거나 aws parameter store 등을 이용해야하는 듯 합니다.
전 파이프라인 내에서 dockerizing 하기 전에 따로 스테이지를 추가해 시크릿파일을 생성하도록 하였습니다.


Build now를 눌러 파이프라인이 정상작동하는지 확인합니다.

이와 같이 뜨면 성공입니다. 스테이지 별로 성공 여부를 알 수 있습니다.

docker container ls 했을 때 컨테이너가 잘 띄어진 것을 확인할 수 있습니다.

마무리


깃허브 레포지토리에서 main 브랜치에 머지했더니 webhook 이벤트가 작동해 자동으로 파이프라인이 돌며 deploy까지 CI / CD가 정상작동함을 확인하였습니다..!

profile
鈍筆勝聰✍️
post-custom-banner

2개의 댓글

comment-user-thumbnail
2022년 3월 26일

오토케스트레이션 ㅋㅋ.. 오케스트레이션이겠죠? 잘 보고 갑니다!

1개의 답글