본문 바로가기

DevOps/Jenkins

[AWS/Jenkins] Spring Boot Jenkins+ECR+ECS를 이용한 CI/CD

회사의 CI/CD 방식을 아예 개편하게 되었다.
CodePipeline+Beanstalk -> Jenkins+ECR+ECS 이렇게.
 

배포 과정

1. 개발자가 push를 하면 jenkins의 webhook이 발동되어 ci/cd job이 실행.
2. jenkins는 git code를 pull 받아 Jib을 통해 docker image를 생성해 ecr에 push.
3. 그 후 ecs update service 명령어를 이용해 ecs가 새로운 배포를 시작.
 

사전준비

1. 깃허브 접근을 위한 ssh-key와 aws 접근을 위한 aws-key를 추가해준다.
2. github settings ->  webhooks에 jenkins webhook url을 추가해준다.

jenkins-url/github-webhook/을 적어주면 된다.
끝에 / 도 꼭 붙여줘야한다. 저거 떼면 webhook 작동하지 않음.
3. ECR 레포지토리를 생성해두어야 하고
4. ECS cluster, task, service도 생성해두야 한다.
 

Spring Boot에 추가해야 할 것

1. docker image로 빌드하기 위해 jib 플러그인을 추가해주어야 한다.

id 'com.google.cloud.tools.jib' version '3.3.0'

2. 그리고 jib 코드를 작성해준다.

jib {
	from {
		image = 'adoptopenjdk/openjdk11:alpine-jre'
	}
	to {
		tags = ['1.0']
	}
	container {
		entrypoint = ['java', '-jar', 'project-name-0.0.1-SNAPSHOT.jar']
		jvmFlags = ['-Xms512m', '-Xmx512m', '-Xdebug', '-XshowSettings:vm', '-XX:+UnlockExperimentalVMOptions', '-XX:+UseContainerSupport']

		environment = [SPRING_OUTPUT_ANSI_ENABLED: "ALWAYS"]
		labels = [version:project.version, name:project.name, group:project.group]

		creationTime = 'USE_CURRENT_TIMESTAMP'
		format = 'Docker'
	}
	extraDirectories {
		paths {
			path {
				from = file('build/libs')
			}
		}
	}
}

3. Jenkinsfile을 작성해준다.

def mainDir="."
def ecrLoginHelper="docker-credential-ecr-login"
def region="ap-northeast-2"
def ecrUrl="$$$$$$$$$.dkr.ecr.ap-northeast-2.amazonaws.com"
def repository="repository-name-${PROJECT_SECTION}"
def ecsCluster="cluster-name-${PROJECT_SECTION}"
def ecsService="ecs-service-name-${PROJECT_SECTION}"

pipeline {
    agent any

    stages {
        stage('Pull Codes from Github'){
            steps{
                checkout scm
            }
        }
        stage('Build Codes by Gradle') {
            steps {
                sh """
                cd ${mainDir}
                ./gradlew clean
                ./gradlew build
                """
            }
        }

         stage('Build Docker Image by Jib & Push to AWS ECR Repository') {
                    steps {
                        withAWS(region:"${region}", credentials:"aws-key") {
                            ecrLogin()
                            sh """
                                curl -O https://amazon-ecr-credential-helper-releases.s3.us-east-2.amazonaws.com/0.4.0/linux-amd64/${ecrLoginHelper}
                                chmod +x ${ecrLoginHelper}
                                mv ${ecrLoginHelper} /usr/local/bin/
                                cd ${mainDir}
                                ./gradlew jib -Djib.to.image=${ecrUrl}/${repository}:latest -Djib.console='plain'
                            """
                        }
                    }
                }

        stage('Deploy to AWS ECS VM'){
             steps {
                script{
                    try {
                        withAWS(region:'${region}', credentials:"aws-key") {
                            sh"""
                                aws ecs update-service --region ${region} --cluster ${ecsCluster} --service ${ecsService} --force-new-deployment
                            """
                        }
                    } catch (error) {
                        print(error)
                        echo 'Remove Deploy Files'
                        sh "rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
                        currentBuild.result = 'FAILURE'
                    }
                }
            }
            post {
                success {
                    echo "The deploy stage successfully."
                }
                failure {
                    echo "The deploy stage failed."
                }
            }
        }
    }
}

${PROJECT_SECTION} profile 설정을 위해 추가한 변수이다. jenkins job에서 넘겨받는다.
 

Jenkins Job 생성

1. 새 아이템 추가하여 pipeline 선택
2. github project에 github url 추가

3. 매개변수 추가

PROJECT_NAME은 그냥 알아보려고 추가해놨다. PROJECT_SECTION 변수는 Jenkinsfile에서 사용하는 변수
4. build trigger로 GitHub hook trigger for GITScm polling 선택