스프링부트에서 Oracle Cloud ATP 사용 & CI/CD (github actions, GAE)

한얼·2023년 9월 3일
1
post-thumbnail

0. 문제점

기존 사용중이던 GCP Cloud SQL의 비용이 너무 비싸서(하루에 약 6,000원) Oracle Cloud ATP(Autonomous Transaction Processing)으로 이주하기로 하였습니다. 프리티어 기준 20GB까지 스토리지를 무료로 제공해주기 때문에 변경하지 않을 이유는 없었습니다.
문제는 기존에 사용하던 방식(호스트 주소&포트)과 달리 TNS 방식으로 연결해야 하며, 해당 과정에서 클라우드 전자지갑(Wallet)을 사용해야 하는데, 이를 CI/CD 파이프라인을 구축할 때 함께 고려해야 한다는 점이었습니다.

1. 전자 지갑 발급 & 스프링 프로젝트에 적용

기본적인 스프링부트 + GAE + github actions를 이용한 CI/CD는 여기를 참고해주세요.

OCI ATP 설정

클라이언트 인증서(전자지갑, Wallet)

Oracle Cloud에서 ATP 인스턴스를 생성 후, 데이터베이스 접속 버튼을 누르면 다음과 같은 화면을 확인할 수 있습니다.

여기서 전자 지갑 다운로드를 눌러 Wallet을 다운해줍니다.(*.zip) TNS 이름 중 _high를 사용할 것이므로 해당 TNS 이름을 기억해줍니다.

각 TNS 이름(TNS_NAME)에 대한 간략한 설명은 다음과 같습니다.

high : 동시성은 낮으나, 가장 리소스가 높고 쿼리가 병렬로 실행됩니다.
medium : 리소스가 줄어들었으나 그만큼 동시성이 높아집니다. 쿼리가 병렬로 실행됩니다.
low : 리소스가 최소이며 최고의 동시성을 갖습니다. 쿼리가 연속적으로 실행됩니다.
참고 : Database Service Names for Autonomous Data Warehouse

Spring Boot 설정

gradle.build

다음과 같은 코드를 dependencies에 추가합니다.

runtimeOnly 'com.oracle.database.jdbc:ojdbc8'
implementation 'com.oracle.database.security:oraclepki'
implementation 'com.oracle.database.security:osdt_core'
implementation 'com.oracle.database.security:osdt_cert'

application.properties

다음과 같은 코드를 추가합니다.

spring.datasource.url=jdbc:oracle:thin:@[TNS_NAME]?TNS_ADMIN=./src/main/resources/OracleCloud
spring.datasource.username=ADMIN
spring.datasource.password=${DB_PASSWORD}
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver

자세한 설명은 다음과 같습니다.

  • spring.datasource.url
    • jdbc:oracle:thin:@[TNS_NAME]?TNS_ADMIN=./src/main/resources/OracleCloud
    • [TNS_NAME]은 아까 기억해두었던 *_high를 넣으면 됩니다. Wallet은./src/main/resources/OracleCloud에 위치시킬 것이므로 TNS_ADMIN을 해당 경로로 설정하였습니다.
  • spring.datasource.username
    • OCI ATP의 기본 username은 ADMIN입니다.
  • spring.datasource.password
    • OCI ATP의 비밀번호는 시스템 환경변수로 설정할 것이므로, ${DB_PASSWORD}와 같이 작성하였습니다.

2. 로컬 테스트

로컬에서 OCI ATP가 제대로 연결되었는지 테스트해보려면 다음과 같은 과정을 거치면 됩니다.

전자 지갑(Wallet) 위치시키기

아까 전에 다운 받은 Wallet의 압축을 풀어 ./src/main/resources/OracleCloud에 위치시켜주세요.

전자 지갑은 github에 push되지 않도록 .gitignore 설정을 해두었습니다.

환경 변수 설정

DB_PASSWORD를 시스템 환경 변수에 등록해두어야 합니다.

a. Windows

  1. 윈도우 탐색창에 시스템 환경 변수 편집 검색
  2. 환경 변수 버튼 클릭
  3. 시스템 변수 새로 만들기 버튼 클릭 후, 변수 이름에 DB_PASSWORD, 변수 값에 OCI ATP 비밀번호 입력 후 적용

b. macOS/Linus

  1. bash 사용 시 ~/.bash_profile 또는 ~/.bashrc 파일을 열고 export DB_PASSWORD=[OCI ATP 비밀번호] 줄 추가
    zsh 사용 시 ~/.zshrc 파일을 열고 같은 줄을 추가
  2. source ~/.bash_profile 또는 source ~/.zshrc을 실행하여 적용.

연결 테스트

다음과 같은 코드를 추가하여 연결을 테스트합니다. 연결 성공 시 화면에 Success가 출력됩니다.

@RestController
public class TestController {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @GetMapping("/test")
    public String testConnection() {
        String sql = "SELECT 'Success' FROM dual";
        return jdbcTemplate.queryForObject(sql, String.class);
    }
}

3. CI/CD 구축

Github Secrets

기존 PROJECT_ID, GCP_SA_KEY와 더불어 두 개를 더 추가해주어야합니다.

DB_PASSWORD

OCI ATP 비밀번호를 등록해주면 됩니다.

OCI_WALLET

Wallet zip 파일을 base64로 인코딩한 결과(텍스트)를 등록해주면 됩니다. base64로 인코딩하려면 다음과 같은 코드를 사용하면 됩니다.

macOS/Linux

base64 -i OracleCloud.zip -o OCI_WALLET.txt

Windows

certutil -encode OracleCloud.zip OCI_WALLET.txt

즉, 총 4개의 Secrets이 존재해야합니다.

main.yaml

name: CICD

on:
  push:
    branches: [ develop ]
  workflow_dispatch:
  
jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3

      - name: Set up JDK 17
        uses: actions/setup-java@v2
        with:
          java-version: '17'
          distribution: 'adopt'

      - name: Decode and Unzip OCI Wallet
        run: |
          echo "${{ secrets.OCI_WALLET }}" | base64 --decode > oci-wallet.zip
          unzip oci-wallet.zip -d ./src/main/resources/OracleCloud

      - name: Set DB_PASSWORD for Github Env
        run: echo "DB_PASSWORD=${{ secrets.DB_PASSWORD }}" >> $GITHUB_ENV

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew
      
      - name: Build with Gradle
        run: ./gradlew build

      - name: Setup app.yaml with secrets
        run: |
          cd ./src/main/appengine
          echo "" >> app.yaml
          echo "env_variables:" >> app.yaml
          echo "  DB_PASSWORD: ${{ secrets.DB_PASSWORD }}" >> app.yaml
      
      - name: Auth to GCP
        uses: 'google-github-actions/auth@v1'
        with:
          credentials_json: ${{ secrets.GCP_SA_KEY }}
        
      - name: Deploy to App Engine
        uses: 'google-github-actions/deploy-appengine@v1'
        with:
          deliverables: build.gradle
          project_id: ${{ secrets.PROJECT_ID }}

1. Set up JDK 17

github actions는 기본적으로 JDK 11을 사용하므로, JDK17 사용 시 따로 설정해주어야 합니다.

2. Decode and Unzip OCI Wallet

아까전에 인코딩했던 OCI_WALLET을 다시 디코딩하여 ./src/main/resources/OracleCloud 위치에 압축 해제합니다.

3. Set DB_PASSWORD for Github Env

테스트 코드에서 DB가 연결되었는지 검사하므로, github actions 서버 내의 DB_PASSWORD 환경 변수를 설정하여야 build 시 문제가 발생하지 않습니다.

4. Setup app.yaml with secrets

app.yaml에 추가적으로 DB_PASSWORD 환경 변수에 대한 코드가 다음과 같이 들어가야 GAE 내에서 문제 없이 Oracle Cloud ATP에 접근할 수 있습니다.

env_variables:
	DB_PASSWORD: [OCI ATP 비밀번호]

하지만 해당 코드를 직접 작성하는 것은 비밀번호 유출의 문제가 있으므로, 해당 단계를 통해 app.yaml에 코드를 추가합니다.

4. CI/CD 구축 완료 및 DB 연결 성공

성공적으로 자동 배포되고, Oracle Cloud ATP에 정상적으로 연결됨을 확인할 수 있습니다.

0개의 댓글