[학습 목표]
배포 자동화에 정의와 이점에 대해 설명할 수 있다.
배포 파이프라인이 무엇인지 정의할 수 있다.
파이프라인을 구성하는 단계(Stages)와 작업(Actions)에 대해 설명할 수 있다.
AWS 개발자 도구를 활용하여 파이프라인을 구축할 수 있다.
배포 자동화 파이프라인 구축 과정에서 문제가 발생할 경우, log 파일과 공식 문서를 통해 해결할 수 있다.
AWS에서 제공하는 IAM 서비스를 이해하고 사용할 수 있다.
그룹, 사용자, 정책, 역할의 차이점과 특징에 대해서 이해할 수 있다.
IAM 정책에 대해 이해하고 특정 주체에게 권한을 부여할 수 있다.
IAM 보안 모범 사례에 대해 찾아보고, 서비스를 이용하며 적용할 수 있다
[배포 자동화]
한 번의 클릭 또는 명령어 입력을 통해 전체 배포 과정을 자동으로 진행하는 것
수동적이고 반복적인 배포 과정을 자동화 -> 시간 절약
Human Error 방지 (수동적으로 배포시 생기는 실수)
[배포 자동화 파이프라인]
파이프라인 : 소스 코드의 관리부터 실제 서비스의 배포 과정을 연결하는 구조.
전체 배포 과정을 여러 단계(Stage)로 분리. 순차적으로 실행. 가변적
Source Stage -------------------------> Build Stage ---------------------------> Deploy Stage
버전 컨트롤 도구를 이용한 코드 컴파일링 변경 사항 실시간 반영
소스코드 관리 및 전달 유닛 테스트 서비스 업데이트
(변경 감지) (컴파일, 빌드, 테스트, 가공) (실제 서비스에 반영)
[AWS 개발자 도구]
개발자 도구 섹션으로 배포 자동화 파이프라인 구축 가능
CodeCommit : Source 단계 구성시 이용. 버전 관리 도구.
CodeBuild : Build 단계시 이용. 빌드 단계에서 필수적으로 실행되어야 할 작업들(유닛테슽, 컴파일, 빌드 등) 명령어로 실행.
CodeDeploy : 실시간 변경 사항 전달 가능
CodePipeline : AWS 프리티어 계정 사용 시 한 계정에 두 개 이상의 파이프라인 생성시 추가 요금 부과

신뢰관계 명시시 access 할 수 있는 서비스 확실하게 완성됨
[서버 배포자동화 파이프라인 순서]
CodePipeline으로 파이프라인 구축
Source 단계에서 GitHub 리포지토리 연결
Build 단계에서 CodeBuild 이용해 EC2 인스턴스로 빌드된 파일 전달
Deploy 단계에서 CodeDeploy 서비스 이용해서 EC2 인스턴스에 변경사항 실시간으로 반영
EC2 인스턴스에 java 설치
$ sudo apt update
$ sudo apt install openjdk-11-jre-headless // -> Y
$ java -version // 설치 완료시 자바 버전 확인 가능
EC2 인스턴스에 AWS CLI 설치
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ sudo apt install unzip
$ unzip awscliv2.zip
$ sudo ./aws/install
$ aws --version // 설치 완료시 버전 확인 가능
EC2 인스턴스에 CodeDeploy Agent 설치
$ sudo apt update
$ sudo apt install ruby-full
$ sudo apt install wget
$ cd /home/ubuntu
$ sudo wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
$ sudo chmod +x ./install
$ sudo ./install auto > /tmp/logfile
$ sudo service codedeploy-agent status // 설치 완료시 active(running) 문구 확인 가능
[EC2 인스턴스 역할 부여]
인스턴스에서 Key - Value 값 확인
IAM 역할 권한 추가 : 권한추가 -> 정책연결 -> AmazonS3FullAccess, AmazonEC2RoleforAWSCodeDeploy, AWSCodeDeployRole, AmazonSSMFullAccess 선택 후 정책 연결 클릭
신뢰 관계 : 신뢰 관계 편집 -> Service에 ["ec2.amazonaws.com", "codedeploy.ap-northeast-2.amazonaws.com" ] 추가
[EC2 활용한 파이프라인 구축]
로컬 환경의 'be-sprint-deployment/DeployServer' 경로에 appspec.yml 파일을 추가
(appspec.yml : 배포 자동화 도와주는 CodeDeploy-Agent가 인식하는 파일)
appspec.yml
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/build
hooks:
BeforeInstall:
- location: server_clear.sh
timeout: 3000
runas: root
AfterInstall:
- location: initialize.sh
timeout: 3000
runas: root
ApplicationStart:
- location: server_start.sh
timeout: 3000
runas: root
ApplicationStop:
- location: server_stop.sh
timeout: 3000
runas: root
로컬 환경의 'be-sprint-deployment/DeployServer' 경로에 buildspec.yml 파일을 추가
(buildspec.yml : 배포 자동화에서 빌드 담당하는 CodeBuild-Agent가 인식하는 파일)
buildspec.yml
version: 0.2
phases:
install:
runtime-versions:
java: corretto11
build:
commands:
- echo Build Starting on `date`
- cd DeployServer
- chmod +x ./gradlew
- ./gradlew build
post_build:
commands:
- echo $(basename ./DeployServer/build/libs/*.jar)
artifacts:
files:
- DeployServer/build/libs/*.jar
- DeployServer/scripts/**
- DeployServer/appspec.yml
discard-paths: yes
로컬 환경의 'be-sprint-deployment/DeployServer' 경로에 scripts 디렉토리 생성
그 안에 initialize.sh, server_clear.sh, server_start.sh, server_stop.sh 총 4개 파일 생성
(appspec.yml 파일이 구성하는 배포 수명 주기에 따라 실행될 예정)
initialize.sh
#!/usr/bin/env bash
chmod +x /home/ubuntu/build/**
server_clear.sh
#!/usr/bin/env bash
rm -rf /home/ubuntu/build
server_start.sh
#!/usr/bin/env bash
cd /home/ubuntu/build
sudo nohup java -jar DeployServer-0.0.1-SNAPSHOT.jar > /dev/null 2> /dev/null < /dev/null &
server_stop.sh
#!/usr/bin/env bash
sudo pkill -f 'java -jar'
모든 파일 저장 후 github에 commit, 이후 main으로 push
AWS CodeDeploy -> 애플리케이션 -> 애플리케이션 생성 -> 배포 그룹 생성
AWS CodePipeline -> 파이프라인 생성 -> 소스 스테이지 (GitHub 2) -> GitHub 연결
AWS CodeBuild -> 프로젝트 생성 (운영체제 : Linux2, 런타임 : Standard, 이미지 : 86_64-standart:3.0) -> Buildspec 에 "DeployServer/buildspec.yml" 작성 -> CodePipeline으로 계속
AWS CodePipeline-> 배포 스테이지 (공급자 : AWS CodeDeploy, 리전 : 서울) -> 파이프라인 생성
파이프라인 생성 동시에 소스 코드 배포 자동으로 실행

deploy 스테이지에서 실패시 로그 확인
: EC2 인스턴스에서 'cd /opt/codedeploy-agent/deployment-root/deployment-logs' 이동 후 ls
nano codedeploy-agent-deployments.log
// stderr : standard error, stdout : standard output
[서버 환경 변수 설정]
비밀번호와 같은 민감한 정보는 Parameter Store에서 관리 가능
Parameter Store -> 파라미터 생성
이름 : /prefix/name/key 값 순으로 네이밍 규칙에 맞게 작성해야!
(ex : /spring-boot-aws/be-112-codinginfant/spring.datasource.url)
값 : application.properties 파일 내 주석 해제하고 더미값 작성. {...} 이 부분 삭제하고 내 것 쓰면 됨.
username은 어제 설정한 admin으로, password는 db 비번을 작성
(ex. spring.datasource.url의 경우
jdbc:mysql://rds엔드포인트주소/test?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC)
spring.jpa.database=mysql
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.datasource.url=jdbc:mysql://{AWS RDS Endpoint}/test?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username={RDS Mysql Admin id}
spring.datasource.password={RDS Mysql Admin password}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
config.domain={AWS S3 Endpoint}
spring.datasource.url, spring.datasource.username, spring.datasource.password, config.domain 총 네 파일 반복해서 각 파라미터 작성
로컬 환경에서 소스 코드인 'be-sprint-deployment'의 build.gradle 파일 수정
build.gradle
plugins {
id 'org.springframework.boot' version '2.5.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.codestates.seb'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web',
'io.jsonwebtoken:jjwt-api:0.11.2'
implementation 'org.springframework.cloud:spring-cloud-starter-aws-parameter-store-config'
implementation 'junit:junit:4.13.1'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.2',
'io.jsonwebtoken:jjwt-jackson:0.11.2'
compileOnly "com.fasterxml.jackson.core:jackson-databind:2.9.4"
compileOnly 'org.projectlombok:lombok'
compileOnly "org.springframework.boot:spring-boot-starter-security"
runtimeOnly 'mysql:mysql-connector-java'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-starter-parent:Hoxton.SR12"
}
}
test {
useJUnitPlatform()
}
src/main/resources/bootstrap.yml 파일 생성
aws:
paramstore:
enabled: true
prefix: /spring-boot-aws
name: be-112-codinginfant
profileSeparator: _
src/main/resources/application.properties 파일 확인 : 변수 이름, 파라미터 확인. 다를 경우 수정 후 저장 -> commit -> main으로 push

[오늘의 에러 파티]

자꾸 이런 에러가 떠서 페어 프로그램을 제대로 하지 못했다
에러코드도 구글링 해보고 다른 동기분들 보면서 찾아봤는데도 2시간을 잡아먹었다
내 실수 원인은
첫째, 어제까지 만들어 놓은 인스턴스의 파일들을 지우지 않았었고
둘째, 그로 인한 에러 코드가 나는 와중에 안일하게 생각하고 넘어가서 파이프라인을 설정하다가 꺼버렸던 것이다
파이프라인을 설정하는 도중에 뒤로 가기를 누르거나 갑자기 꺼버리면 설정이 미완인 상태 그대로 저장되어버리는 것 같다
코드를 다시 쳐보고 설정 파일 위치 확인해도 안되서 멘붕이었다
기존에 만든 걸 완전히 삭제하거나 삭제가 되지 않는 것들은 기존 이름에 덮어 씌우고 처음 과정부터 새로 만들어봤더니 드디어 정상 작동했다