그동안 AWS RDS, S3, credentials와 같은 민감 정보를 Springboot project git 레포에 올릴 수가 없어서 .gitignore로 처리하였고 submodule을 이용해서 private repo access token을 git secret 상에 넣고 cicd pipeline에서 submodule 항목을 true로 설정하여 build시 submodule 내 코드들을 원하는 프로젝트 path로 복사하여 jar 파일을 만듦으로써 해결하였다.
그러나 dev에서는 jpa 속성을 update로 하는 것이 좋지만 prod 환경에서는 validate로 설정이 되어야했기에 이러한 부분까지 submodule로 분리하여 관리하는 것이 어렵다고 느껴져 submodule을 해제하고 git secrets로 바꾸게 되었다. 코드는 이 pr 링크에서 확인할 수 있다.
submodule을 관리하면서 겪었던 에러와 이를 git secrets로 바꾼 과정을 게시글에 담았다.
문제 상황: fatal: Fetched in submodule path 'src/main/resources/secret', but it did not contain 7855364c6f950ea9ed7ad4f7e98bf19289ea4bf0. Direct fetching of that commit failed.
기존 작업하던 pr을 merge하던 중 아래와 같은 에러가 떴다. 위 경로 중 최종 secret 경로 상에서 git remote -v를 git bash에 입력하면 application 파일들을 관리하던 private repo 주소가 뜬다. secret 폴더가 내가 생성한 submodule이 담긴 폴더였기 때문에 error 문구 중 path가 위와 같이 뜬 것이다.
그래서 내가 서브모듈로 설정해주었던 secret 경로로 프로젝트 root 경로에서 cd 명령어를 통해 이동했고 가장 최근 상태로 커밋 내역을 동기화시켜 fetch하고자 application 관련 파일이 모두 저장된 private repo로 부터 pull을 땡겼다. 그러나 Everything up-to-date라는 문구가 출력되었음에도 위 문제 상황이 해결되지 않았었다.
이 상황이 내가 merge를 했던 pr이 브랜치를 따로 파서 작업을 했던 부분이고 그 과정에서 submodule의 수정이 있었던 상황이었다(application 관련 파일의 변경 사항이 있어서 push한 뒤 secret 경로에 최신화를 마치고 merge를 했는데도 왜 위 에러가 발생했을까ㅜㅠ). 위 사진은 develop에 merge하여 cicd pipeline이 돌아가는 중에 발생한 에러였다.
그래서 앞으로 기능이 추가되거나 다른 민감정보가 추가될 때마다 submodule repo에 계속 변경사항을 업데이트하기 위해 push를 할 것이고 이때마다 이런 에러가 생기는 불편함을 겪을텐데 springboot application을 다른 방식으로 관리하는 방법은 없을까 생각하던 중!!
.gitignore 처리했던 application 관련 파일들을 pipeline 상에서 git secrets으로 불러오는 루트를 뚫어만 놓는다면 git secret 안의 내용은 쉽게 변경을 할 수 있으므로 application 파일 관리가 더 용이해지겠다라는 생각이 들어 submodule을 git secret으로 수정하게 되었다.
실제 아직 dev와 prod도 분리가 되지 않은 상황이었기 때문에 이때 같이 분리 작업을 해주었다.
우선 기존 application.yml 파일은 아래와 같았다. include로 되어있는 4가지 항목들은 .gitignore 처리가 되어있는 파일이라 git action에서 실제로는 git hub에 이 파일이 없기 때문에 submodule로 불러오든지 git secret을 통해 불러온 뒤에 빌드를 해주어야 jar파일을 ec2에서 실행했을 때 서버가 정상적으로 켜지며 제기능을 한다.
처음에 AWS Code Depoly, S3로 처음 배포 자동화 파이프라인을 설계할 때 이 부분을 몰랐기 때문에 datasource url등이 없어서 빌드는 되더라도 배포 이후에 ec2에서 서버 실행이 안되었었다. 그에 대한 해결책으로 application 파일을 submodules로 땡겨서 빌드 직전에 private repo에 접근하는 방식으로 파이프라인을 짰었고(이 과정에서 처음하는 DevOps 역할이라 문제를 분석하는 것에서부터 고치기까지 시간이 반나절이 소요되었만 배포 자동화에 대해 많이 깨우치게 되었다....) 이제 이 방법에서 git secrets로 변경하려고 한다.
spring:
profiles:
include: credentials, rds, s3, crawl
logging:
level:
com.whoa.whoaserver: DEBUG
여기서 profiles을 group으로 나누어 dev와 prod로 분리하였고 실제 local에서 실행할 땐 datasource url이 인식이 안되는 오류가 있어서 이 링크를 참고하여 intellj에서 active profile을 prod가 아니라 내가 원하는 dev로 설정하였다.
spring:
profiles:
group:
dev: "dev, rds, s3, crawl"
prod: "prod, rds, s3, crawl"
include:
- credentials
jpa:
hibernate:
ddl-auto: update
show-sql: true
logging:
level:
com.whoa.whoaserver: DEBUG
아래는 application-dev.yml이다. prod와의 차이점은 ddl-auto가 update인지 validate인지 여부이다.
spring:
config:
activate:
on-profile: "dev"
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
show_sql: true
format_sql: true
logging:
level:
org:
springframework:
web: DEBUG
hibernate:
orm:
jdbc:
bind: trace
아래는 application-prod.yml 파일이다. 이 파일은 cicd pipeline에 적용이 될 것이고 이제 내 로컬 개발 환경 상에서는 dev가, ec2 운영 환경 상에서는 prod로 운영되어 dev와 prod가 분리(pr 링크 참고)되는 상황을 만들었다.
spring:
config:
activate:
on-profile: "prod"
jpa:
hibernate:
ddl-auto: validate
properties:
hibernate:
show_sql: true
format_sql: true
logging:
level:
org:
springframework: ERROR
hibernate:
orm:
jdbc:
bind: trace
그 다음으로 주의할 점은 dev와 prod 뿐만 아니라 기존 include에 포함되어있었던 application-*.yml 파일도 마찬가지로 내용은 그대로 두고 아래의 코드를 추가해야 했다.
spring:
config:
activate:
on-profile: "각 파일별 application 이름을 쓰면 된다"
이제 이 프로필들을 git secrets에 등록을 하고 아래에서 어떻게 submodule에서 git secret으로 .gitignore 파일들을 불러왔는지 살펴보도록 하자.
해결 방법: git secrets로 on-profile 내용 불러오기
여기서는 반드시 빌드전에 먼저 on-profile application-*.yml을 불러와야 했으므로 cicd pipeline에서 빌드 전 부분만 수정되었다.
빌드 단계 직전까지 기존 submodule을 통해 불러왔을 때의 코드는 아래와 같았다.
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build-with-gradle:
runs-on: ubuntu-latest
steps:
- name: Checkout-source code
uses: actions/checkout@v3
with:
token: ${{ secrets.PRIVATE_REPO_ACCESS_TOKEN }}
submodules: true
ref: main
- name: JDK 17 설치
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
with token, submodules, ref를 삭제하고 아래와 같이 수정하였다. local에서는 intellj로 dev profile을 적용했고 배포 시에는 application-prod.yml이 실행되도록 하였다.
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build-with-gradle:
runs-on: ubuntu-latest
steps:
- name: Checkout-source code
uses: actions/checkout@v3
- name: JDK 17 설치
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Make application.yml
run: |
cd ./src/main/resources
touch ./application.yml
touch ./application-prod.yml
touch ./application-credentials.yml
touch ./application-rds.yml
touch ./application-s3.yml
touch ./application-crawl.yml
echo "$APPLICATION" > ./application.yml
echo "$APPLICATION_PROD" > ./application-prod.yml
echo "$APPLICATION_CREDENTIALS" > ./application-credentials.yml
echo "$APPLICATION_RDS" > ./application-rds.yml
echo "$APPLICATION_S3" > ./application-s3.yml
echo "$APPLICATION_CRAWL" > ./application-crawl.yml
env:
APPLICATION: ${{ secrets.APPLICATION }}
APPLICATION_PROD: ${{ secrets.APPLICATION_PROD }}
APPLICATION_CREDENTIALS: ${{ secrets.APPLICATION_CREDENTIALS }}
APPLICATION_RDS: ${{ secrets.APPLICATION_RDS }}
APPLICATION_S3: ${{ secrets.APPLICATION_S3 }}
APPLICATION_CRAWL: ${{ secrets.APPLICATION_CRAWL }}
shell: bash
cd 명령어로 application 파일들이 위치해야할 경로로 이동하여 touch를 통해 파일을 생성하고 echo를 통해 env 변수상에 저장해놓았던 미리 복붙해놓은 git secrets 파일들을 가져와 복사해준다.
여기서 주의할 점은 env: 부분의 들여쓰기 위치이다. run과 들여쓰기 위치가 동일해야하는데 내가 한번 더 들여쓰기를 해버려서 env를 찾을 수 없다는 에러가 떴었고 위치를 다시 조절하여 해결했다.
뭐 하나 쉬운게 없다.
이렇게 여러 시행착오를 통해 배운만큼 더 오래 기억에 남겠지~
'AWS & CICD' 카테고리의 다른 글
[AWS] RDS를 cmd로 localhost에 복제하기 (0) | 2025.02.23 |
---|---|
[DevOps] Docker Compose 블루그린 무중단 배포 성공 (0) | 2024.08.29 |
[AWS] Nginx 502 해결 시행착오 (0) | 2024.08.18 |
[AWS] CloudWatch로 Memory 모니터링 및 Email 경보 발송 (0) | 2024.07.02 |
[AWS] 프리티어 EC2 예기치 않은 중단 현상(feat. swap memory) (0) | 2024.06.23 |