2022년 전에 정리한 문서들

ECS CI/CD Workshop 정리(3) - Rolling Deploy

반가운사람2 2022. 8. 23. 20:55
반응형

이 실습에서는 스테이징 환경에서 실행되는 ECS 서비스에 애플리케이션 코드 변경 사항을 배포하는 데 사용할 수 있는 파이프라인을 구축합니다.


구축 환경 설명

URL에 대한 GET http://<path-to-service>/hello/Bob"Hi Bob" 메시지를 표시하는 HTML 페이지를 반환합니다.

실습 단계 요약

  • 1단계: 도커 이미지를 호스팅할 Amazon ECR 리포지토리를 생성합니다.
  • 2단계: 애플리케이션 코드를 저장할 AWS CodeCommit 리포지토리를 생성합니다.
  • 3단계: 소스 리포지토리를 준비합니다.

파이프라인을 빌드하려면:

  • 4단계: ECS 작업을 위한 CloudWatch Log Group을 생성합니다.
  • 5단계: ECS 작업 정의를 생성합니다.
  • 6단계: ECS 서비스를 생성합니다.
  • 7단계: CodeBuild 프로젝트 종속성을 생성합니다.
  • 8단계: 파이프라인을 생성합니다(CodeBuild 프로젝트 포함).

파이프라인이 생성되면:

  • 9단계: 파이프라인 실행을 관찰합니다.
  • 10단계: 서비스를 테스트합니다.
  • 11단계: 변경 사항을 커밋하고 서비스에 푸시하여 파이프라인을 다시 트리거한 다음 다시 테스트합니다.

1. 도커 이미지를 호스팅할 Amazon ECR 리포지토리를 생성합니다.

save_var IMAGE_REPO_URI $( \
    aws ecr create-repository \
        --repository-name hello-server \
        --query repository.repositoryUri \
        --output text \
)
echo Repo URI: $IMAGE_REPO_URI

#확인
aws ecr describe-repositories --repository-name hello-server

2. 애플리케이션 코드를 저장할 AWS CodeCommit 리포지토리를 생성합니다.

save_var SRC_REPO_URL $( \
    aws codecommit create-repository \
        --repository-name hello-server \
        --query repositoryMetadata.cloneUrlHttp \
        --output text \
)
echo New repo created at $SRC_REPO_URL

#확인
aws codecommit get-repository --repository-name hello-server

3.  소스 리포지토리를 준비합니다.

#리포지토리 접근
cd ~/environment
mkdir hello-server
git clone $SRC_REPO_URL hello-server

#출력
Cloning into 'hello-server'...
warning: You appear to have cloned an empty repository.

#CodeCommmit 리포지토리를 사용하여 로컬 리포지토리를 자동으로 설정
cd hello-server
git remote -v

#출력
origin  https://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/hello-server (fetch)
origin  https://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/hello-server (push)

#Hello-server App의 Source File를 Local 리포지토리에 복사
cp ~/environment/cicd-for-ecs-workshop-code/app/hello-server/* .

#Dockerfile 수정합니다.
sed -i 's%node\:buster-slim%public.ecr.aws/wizriz/node\:buster-slim%' Dockerfile
cat Dockerfile

#image 저장소 URI로 buildspec을 추가합니다.
cp  ~/environment/cicd-for-ecs-workshop-code/lab-1/buildspec-hello-server.yml ./buildspec.yml

#이미지 저장소에 대한 올바른 URI로 파일을 업데이트
sed -i "s%<IMAGE_REPO_URI>%$IMAGE_REPO_URI%" buildspec.yml
#확인 -> cat buildspec.yml
#buildspec.yml 파일 부분에서 중요한 부분은 post_build단계에서 magedefinitions.json 파일을 생성한다는 점을 중요시합니다.

#완료되면 소스 파일을 커밋하고 푸시합니다.
git add .
git commit -m "First commit"
git push -u origin master

- Codecommit 확인

- markdown File을 사용해서 아래 Docker Build 방법을 Codecommit에 표시할 수 있습니다.

4. ECS 작업을 위한 CloudWatch Log Group을 생성합니다.

#/ecs/hello-server LogGroup 생성
aws logs create-log-group --log-group-name /ecs/hello-server

5. ECS 작업 정의를 생성합니다.

#제공된 JSON 템플릿을 사용하여 작업 정의를 생성! > envsubst는 환경 변수의 값을 대체합니다
cd ~/environment
mkdir lab-1
cd lab-1
envsubst < ~/environment/cicd-for-ecs-workshop-code/lab-1/task-definition-hello-server.json.template > task-definition.json
cat task-definition.json

#작업 정의 등록
aws ecs register-task-definition --cli-input-json file://task-definition.json

1. 이미지는 1단계에서 만든 ECR 리포지토리를 참조
2. 로그 그룹은 이전 단계에서 생성한 Cloudwatch Logs Group을 참조합니다.
3. 포트 매핑은 TCP 컨테이너 포트 80을 노출합니다.

6. ECS 서비스를 생성합니다.

#먼저 ECS Service에 대한 ALB Target Group을 생성
save_var STAGING_VPC $( \
  aws cloudformation describe-stacks \
  --stack-name staging-cluster \
  --query "Stacks[0].Outputs[?OutputKey == 'VpcId'].OutputValue" \
  --output text \
)
save_var STAGING_TARGET_GROUP_ARN $( \
  aws elbv2 create-target-group \
  --name hello-server-tg \
  --port 80 \
  --protocol HTTP \
  --health-check-path /ping \
  --health-check-timeout-seconds 3 \
  --health-check-interval-seconds 5 \
  --healthy-threshold-count 2 \
  --target-type instance \
  --vpc-id $STAGING_VPC \
  --query "TargetGroups[0].TargetGroupArn" \
  --output text \
)
aws elbv2 modify-target-group-attributes \
  --target-group-arn $STAGING_TARGET_GROUP_ARN \
  --attributes "Key=deregistration_delay.timeout_seconds,Value=5"
  
  #리소스 경로로 HTTP 요청을 라우팅해야하기떄문에 ALB 리스너에 /hello/* 규칙을 추가합니다.
  cat <<EoF >conditions-pattern.json
[
    {
        "Field": "path-pattern",
        "PathPatternConfig": {
            "Values": ["/hello/*"]
        }
    }
]
EoF
cat <<EoF >actions.json
[
    {
        "Type": "forward",
        "ForwardConfig": {
            "TargetGroups": [ { "TargetGroupArn": "${STAGING_TARGET_GROUP_ARN}" } ]
        }
    }
]
EoF
save_var STAGING_LISTENER_ARN $( \
  aws cloudformation describe-stacks \
  --stack-name staging-cluster \
  --query "Stacks[0].Outputs[?OutputKey == 'PublicListener'].OutputValue" \
  --output text \
)
save_var STAGING_LISTENER_RULE_ARN $( \
    aws elbv2 create-rule \
    --listener-arn $STAGING_LISTENER_ARN \
    --priority 10 \
    --conditions file://conditions-pattern.json \
    --actions file://actions.json \
    --query "Rules[0].RuleArn" \
    --output text \
)

#제공된 JSON 템플릿을 사용하여 스테이징 서비스 사양을 생성
envsubst \
  < ~/environment/cicd-for-ecs-workshop-code/lab-1/service-hello-server.json.template \
  > staging_service.json
cat staging_service.json

#ECS Service Create
aws ecs create-service --cli-input-json file://staging_service.json
  • 로드 벨런서 생성확인

  • ECS Service 생성확인

처음에는 계속 Service에 Task가 실행이 실패됩니다. 이유는 아직 ECR에 Image를 Push하지 않았기 때문입니다. 즉, Codepipeline을 구축해서 이 문제점을 해결하도록 하겠습니다.

7. CodeBuild 프로젝트 종속성을 생성합니다.

#Codebuild Log Group Create
aws logs create-log-group --log-group-name /codebuild/hello-server

#Codebuild 프로젝트에 대한 IAM 역할 생성 
cat <<EoF > codebuild_trust_policy_doc.json
{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "codebuild.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EoF

#AmazonEC2ContainerRegistryPowerUser정책을 Codebuild Role에 적용합니다.
save_var CODEBUILD_ROLE_NAME Cloud9-CodeBuild-Role-$(date +%s)
save_var CODEBUILD_ROLE_ARN $( \
    aws iam create-role \
        --role-name $CODEBUILD_ROLE_NAME \
        --assume-role-policy-document file://codebuild_trust_policy_doc.json \
        --query Role.Arn \
        --output text \
)
aws iam attach-role-policy \
   --role-name $CODEBUILD_ROLE_NAME \
   --policy-arn arn\:aws\:iam::aws\:policy/AmazonEC2ContainerRegistryPowerUser

8. 파이프라인을 생성합니다(CodeBuild 프로젝트 포함) Console을 이용합니다.

  • 먼저 Codepipeline Console(console.aws.amazon.com/codepipeline )에 이동합니다. 그런다음 파이프라인 생성을 선택합니다. 그 후, 아래와 같이 설정합니다. 다음을 선택합니다.

  • 마찬 가지로 아래와 같이 설정합니다. 다음을 선택합니다.

  • 빌드 공급자에서 Codebuild를 선택한다음 프로젝트 생성을 선택합니다.

  • 빌드 프로젝트 이름을 입력합니다.

  • 환경을 설정합니다. 아래와 같이 설정해주세용!! IAM은 아까 전에 생성한 Codebuild IAM을 선택합니다.

  • 이제 맨 아래 Cloudwatch 부분을 설정합니다.

  • CodePipeline으로 계속을 선택합니다.
  • Codebuild 생성을 확인을 합니다.

  • 배포 단계에서 공급자 배포 중 Amazon ECS를 선택 후 Cluster Name, Service Name을 선택한 후 나머지 필드는 비워둡니다.

  • 생성 합니다!! Codepipeline이 성공적으로 실행되신 것을 확인할 수 있습니다.

  • 그럼 이제 ECS Service Task가 실행되고 있고 Service에 작업 정의에 Version은 2인 것을 확인합니다.

  • Curl 테스트
save_var STAGING_ALB_URL $( \
  aws cloudformation describe-stacks \
  --stack-name staging-cluster \
  --query "Stacks[0].Outputs[?OutputKey == 'ExternalUrl'].OutputValue" \
  --output text \
)
curl $STAGING_ALB_URL/hello/bob

9. 마지막 단계입니다. 변경 사항을 커밋하고 서비스에 푸시하여 파이프라인을 다시 트리거한 다음 다시 테스트합니다. 이게 바로 CI/ CD에 꽃입니다. 코드가 업데이트 되자마자 CodePipeline은 감지하고 바로 코드를 수정합니다.

cd ~/environment/hello-server
vi server.js
#Hi Thtre을 Hello로 변경합니다.

#변경사항 Commit -> Push
cd ~/environment/hello-server
git add -u
git commit -m "Changed greeting"
git push origin master

10. curl를 통해 응답이 바뀐 것을 확인합니다.

반응형