본문 바로가기

CICD/ECS

ECS CICD Automation - 4. Jenkins Job (Rolling)

이제 ECS의 배포 순서를 다시 간단하게 순서를 나열하면 다음과 같습니다.

 

1. Git Clone

2. Maven Build & S3 Upload (사실 안 해도 됨 그래서 생략 할 예정)

3. Create Docker file & Docker Build -> ECR Push

4. Create Task Definition (Modifiy ECR URL Version) & Update Service (Modify Task Definition Version)

 

젠킨스 세팅에 관한 부분은 EC2 CICD부터 수행해오며 모두 되어 있기 때문에,

해당 포스트만 보실 경우 앞 포스트들을 보며 세팅을 하시거나 아니면 알아서 잘 세팅한 후 진행하시면 됩니다.

 

는 아니고 ecs에서 아래와 같이 CLI를 수행해야하기 때문에 ecs와 관련된 policy를

Jenkins에 등록한 aws credentials iam에 추가시켜주셔야 합니다.

 


젠킨스 파이프라인 잡을 만들어 준 후 변수를 아래와 같이 설정해줍니다.

 

 

 

자 이제 파이프라인 코드를 아래와 같이 구성해 주면 끝입니다.

pipeline {
    agent any
    stages {
        stage('Git Clone') {
            steps {
                script {
                    try {
                        git url: "https://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/cb-test-api", branch: "master", credentialsId: "$GIT_CREDENTIALS_ID"
                        sh "sudo rm -rf ./.git"
                        env.cloneResult=true
                    } catch (error) {
                        print(error)
                        env.cloneResult=false
                        currentBuild.result = 'FAILURE'
                    }
                }
            }
        }
        stage('Build JAR') {
            when {
                expression {
                    return env.cloneResult ==~ /(?i)(Y|YES|T|TRUE|ON|RUN)/
                }                
            }
            steps {
                script{
                    try {
                        sh """
                        rm -rf deploy
                        mkdir deploy
                        """ 
                        sh "sudo sed -i \"s/module_name=.*/module_name=${env.JOB_NAME}\\:${env.BUILD_NUMBER}/g\" /var/lib/jenkins/workspace/${env.JOB_NAME}/src/main/resources/application.properties"
                        sh "cat /var/lib/jenkins/workspace/${env.JOB_NAME}/src/main/resources/application.properties"
                        sh 'mvn -Dmaven.test.failure.ignore=true clean install'
                        sh """
                        cd deploy
                        cp /var/lib/jenkins/workspace/${env.JOB_NAME}/target/*.jar ./${env.JOB_NAME}.jar
                        """
                        env.mavenBuildResult=true
                    } catch (error) {
                        print(error)
                        echo 'Remove Deploy Files'
                        sh "sudo rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
                        env.mavenBuildResult=false
                        currentBuild.result = 'FAILURE'
                    }
                }
            }
            post {
                success {
                    slackSend channel: '#pipeline-deploy', color: 'good', message: "The pipeline ${currentBuild.fullDisplayName} stage Build JAR successfully."
                }
                failure {
                    slackSend channel: '#pipeline-deploy', color: 'danger', message: "The pipeline ${currentBuild.fullDisplayName} stage Build JAR failed."
                }
            }
        }
        stage('Docker Build'){
            when {
                expression {
                    return env.mavenBuildResult ==~ /(?i)(Y|YES|T|TRUE|ON|RUN)/
                }
            }
            steps {
                script{
                    try {
                        sh"""
                        #!/bin/bash
                        cd ./deploy
                        cat>Dockerfile<<-EOF
FROM ${ECR_BASE_URL}:latest
ADD ${env.JOB_NAME}.jar /home/${env.JOB_NAME}.jar
CMD nohup java -jar /home/${env.JOB_NAME}.jar 1> /dev/null 2>&1
EXPOSE 9000
EOF"""
                        sh"""
                        cd ./deploy
                        docker rmi -f \$(docker images -q)
                        \$(aws ecr get-login --no-include-email --region ap-northeast-2)
                        docker build -t ${SERVICE_NAME.toLowerCase()} .
                        docker tag ${SERVICE_NAME.toLowerCase()}:latest ${ECR_TASK_URL}:ver${env.BUILD_NUMBER}
                        docker push ${ECR_TASK_URL}:ver${env.BUILD_NUMBER}
                        """
                        echo 'Remove Deploy Files'
                        sh "sudo rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
                        env.dockerBuildResult=true
                    } catch (error) {
                        print(error)
                        echo 'Remove Deploy Files'
                        sh "sudo rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
                        env.dockerBuildResult=false
                        currentBuild.result = 'FAILURE'
                    }
                }
            }
            post {
                success {
                    slackSend channel: '#jenkins', color: 'good', message: "The pipeline ${currentBuild.fullDisplayName} stage Docker Build successfully."
                }
                failure {
                    slackSend channel: '#jenkins', color: 'danger', message: "The pipeline ${currentBuild.fullDisplayName} stage Docker Build failed."
                }
            }
        }
        stage('Deploy'){
            when {
                expression {
                    return env.dockerBuildResult ==~ /(?i)(Y|YES|T|TRUE|ON|RUN)/
                }
            }
            steps {
                script{
                    try {
                        withAWS(credentials:"$AWS_CREDENTIALS") {
                            sh "aws ecs describe-task-definition --task-definition ${TASK_DEFINITION} --region ap-northeast-2 --query \"taskDefinition.{\"family\": family, \"containerDefinitions\": containerDefinitions, \"executionRoleArn\": executionRoleArn,\"requiresCompatibilities\": requiresCompatibilities}\" --output json > task-definition.json"
                            def task_repository_name = sh(
                                    script:"""
                                    echo \"${ECR_TASK_URL}\" | awk \'{ split(\$0, arr, \"/\"); print arr[2] }\'
                                    """,
                                    returnStdout: true
                                ).trim()
                            sh "sudo sed -i \"9s/${task_repository_name}:.*/${task_repository_name}:ver${env.BUILD_NUMBER}\\\",/g\" task-definition.json"
                            sh "cat task-definition.json"
                            sh "aws ecs register-task-definition --cli-input-json file://task-definition.json --region ap-northeast-2"
                            sh "aws ecs update-service --cluster ${CLUSTER_NAME} --service ${SERVICE_NAME} --task-definition ${TASK_DEFINITION} --region ap-northeast-2"
                        }
                    } catch (error) {
                        print(error)
                        echo 'Remove Deploy Files'
                        sh "sudo rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
                        currentBuild.result = 'FAILURE'
                    }
                }
            }
            post {
                success {
                    slackSend channel: '#jenkins', color: 'good', message: "The pipeline ${currentBuild.fullDisplayName} successfully."
                }
                failure {
                    slackSend channel: '#jenkins', color: 'danger', message: "The pipeline ${currentBuild.fullDisplayName} failed."
                }
            }
        }
    }
}

 

저는 잡다한 에러를 고치느라 8번만에 성공했습니다.

 

 

 

 

 

 

성공적으로 배포가 됐음을 볼 수 있습니다.

 

다음 포스트에서는 service를 블루/그린 배포로 구성하여 배포를 진행해보도록 하겠습니다.