하나의 마이크로서비스의 CI/CD를 구축해서 적용시켰다면 나머지 서비스에 대해서도 동일하게 적용시켜보자
각각의 마이크로서비스의 CI/CD 적용과정은 복사붙이기가 전부라서 빠르게 진행한다
마이크로서비스들의 CI/CD를 진행하던 중에 applcation.yml 파일에 대한 암호화를 진행하는 문제가 발생
해당 문제를 해결하기위해 환경변수를 지정해줘서 지정변수가 노출되지 않도록 설정해보려고한다.
이전에 작성했던 application.yml은 코드 push 할때 중요정보가 노출될 위험이 있기때문에 코드를 수정한다.
spring:
datasource:
url: jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul
username: ${DB_USER}
password: ${DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
${}로 감싸진 해당 변수들에 올바른 값들을 넣어주기 위해서 환경변수를 설정해주어야하고 이를 위해서 docker run 할때의 Script를 수정해준다.
steps {
sh '''
docker run --name notification -d \
-p 8083:8083 \
-e DB_HOST=j11a604.p.ssafy.io \
-e DB_PORT=3306 \
-e DB_USER=root \
-e DB_PASSWORD=ssafy \
-e DB_NAME=trabean \
qkrtprjs/notification
'''
echo 'Run New member image'
}
NotificationApplicationTests > contextLoads() FAILED
java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:180
Caused by: org.springframework.beans.factory.BeanCreationException at AbstractAutowireCapableBeanFactory.java:1806
Caused by: jakarta.persistence.PersistenceException at AbstractEntityManagerFactoryBean.java:421
Caused by: org.hibernate.exception.JDBCConnectionException at SQLExceptionTypeDelegate.java:51
Caused by: java.sql.SQLNonTransientConnectionException at SQLError.java:111
Caused by: com.mysql.cj.exceptions.UnableToConnectException at null:-1
Caused by: com.mysql.cj.exceptions.WrongArgumentException at null:-1
Caused by: java.lang.NumberFormatException at null:-1
위와 같은 에러가 발생했고 원인은 데이터베이스에 연결할 수 없음을 나타낸다고 한다.
생각해보니 실패는 이미지 빌드하는 과정에서 실패했고 수정해준 코드는 docker run 하는 부분이다. 즉. 빌드하는 과정에서는 환경변수가 적용되지 않는것 같아서 발생한 에러같다.
찾아보니 빌드하는 과정에서도 사용할 환경 변수를 설정해주어야 빌드시에 에러가 발생하지 않다고 한다.
시도 1 : 빌드하는 과정에도 환경변수 설정
FROM eclipse-temurin:17-jdk
ARG DB_HOST
ARG DB_PORT
ARG DB_USER
ARG DB_PASSWORD
ARG DB_NAME
WORKDIR /app
COPY build/libs/notification-0.0.1-SNAPSHOT.jar app.jar
ENV DB_HOST=${DB_HOST}
ENV DB_PORT=${DB_PORT}
ENV DB_USER=${DB_USER}
ENV DB_PASSWORD=${DB_PASSWORD}
ENV DB_NAME=${DB_NAME}
EXPOSE 8083
ENTRYPOINT ["java", "-jar", "app.jar"]
VOLUME ["/data"]
dir('notification') {
sh 'chmod +x ./gradlew'
sh './gradlew build'
sh 'pwd'
sh '''
docker build -t qkrtprjs/notification \
--build-arg DB_HOST=j11a604.p.ssafy.io \
--build-arg DB_PORT=3306 \
--build-arg DB_USER=root \
--build-arg DB_PASSWORD=ssafy \
--build-arg DB_NAME=trabean .
'''
}
시도 2 : ubuntu에 접속해서 직접 docker 명령어를 실행
정상적으로 작동되는 것을 확인 심지어 run하는 과정에서는 환경변수 설정도 해주지 않음
./gradlew build
이 과정에서 에러가 발생했다고 생각, 프로젝트에서 따로 터미널을 열어서 해당코드를 실행시켜보니 같은 에러 발생.시도 3 : ./gradlew build
하는 과정에도 환경변수를 설정해주는 방법
sh '''
export DB_HOST=j11a604.p.ssafy.io
export DB_PORT=3306
export DB_USER=root
export DB_PASSWORD=ssafy
export DB_NAME=trabean
./gradlew build
'''
해당 스크립트에서 export 명령어를 사용해서 빌드하는 과정에 환경변수를 미리 세팅해주는 과정으로 진행
그렇다면, 빌드하는과정, 이미지 빌드하는 과정, 이미지 실행시키는 과정 이 세개의 과정에서 모두 반복되는 환경변수 세팅을 해줘야하는 것인데, 반복적인 과정이 비효율적 처럼보인다. 하지만 이를 해결하기 위해서는 따로 파일을 지정해주는 방식이 있다고 하는데 이 또한, GitLab이나 Github에 올리게되면 중요 내용이 노출될 가능성이 있다. 좀 더 공부해보자
알아보니 Spring Cloud Config를 활용하면 설정 파일을 외부로 분리하는 아키텍처를 활용할 수 있다고 한다.
- 개발/테스트 환경 그리고 운영 환경까지 모든 환경 구성을 간편하게 관리
- 환경변수가 바뀌었을때 어플리케이션을 다시 빌드하고 배포할 필요가 없기 때문에 개발 생산성에 좋은 영향
결과적으로, 설정이 바뀔 때마다 빌드와 배포가 필요 없는 구조로 어플리케이션을 설계 가능
추가적으로 진행해서 나머지 마이크로서비스들의 CI/CD를 완성시켰고 이제 API Gateway와 Eureka를 적용시켜서 조금 더 완성적인 MSA 구조를 만들어보자