์คํํธ์ ์์ ์๋ฒ ์ธํ๋ผ๋ฅผ ๊ตฌ์ถํ๋ฉด์ ์ด๊ธฐ์๋ ec2 + ecr + codedeploy๋ก ๊ตฌ์ถ์ ํ์์ต๋๋ค. ์๊ฐ๋ณด๋ค ์๋น์ค์ ๊ท๋ชจ๊ฐ ๋น ๋ฅด๊ฒ ํ์ฅ๋๋ฉด์ ๋ช๊ฐ์ง ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ฒ ๋์์ต๋๋ค.
์ด๋ฌํ ๋ฌธ์ ๋ฅผ ๊ฐ์ ํ๊ธฐ ์ํด์ ์์ฌ์ด ๋ฐฐํฌ
, ์ค์ผ์ผ ์ธ/์์ ํธ์
, ์ธํ๋ผ ๊ด๋ฆฌ์ ์ฉ์ด์ฑ
์ ๊ณ ๋ คํ์ฌ EB(Elastic Beanstalk)์ผ๋ก ๋์ด๊ฐ๊ฒ ๋์์ต๋๋ค.
๋ฐฐํฌ ๊ตฌ์ฑ์ ์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ๊ตฌ์ฑํ์์ต๋๋ค.
ํ๋ก๋์ ํ๊ฒฝ์์ ์๋น์ค ์ด์์ ์ํด์ Spring Boot Application์ธ์ 2๊ฐ์ง์ ์๋น์ค๋ฅผ ์ถ๊ฐ๋ก ์ฌ์ฉํ๊ณ ์์๊ธฐ๋๋ฌธ์ ์๋ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด Pinpoint, Filebeat์ ์ถ๊ฐ๋ก ๊ตฌ์ฑํ์์ต๋๋ค.
Pinpoint, Filebeat, Micrometer 3๊ฐ์ง๋ฅผ ์ฌ์ฉํ์ฌ ์๋น์ค ๋ชจ๋ํฐ๋ง์ ํ๊ณ ์๊ธฐ๋๋ฌธ์ Pinpoint์ Filebeat์ ์ถ๊ฐ๋ก ์ค์นํ์์ผ๋ฉฐ ์ด์ ํ๊ฒฝ์ ๋ฐ๋ผ ์๋ง๋ ์๋น์ค ๋ชจ๋ํฐ๋ง ๋๊ตฌ๋ฅผ ์ ํํ๋ฉด ๋๋ค.
# 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
์ฐ์ ์๋น์ค ๊ตฌ๋์ ์ํ EB ํ๊ฒฝ์ ์์ฑํด์ผ ํฉ๋๋ค. ์ ํ๊ฒฝ ์์ฑ
์ ํตํด์ ์์ฑํ ์ ์์ผ๋ฉฐ ์๋์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด Docker
ํ๋ซํผ์ผ๋ก ์์ฑํ์์ต๋๋ค.
EB์ Docker ๊ตฌ์ฑ์๋ ๋จ์ผ์ปจํ ์ด๋, ๋ฉํฐ์ปจํ ์ด๋ 2๊ฐ์ง ์ข ๋ฅ๋ฅผ ์ง์ํ๋๋ฐ ์์ง ์๋น์ค์ ์ข ๋ฅ๊ฐ ๋ง์ง ์๊ณ ๋จ์ผ ์๋น์ค์์ Modular Monolith๋ก ๊ฐ๋ฐํ์๊ธฐ๋๋ฌธ์ ๋จ์ผ์ปจํ ์ด๋๋ฅผ ์ ํํ์์ต๋๋ค.
EB ํ๊ฒฝ์ ์์ฑํ ๋ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๋ ๋ก๋ ๋ฐธ๋ฐ์, VPC, ์ฉ๋์ ๊ดํ ์ค์ ์ ํด ์ฃผ์์ต๋๋ค. Spring Boot Application์ ์ฌ์ฉํ๊ธฐ ์ํ ํน์ด ์ฌํญ์ผ๋ก ์๋ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด 3๊ฐ์ง ํ๊ฒฝ๋ณ์๋ฅผ ์ฌ์ฉํ์์ต๋๋ค.
๋ณ๋์ ๋์ปค ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๊ฑฐ๋ Docker hub ๋ฅผ ์ฌ์ฉํด๋ ๋ฌด๋ฐฉํ์ง๋ง AWS ์ธํ๋ผ๋ฅผ ์ฌ์ฉํ๋ค๋ณด๋ IAM์ ํตํ ์ธ์ฆ์ ํธ์์ฑ์ด ์์ด์ ECR์ ์ฌ์ฉํ์์ต๋๋ค.
์ ํจ์ค ํ์ดํ ๋ผ์ธ์ ํตํด ci, build, deploy ์คํญ์ ๊ตฌ์ฑํ์์ต๋๋ค. CI๊ณผ์ ์ ์ ์ธํ ๋น๋ ๊ณผ์ ์ ์ดํด๋ณด๋ฉด ์๋์ ๊ฐ์ต๋๋ค.
stage('Docker Build') {
docker.build("demo-application:${GIT_COMMIT}", "-f ./demo-application/Dockerfile .")
}
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"
}
}
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}
'''
}
}
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๋ก ๋ณ๊ฒฝ์ ํ๋ฉด์ ๋ฐฐํฌ, ํ์ฅ, ๊ด๋ฆฌ ๋ถ๋ถ์์ ์ด์ ๋ณด๋ค ๋ ์ฝ๊ณ ๋น ๋ฅด๊ฒ ๋์ ํ ์ ์์์ต๋๋ค.
์ค์ ๋ก ์ฌ์ฉํด๋ณด๋ ๊ฐ๋ฐํ๊ณผ ์๋น์ค์ ๊ท๋ชจ๋ ์ง์์ ์ผ๋ก ์ปค์ง๊ณ ์์ง๋ง ๋ณ๋์ ์ธํ๋ผ ๊ด๋ฆฌ๋ฅผ ์ํ ์ธ๋ ฅ์ ์ด์ฉํ๊ธฐ๋ ํ๋ ์คํํธ์ ์ ๊ต์ฅํ ์ ๋ง๋ ๊ตฌ์ฑ์ด์์ต๋๋ค.