[Spring/TIL] Github Actions 배포환경에서 Github Submodule로 application.yml 관리하기.

resilient

·

2023. 4. 19. 23:40

728x90
반응형

현재 프로젝트의 핵심 기능 구현이 어느 정도 마무리가 되면서 이제 배포환경을 고려해야 했습니다.

 

가장 흔하게 사용하는 Jenkins 말고 이번에는 Github Actions를 사용해 보기로 결정했는데요. 여러 방면으로 Jenkins와 Github Action의 장점을 따져본 뒤 지금 프로젝트에는 Github Actions가 더 낫다고 판단했습니다.

 

이번 포스팅에서는 Github Actions CI/CD 환경에서 프로퍼티 설정들을 관리하는 방법들에 대해서 정리해보려고 합니다.

 

0. Github Action을 사용한 이유?

 

첫 번째로 Jenkins는 초기 설정 시 Github Actions 보다 리소스가 많이 발생합니다. 호스팅을 처음부터 끝까지 직접해야 하기 때문에 문서 또한 관리를 해야 하죠. Github 사용 시 작업들이 대부분 클라우드에서 작동하기 때문에 로컬에서 실행할 수도 있는데요. Jenkins는 공식 관리 서비스 제품이 없습니다.

 

두 번째는 Github Actions는 yaml 파일과 sh 파일로 작성되고 따라서 코드처럼 편집, 재사용, 공유가 쉽습니다.

 

세 번째로는 Github을 사용할 경우 저장소를 포크만 하더라도 Github Actions 작업도 포크가 되기 때문에 다른 사람의 작업물도 더 쉽게 실행 가능하죠.

 

더 많은 이유가 있겠지만 사실 가장 큰 이유는 '규모에 따른 리소스가 Jenkins보다 적게 들고 한 번 써보고 싶어서' 였습니다.

 

1. application.yml 관리 방법

 

현재 properties파일 말고 application.yml 파일로 관리를 하고 있습니다.

 

AWS계정 정보, DB계정 정보를 포함한 애플리케이션에 필요한 모든 정보들이 application.yml에 담기게 되는데요.

 

민감한 정보들이 Github Repository 올라가면 안 되겠죠?

 

하지만 Repository에 올라가지 않게 하려면 gitignore에 추가가 되어야 하는데요.

 

배포를 할 경우에는 무조건적으로 필요한 application.yml을 어떻게 관리할 수 있을까요?

 

2. Jasypt를 사용한 설정 파일 암호화

 

Jasypt(Java Simplified Encryption)이라는 라이브러리를 사용하는 방법입니다.

 

Jasypt를 사용할 경우 application.yml 파일 예시는 아래와 같습니다.

 

spring:
  datasource:
    url: ENC(GE1npS9T7z/GOqwcRLBPMbUSGQzj+WgSNCFvH5PoU83Z6ljps9ninis4P+4WNxBNz/RNhOrmReM=)
    username: ENC(GFHmfIqHmrTaME93hLZqgg==)
    password: ENC(oBMaRuMSZyJDmebXacU8Vg==)
    
jasypt:
  encryptor:
    bean: jasyptStringEncryptor

 

Jasypt를 사용한 암호화 방법은 구체적으로 다루지 않겠습니다.

 

결과적으로 암호화 방법은 사용하지 않았습니다. 이유는 코드레벨에서 따로 config 작업을 해줘야 하고, 암호화를 위해 라이브러리를 설치하는 것 자체가 과연 필요한가? 라는 의문이 들었기 때문이죠.

 

또한 암호화 복호화를 하기 위해서는 키가 필요한데 키를 직접 관리해야 한다는 불편함과 키가 누출되었을 경우 암호화가 무의미해지기 때문에 보안성이 뛰어나다고 할 수도 없습니다.

 

 

3. Github Secret 사용하기

 

Github Action을 사용하기 위해서 필요한 secret키들이 있습니다. 예를 들어 Code deploy에 사용되는 AWS key 값들을 애플리케이션이 실행되기 전 Github Action을 사용해서 빌드를 하는 시점에서 사용되는 값들 등이 있죠.

 

Github Repository - Settings - Secrets and Variables - Actions에 가면 Github Actions에 필요한 값들을 Secret에 넣어놓고 사용할 수 있죠. 

Github Actions에 필요한 secrets

 

위 값들은 아래와 같이 github/workflows/gradle.yml 파일 안에서 사용됩니다.

secrets.xxx 사용

 

이 방식을 이용해서 yml 파일을 관리할 수 있습니다.

 

Secrets는 Key와 Value로 이루어져 있는데요.

 

Value에 배포에 필요한 application.yml 파일을 모두 긁어서 붙인 후에, 해당 Key값으로 불러와서 Github Actions 실행에 필요한 worksflow에서 명령어로  main/resources/application.yml 파일에 copy 하는 방법을 사용하는 것입니다.

 

예를 들어보겠습니다.

 

위와 같이 Secret에 application.yml 파일을 붙여 넣고 사용하는 방법입니다.

 

여기서 주의할 점은 Secret의 Value값에는 해당 application.yml 파일을 그대로 붙여 넣으면 안 됩니다. Base64 포맷으로 인코딩을 해서 붙여 넣어야 합니다.

 

위와 같이 Secret을 지정해 준 뒤 Github Actions 실행에 필요한 worksflow 파일을 아래와 같이 작성해 주면 됩니다.

 

- uses: actions/checkout@v2
    - run: touch ./src/main/resources/application.yml
    - run: echo "${{env.APPLICATION}}" > ./src/main/resources/application.yml
    - uses: actions/upload-artifact@v2
      with:
        name: application.yml
        path: ./src/main/resources/application.yml

 

자 그러면 이 방법을 사용했냐? 아닙니다.

 

매번 application.yml 파일이 수정될 때마다 secret에 들어와서 Base64로 인코딩 된 application.yml 파일을 붙여 넣은 뒤 Github Actions를 실행해서 빌드를 하는 작업을 너무 번거롭습니다.

 

application.yml 파일이 수정이 되면 commit push 및 develop branch merge를 통해서 바로바로 Github Actions로 배포를 하게 설정을 해놨기 때문에 더 간단하고 안전한 방법이 필요했습니다.

 

4. Github Submodule 사용하기

 

결과적으로 이 방법을 선택했습니다.

 

Submodule은 말 그대로 보조해 주는 모듈을 추가해 주는 것입니다.

 

사용 중인 pinnit-backend라는 레포지토리 안에 application.yml 파일만 관리하는 submodule-config라는 레포지토리를 넣어서 사용한다고 생각하면 됩니다. 먼저 pinnit-backend/projces/src/main/resoucres에 있던 application.yml 은 gitignore에 추가해 줍니다.

 

4-1. submodule 생성

 

프로퍼티들을 관리하는 Submodule을 사용하기 위해서는 먼저 Private 레포지토리를 생성해 줍니다.

 

Private submodule-config repository

 

4-2. Submodule 등록

 

pinnit-backend 레포지토리에 submodule-config 레포지토리를 Submodule로 등록을 해줘야 합니다.

 

pinnit-backend 경로에서 아래 명령어를 실행시켜 줍니다.

 

git add submodule https://github.com/team-pinnit/submodule-config

 

다음으로 pinnit-backend 레포지토리에. gitmodules를 추가해줘야 합니다.

 

.gitmodules 추가

 

gitmodules 파일 안에는 pinnit-backend와 submodule-config 간의 Submodule 관계를 맺어주는 설정이 필요합니다.

 

branch에는 default branch가 master 브랜치가 아닐 경우 명시해줘야 합니다. 현재는 default 브랜치가 develop이기 때문에 아래와 같이 작성해 줬습니다.

[submodule "project/submodule-config"]
	path = project/submodule-config
	url = https://github.com/team-pinnit/submodule-config
	branch = develop

 

위의 과정을 거치게 되면 아래처럼 최신 commit hash와 함께 submodule-config가 private으로 관리되고 있다는 사실을 확인할 수 있습니다.

 

4-3. application.yml이 수정되었을 경우

 

submodule-config 레포지토리에서 수정한 application.yml 파일들을 pinnit-backend에도 업데이트를 시켜줘야 배포 시에 최신 application.yml 파일이 적용될 것입니다. 아래 명령어를 입력하면 업데이트가 가능합니다.

 

git submodule update --remote

 

주의할 점이 하나 있습니다.

 

위의 명령어를 입력한다고 해서 pinnit-backend에 적용이 되는건 아닙니다.

Git 을 사용할 때 변경사항이 생기면 remote에 푸시를 해야 적용이 되는 것 처럼 변경된 업데이트 된 최신 submodule 커밋을 pinnit-backend에 적용시키려면 아래 명령어가 필요합니다.

git submodule foreach git pull 

git add. 
git commit
git push

위의 과정을 마치면 이제야 비로소 pinnit-backend 레포지토리에 적용이 됩니다.

 

5. Github Action에 Submodule 등록하기

 

되게 사소한 점을 빼먹어서 가장 시간을 많이 썼던 과정입니다.

 

먼저 Github Actions 실행을 위한 worksflow/gradle.yml 파일에 아래 명령어를 추가해 주면 됩니다.

 

- name: Checkout 
      uses: actions/checkout@v1
      with:
        token: ${{ secrets.ACTION_TOKEN }}
        submodules: true

 

ACTION_TOKEN은 profile - settings - Personal access tokens - Tokens(classic) 카테고리에서 AUTH_TOKEN을 발급받아서 위에서 언급했던 Secret에 추가해 주면 됩니다.

 

여기서 주의할 점은 제가 Intellij나 다른 서비스에서 사용하는 Github AUTH_TOKEN 생성 방식과는 다르게 Expire을 반드시 설정해 줘야 한다는 점입니다. 최소 30일간의 Expire date를 설정해 줘야 정상적으로 작동합니다.

Expire 추가 필수!

 

위와 같은 과정들을 모두 거치면 아래와 같이 Submodule을 사용해서 application.yml 관리를 적용한 빌드가 성공하고 정상적으로 배포가 됩니다.

 

배포 완료

 

6. 정리

 

이번 포스팅에서는 Github Actions를 사용한 배포 및 Github Actions에서 Submodule을 사용해서 프로퍼티들을 관리하는 방법에 대해서 정리해 봤습니다.

 

CI/CD는 개발자가 본인이 편하기 위해 필수적인 작업이라고 생각합니다.

 

아직은 Github Actions나 Jenkins를 능숙하게 다루지는 못하지만 프로젝트나 실무를 하면서 많은 CI/CD 환경을 경험해 보고 상황에 맞게 배포 환경을 판단할 수 있는 능력이 꽤나 중요하겠다는 생각이 들었습니다.

 

CI/CD에 대해서 조금 더 공부해 보고 적용해 본 뒤 정리를 잘해서 블로그에 정리를 해보려고 합니다.

 

감사합니다.

반응형