자 먼저 젠킨스 잡을 ECS Fargate Rolling에서 Copy하시고, 변수는 아래와 같이 설정해주시면 됩니다.
스크립트 또한 아래와 같이 입력해주신 후 저장하고 젠킨스 빌드를 해주도록 하겠습니다.
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('Appspec Upload'){
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, \"networkMode\": networkMode,\"containerDefinitions\": containerDefinitions, \"executionRoleArn\": executionRoleArn,\"requiresCompatibilities\": requiresCompatibilities,\"cpu\":cpu, \"memory\":memory}\" --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 "aws ecs register-task-definition --cli-input-json file://task-definition.json --region ap-northeast-2"
}
def task_arn = sh(
script:"aws ecs describe-task-definition --task-definition ${TASK_DEFINITION} --region ap-northeast-2 --query \"taskDefinition.taskDefinitionArn\"",
returnStdout: true
).trim()
echo "${task_arn}"
sh"""
#!/bin/bash
mkdir appspec
cd ./appspec
cat>appspec.yaml<<-EOF
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: ${task_arn}
LoadBalancerInfo:
ContainerName: "cb-test-api"
ContainerPort: 9000
EOF"""
withAWS(credentials:"$AWS_CREDENTIALS") {
s3Upload(path:"${env.JOB_NAME}/${env.BUILD_NUMBER}/", file:"/var/lib/jenkins/workspace/${env.JOB_NAME}/appspec/appspec.yaml",bucket:'cb-test-deploy')
env.uploadResult=true
}
echo 'Remove Deploy Files'
sh "sudo rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
env.uploadResult=true
} catch (error) {
print(error)
echo 'Remove Deploy Files'
sh "sudo rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
env.uploadResult=false
currentBuild.result = 'FAILURE'
}
}
}
post {
success {
slackSend channel: '#jenkins', color: 'good', message: "The pipeline ${currentBuild.fullDisplayName} stage Appspec Upload successfully."
}
failure {
slackSend channel: '#jenkins', color: 'danger', message: "The pipeline ${currentBuild.fullDisplayName} stage Appspec Upload failed."
}
}
}
stage('Deploy'){
when {
expression {
return env.uploadResult ==~ /(?i)(Y|YES|T|TRUE|ON|RUN)/
}
}
steps {
script{
try {
withAWS(credentials:"$AWS_CREDENTIALS") {
sh"""
aws deploy create-deployment \
--application-name AppECS-${CLUSTER_NAME}-${SERVICE_NAME} \
--deployment-group-name DgpECS-${CLUSTER_NAME}-${SERVICE_NAME} \
--region ap-northeast-2 \
--s3-location bucket=cb-test-deploy,bundleType=YAML,key=${env.JOB_NAME}/${env.BUILD_NUMBER}/appspec.yaml \
--output json > DEPLOYMENT_ID.json
"""
}
def DEPLOYMENT_ID = readJSON file: './DEPLOYMENT_ID.json'
echo "${DEPLOYMENT_ID.deploymentId}"
sh "rm -rf ./DEPLOYMENT_ID.json"
def DEPLOYMENT_RESULT = ""
while("$DEPLOYMENT_RESULT" != "\"Succeeded\"") {
DEPLOYMENT_RESULT = withAWS(credentials:"$AWS_CREDENTIALS") {
sh(
script:"aws deploy get-deployment \
--query \"deploymentInfo.status\" \
--region ap-northeast-2 \
--deployment-id ${DEPLOYMENT_ID.deploymentId}",
returnStdout: true
).trim()
}
echo "$DEPLOYMENT_RESULT"
if ("$DEPLOYMENT_RESULT" == "\"Failed\"") {
throw new Exception("CodeDeploy Failed")
break
}
sleep(15)
}
} 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."
}
}
}
}
}
그러면 코드디플로이가 수행하면서 컨테이너가 하나 더 뜨고,
아직은 리스너 등록이 안되었기 때문에 unused지만 컨테이너가 타겟그룹에 세팅됩니다.
아... 제가 깜빡하고 이전에 ECS EC2 Cluster처럼 대기시간을 없앴어야 했는데 깜빡했네요..
배포 그룹으로 이동해서 편집 -> 대기시간을 없애주겠습니다.
중단 후 위와 같이 수정하면,
사실 리스너는 이미 변경되고 헬스체크 및 서비스도 정상으로 되어있는 모습을 볼 수 있습니다.
TG1에 있는 컨테이너를 ECS 서비스 -> 작업에서 수동으로 중지해서 지워주시고 다시 배포하도록 하겠습니다.
이로써, ECS에서의 자동화 배포 기본 구성에 대해서 모두 알아봤습니다.
'CICD > ECS' 카테고리의 다른 글
ECS CICD Automation - 10. ECS Linear Deployment (0) | 2020.02.11 |
---|---|
ECS CICD Automation - 9. ECS Linear, Canary Deployment Intro (0) | 2020.02.09 |
ECS CICD Automation - 8. ECS Fargate Blue/Green 생성 (0) | 2020.01.31 |
ECS CICD Automation - 7. Jenkins Job (ECS Fargate Rolling) (0) | 2020.01.31 |
ECS CICD Automation - 6. ECS Fargate 생성 (0) | 2020.01.31 |