인프라

[CI/CD] Jenkins 와 GitLab 연동 및 배포 자동화

김 숨 2024. 10. 10. 10:53

시나리오

1) pycharm, VScode등 IDE 에서 코드 commit 후 push
2) gitlab webhook으로 jenkins에 전달
3) jenkins에서 Jenkins 파이프라인 스크립트와  Dockerfile에 정의 된 대로 docker image로 빌드
4) 빌드된 Docker 이미지 nexus 레지스트리에 전달(Jenkins 파이프라인 스크립트에 정의)
5) 레지스트리에서 운영 서버로 이미지 push후 실행

 

Fast API로 작은 python 프로젝트를 만들고 도커 빌드 및 운영 서버에 배포하기 위해 CI/CD 파이프 라인을 구축했다. 

 

1. GitLab과 Jenkins 연동하기

 1) GitLab 설치 & Jenkins 설치하기

(외부링크 첨부)

 

 2) Jenkins 설정

 - GitLab과 Docker , SSH 관련 플러그인 설치 

  •  Jenkins > Jenkins 관리 > Plugins 클릭
  • Available plugins > GitLab 검색 > 설치할 플러그인 체크 후 > Install 버튼 클릭
설치할 플러그인 목록 
- Git
- Git client
- Generic Webhook Trigger
- GitLab
- GitLab API
- Docker plugin
- Docker Pipeline
- SSH

- Credentials 등록하기 

  •  Jenkins > Jenkins 관리 > Security : Credentials 클릭
  •  Stores coped to Jenkins > Domains : Add credentials 클릭

 

- GitLab에서 personal access tokens 발급받기 

  • User > Edit profile > AccessTokens > [Add new Token] 버튼 클릭
  • 토큰 이름과, 만료일, 필요한 scopes 클릭후 토큰 생성
  • 생성한 토큰을 복사 > Jenkins 페이지로 돌아가기

 

- Jenkins 에서 credential 추가하기

  • Kind : GitLab Personal Access Token  > Token : 아까 복사한 토큰 붙여넣기 > ID : 해당 토큰의 ID 작성 > [Create] 버튼 클릭 

 

그 외에 추가하면 좋은 것

GitLab API token

:  GitLab 프로젝트의 Settings >  access tokens > Project Access Tokens 발급

Username with password 

: GitLab의 User와 Password 작성 

 

 

- Jenkins 환경변수 설정하기

  •  Jenkins > Jenkins 관리 > System 클릭

  •  스크롤을 쭉 내려서 GitLab Servers 항목을 찾고 
    - GitLab 서버 Url 입력
    > 전 단계에서 설정한 Credientials을 등록 (Personal Access Token 리스트만 노출 된다)
    > Web Hook 체크 
    > 위 설정이 다 되었으면 오른쪽 하단 [Test Connection]을 클릭해 실제로 connection이 되는지 체크 한다. 

 

- 프로젝트 생성 후 GitLab과 연동하기 

  • Jenkins > [+ 새로운 Item] > 프로젝트 이름 작성 후 Pipeline project 클릭 

 

※ Freestyle project와 Pipeline의 차이점?

더보기

Freestyle은 GUI 기반 단순한 CI/CD 파이프라인 또는 단일한 빌드 작업을 설정할 때 사용  

파이프라인의 구조를 마음대로 바꿀수 없고 커스텀마이징 또한 할수 없음

 

Pipeline의 경우 복잡한 CI/CD 파이프라인을 필요로 하거나, 작업 흐름을 코드로 관리하고 버전 컨트롤에서 추적하려는 경우 사용

  • Configuer의 General > Build Triggers에 : Bulid ~ GitLab hook URL 체크 
    > 관련 설정 영역이 노출 될 텐데 이 때 [고급] 버튼 클릭 후 Secret token 발급
  • URL와 Secret 토큰을 복사해 둔다 이것은 GitLab Webhook 설정할 때 사용 한다. 

 

 3) GitLab Webhook 설정하기

- 프로젝트 Webhooks 설정

  • [add new webhook] > Jenkins에서 발급받은 url와 Secret token을 입력
  • Trigger : Push events설정

  • 생성된 Webhook을 테스트 해본다. 
    Hook executed successfully라는 문구가 뜨면 성공!

 

 

※ 테스트가 안되는 경우도 있다?

만약 GitLab과 Jenkins가 같은 네트워크 망 혹은 로컬에 설치된 경우 : 관리자 계으로 접속해서

 Admin > Settings > Network > Outbound requests > Allow requests local network ~ (생략) 을 체크 한다. 

 

 

2. Jenkins Pipeline 스크립트 작성하기 

1) SCM 으로 스크립트 작성하기 

- 해당 아이템 > 설정에 Pipeline 클릭 > Definition으로 ~ SCM 클릭

SCM(Source Code Management)이란? 
git 같은 소스코드의 형상을 관리 하는 것

 즉, GitLab프로젝트 레포지토리에 파이프라인 스크립트를 추가하여 관리하겠다는 뜻이다. 

  • 레포지토리 url 을 추가 
  • 해당 프로젝트를 관리하는 / 접근 가능한 User Credentials을 추가
  • 어느 브랜치를 바라볼건지?
  • 스크립트 경로 (Jenkinsfile)

 

  • Jenkinsfile 이라는 이름을 가진 파일에 스크립트를 작성한다.
  • 민감한 정보는 환경변수에 등록해서 사용해야 한다. 

 환경변수 등록 : Jenkins 관리 > 시스템 설정 > Global properties > Enviroment variables 

pipeline {
    agent any

    environment {
        DOCKER_IMAGE = "python-cicd-test"  // Docker 이미지 이름
        DOCKER_TAG = "latest"  // Docker 태그
        REGISTRY = "10.22.5.110:5000"  // Docker 레지스트리 URL
        DOCKER_USERNAME = "admin"
        DOCKER_PASSWORD = "password"
        SSH_CREDENTIALS_ID = "ssh-credentials"  // 운영 서버에 SSH 접속할 자격 증명 ID
        REMOTE_HOST = "development@10.3.20.126"  // 운영 서버의 SSH 호스트 정보
    }

    stages {
        stage('Clone') {
            steps {
                // GitLab 저장소 클론
                git branch: 'main', url: 'http://10.3.20.122/root/ipm.git'
            }
        }

        stage('Build Docker Image') {
            steps {
                script {
                    // Docker 이미지 빌드
                    sh 'docker build -t ${REGISTRY}/${DOCKER_IMAGE}:${DOCKER_TAG} .'
                }
            }
        }

        stage('Push Docker Image') {
            steps {
                script {
                    // Docker 레지스트리에 로그인
                    sh 'docker login -u ${DOCKER_USERNAME} -p ${DOCKER_PASSWORD} $REGISTRY'

                    // Docker 이미지 푸시
                    sh 'docker push ${REGISTRY}/${DOCKER_IMAGE}:${DOCKER_TAG}'
                }
            }
        }

        stage('Deploy') {
            steps {
                script {
                        sshagent(credentials: [SSH_CREDENTIALS_ID]) {
                    // 운영 서버에서 Docker 컨테이너를 중지하고 제거 후 새 컨테이너 실행
                    sh '''
                    ssh -o StrictHostKeyChecking=no ${REMOTE_HOST} "
                        docker login -u ${DOCKER_USERNAME} -p ${DOCKER_PASSWORD} $REGISTRY
                        docker stop python-cicd-test || true
                        docker rm python-cicd-test || true
                        docker pull ${REGISTRY}/${DOCKER_IMAGE}:${DOCKER_TAG}
                        docker run -d --name python-cicd-test -p 80:80 ${REGISTRY}/${DOCKER_IMAGE}:${DOCKER_TAG}
                    "
                    '''
                }

            }
        }
    }

}
}

 

docker.withRegistry("http://${DOCKER_REGISTRY}", "${DOCKER_CREDENTIALS_ID}") { ... } 로도 가능 하다는데 이건 다음에 해봐야겠다.

2) 운영서버에 Jenkins SSH 접속 허용하기

 

 

참고 블로그 

 

Pipeline이란?

https://lovethefeel.tistory.com/95

'인프라' 카테고리의 다른 글

디스크와 파티션 볼륨 그리고 파일시스템  (0) 2024.10.07