CI / CD AWS Code Deploy & Code Pipeline 활용

InSeok·2023년 1월 31일
0

TIL

목록 보기
45/51

CI(Continuous integration)

  • 개발자를 위한 자동화 프로세스인 지속적인 통합(Continuous Integration)을 의미
  • 테스트, 빌드, Dockerizing, 저장소에 전달 까지 프로덕션 환경으로 서비스를 배포할 수 있도록 준비하는 프로세스
  • 애플리케이션에 대한 새로운 코드 변경 사항이 정기적으로 빌드 및 테스트되서 공유 레파지토리에 통합되므로 여러 명의 개발자가 동시에 애프리케이션 개발과 관련된 코드 작업을 할 경우 충돌하는 문제를 해결할 수 있다.

CD (Continuous Deployment)

  • 배포 자동화란 한번의 클릭 혹은 명령어 입력을 통해 전체 배포 과정을 자동으로 진행하는 것입니다.
  • 저장소로 전달된 프로덕션 서비스를 실제 사용자들에게 배포하는 프로세스
  • 장점
    • 수동적이고 반복적인 배포 과정을 자동화함으로써 시간이 절약

    • 전체 배포 과정을 매번 일관되게 진행하는 구조를 설계하여 휴먼 에러 발생 가능성을 낮출 수 있습니다.

      휴먼에러 : 수동적으로 배포 과정을 진행하는 중에 생기는 실수

**배포 자동화 파이프라인**

  • 파이프라인(Pipeline)이란 소스 코드의 관리부터 실제 서비스로의 배포 과정을 연결하는 구조
  • 파이프라인은 전체 배포 과정을 여러 단계(Stages)로 분리합니다. 각 단계는 파이프라인 안에서 순차적으로 실행되며, 각 단계마다 주어진 작업(Actions)들을 수행합니다.
  • 파이프라인의 단계는 상황과 필요에 따라 더 세분화되거나 간소화될 수 있습니다
    1. Source 단계: Source 단계에서는 원격 저장소에 관리되고 있는 소스 코드에 변경 사항이 일어날 경우, 이를 감지하고 다음 단계로 전달하는 작업을 수행합니다.
    2. Build 단계: Build 단계에서는 Source 단계에서 전달받은 코드를 컴파일, 빌드, 테스트하여 가공합니다. 또한 Build 단계를 거쳐 생성된 결과물을 다음 단계로 전달하는 작업을 수행합니다.
    3. Deploy 단계: Deploy 단계에서는 Build 단계로부터 전달받은 결과물을 실제 서비스에 반영하는 작업을 수행합니다.

**AWS 개발자 도구**

**CodeCommit**

  • Source 단계를 구성할 때 CodeCommit 서비스를 이용합니다. CodeCommit은 GitHub과 유사한 서비스를 제공하는 버전 관리 도구

**CodeBuild**

  • Build 단계에서는 CodeBuild 서비스를 이용합니다. CodeBuild 서비스를 통해 유닛 테스트, 컴파일, 빌드와 같은 빌드 단계에서 필수적으로 실행되어야 할 작업들을 명령어를 통해 실행
  • CodeBuild 서비스는 사용자가 작성한 buildspec.yml 파일을 참조하여 작업을 수행

**CodeDeploy**

  • CodeDeploy 서비스를 이용하면 실행되고 있는 서버 애플리케이션에 실시간으로 변경 사항을 전달
  • 사용자가 작성한 appspec.yml 파일을 참조하여 작업을 수행
  • S3 서비스를 통해 S3 버킷을 통해 업로드된 정적 웹 사이트에 변경 사항을 실시간으로 전달하고 반영

**CodePipeline**

  • 각 단계를 연결하는 파이프라인을 구축할 때 CodePipeline 서비스를 이용

AWS 프리티어 계정 사용 시 한 계정에 두 개 이상의 파이프라인을 생성하면 추가 요금이 부여될 수 있습니다.

**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 AWS CLI의 설치 여부를 확인

**CodeDeploy Agent 설치**

$ sudo apt update
$ sudo apt install ruby-full                # [Y / n] 선택시 Y 입력
$ 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 서비스가 실행중인지 확인

에러발생시, 로그를 지운 뒤 다시 설치를 진행

  • /tmp/codedeploy-agent.update.log
  • /tmp/logfile
  • 인스턴스를 검색하여 선택한 후 [ 태그 ] 를 확인
    • 파이프라인 구축 단계에서 인스턴스를 잘 식별하기 위함
  • IAM 역할에 AmazonEC2RoleforAWSCodeDeploy 추가, AmazonS3FullAccess 추가, AWSCodeDeployRole 추가, AmazonSSMFullAccess 추가
  • 신뢰 관계를 편집
    • 신뢰 관계란, 해당 역할을 취할 수 있는 서비스나 사용자를 명시하는 부분
    • access 할 수 있는 서비스를 신뢰 관계에서 명시함으로써 역할이 확실히 완성
    • "Service"의 값에 "codedeploy.ap-northeast-2.amazonaws.com" 값을 추가

AWS Pipeline 활용한 CI/CD

  • 해당 로컬 파일 경로에 appspec.yml 파일을 추가
    • appspec.yml은 배포 자동화를 도와주는 CodeDeploy-Agent가 인식하는 파일

    • CodeDeploy에서 지정한 각 단계에 맞춰 어떤 셸 스크립트를 실행하는지 지정

    • appspec.yml

      ersion: 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
  • 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
  • 최상위에 scripts 디렉토리를 생성한 후 그 안에 initialize.sh, server_clear.sh, server_start.sh, server_stop.sh 파일 4개를 생성
    • **scripts/initialize.sh**
      - 빌드 결과물을 실행할 수 있도록 실행 권한을 추가

      #!/usr/bin/env bash
      chmod +x /home/ubuntu/build/**
    • **scripts/server_clear.sh**

      • 빌드 결과물이 저장되어있는 build 디렉토리를 제거합니다.

        #!/usr/bin/env bash
        rm -rf /home/ubuntu/build
    • **scripts/server_start.sh**

      • DeployServer-0.0.1-SNAPSHOT.jar라는 빌드 결과물을 실행

        #!/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 &
    • **scripts/server_stop.sh**
      - 실행중인 Spring Boot 프로젝트를 종료

      #!/usr/bin/env bash
      sudo pkill -f 'java -jar'
  • 각 파일은 appspec.yml 파일이 구성하고 있는 배포 수명 주기에 따라서 실행될 예정
  • AWS CodeDeploy 대시보드로 이동해 애플리케이션으로 이동
  • 애플리케이션 생성
  • 컴퓨팅 플랫폼을 'EC2/온프레미스'로 선택한 뒤, 애플리케이션 생성
  • 생성한 애플리케이션의 배포 그룹 탭을 클릭하여 배포 그룹 생성
  • 서비스 역할 영역을 클릭하면 연결할 수 있는 IAM 역할 목록이 보여집니다.
    이 중 본인 소유의 EC2 인스턴스에 연결되어있는 IAM 역할을 선택
  • 환경 구성 중 'Amazon EC2 인스턴스'를 선택하고, 태그 그룹에 EC2 인스턴스의 이름인 Name 태그 키와 값을 선택
  • 로드 밸런싱 활성화 체크 해제

AWS CodePipeline 을 이용해 서버 배포 자동화 파이프라인을 구축

  • CodePipeline 대시보드로 이동 후, 파이프라인 생성

소스 스테이지 추가

  • GitHub(버전 2)를 소스 공급자로 선택
  • GitHub에 연결
    • 새 앱 설치
    • 자신의 GitHub 계정 연결
  • Only select repositories'를 선택한 후, 소스 코드로 이용할 리포지토리를 선택
  • 리포지 토리 이름과 브랜치, 출력 아티팩트 형식 선택
    • 출력 아티팩트 형식은 'CodePipeline 기본값'으로 지정

빌드 스테이지 추가

  • 빌드 공급자에서 AWS CodeBuild를 클릭
  • 프로젝트 생성
    • 운영체제는 Amazon Linux 2를 선택
    • 런타임은 Standart를 선택
    • 이미지는 aws/codebuild/amazonlinux2-x86_64-standart:3.0을 선택
  • Buildspec 이름에 "DeployServer/buildspec.yml"을 작성

배포 스테이지 추가

  • 배포 공급자는 'AWS CodeDeploy'를 선택
  • 리전은 '아시아 태평양(서울)'을 선택
  • 파이프라인 생성
  • CodeDeploy-Agent는 파이프라인 실행 때마다 로그를 해당 EC2 instance에 저장한다.
  • 구축한 파이프라인 중 deploy 스테이지에서 실패가 발생하는 경우 로그 확인하는 방법
    • EC2 인스턴스의 터미널에 'cd /opt/codedeploy-agent/deployment-root/deployment-logs' 명령어를 입력하여 로그 파일이 저장된 경로로 이동
    • ls 명령어를 입력하여 어떤 파일이 존재하고 있는지 확인
    • codedeploy-agent-deployments.log 라는 파일이 존재한다면 vim으로 확인
  • lifecycle을 돌면서 sh 파일을 실행시킨 로그를 확인가능
  • stderr는 standard error, stdout은 standard output을 뜻합니다.

서버 환경 변수 설정

  • 파이프라인에 올린 EC2 instance에 환경 변수를 전달하는 방법
  • AWS Parameter Store 서비스를 이용하면 EC2 instance에 환경 변수를 전달할 수 있습니다.
  • Parameter Store 대시보드로 이동 후, [ 파라미터 생성 ] 버튼을 클릭
  • 이름에 환경 변수명을 적어주고, 환경 변수에 할당되어야 할 값을 입력
  • 이름은 꼭 /prefix/name/key 의 순서로 네이밍 규칙에 맞게 작성되어야 합니다.
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-aws-parameter-store-config' // 추가
}
dependencyManagement { // 블록 추가
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-starter-parent:Hoxton.SR12"
	}
}
  • src/main/resources/bootstrap.yml 파일을 생성
    • 파라미터 스토어에 저장된 변수를 조회하는 파일

      aws:
        paramstore:
          enabled:trueprefix: /spring-boot-aws
          name:  # 리소스 이름을 작성합니다.
          profileSeparator: _
  • **application.properties**
  • pplication.properties에 직접적인 변수 값을 작성하지 않아도 파라미터 스토어에 저장된 값을 읽어올 수 있습니다.
server.port=80 #포트 변경은 선택입니다.
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}
profile
백엔드 개발자

0개의 댓글