[CI/CD] (5) 배포 자동화 - 1
💡 CICD 과정은 LINK의 개요에 따라 작성되었습니다.
순서를 따르면 순조롭게 진행할 수 있습니다.
Jenkins에서 Build 진행하기
Jenkins는 Jenkinsfile
을 읽고 여러 stage
를 순서대로 실행하게 된다.
Jenkins의 배포 기본 과정은 다음과 같다.
- github에서 소스파일을 checkout해온다.
- 암호화된 파일을 git secret을 이용해 복호화 시킨다.
- 프로젝트가 실행될 포트를 파싱한다.
- 소스파일을 테스트, 빌드한다.
- 빌드된 jar파일을 도커 이미지로 만들고 도커 허브에 push한다.
- 개발/운영 서버에 접속해 도커 이미지를 내려받고 기존 컨테이너를 내린 후 새 컨테이너를 실행한다. 위에서 말했듯이 순서대로 적용해 보겠다.
위의 과정대로 stage
를 하나하나 작성해보자.
Checkout
가장 먼저 프로젝트 최상위에 Jenkinsfile
이라는 파일을 생성하자. 첫 stage
에서는 GIthub 원격 리포지토리에서 변경이 감지된 브랜치를 checkout 해올 것이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
pipeline {
agent any
stages {
stage('Git Checkout') {
steps {
echo 'Checkout Remote Repository'
git branch: "${env.BRANCH_NAME}",
url: '[원격 레포지토리 URL]'
}
}
}
}
위 처럼 작성하면 변경이 감지된 브랜치를 checkout해오는 stage가 완성된다. 기본적인 pipeline syntax는 공식 문서를 참고하자.
git
은 jenkins git plugin인데 Jenkins를 처음 실행할 때 기본적으로 설치되는 플러그인이다. 공식 문서에서 jenkins git plugin의 checkout pipeline 작성 예시를 확인할 수 있다.
env
는 Jenkins의 기본적인 환경변수이다. env
의 variable들은 공식 문서에서 다음과 같이 확인할 수 있다.
- BUILD_ID
- BUILD_NUMBER
- BUILD_TAG
- BUILD_URL
- EXECUTOR_NUMBER
- JAVA_HOME
- JENKINS_URL
- JOB_NAME
- NODE_NAME
- WORKSPACE
또한 공식 문서에 따르면 Multibranch Pipelines
에서는 추가적으로 다음과 같은 variable을 추가로 가진다.
- BRANCH_NAME
- CHANGE_ID
따라서 위에 있는 BRANCH_NAME
을 활용해 변경이 감지된 브랜치를 checkout해 올 수 있다.
참고 : groovy의 double-quoted-string과 single-quoted-string의 차이
single-quoted-string은
java.lang.String
과 같은 클래스이고, double-qouted-string은org.codehaus.groovy.runtime.GStringImpl
클래스로서, GString이라고 불린다. GString은 lazy loading을 지원해${변수명}
을 포함시켜toString()
이 호출될 때 실제 문자열로 변환된다. 예시로 동적 SQL문을 생성할 때 사용할 수 있다.위와 같은 이유로 branch명을 불러올 때 double-qouted-string을 사용했다.
복호화
이제 checkout해온 소스파일에서 암호화된 파일을 복호화 하는 과정을 해야한다.
가장 먼저 아까 만들어 두었던 test-jenkins
의 private key를 jenkins의 credential로 등록해 줄 것이다.
가장 먼저 private-key를 복사해 보자
1
$ gpg --export-secret-key test-jenkins > private.key
위의 명령어를 입력하면 private.key라는 파일에 private-key가 추출된다.
이제 credential을 만들어 jenkins에 private-key를 등록 시키자.
해당 private key는 cicd-test라는 프로젝트에 국한된 것이기 때문에, cicd-test item 스코프에 국한된 credential을 생성해보자.
cicd-test
item의 credential에 들어간다.
cicd-test
를 눌러 해당 아이템에서 접근 가능한 도메인 목록에 들어간다.
현재는 Global credentials
밖에 존재하지 않는다. Add domain
버튼을 눌러 도메인을 생성해 준다.
위처럼 도메인 폴더를 생성한다. 이제 해당 item에서만 접근할 수 있는 도메인이 생성되었다.
Add Credentials
버튼을 눌러 Credential을 추가한다.
다양한 종류의 Credential을 생성할 수 있다. private.key
를 등록해 줄것이기 때문에 위와 같이 Secret file로 Credential을 등록해준다. 이제 private.key는 필요 없으니 삭제해준다.
1
$ rm private.key
jenkins에서 gpg와 git-secret을 이용해 파일을 복호화 해야 하니 jenkins에 접속해 gpg와 git-secret을 설치해 준다.
1
2
3
4
5
6
7
8
# Jenkins bash 접속
$ docker exec -it jenkins /bin/bash
# gpg, git-secret 설치
$ apt update
$ apt install gpg git-secret -y
$ exit
Jenkinsfile 의 agent any
다음에 다음 환경변수 설정을 해준다.
1
2
3
4
5
agent any
environment {
GPG_SECRET_KEY = credentials('GPG_SECRET_KEY')
}
만들어 놓았던 Credential을 GPG_SECRET_KEY
라는 변수에 저장한다. 이제 Jenkinsfile에 복호화 stage를 추가해 준다.
1
2
3
4
5
6
7
8
stage('Git Secret Reveal') {
steps {
echo 'Git Secret Reveal'
sh(script:
('gpg --batch --import ' + GPG_SECRET_KEY + ' && '
+ ' git secret reveal -f'))
}
}
private.key
를 등록시켜둔 Credential을 gpg-key로 import 시킨다. 그리고 checkout해온 소스파일에서 암호화된 파일을 복호화 시킨다.
String
들을 +
문법을 사용해 연결시켰는데 이는 Credential을 직접 double-quoted-string
안에 호출하면 다음과 같은 Warning이 생기기 때문이다.
해당 방법은 insecure하므로 +
문법을 사용해 더해주자.
sh
에 관한 문법은 공식 문서에서 확인할 수 있듯이 String 타입인 script만 필수이고 나머지는 optional이므로sh 'aaa'
의 형식으로 입력하면 된다.
'''
는 groovy의Triple-single-quoted String
으로 여러줄의 문자를 입력하는 데 용이한 문법이다. 현재 커맨드는 여러줄이 아니지만 시인성을 위해 사용했다. (참고 : LINK)
Build
복호화 다음 stage
는 포트를 파싱하는 것이지만 나중에 필요성이 생길 때 작성하고 build stage
를 먼저 작성하겠다.
이제 받아온 프로젝트 소스파일을 gradlew
를 이용해 빌드한다. 다음과 같은 stage를 추가해준다.
1
2
3
4
5
6
7
8
stage('Build') {
steps {
echo 'Build With gradlew'
sh '''
./gradlew clean build
'''
}
}
위와 같이 작성하면 ./gradlew clean build
라는 명령어를 이용해 build
를 진행한다. 특별한 설정을 만지지 않았다면 여기서 test
가 진행되게 되고 test
를 통과하지 못하면 build stage
가 중단되고 배포가 실패하게 된다.
최종적인 Jenkinsfile
의 내용은 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
pipeline {
agent any
environment {
GPG_SECRET_KEY = credentials('GPG_SECRET_KEY')
}
stages {
stage('Git Checkout') {
steps {
echo 'Checkout Remote Repository'
git branch: "${env.BRANCH_NAME}",
url: '[원격 레포지토리 URL]'
}
}
stage('Git Secret Reveal') {
steps {
echo 'Git Secret Reveal'
sh(script:
('gpg --batch --import ' + GPG_SECRET_KEY + ' && '
+ ' git secret reveal -f'))
}
}
stage('Build') {
steps {
echo 'Build With gradlew'
sh '''
./gradlew clean build
'''
}
}
}
}
이제 변경사항을 push하고 결과를 확인해보자.
1
2
3
$ git add .
$ git commit -m "chore: Jenkinsfile 생성 및 checkout, secret reveal, build stage 추가"
$ git push
push
후 Jenkins를 확인해 보자.
성공적으로 진행된 것을 확인할 수 있다.
Console Output
을 확인해보면 위처럼 checkout, 복호화, build 과정이 잘 진행되었다는 로그를 확인할 수 있다.
다음 포스트에서는 Build된 결과를 Docker Image로 Build하고 Docker Hub에 Push하는 과정을 진행해 보자.
댓글남기기