Tags

๐Ÿšง Spring Boot Elastic Beanstalk ์ธํ”„๋ผ ๊ตฌ์„ฑํ•˜๊ธฐ

namjug-kim โ€ข 2020๋…„ 6์›” 02์ผ
aws
infra

AWS Elastic Beanstalk์„ ์„ ํƒํ•œ ์ด์œ 

์Šคํƒ€ํŠธ์—…์—์„œ ์„œ๋ฒ„ ์ธํ”„๋ผ๋ฅผ ๊ตฌ์ถ•ํ•˜๋ฉด์„œ ์ดˆ๊ธฐ์—๋Š” ec2 + ecr + codedeploy๋กœ ๊ตฌ์ถ•์„ ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ƒ๊ฐ๋ณด๋‹ค ์„œ๋น„์Šค์˜ ๊ทœ๋ชจ๊ฐ€ ๋น ๋ฅด๊ฒŒ ํ™•์žฅ๋˜๋ฉด์„œ ๋ช‡๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  • ์„œ๋น„์Šค ๋ฐฐํฌ/๋กค๋ฐฑ, ํ”„๋กœ๋น„์ €๋‹ ๊ด€๋ฆฌ์˜ ๋ณต์žกํ•จ์ด ๋ฐœ์ƒ
  • ๊ธ‰ํ•˜๊ฒŒ ์„œ๋น„์Šค ๊ทœ๋ชจ ํ™•์žฅ์ด ํ•„์š”ํ•œ ์ผ€์ด์Šค๊ฐ€ ๋ฐœ์ƒ
  • ํŒ€์— ์‹ ๊ทœ๋กœ ๋“ค์–ด์˜จ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๊ธฐ์กด ์ธํ”„๋ผ์— ๋Œ€ํ•œ ๊ต์œก์ด ํ•„์š”

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์†์‰ฌ์šด ๋ฐฐํฌ, ์Šค์ผ€์ผ ์ธ/์•„์›ƒ ํŽธ์˜, ์ธํ”„๋ผ ๊ด€๋ฆฌ์˜ ์šฉ์ด์„ฑ์„ ๊ณ ๋ คํ•˜์—ฌ EB(Elastic Beanstalk)์œผ๋กœ ๋„˜์–ด๊ฐ€๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฐฐํฌ ๊ตฌ์„ฑ

Untitled Diagram (9) ๋ฐฐํฌ ๊ตฌ์„ฑ์€ ์œ„ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

  1. ์†Œ์Šค ์ฝ”๋“œ checkout
  2. Jenkins์—์„œ CI, ๋„์ปค ์ด๋ฏธ์ง€ ๋นŒ๋“œ
  3. ๋„์ปค ์ด๋ฏธ์ง€๋ฅผ AWS ECR๋กœ ํ‘ธ์‹œ
  4. AWS S3์— EB ์‹คํ–‰์„ ์œ„ํ•œ Docker.aws.run ํŒŒ์ผ ์—…๋กœ๋“œ
  5. AWS EB์— 3๋ฒˆ์—์„œ ์—…๋กœ๋“œํ•œ ํŒŒ์ผ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฐฐํฌ

1. Spring Boot Application ๋„์ปค ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑํ•˜๊ธฐ

ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ์„œ๋น„์Šค ์šด์˜์„ ์œ„ํ•ด์„œ Spring Boot Application์™ธ์— 2๊ฐ€์ง€์˜ ์„œ๋น„์Šค๋ฅผ ์ถ”๊ฐ€๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ๊ธฐ๋•Œ๋ฌธ์— ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด Pinpoint, Filebeat์„ ์ถ”๊ฐ€๋กœ ๊ตฌ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

Pinpoint, Filebeat, Micrometer 3๊ฐ€์ง€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋น„์Šค ๋ชจ๋‹ˆํ„ฐ๋ง์„ ํ•˜๊ณ  ์žˆ๊ธฐ๋•Œ๋ฌธ์— Pinpoint์™€ Filebeat์„ ์ถ”๊ฐ€๋กœ ์„ค์น˜ํ•˜์˜€์œผ๋ฉฐ ์šด์˜ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ์•Œ๋งž๋Š” ์„œ๋น„์Šค ๋ชจ๋‹ˆํ„ฐ๋ง ๋„๊ตฌ๋ฅผ ์„ ํƒํ•˜๋ฉด ๋œ๋‹ค.

Untitled Diagram (8)

# build filebeat
FROM docker.elastic.co/beats/filebeat-oss:7.7.0 as filebeat
COPY scripts/conf/filebeat/filebeat.yml /usr/share/filebeat/filebeat.yml

# build pinpoint
FROM alpine:3.9.6 as pinpoint
ENV PINPOINT_VERSION=2.0.1
RUN apk add --update curl bash \
    && curl -SL https://github.com/naver/pinpoint/releases/download/v$PINPOINT_VERSION/pinpoint-agent-$PINPOINT_VERSION.tar.gz -o pinpoint-agent.tar.gz \
    && tar -xvf pinpoint-agent.tar.gz \
    && mv /pinpoint-agent-$PINPOINT_VERSION /pinpoint-agent
RUN mv /pinpoint-agent/pinpoint-bootstrap-$PINPOINT_VERSION.jar /pinpoint-agent/pinpoint-bootstrap.jar

# build jdk
FROM openjdk:8-jdk-alpine

VOLUME ["/logs"]

ENV JAVA_OPTS=""
ENV SPRING_PROFILES_ACTIVE=""

# copy pinpoint
COPY --from=pinpoint /pinpoint-agent /pinpoint-agent
# copy filebeat
RUN apk add --update-cache libc6-compat curl bash go
COPY --from=filebeat /usr/share/filebeat /usr/share/filebeat
COPY --from=filebeat /usr/local/bin/docker-entrypoint /usr/local/bin/docker-entrypoint
ENV PATH="/usr/share/filebeat:${PATH}"

ARG DEPENDENCY=lvup-api-server/build/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app

# spring boot run script
COPY scripts/common/spring-boot-run.sh spring-boot-run.sh
RUN chmod +x /spring-boot-run.sh

ENTRYPOINT docker-entrypoint -c /usr/share/filebeat/filebeat.yml -environment container \
        & /spring-boot-run.sh com.demo.DemoServerApplicationKt

2. Elastic Beanstalk ํ™˜๊ฒฝ ์ƒ์„ฑํ•˜๊ธฐ

์šฐ์„  ์„œ๋น„์Šค ๊ตฌ๋™์„ ์œ„ํ•œ EB ํ™˜๊ฒฝ์„ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ ํ™˜๊ฒฝ ์ƒ์„ฑ์„ ํ†ตํ•ด์„œ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์•„๋ž˜์™€ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด Docker ํ”Œ๋žซํผ์œผ๋กœ ์ƒ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค. screencapture-ap-northeast-2-console-aws-amazon-elasticbeanstalk-home-2020-06-01-22_01_18

EB์˜ Docker ๊ตฌ์„ฑ์—๋Š” ๋‹จ์ผ์ปจํ…Œ์ด๋„ˆ, ๋ฉ€ํ‹ฐ์ปจํ…Œ์ด๋„ˆ 2๊ฐ€์ง€ ์ข…๋ฅ˜๋ฅผ ์ง€์›ํ•˜๋Š”๋ฐ ์•„์ง ์„œ๋น„์Šค์˜ ์ข…๋ฅ˜๊ฐ€ ๋งŽ์ง€ ์•Š๊ณ  ๋‹จ์ผ ์„œ๋น„์Šค์—์„œ Modular Monolith๋กœ ๊ฐœ๋ฐœํ•˜์˜€๊ธฐ๋•Œ๋ฌธ์— ๋‹จ์ผ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์„ ํƒํ•˜์˜€์Šต๋‹ˆ๋‹ค.

EB ํ™˜๊ฒฝ์„ ์ƒ์„ฑํ• ๋•Œ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ, VPC, ์šฉ๋Ÿ‰์— ๊ด€ํ•œ ์„ค์ •์„ ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. Spring Boot Application์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํŠน์ด ์‚ฌํ•ญ์œผ๋กœ ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด 3๊ฐ€์ง€ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

  • SPRING_PROFILES_ACTIVE : ํ™œ์„ฑํ™” ์‹œํ‚ฌ ์Šคํ”„๋ง ํ”„๋กœํŒŒ์ผ
  • JAVA_OPTS : ์ž๋ฐ” ์‹คํ–‰ ์˜ต์…˜
  • APPLICATION_NAME : ๋ชจ๋‹ˆํ„ฐ๋ง์— ์‚ฌ์šฉ๋  ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ด๋ฆ„

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2020-06-02 แ„‹แ…ฉแ„’แ…ฎ 5.52.22

3. AWS Elastic Container Registry ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์ƒ์„ฑํ•˜๊ธฐ

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2020-06-02 แ„‹แ…ฉแ„’แ…ฎ 5.55.12

๋ณ„๋„์˜ ๋„์ปค ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๊ตฌ์„ฑํ•˜๊ฑฐ๋‚˜ Docker hub ๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๋ฌด๋ฐฉํ•˜์ง€๋งŒ AWS ์ธํ”„๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค๋ณด๋‹ˆ IAM์„ ํ†ตํ•œ ์ธ์ฆ์˜ ํŽธ์˜์„ฑ์ด ์žˆ์–ด์„œ ECR์„ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

4. Jenkins Pipeline ์ƒ์„ฑํ•˜๊ธฐ

์  ํ‚จ์Šค ํŒŒ์ดํ”„ ๋ผ์ธ์„ ํ†ตํ•ด ci, build, deploy ์Šคํƒญ์„ ๊ตฌ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค. CI๊ณผ์ •์„ ์ œ์™ธํ•œ ๋นŒ๋“œ ๊ณผ์ •์„ ์‚ดํŽด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

stage('Docker Build') {
    docker.build("demo-application:${GIT_COMMIT}", "-f ./demo-application/Dockerfile .")
}
  1. ๋„์ปค ์ด๋ฏธ์ง€ ๋นŒ๋“œ ๋„์ปค ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜์˜€์œผ๋ฉฐ GIT COMMIT SHA(${GIT_COMMIT})๋ฅผ ํƒœ๊ทธ๋กœ ์ง€์ •ํ•˜์—ฌ ๋„์ปค ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.
stage('Docker push') {
    script {
        // login to ECR - for now it seems that that the ECR Jenkins plugin is not performing the login as expected. I hope it will in the future.
        sh '$(aws ecr get-login --no-include-email --region ap-northeast-2)'
        // Push the Docker image to ECR
        docker.withRegistry('http://{ecrId}.dkr.ecr.ap-northeast-2.amazonaws.com')
        {
            docker.image("demo-application:${GIT_COMMIT}").push()
        }

        // make sure that the Docker image is removed
        sh "docker rmi demo-application:${GIT_COMMIT} | true"
    }
}
  1. ๋„์ปค ์ด๋ฏธ์ง€๋ฅผ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ํ‘ธ์‹œ AWS ecr์— ์ƒ์„ฑํ•œ ๋„์ปค ์ด๋ฏธ์ง€๋ฅผ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€ ๋“ฑ๋ก์€ ๋„์ปค ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜์˜€์œผ๋ฉฐ ์ธ์ฆ์€ sh '$(aws ecr get-login --no-include-email --region ap-northeast-2)'์™€ ๊ฐ™์ด aws cli๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.
stage('Deploy AWS') {
    script {
        env.BUILD_ENVIRONMENT = "DEV"
        env.EB_APPLICATION_NAME = "demo-application"
        env.EB_ENV_NAME = "DemoApplication-Env"

        sh '''
        # create Dockerrun.aws.json files
        sed -i "s|GIT_COMMIT_SHA|${GIT_COMMIT}|g" "${WORKSPACE}/scripts/demo-application/Dockerrun.aws.json"

        # Upload S3
        aws s3 cp "${WORKSPACE}/scripts/demo-application/Dockerrun.aws.json" s3://eb-deploy-files/${BUILD_ENVIRONMENT}-${EB_APPLICATION_NAME}-${GIT_COMMIT}.aws.json \
            --region ap-northeast-2

        # Execute Beanstalk
        aws elasticbeanstalk create-application-version \
            --region ap-northeast-2 \
            --application-name ${EB_APPLICATION_NAME} \
            --version-label ${GIT_COMMIT}-${BUILD_NUMBER} \
            --description ${GIT_COMMIT}-${BUILD_NUMBER} \
            --source-bundle S3Bucket="eb-deploy-files",S3Key="${BUILD_ENVIRONMENT}-${EB_APPLICATION_NAME}-${GIT_COMMIT}.aws.json"

        aws elasticbeanstalk update-environment \
            --region ap-northeast-2 \
            --environment-name ${EB_ENV_NAME} \
            --version-label ${GIT_COMMIT}-${BUILD_NUMBER}
        '''
    }
}
  1. ๋„์ปค ์ด๋ฏธ์ง€ EB์— ๋ฐฐํฌํ•˜๊ธฐ EB๋ฐฐํฌ ๋กœ์ง์€ ๊ธฐ์–ต๋ณด๋‹ค ๊ธฐ๋ก์„๋‹˜์˜ ๋ธ”๋กœ๊ทธ์— ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
    • S3์— Dockerrun.aws.jsonํŒŒ์ผ ์—…๋กœ๋“œ
    • S3์— ์—…๋กœ๋“œํ•œ ํŒŒ์ผ์„ ๊ธฐ๋ฐ˜์œผ๋กœ EB ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฒ„์ „ ์ƒ์„ฑํ•˜๊ธฐ
    • EB ์—…๋ฐ์ดํŠธ EB์— ์‹ฑ๊ธ€ ์ปจํ…Œ์ด๋„ˆ ๋„์ปค ์‹คํ–‰์„ ์œ„ํ•ด์„œ๋Š” Dockerrun.aws.json ํ˜•์‹์˜ ํŒŒ์ผ์„ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ • ํŒŒ์ผ์„ ๊ตฌ์„ฑํ•˜๊ณ  GIT_COMMIT_SHA๋ฅผ ์‹ค์ œ 2๋ฒˆ ๊ณผ์ •์—์„œ ํ‘ธ์‹œํ•œ ์ด๋ฏธ์ง€์˜ ํƒœ๊ทธ๋กœ ๋ณ€๊ฒฝํ•ด์„œ ์›ํ•˜๋Š” ๋ฐฐํฌ๋ณธ์ด ๋ฐฐํฌ๋จ์„ ๋ณด์žฅํ•˜์˜€์Šต๋‹ˆ๋‹ค.
{
  "AWSEBDockerrunVersion": "1",
  "Image": {
    "Name": "{/*private*/}.dkr.ecr.ap-northeast-2.amazonaws.com/demo-application:GIT_COMMIT_SHA",
    "Update": "true"
  },
  "Volumes": [/*volume config*/],
  "Ports": [/*port config*/]
}

์ข…ํ•ฉ

Jenkins์™€ AWS Elastic Beanstalk์„ ํ†ตํ•˜์—ฌ ์ธํ”„๋ผ ํ™˜๊ฒฝ ๊ตฌ์ถ•์„ ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

๊ธฐ์กด์—๋Š” EC2์—์„œ ์ˆ˜๋™์œผ๋กœ ๊ตฌ์„ฑ์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋งŽ์€ ์‹œ๊ฐ„์ด ์†Œ์š”๋˜์—ˆ๊ณ  ์„œ๋น„์Šค ์„ฑ์žฅ์— ๋งž๋Š” ์ธํ”„๋ผ ํ™•์žฅ์ด ์‰ฝ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. EB๋กœ ๋ณ€๊ฒฝ์„ ํ•˜๋ฉด์„œ ๋ฐฐํฌ, ํ™•์žฅ, ๊ด€๋ฆฌ ๋ถ€๋ถ„์—์„œ ์ด์ „๋ณด๋‹ค ๋” ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ๋Œ€์‘ ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ์‚ฌ์šฉํ•ด๋ณด๋‹ˆ ๊ฐœ๋ฐœํŒ€๊ณผ ์„œ๋น„์Šค์˜ ๊ทœ๋ชจ๋Š” ์ง€์†์ ์œผ๋กœ ์ปค์ง€๊ณ  ์žˆ์ง€๋งŒ ๋ณ„๋„์˜ ์ธํ”„๋ผ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ์ธ๋ ฅ์„ ์šด์šฉํ•˜๊ธฐ๋Š” ํž˜๋“  ์Šคํƒ€ํŠธ์—…์— ๊ต‰์žฅํžˆ ์ž˜ ๋งž๋Š” ๊ตฌ์„ฑ์ด์—ˆ์Šต๋‹ˆ๋‹ค.