AWS CodePipeline을 이용하여 정적 웹 사이트를 S3에 배포
AWS CodePipeline을 이용하여 정적 웹 사이트를 S3에 배포
- CodePipeline이란?
소프트웨어 릴리스에 필요한 단계를 모델링, 시각화 및 자동화하는 데 사용할 수 있는 지속적 전달하는 서비스로, 릴리스 프로세스의 여러 단계를 신속하게 모델링하고 구성할 뿐 아니라 소프트웨어 변경 사항을 지속적으로 릴리스하는 데 필요한 단계를 자동화합니다.
- S3란?
최고의 확장성, 데이터 가용성, 보안 및 성능을 제공하는 객체 스토리지 서비스로, 데이터 레이크, 웹사이트, 모바일 애플리케이션, 백업 및 복원, 아카이브, 엔터프라이즈 애플리케이션, IoT 디바이스, 빅 데이터 분석 등 다양한 사용 사례에서 원하는 양의 데이터를 저장할 뿐 아니라 보호합니다.
# TL;DR
CloudFormation 템플릿을 활용하여 CodePipeline과 S3 서비스 구축하여 정적 웹 사이트를 배포합니다.
웹사이트 호스트 설정을 한 S3 Bucket을 Management console 상에서 미리 생성한 후에 진행합니다.
GitHub 리포지토리와 CodePipeline과 연동한 후에 git push, merge 를 계기로 vue.js 소스코드를 빌드하여 S3 bucket에 배포합니다.
buildspec.yml을 이용하여 CodeBuild를 정의하며. Cloudformation템플릿으로 CodePipeline.yml을 작성하여 CodePipeline을 정의합니다.
서비스 구축은 아래와 같은 순서로 진행합니다.
- CodePipeline 구축 순서
- Codebuild에서 수행할 작업을 정의하는 buildspec.yml 작성
- Cloudformation템플릿(CodePipeline.yml)의 파라미터를 정의한 Parameters.json 작성
- CodePipeline을 구성하기 위한 Cloudformation템플릿(CodePipeline.yml) 작성
- AWS CLI로 CloudFormation 스택 생성
- CodePipeline 실행 테스트
- AWS CLI로 CloudFormation 스택 삭제
# 아키텍처 다이어그램
- GitHub Repository의 소스 코드를 git clone, 빌드하여 S3 Bucket에 배포하는 다이어그램입니다.
- CodeBuild와 CodePipeline에서 S3 bucket에 엑세스하기 위하여 권한을 부여하는 IAM role이 필요합니다.
# 개요
CI/CD 파이프라인을 Codepipeline으로 구현하여 GitHub 리포지토리에 있는 소스 코드를 빌드하여 자동으로 S3 bucket으로 배포하는 서비스를 구축합니다.
서비스 | 역할 |
AWS CloudFormation | 스택 생성 |
AWS IAM | 액세스 권한 추가 |
AWS S3 | 콘텐츠 배치, 아티팩트 |
CodeBuild | 코드 빌드 |
CodeDeploy | 코드 배포 |
CodePipeline | CI/CD 파이프라인 구축 |
GitHub | 리포지토리 |
# Codebuild에서 실행하는 작업을 명시하는 buildspec.yml 작성
version: 0.2
phases:
install:
runtime-versions:
nodejs: 14
pre_build:
commands:
- echo cache clear
- npm cache clear --force
- echo npm install
- npm install
build:
commands:
- echo code build
- npm run build
artifacts:
files:
- "**/*"
base-directory: dist
- nodejs : 14 -> nodejs버전을 지정합니다.
- base-directory : dist -> 아티팩트의 base(root)를 빌드한 소스가 저장되는 dist 디렉토리로 지정하며 files: **/* 로 dist 디렉토리의 모든 파일을 아티팩터로 저장합니다. codedeploy에서 아티팩터에 저장된 빌드된 소스를 s3 bucket에 배포하기 위하여 필요합니다.
# GitHub와 CodePipeline을 연동
우선 AWS Management console에서 Create connection을 통해 GitHub와 CodePipeline을 연동하도록 설정합니다.
connection 생성한 후엔 ConnectionArn의 값을 메모하여 다음 cloudformation parameter 파일에 추가하도록 합니다.
- AWS management console을 통해 GitHub와 CodePipeline 연동하는 방법
https://docs.aws.amazon.com/dtconsole/latest/userguide/connections-create-github.html
# Cloudformation작성에 필요한 파라미터 파일 codepipeline.json 작성
[
{
"ParameterKey": "Env",
"ParameterValue": "dev"
},
{
"ParameterKey": "Branch",
"ParameterValue": "${git의 branch명}"
},
{
"ParameterKey": "Repository",
"ParameterValue": "${git의 리포지토리명}"
},
{
"ParameterKey": "AppBucketName",
"ParameterValue": "${정적웹사이트의 S3 bucket명}"
},
{
"ParameterKey": "GitConnectionArn",
"ParameterValue": "${ConnectionArn의 값}"
}
]
- Codepipeline과 연동할 git의 branch명, 리포지토리명, CodeConnetction Arn을 파라미터로 지정합니다.
- 미리 생성한 S3 bucket명을 파라미터로 지정합니다.
#CodePipeline을 구성하기 위한 Cloudformation 파일 (codepipeline.yml) 작성
AWSTemplateFormatVersion: "2010-09-09"
Description: CodePipeline S3 stack.
# ------------------------------------------------------------
# Parameter
# ------------------------------------------------------------
Parameters:
Env:
Type: String
Default: "dev"
Branch:
Type: String
Default: ""
Repository:
Type: String
Default: ""
AppBucketName:
Type: String
Default: ""
GitConnectionArn
Type: String
Default: ""
Resources:
# ------------------------------------------------------------
# Artifact용 S3 Bucket
# ------------------------------------------------------------
ArtifactBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${Env}-artifact
VersioningConfiguration:
Status: Enabled
# ------------------------------------------------------------
# CodeBuild
# ------------------------------------------------------------
CodeBuild:
Type: AWS::CodeBuild::Project
Properties:
Name: !Sub ${Env}-codebuild
Source:
BuildSpec: buildspec.yml
Type: CODEPIPELINE
Artifacts:
Name: !Sub ${Env}-codepipeline
Packaging: NONE
Type: CODEPIPELINE
Cache:
Type: NO_CACHE
# 환경설정
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/standard:5.0
ImagePullCredentialsType: CODEBUILD
PrivilegedMode: false
Type: LINUX_CONTAINER
ServiceRole: !GetAtt CodebuildServiceRole.Arn
TimeoutInMinutes: 60
QueuedTimeoutInMinutes: 480
BadgeEnabled: false
# 로그 설정
LogsConfig:
CloudWatchLogs:
Status: ENABLED
S3Logs:
Status: DISABLED
# ------------------------------------------------------------
# CodePipeline
# ------------------------------------------------------------
CodePipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
Name: !Sub ${Env}-pipeline
RoleArn: !GetAtt CodepipelineServiceRole.Arn
ArtifactStore:
Location: !Ref ArtifactBucket
Type: S3
Stages:
- Name: Source
Actions:
- Name: Source
ActionTypeId:
Category: Source
Owner: AWS
Provider: CodeStarSourceConnection
Version: "1"
Configuration:
# 브랜치 지정
BranchName: !Ref Branch
# github 연동
ConnectionArn:
- !Ref GitConnectionArn
# 리포지토리 지정
FullRepositoryId: !Ref Repository
OutputArtifactFormat: CODE_ZIP
OutputArtifacts:
- Name: SourceArtifact
Namespace: SourceVariables
RunOrder: 1
- Name: Build
Actions:
- Name: Build
ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: "1"
Configuration:
EnvironmentVariables: !Sub |
[
{"name":"STAGE","value":"dev","type":"PLAINTEXT"}
]
ProjectName: !Ref CodeBuild
InputArtifacts:
- Name: SourceArtifact
OutputArtifacts:
- Name: BuildArtifact
Namespace: BuildVariables
RunOrder: 1
- Name: Deploy
Actions:
- Name: Deploy
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: S3
Version: "1"
Configuration:
BucketName: !Ref AppBucketName
Extract: true
InputArtifacts:
- Name: BuildArtifact
Namespace: DeployVariables
RunOrder: 1
# ------------------------------------------------------------
# IAM
# ------------------------------------------------------------
#### CodeBuild Role 생성
CodebuildServiceRole:
Type: AWS::IAM::Role
Properties:
Path: /
RoleName: !Sub ${Env}-codebuild-service-role
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- codebuild.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: !Sub ${Env}-build-policy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Resource:
- !GetAtt LogGroup.Arn
Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- Resource:
- arn:aws:s3:::codepipeline-ap-northeast-2-*
- !Sub arn:aws:s3:::${ArtifactBucket}/
- !Sub arn:aws:s3:::${ArtifactBucket}/*
Effect: Allow
Action:
- s3:GetObject
- s3:PutObject
- s3:GetObjectVersion
- s3:GetBucketAcl
- s3:GetBucketLocation
- s3:List*
- Resource:
- !Ref ReportGroup
Effect: Allow
Action:
- codebuild:CreateReportGroup
- codebuild:CreateReport
- codebuild:UpdateReport
- codebuild:BatchPutTestCases
- codebuild:BatchPutCodeCoverages
### CodePipeline Role 생성
CodepipelineServiceRole:
Type: AWS::IAM::Role
Properties:
Path: /
RoleName: !Sub ${Env}-codepipeline-service-role
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- codepipeline.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: !Sub ${Env}-codepipeline-base-policy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Resource:
- "*"
Effect: Allow
Action:
- codedeploy:CreateDeployment
- codedeploy:GetApplicationRevision
- codedeploy:GetDeployment
- codedeploy:GetDeploymentConfig
- codedeploy:RegisterApplicationRevision
- Resource:
- "*"
Effect: Allow
Action:
- codestar-connections:UseConnection
- Resource:
- "*"
Effect: Allow
Action:
- s3:*
- Resource:
- "*"
Effect: Allow
Action:
- codebuild:BatchGetBuilds
- codebuild:StartBuild
- Resource: "*"
Effect: Allow
Action:
- servicecatalog:ListProvisioningArtifacts
- servicecatalog:CreateProvisioningArtifacts
- servicecatalog:DescribeProvisioningArtifacts
- servicecatalog:DeleteProvisioningArtifacts
- servicecatalog:UpdateProduct
# ------------------------------------------------------------
# log-group && report-group 생성
# ------------------------------------------------------------
LogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/codebuild/${Env}-codebuild
ReportGroup:
Type: AWS::CodeBuild::ReportGroup
Properties:
Name: !Sub ${Env}-report-group
Type: TEST
ExportConfig:
ExportConfigType: NO_EXPORT
- CodePipeline 아티팩트용 S3 Bucket을 생성합니다.
- Codepipleline과 CodeBuild에는 필요한 IAM role을 생성합니다.
- CodeBuild를 통해 소스 코드 빌드 시 에러 로그를 확인할 수 있도록 로그 그룹을 생성합니다.
# AWS CLI로 CloudFormation 스택 생성
# 스택생성
$ ENV=dev
$ aws cloudformation create-stack \
--stack-name "$ENV-stack" \
--template-body file://codepipeline.yml \
--parameters file://codepipeline.json \
--capabilities CAPABILITY_NAMED_IAM
- CloudFormation 스택 생성을 위한 AWS CLI는 위 내용과 같이 command를 실행합니다.
- --stack-name에는 생성되는 스택명, --template-body에는 cloudformation template명 , --parameters에는 파라미터의 json을 지정합니다.
- --capabilities의 경우 IAM role생성 시 필수로 적용해야 하는 옵션입니다.
# CodePipeline 실행 테스트
Codepipeline 실행 성공 여부는 Management console의 Codepipeline의 Pipelines에서 확인합니다.
- Git 리포지토리에 있는 소드 코드가 문제없이 성공적으로 업데이트된 화면입니다.
- CodeBuild를 실행된 화면입니다.
- 빌드된 소스 코드가 S3 bucket에 성공적으로 배포된 화면입니다.
# AWS CLI로 CloudFormation 스택 삭제
# 스택삭제
$ ENV=dev
$ aws cloudformation delete-stack --stack-name "$ENV-stack"
- CloudFormation 스택 삭제를 위한 AWS CLI는 상기 command로 삭제합니다.
# 요약
- CodePipeline을 활용하면 CI/CD 파이프라인을 쉽게 구축하는 것이 가능합니다.
- CodePipeline을 사용하면 소스 코드가 업데이트될 때마다 자동으로 빌드하고 배포시킬 수 있게 됩니다.
- CloudFormation을 활용하면 빠르게 AWS Service를 구축할 수 있어 유용합니다.
# 참고 공식문서
- S3 Bucket 생성
https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/create-bucket-overview.html
버킷 생성 - Amazon Simple Storage Service
객체 잠금을 사용하는 버킷을 생성하려면 s3:CreateBucket, s3:PutBucketVersioning 및 s3:PutBucketObjectLockConfiguration 권한이 있어야 합니다.
docs.aws.amazon.com
- GitHub 연동 콘솔활용
https://docs.aws.amazon.com/ko_kr/codepipeline/latest/userguide/connections-github.html
GitHub 연결 - AWS CodePipeline
AWS CLI 또는 AWS CloudFormation을 통해 생성된 연결은 기본적으로 PENDING 상태입니다. CLI 또는 AWS CloudFormation을 사용하여 연결을 생성한 후 콘솔을 통해 연결을 편집하여 상태를 AVAILABLE로 설정합니다.
docs.aws.amazon.com
- CodePipeline CodestarConnetion 참고
CodeStarSourceConnection for Bitbucket Cloud, GitHub, GitHub Enterprise Server, GitLab.com, and GitLab self-managed actions - AW
This feature is not available in the Asia Pacific (Hong Kong), Asia Pacific (Hyderabad), Asia Pacific (Jakarta), Asia Pacific (Melbourne), Asia Pacific (Osaka), Africa (Cape Town), Middle East (Bahrain), Middle East (UAE), Europe (Spain), Europe (Zurich),
docs.aws.amazon.com