CI/CD 과정을 구성하다보면 CodeBuild라는 과정이 필요해지는데요. 소스를 작성하고 코드를 실제로 배포하기 전에 빌드 즉, 실제 환경에서 잘 돌아가는지 먼저 테스트해보는 과정이라고 할 수 있겠습니다.
소규모 프로젝트의 경우에는 빌드 과정을 생략해도 무방하나 서비스가 커지고 안정성이 중요해지는 상용 프로젝트의 경우에는 빌드 과정에서 먼저 검증을 하는 것이 무엇보다 중요해집니다.
저희는 AWS CodeBuild를 통해 이 과정을 해보려고 합니다.
CodeBuild를 검색해서 들어가셔도 좋지만 저희는 기본적으로 codepipeline를 활용해서 진행하기 때문에 이 codepipeline의 진행화면에서 프로젝트 생성을 통해 진행하겠습니다.
새로 뜬 창에 [프로젝트명]-codebuild-stage-v1나 [프로젝트명]-codebuild-prod-v1로 이름을 지어줍시다. 추가 구성은 건드리지 않을꺼예요.
저희는 codepipeline의 연장선으로 구현하기 때문에 이 부분이 따로 설정하지 않겠습니다. 따로 설정하려고 하는 분들은 CI/CD codepipeline으로 구성하기 게시글의 소스 추가 부분을 보시면 됩니다.
Amazon Linux와 Ubuntu가 있는데 따로 커스텀하거나 오류에 대한 커뮤니티, 유연성을 원하시는 경우 Ubuntu를 선택하시는게 더 좋습니다.
Amazon Linux의 경우는 Amazon에서 직접 관리하기 때문에 최적화와 빌드되기까지의 시간이 적게 걸리고 보안적인 측면에서 강력함을 보입니다. 예제에서는 이 Amazon Linux로 구성할 예정입니다.
런타임은 Standard밖에 없으므로 넘어갑니다.
이미지는 가장 최신으로 사용하고 이미지 버전 역시 가장 최신 이미지 사용 세팅을 하겠습니다.
운영을 하면서 역할을 따로따로 나눠서 분류해놓는게 더 좋기 때문에 [프로젝트명]-codebuild-service-role 이런 식으로 짓는 것이 좋습니다.
여기서 입력한 서비스 역할 명을 기억해주세요. 나중에 역할에 정책들을 추가해주어야합니다.
자동 재시도 제한 횟수는 기본적으로 저는 3번으로 설정하는 편입니다.
나머지 제한 시간은 건들지 않구요
도커로 따로 빌드해서 구성하시는 경우 권한이 있음 부분을 무조건 체크해주셔야합니다.
인증서를 사용하실 분들은 버킷에서 인증서를 불러오시구요 아닌 경우는 설치 안함 옵션을 선택해줍니다.
접속할 VPC를 선택하셔도 됩니다. VPC를 선택하시면 그에 맞는 인터넷과 연결된 서브넷, 보안 그룹을 설정하시고 VPC 설정 검증 버튼을 누르셔서 실제로 연결이 되는지 확인해주세요.
컴퓨팅은 현재 빌드할 프로젝트 규모에 맞게 선택해주세요
환경 변수는 빌드할때 프로젝트 상에서 필요한 env들의 값들을 여기에 입력해주어야 합니다. 예를 들어 AWS의 자격 증명이라든지 DB나 env 파일에 있는 부분들을 입력해주시면 됩니다.
유형에 일반 텍스트, 파라미터, Secrets Manager가 있는데 무조건 Secrets Manager
로 입력하셔야 됩니다. 일반 텍스트나 파라미터는 노출될 확률이 있기 때문에 Secrets Manager로 설정해주셔야 안전합니다.
파일 시스템의 경우 넘어가겠습니다.
buildsepc.yml 파일을 올릴 프로젝트의 루트 디렉토리에 생성해서 작성해줍니다.
저 같은 경우는 node 20, nest 10 버전을 사용중이고 그에 맞는 빌드 세팅을 합니다.
buildspec 파일의 버전입니다. AWS에서는 현재 0.2 버전을 사용합니다.
install:
runtime-versions: 사용할 Node.js 버전 지정합니다.
commands: 글로벌 NestJS CLI 설치 및 프로젝트 의존성 설치를 진행해주구요
pre_build:
commands: 린트 검사 및 테스트 실행을 거칩니다.
build:
commands: 애플리케이션 빌드합니다.
post_build:
commands: 빌드 완료 메시지를 출력합니다.
files: 배포할 파일 패턴 지정해줍니다.
base-directory: 아티팩트의 기본 디렉토리 (dist 폴더) 저는 nodejs이기 때문에 dist에 지정해주시구요
discard-paths: 경로를 무시하고 파일만 포함옵션입니다.
paths: 캐시할 경로 지정 (node_modules).
캐시를 하게 되면 다음에 node_modules을 전부 올리는 게 아니라 속도가 더 빨라집니다.
version: 0.2
phases:
install:
runtime-versions:
nodejs: 20
commands:
- echo "Installing global dependencies..."
- npm install -g @nestjs/cli
- echo "Installing project dependencies..."
- npm install
pre_build:
commands:
- echo "Running lint checks..."
- npm run lint
- echo "Running tests..."
- npm run test -- --watch=false --coverage
build:
commands:
- echo "Building the NestJS application..."
- npm run build
post_build:
commands:
- echo "Build completed on `date`"
artifacts:
files:
- '**/*'
base-directory: dist
discard-paths: yes
cache:
paths:
- 'node_modules/**/*'
로그는 선택사항이긴 하지만 하시는게 어떤 부분에서 에러가 났고 반려됬는지 파악하기 좋아 하시는 걸 추천드립니다.
그 후 CodePipeline으로 계속을 눌러줍시다.
저희는 이제 IAM을 통해서 필요한 권한들을 추가해줄 예정입니다.
새창을 열고 IAM를 검색해줍니다.
IAM이란? 권한을 관리하는 곳인데 아무래도 보안이 중요한 서비스가 AWS입니다. 해킹 당했을 시 위험도 있고 어느 서비스에서는 접근이 가능하고 어느 서비스에서는 접근이 불가능하게 하거나 계정 별로 권한을 따로 넣어서 관리하기도 합니다.
그다음 역할을 클릭하세요
그 후 아까 생성한 [프로젝트명]-codebuild-service-role의 이름을 찾습니다.
권한 추가를 해서 필요한 권한들을 찾아서 추가해주어야 합니다.
저랑 똑같이 진행하셨다면 기본적으로 설정된 권한이 3개정도 있을겁니다.
저희가 구성해야 되는 권한은
CodeBuild에 관한 권한과 CodePipeline과 관련된 권한, SecretsManager를 이용했기 때문에 SecretsManager을 읽는 권한, CloudWatch에 관한 권한을 기본적으로 탑재해야합니다.
AWSCodeBuildDeveloperAccess
: CodeBuild의 개발자 풀접근 권한입니다.AmazonS3ReadOnlyAccess
: S3에 접근해서 파일을 읽기 위한 권한입니다.AWSCodePipeline_ReadOnlyAccess
: codePipeline의 읽기 권한입니다.AmazonEC2ContainerRegistryReadOnly
: 도커로 구성했을 경우 필요한 권한입니다.(저희 예제에서는 필요 없습니다.)SecretsManagerReadWrite
: SecretsManager을 읽는 권한입니다.AWS에서 부여한 권한을 복사 해주시고 지워주세요
위에 필요한 권한을 부여한 뒤 확인합니다.
권한을 그대로 쓸지 아니면 커스텀할지 나눠는데요 그대로 쓰셔도 무방하긴 하지만 권한은 최소 권한만 부여하는 게 좋기 때문에 커스텀하는 걸 추천드립니다.
권한 추가의 인라인 정책 생성을 클릭해준 뒤 JSON을 눌러 정책 편집기를 열어줍시다.
그 후 복사 해놓은 파일을 아래와 같은 형식으로 맞춰서 바꿔주세요.
아래 코드를 복사 해주시고 기존에 복사했던 정책들에서 ex) 부분 양식에 맞춰 넣어주세요 ex) 부분을 제외하고 나머지를 입력해주셔야합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::codepipeline-ap-northeast-2-*",
"arn:aws:s3:::codepipeline-ap-northeast-2-*/*"
]
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogStreams"
],
"Resource": [
"ex) arn:aws:logs:ap-northeast-2:블라블라:log-group:/aws/codebuild/test-codebuild-stage-v1"
"[기존 생성된 권한의 log-group이 써져 있는 부분]",
"[기존 생성된 권한의 log-group이 써져 있는 부분:*]"
]
},
{
"Effect": "Allow",
"Action": [
"codebuild:StartBuild",
"codebuild:BatchGetBuilds",
"codebuild:BatchGetProjects",
"codebuild:RetryBuild",
"codebuild:CreateReportGroup",
"codebuild:CreateReport",
"codebuild:UpdateReport",
"codebuild:BatchPutTestCases",
"codebuild:BatchPutCodeCoverages"
],
"Resource": [
"ex) ex) arn:aws:codebuild:ap-northeast-2:블라블라:project/test-codebuild-stage-v1"
"[기존 생성된 권한의 codebuild이 써져 있는 부분]",
"[기존 생성된 권한의 codebuild이 써져 있는 부분-*]"
]
},
{
"Effect": "Allow",
"Action": [
"elasticbeanstalk:CreateApplicationVersion",
"elasticbeanstalk:UpdateEnvironment",
"elasticbeanstalk:DescribeApplications",
"elasticbeanstalk:DescribeEnvironments",
"elasticbeanstalk:DescribeApplicationVersions",
"elasticbeanstalk:ListAvailableSolutionStacks"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": [
"ex) arn:aws:secretsmanager:ap-northeast-2:블라블라:secret:/CodeBuild/*"
"[기존 생성된 권한의 secretsmanager 써져 있는 부분]"
]
}
]
}
자 이제 CodeBuild를 사용하기 위한 단계가 끝났습니다.
나머지는 이 게시글을 참고 하시면 되겠습니다. CI/CD codepipeline으로 구성하기
틀린 점이 있다면 알려주시면 감사하겠습니다.
정성글 개추드립니다