Jenkins 설정
이번 장은 앞서 다뤘던 내용을 바탕으로 Jenkins 서버에서 CodeCommit 과 ECR을 연동하고, git push 부터 Docker Image 빌드를 자동화 하는
내용을 다뤄보겠습니다.
얼마 전 Python flask 프레임워크를 이용해 월간보고서를 자동화 하는 백엔드 서버를 생성했는데요, 해당 서비스에 CI/CD를
구축해서 배포 자동화를 진행 해 보도록 하겠습니다.
Pipeline 생성
Jenkins 대시보드에서 새로운 Items 을 눌러 Pipeline 잡을 생성합니다.
매개변수 설정
매개변수를 설정하기 앞서 [대시보드 - Jenkins 관리 - Manage Credentials] 경로에서 아래와 같이 credential를 생성합니다.
해당 부분은 git credentials를 설정하는 부분으로 앞장에서 다뤘던 codecommit의 자격증명을 Username Password로 설정합니다.
이제 다시 돌아가서 앞서 생성한 Pipeline의 매개변수를 설정합니다.
저희가 설정할 매개변수는 총 5개이며, type과 내용은 아래와 같습니다.
각 설정에 맞게 매개변수를 채워 넣어주시면 됩니다.
No. |
매개변수 명 |
Credentials type |
사용 용도 |
1. |
GIT_CREDENTIALS_ID |
Username with password |
Codecommit 자격 증명 |
2. |
GIT_URL |
String |
Codecommit URL |
3. |
ECR_URI |
String |
ECR URI 초기 연결 |
4. |
ECR_BASE_URI |
String |
Docker build 초기 이미지가 저장된 레지스트리 URI |
5. |
ECR_TASK_URI |
String |
Build 된 이미지가 저장될 레지스트리 URI |
Script 설정
Jenkins Pipeline은 Script 형식으로 구성이 가능합니다.
Stage 단위로 실행 단위를 나눌 수 있어 관리하기 편합니다.
pipeline {
agent any
stages {
stage('Git Clone') {
steps {
script {
try{
git url: "https://$GIT_URL", branch: "master", credentialsId: "$GIT_CREDENTIALS_ID"
env.cloneResult=true
}catch(error){
print(error)
env.cloneResult=false
currentBuild.result='FAILURE'
}
}
}
}
stage('Docker Build'){
when{
expression {
return env.cloneResult ==~ /(?i)(Y|YES|T|TRUE|ON|RUN)/
}
}
steps {
script{
try{
sh"""
#!/bin/bash
cat>Dockerfile<
# build stage
FROM ${ECR_BASE_URI}:init as build-stage
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "flasktest:app", "-w", "2", "--timeout=300", "-k", "gevent"]
EOF"""
sh"""
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin ${ECR_URI}
docker build -t ${env.JOB_NAME.toLowerCase()} .
docker tag ${env.JOB_NAME.toLowerCase()}:latest ${ECR_TASK_URI}:ver${env.BUILD_NUMBER}
docker push ${ECR_TASK_URI}:ver${env.BUILD_NUMBER}
"""
env.dockerBuildResult=true
}catch(error){
print(error)
env.dockerBuildResult=false
currentBuild.result='FAILURE'
}
}
}
}
}
}
Codecommit 호출
기본적으로 Jenkins는 GitHub와 같은 git 레포지터리와 연동을 지원한다. 하지만 Codecommit과의 연동은 아직까지 지원하지 않기 때문에,
AWS Lambda를 설정하여 main branch에서 push가 이루어질 때 Jenkins 파이프라인을 호출하는 함수를 생성합니다.
Lambda가 Jenkins 서버의 API를 이용하여 호출 하는 형식이기에, Private 서브넷에 위치한 Jenkins 서버와 통신하기 위해 Lambda도 같은
VPC 내의 서브넷에 위치해야 합니다.
Lambda가 VPC 내부에 위치하기 위해서는 ENI가 필요하다. ENI를 생성할 수 있는 권한 (EC2FullAccess)을 역할에 추가 해 줍니다.
물론, EC2FullAccess가 아닌 최소 권한만 주는것이 바람직합니다.
Jenkins 서버의 위치와 동일한 서브넷과 관련 SG를 설정 해 줍니다.
CodeCommit과 Lamba의 연동 방법입니다. 트리거를 아래와 같이 구성하여, master 브랜치에서 푸쉬가 호출될 때 트리거가 진행됩니다.
위에서 말했 듯이, Jenkins 서버를 API로 호출하는 것이여서 jenkins API 토큰을 발급 받아야합니다.
Jenkins 대시보드에서 [사람 - 사용자 선택 - 설정] 경로에서 아래와 같이 API Token을 발급받습니다.
Lambda 코드에 들어갈 환경 변수를 따로 설정 해 줍니다.
아래는 선택 사항입니다. 메모리를 늘리거나 제한 시간을 조절하여 함수가 잘 돌아가도록 세팅합니다.
[Nodejs 14.x]
const http = require('http')
exports.handler = (event, context, callback) => {
var auth = 'Basic ' + Buffer.from(process.env.JenkinsUserId+':'+process.env.JenkinsAPIToken).toString('base64');
var options = {
host: process.env.JenkinsIP,
path: '/job/Deploy_SREBGK_MonthlyReport/buildWithParameters',
port: '8080',
method: 'POST',
headers: { 'Authorization': auth }
};
const req = http.request(options, (res) => {
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(chunk);
// if you need the returned data modify here
});
res.on('end', () => {
callback(null, 'Jenkins job triggered successfully');
});
});
req.on('error', (e) => {
console.log(e);
callback(null, "An error occurred while triggering Jenkins job.");
});
req.end();
};
이제 모든 설정은 끝이 났습니다. CodeCommit을 설정한 코드에서 master 브래치로 이동 후에 git push를 진행 해 보겠습니다.
Git Push
Master 브랜치에 로컬 저장소를 push 합니다.
% git checkout master
'master' 브랜치로 전환합니다
브랜치가 'origin/master'에 맞게 업데이트된 상태입니다.
% git merge develop
업데이트 중 fb654d0..74b11ec
Fast-forward
…
% git push
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To https://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/Monthly_Report
fb654d0..74b11ec master -> master
AWS Lambda가 트리거 된 후 Jenkins 서버에 API 통신이 진행되고 Jekins Pipeline JOB이 아래와 같이 실행된 것을 확인할 수 있습니다.
오늘의 최종 목표인 ECR에 build된 도커 이미지가 생성 및 저장되었습니다.
이런식으로 Jenkins Pipeline을 이용하면 docker build 까지 자동화 할 수 있으며 더 나아가, Pod의 Rolling Update를 구성할 수 있습니다.
다음에는 저희의 최종 목표인 POD rolling update 까지 구성 해 보도록 하겠습니다.
감사합니다.