Jenkins 설정

이번 장은 앞서 다뤘던 내용을 바탕으로 Jenkins 서버에서 CodeCommit 과 ECR을 연동하고, git push 부터 Docker Image 빌드를 자동화 하는 

내용을 다뤄보겠습니다.

 

얼마 전 Python flask 프레임워크를 이용해 월간보고서를 자동화 하는 백엔드 서버를 생성했는데요, 해당 서비스에 CI/CD를

구축해서 배포 자동화를 진행 해 보도록 하겠습니다.

 

 

Pipeline 생성

 

Jenkins 대시보드에서 새로운 Items 을 눌러 Pipeline 잡을 생성합니다.

 

Enter an item name 
» Required field 
Freestyle project 
Jenkins@l PI-SPLICE Jenkinse Al-g-g + 
Pipeline 
Orchestrates long-running activities that can span multiple build agents. Suitable for building pipelines (formerly known as workflows) and/or organizing complex activities that do not easily fit in free-style job type.


 

매개변수 설정

 

매개변수를 설정하기 앞서 [대시보드 - Jenkins 관리 -  Manage Credentials] 경로에서 아래와 같이 credential를 생성합니다.

 

Stores scoped to Jenkins 
Store I 
Jenkins 
Domains

 

해당 부분은 git credentials를 설정하는 부분으로 앞장에서 다뤘던 codecommit의 자격증명을 Username Password로 설정합니다.

Kind 
Back to credential domains 
Username with password 
Add Credentials 
Scope 
Global (Jenkins, nodes, items, all child items, etc) 
Username 
sanghyeon.park-a 
Treat username as secret 
Password 
Description

 

이제 다시 돌아가서 앞서 생성한 Pipeline의 매개변수를 설정합니다.

 

a 01 
Credentials Parameter 
Name 
Credential type 
Username with password 
Required


 

저희가 설정할 매개변수는 총 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 
Definition 
Pipeline script 
Script 
1 • pipeline { 
5. 
8. 
branch:

 

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가 아닌 최소 권한만 주는것이 바람직합니다.

역할 〉 triggerJenkinsFromCodeCommit-roIe-n9089df8 
요약 
권한 신뢰 관계 
역할 ARN 
역할 설명 
인스턴스 프로파일 ARN 
경로 
생성 시간 
마지막 활동 
최대 세션 지속 시간 
태그 액세스 관리자 세션 취소 
arn:aws:lam: 
편집 
/service-role/ 
:role/service-roIe/triggerJenkinsFromCodeCommit-role-n9089df8 勿 
2021-06-27 21 :47 UTC+0900 
추적 기간에 액세스되지 않음 
1 시간 편집 
Permissions policies (2 정책이 적용대 
정책 연결 
정책 이름 
AWSLambdaBasicExecutionRole-75763f35-444b-4bb5-8b45-b7c1cb433b52 
AmazonEC2FullAccess 
정책 유형 
관리형 정책 
AWS 관리형 정책 
역할 삭제 
0 인라인 정책 추가 
X

 

Jenkins 서버의 위치와 동일한 서브넷과 관련 SG를 설정 해 줍니다.

 

VPC 편집 
VPC 
0 계정의 VPC에 함수를 연결하면 VPC가 액세스를 제공하지 않는 한 인터넷에 액세스할 수 없습니다. 함수에 인터넷 액세스 권한 
을 부여하려면 퍼블릭 서브넷의 NAT 게이트웨이로 아웃바운드 트래픽을 라우팅합니다. 자세히 알아보기 
VPC Info 
액세스할 함수에 대한 VPCS 선택합니다. 
vpc-0685cb6e2c8413249 (10.1290.0/16) 
서브넷 
VPC 구성을 설정하는 데 사용할 Lambda의 VPC 서브넷을 선택합니다. 
서브넷 선학 
subnet-Oc5df8fc1 b2332ede (10.129.176.0/20) 
ap-northeast-2a X 
kubernetes.io/cluster/srebgk_cluster: shared Name: an2-kr-prd-srebgk-subnet-pri-a 
subnet-Ol f92602a98f1 a 1 b8 (10.129240.0/20) 
ap-northeast-2c X 
Name: an2-kr-prd-srebgk-subnet-pri-c kubernetes.io/cluster/srebgk—cluster: shared 
보안 그룹 
Lambda가 VPC 구성을 설정하는 데 사용할 VPC 보안 그릅을 선택합니다. 아래 표에서는 선택한 보안 그릅의 인바운드 규칙과 아웃바운드 규칙을 보여줍니다. 
보안 그룹 선학 
sg-016846739b2b795f1 (an2-kr-prd-srebgk-jenkins-sg) X 
an2-kr-prd-Srebgk-jenkins-sg created 2021-02-09T11 :43:39.851 +09:00

 

CodeCommit Lamba의 연동 방법입니다트리거를 아래와 같이 구성하여, master 브랜치에서 푸쉬가 호출될 때 트리거가 진행됩니다.

 

트리거 구성 
CodeCommit 
aws developer-tools 
리포지토리 이름 
glt 
이 함수를 호출하는 트리거의 이름을 입력합니다. 
Monthly—Report 
트리거 이름 
이 함수를 호출하는 트리거의 이름을 입력합니다. 
codecommit_Trigger 
이벤트 
수신할 이벤트를 하나 이상 선택합니다.

 

위에서 말했 듯이, Jenkins 서버를 API로 호출하는 것이여서 jenkins API 토큰을 발급 받아야합니다.

Jenkins 대시보드에서 [사람 - 사용자 선택 - 설정] 경로에서 아래와 같이 API Token을 발급받습니다.

 

API Token 
Current token(s) 
jenkins_api 
Created 121 day(s) ago 
Used 11 time(s), last time was 45 day(s) ago

 

Lambda 코드에 들어갈 환경 변수를 따로 설정 해 줍니다.

 

환경 변수 편집 
환경 변수 
환경 변수를 함수 코드에서 액세스할 수 있는 키-값 페어로 정의할 수 있습니다. 이렇게 하면 함수 코드를 변경하지 않고도 구성 설정을 저장 
하는 데 유용합니다. 자세히 알아보기 
키 
」enkinsAPlToken 
」enkinslP 
」enkinsUserld 
환경 변수 추가 
> 암호화 구성 
값 
10.129.176.192 
sanghyeon—park 
제거 
제거 
제거 
취소 
저장

 

아래는 선택 사항입니다메모리를 늘리거나 제한 시간을 조절하여 함수가 잘 돌아가도록 세팅합니다

 

기본 설정 편집 
기본 설정 
Info 
설명 - 선택 사함 
메모리(MB) Info 
구성된 메모리에 비례하는 CPU가 함수에 할당됩니다. 
128 
MB 
메모리를 128MB~10240MB 범위로 설정 
제한 시간 
30 
조

 

 

[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이 아래와 같이 실행된 것을 확인할 수 있습니다.

 

Recent Changes 
Stage View 
Git Clone 
2s 
3s 
Docker Build 
20s 
Jun 27 
22:14 
Average stage times: 
No 
Changes

 

오늘의 최종 목표인 ECR build된 도커 이미지가 생성 및 저장되었습니다.

 

monthly_report 
0101Ăl 
(1) 
Q 
0/0/1/ 
272 10:16:28 
c 
01018 EHZL 
vers 
2021ă 6' 
a71(MB) 
542.60 
0101Ăl URI 
13 sha256:7d2c9d819443ac5e7987aed5410e4...

 

이런식으로 Jenkins Pipeline을 이용하면 docker build 까지 자동화 할 수 있으며 더 나아가, Pod Rolling Update를 구성할 수 있습니다.

 

다음에는 저희의 최종 목표인 POD rolling update 까지 구성 해 보도록 하겠습니다.

 

감사합니다.