ysuekkom의 IT study note

[AWS Cloud] AWS CI/CD 자동화 구축하기 -CodeDeploy, CodePipeline 본문

Cloud Service/AWS

[AWS Cloud] AWS CI/CD 자동화 구축하기 -CodeDeploy, CodePipeline

ysuekkom 2023. 5. 17. 13:38

 

 이전 포스팅에서 AWS CodeDeploy를 통해 자동 배포를 실습해 보았다. 본 포스팅에서는 완전한 자동화를 위해 CodePipeline을 구축해보자. 소스코드의 변화가 감지되면 자동으로 CodeDeploy를 수행하게 하는 CodePipeline을 구축해 보겠다.

 

 애플리케이션 업로드용 S3를 생성하고, 총 3개의 소스코드 파일을 S3에 순차 업로드한다. version1는 이전 포스팅에서처럼 CodeDeploy에서 배포 생성을 수행하여 업로드 및 배포 한다. 이후 CodePipeline을 구축하여 CodeDeploy를 호출, version2를 배포한다. 

 이후, CodePipeline 기능 구현 테스트를 위해 version3을 S3에 업로드 한다. 이때, CloudWatch가 변화를 감지하여 자동으로 CodeDeploy를 수행하게 하는 CodePipeline이 정상 작동하는지 확인해 보자.

 

 

다음 단계로 진행된다.

1. CloudFormation용 S3를 생성하고, 템플릿을 이용하여 EC2를 생성한다(EC2, IAM 등 간편하게 생성)

2. 애플리케이션 업로드용 S3를 생성

3. S3에 애플리케이션 version1 업로드

4. CodeDeploy로 version1 배포

5. CodePipeline을 구축하여 version2 배포

5. CodePipeline 기능 정상 동작 테스트: version3 업로드 시, 자동 배포되는지 확인

 

 


1. S3를 생성한 뒤, CloudFormation 템플릿을 업로드한다.

>>S3 생성 후, 사용자 IAM 정책 및 권한 부여하기

  1. CF 템플릿 업로드 할 S3 Bucket 생성
  2. Region 내 KeyPair 생성 및 권한 변경
  3. 사용자 권한/역할/정책 부여

 

1. CF 템플릿 업로드용 S3 > Bucket > 생성하기

  • name: ysue-codepipeline
  • region: us-east-1(버지니아 북부)
  • 버킷 버전 관리: 활성화

 

2. Region 내 KeyPair 생성 및 권한 변경

>>us-east-1 리전 내 키페어 생성하기

>>키페어 저장 된 경로로 이동하여 권한 변경

chmod 400 ysue-cp-test.pem

>>현재 사용자와 리전 확인 및 변경

aws iam get-user
aws configure list
aws configure

 

3. 사용자 권한/역할/정책 생성 및 부여

>>Management console로 이동하여 사용자 권한/역할 확인

해당 user로 하여금 CF를 돌릴 수 있도록 IAM > 정책 > 정책 생성 > JSON > 정책 만들기

  • policy name: ysue-cp-policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "cloudformation:*",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "iam:*",
            "Resource": "*"
        },
        {
            "Action": "ec2:*",
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}

 

>>IAM > 사용자 선택 > 권한 추가 > 기존 정책 직접 연결 > ysue-cp-policy 선택 > 권한 추가 

 

기본 세팅 끝!!

 

 

 

1.(이어서) CloudFormation의 Template으로 EC2를 생성한다.

>>CF 템플릿 파일(CF_Template-test.json) 업로드하여 EC2 생성하기

CloudFormation을 사용하여 EC2을 생성해 보자(aws document참고). CF Template파일은 반드시 지정한 S3에 있어야 한다. CF가 S3를 참조하여 템플릿을 찾기 때문이다. 또한 템플릿 내 region, S3 name, keypair 등 정확한 정보를 입력 및 확인 후 스택을 생성한다.  

  **CF 템플릿에는 인스턴스 타입, 태깅, 키 페어, 인스턴스 접근을 위한 SSH Location, Mapping(Region) 정보 등을 담고 있다. 자세한 CF 템플릿 구조확인하기.

/* AWS 공식 Document 예시 참고 */
{
  "AWSTemplateFormatVersion" : "2010-09-09",

  "Description" : "AWS CloudFormation sample template LAMP_Single_Instance: Create a LAMP stack using a single EC2 instance and a local MySQL database for storage. This template demonstrates using the AWS CloudFormation bootstrap scripts to install the packages and files necessary to deploy the Apache web server, PHP, and MySQL at instance launch time. **WARNING** This template creates an Amazon EC2 instance. You will be billed for the AWS resources used if you create a stack from this template.",

  "Parameters" : {
    "KeyName": {
      "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instance",
      "Type": "AWS::EC2::KeyPair::KeyName",
      "ConstraintDescription" : "Can contain only ASCII characters."
    },  
    "InstanceType" : {
      "Description" : "WebServer EC2 instance type",
      "Type" : "String",
      "Default" : "t2.small",
      "AllowedValues" : [ 
        "t2.micro", 
      ],
      "ConstraintDescription" : "must be a valid EC2 instance type."
    },
    "SSHLocation" : {
      "Description" : "The IP address range that can be used to SSH to the EC2 instances",
      "Type": "String",
      "MinLength": "9",
      "MaxLength": "18",
      "Default": "0.0.0.0/0",
      "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
      "ConstraintDescription": "Must be a valid IP CIDR range of the form x.x.x.x/x"
    } 
  },

      
  "Mappings" : {
    "AWSInstanceType2Arch" : {
      "t2.micro"    : { "Arch" : "HVM64"  },
    },

    "AWSRegionArch2AMI" : {
      "us-east-1"        : {"HVM64" : "ami-0ff8a91507f77f867", "HVMG2" : "ami-0a584ac55a7631c0c"},
      "us-west-2"        : {"HVM64" : "ami-a0cfeed8", "HVMG2" : "ami-0e09505bc235aa82d"},
      "us-west-1"        : {"HVM64" : "ami-0bdb828fd58c52235", "HVMG2" : "ami-066ee5fd4a9ef77f1"},
      "eu-west-1"        : {"HVM64" : "ami-047bb4163c506cd98", "HVMG2" : "ami-0a7c483d527806435"},
      "eu-west-2"        : {"HVM64" : "ami-f976839e", "HVMG2" : "NOT_SUPPORTED"},
      "eu-west-3"        : {"HVM64" : "ami-0ebc281c20e89ba4b", "HVMG2" : "NOT_SUPPORTED"},
      "eu-central-1"     : {"HVM64" : "ami-0233214e13e500f77", "HVMG2" : "ami-06223d46a6d0661c7"},
      "ap-northeast-1"   : {"HVM64" : "ami-06cd52961ce9f0d85", "HVMG2" : "ami-053cdd503598e4a9d"},
      "ap-northeast-2"   : {"HVM64" : "ami-0a10b2721688ce9d2", "HVMG2" : "NOT_SUPPORTED"},
      "ap-northeast-3"   : {"HVM64" : "ami-0d98120a9fb693f07", "HVMG2" : "NOT_SUPPORTED"},
      "ap-southeast-1"   : {"HVM64" : "ami-08569b978cc4dfa10", "HVMG2" : "ami-0be9df32ae9f92309"},
      "ap-southeast-2"   : {"HVM64" : "ami-09b42976632b27e9b", "HVMG2" : "ami-0a9ce9fecc3d1daf8"},
      "ap-south-1"       : {"HVM64" : "ami-0912f71e06545ad88", "HVMG2" : "ami-097b15e89dbdcfcf4"},
      "us-east-2"        : {"HVM64" : "ami-0b59bfac6be064b78", "HVMG2" : "NOT_SUPPORTED"},
      "ca-central-1"     : {"HVM64" : "ami-0b18956f", "HVMG2" : "NOT_SUPPORTED"},
      "sa-east-1"        : {"HVM64" : "ami-07b14488da8ea02a0", "HVMG2" : "NOT_SUPPORTED"},
      "cn-north-1"       : {"HVM64" : "ami-0a4eaf6c4454eda75", "HVMG2" : "NOT_SUPPORTED"},
      "cn-northwest-1"   : {"HVM64" : "ami-6b6a7d09", "HVMG2" : "NOT_SUPPORTED"}
    }
  },

  "Resources" : {

    "WebServerInstance": {
      "Type": "AWS::EC2::Instance",
      "Properties": {
        "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
                          { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
        "InstanceType"   : { "Ref" : "InstanceType" },
        "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
        "KeyName"        : { "Ref" : "KeyName" }
      }
    },
    "WebServerSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Enable HTTP access via port 80",
        "SecurityGroupIngress" : [
          {"IpProtocol" : "tcp", "FromPort" : 80, "ToPort" : 80, "CidrIp" : "0.0.0.0/0"},
          {"IpProtocol" : "tcp", "FromPort" : 22, "ToPort" : 22, "CidrIp" : { "Ref" : "SSHLocation"}}
        ]
      }
    }
  },

  "Outputs" : {
    "WebsiteURL" : {
      "Description" : "URL for newly created LAMP stack",
      "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServerInstance", "PublicDnsName" ]}]] }
    }
  }
}

 

>>터미널에서 S3 Bucket 설정

  • --template-url: CF용으로 생성한 S3의 객체 url 입력(S3 name: ysue-codepipeline)
  • ParameterKey=KeyPairName,ParameterValue: 생성한 키페어 입력
aws cloudformation create-stack --stack-name CodeDeployDemoStack \
--template-url https://ysue-codepipeline.s3.amazonaws.com/CF_Template-test.json \
--parameters ParameterKey=InstanceCount,ParameterValue=1 \
ParameterKey=InstanceType,ParameterValue=t2.micro \
ParameterKey=KeyPairName,ParameterValue=ysue-cp-test \
ParameterKey=OperatingSystem,ParameterValue=Linux \
ParameterKey=SSHLocation,ParameterValue=0.0.0.0/0 \
ParameterKey=TagKey,ParameterValue=Name \
ParameterKey=TagValue,ParameterValue=CodeDeployDemo \
--capabilities CAPABILITY_IAM

>>실행

>>StackId 뜨면 스택 정상 생성 중

 

>>CloudFormation 스택 생성 후 상태 확인(공식문서 참고)

  • CREATE_COMPLETE
  • CREATE_IN_PROGRESS
  • CREATE_FAILED
  • DELET_COMPLETE
  • DELETE_FAILED
  • ROLLBACK_COMPLETE
  • etc
aws cloudformation describe-stacks --stack-name CodeDeployDemoStack --query "Stacks[0].StackStatus" --output text

 

 

 

2. 애플리케이션 업로드용 S3를 생성한다.

>>Management console에서 S3 버킷(애플리케이션 파일 업로드용) 생성하기

  • name: ysue-code-pipeline-app
  • region: us-east-1
  • bucket version 관리 활성화 필수(다른 버전의 어플리케이션 업로드를 허용하고, 변화를 codepipeline이 감지하기 위해 활성화)

 

 

 

 

3. S3에 애플리케이션 version1을 업로드한다.

>>생성된 버킷에 version1 업로드하기(mywebapp.zip)

 

>>매니지먼트 콘솔에서 실행 중 EC2 > Pulic IP 복사 > 터미널로 가기 > 키페어가 들어가 있는 디렉터리로 이동 

 

 

>>CF로 만든 EC2에 CodeDeploy가 정상 설치되어 있는지 확인 후, EC2 접속하기

ssh -i "ysue-cp-test.pem" ec2-user@EC2 Public IP입력

 

>>CodeDeploy정상 동작 확인

sudo service codedeploy-agent status

 

 

 

4. CodeDeploy로 version1을 배포한다.

>>S3에 업로드한 애플리케이션 version1을 CodeDeploy를 사용하여 배포

Management console > CodeDeploy > 배포 > 시작하기 >애플리케이션 생성

  • 어플리케이션 이름: mywebapp
  • 컴퓨팅 플랫폼: EC2/온프레미스 

 

 

>>애플리케이션 배포 그룹 생성하기

  • 배포 그룹 이름: ysue-deploy-group
  • 서비스 역할: codedeployROLE(CodeDeploy 실습 때 만들어놓은 role 사용)
  • 배포 유형: 현재 위치
  • 환경 구성: EC2 인스턴스(어떤 인스턴스가 배포 그룹 안으로 들어올지 세팅)-태그 그룹(EC2 내 태그 정보 확인 후 선택)
  • 배포 설정 및 로드밸런서 선택: CodeDeployDefaultAllAtOnce/비활성화

 

>>배포 그룹 생성 결과 확인

 

 

>>배포 생성하기(S3에 애플리케이션. zip 파일 업로드 후, CodeDeploy로 수동 배포 테스트)

 

 

>>애플리케이션 version1 CodeDeploy 배포 결과 확인: EC2의 public IP로 접속 시도(version1)

 

 

 

5. CodePipeline을 구축하여 version2를 배포한다.

 CodePipeline 구축 시 배포 공급자를 CodeDeploy로 설정한 뒤, 애플리케이션이 업로드 되는 S3의 어플리케이션 파일명을 지정하여 CloudWatch가 모니터링한다. CloudWatch가 변화를 감지하면, 자동으로 CodeDeploy를 실행시켜 지정한 S3 내 애플리케이션을 자동 배포하는 파이프라인을 구축해 보자. 

 

>>S3에 version2 업로드 후, CodePipeline을 생성한다. 

 

>>파이프라인 생성하기

  • name: ysue-code-pipeline
  • 서비스 역할: 새 서비스 역할
  • 역할 이름: 자동완성

 

>>소스 스테이지

  • 소스 공급자: Amazon S3
  • 버킷: ysue-code-pipeline-app(애플리케이션 파일이 업로드 되는 버킷이름)
  • S3 객체 키: mywebapp.zip(버킷 내 업로드 되는 어플리케이션 파일 명)
  • 변경 감지 옵션: CloudWatch 권장(S3 버킷에 mywebapp.zip 파일이 업로드될 경우, 배포를 자동화시킨다는 의미)

 

>>빌드 스테이지 추가(본 실습에서는 건너뛰기)

>>배포 스테이지 추가

  • 배포 공급자: AWS CodeDeploy(CodeDeploy로 배포할 것)
  • 리전: us-east-1
  • 애플리케이션 이름: mywebapp
  • 배포 그룹: ysue-deploy-group

 

>>검토 후 파이프라인 생성(시간 소요됨)

 

 

>>EC2 public IP로 접속, 새로고침 하면 version2가 CodeDeploy 배포 생성 없이 자동 배포 된 것을 확인할 수 있음

 

 

 

 

6. CodePipelin 기능 정상 동작 테스트: version3 업로드 시, 자동 배포되는지 확인

>>S3에 업로드한 애플리케이션 version1을 CodeDeploy를 사용하여 배포

Management console > CodeDeploy > 배포 > 시작하기 > 애플리케이션 생성

 

정상 구축되었다면 version3을 S3에 업로드 시, 별도의 배포 작업을 거치지 않고도 배포결과를 확인할 수 있어야 한다.

>>S3에 업로드 후, CodeDeploy로 가면 CloudWatch가 지정한 S3버킷의 파일 변화를 자동으로 감지하여 릴리스 중인 것을 확인 할 수 있다. 

 

 

>>페이지 결과: version3 자동 배포

 

>>개발자도구> CodeDeploy > 배포 > 배포내역 

배포 히스토리를 확인할 수 있다.

 

 

 

이로써 CodeDeploy를 배포 공급자로 세팅한 CodePipeline 기능 구현 실습을 끝내보았다. 모든 자원은 반드시 삭제하기 바란다. 간단한 실습으로 EC2를 통한 CI/CD를 실습해 보았지만, 실제 기업에서 구축하고 운영하는 클라우드 서비스들은 MSA로 구축되어 있다. 추후 포스팅에서는 AWS CDK를 사용하여 마이크로서비스를 위한 CI/CD 파이프라인과 ECS 클러스터 자동 구축 실습을 다뤄보겠다. 추가로 테라폼을 이용한 IaC로 구축 및 자동화 실습 또한 고려 중이다. 

 

 

 

 

 

 

 

 

 

https://docs.aws.amazon.com/ko_kr/prescriptive-guidance/latest/patterns/automatically-build-ci-cd-pipelines-and-amazon-ecs-clusters-for-microservices-using-aws-cdk.html

https://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/using-cfn-describing-stacks.html

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-guide.html

https://www.inflearn.com/users/@zeus0510