개발일기
[Spring Boot] RDS public IP 요금 결제 안되게 구성하는 방법 본문
🔥 우선적으로 public IP를 구성하면 IPv4에 대한 요금이 지출되기에 privateIP로 선택해주었다. 완벽하게 RDS를 무료로 쓰기 위해서는 해당 방식으로 구현해야한다. 지금부터 무료로 사용하기 달려가보자..! 🔥
우선 public ip로 하던 것을 퍼블릭 액세스 불가능 선택
해당 RDS와 연결할 EC2 선택 ..!
이제부터 본격적으로 스프링에서 어떤방식으로 public IP를 구성하지 않으면 작성해야되는지 알아보자..!
spring:
config:
activate:
on-profile: "local"
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:[forwardedPort]/[디비명]?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
username: 디비 유저이름
password: 패스워드
ssh:
remote_jump_host: # ssh 연결할 중간 서버 주소, ec2 ip 주소
ssh_port: 22 # ssh 프로토콜 포트, 보통 22
user: # 유저명
private_key: / # ssh 연결 시 사용할 개인키 파일 경로
database_url: # RDS 엔드포인트 URL
database_port: # 포트 번호
위에와 같이 .yml파일을 작성해준다.
// ssh 터널링
implementation 'com.github.mwiede:jsch:0.2.17'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
ssh 터널링을 해주기 위해서는 위에의 임포트가 필수적이다.
package com.realworld.global.config.ssh;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import jakarta.annotation.PreDestroy;
import jakarta.validation.constraints.NotNull;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import java.util.Properties;
import static java.lang.System.exit;
@Slf4j
@Profile("local")
@Component
@ConfigurationProperties(prefix = "ssh")
@Validated
@Setter
public class SshTunnelingInitializer {
@NotNull
private String remoteJumpHost;
@NotNull
private String user;
@NotNull
private int sshPort;
@NotNull
private String privateKey;
@NotNull
private String databaseUrl;
@NotNull
private int databasePort;
private Session session;
@PreDestroy
public void closeSSH() {
if(session.isConnected()) {
session.disconnect();
}
}
public Integer buildSshConnection() {
Integer forwardedPort = null;
try{
log.info("{}@{}:{}:{} with privateKey", user, remoteJumpHost, sshPort, databasePort);
JSch jSch = new JSch();
log.info("creating ssh tunneling..");
jSch.addIdentity(privateKey);
session = jSch.getSession(user, remoteJumpHost, sshPort);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
log.info("start creating ssh session");
log.info("start connecting ssh connection");
session.connect();
log.info("success connecting ssh connection");
log.info("start forwarding");
forwardedPort = session.setPortForwardingL(0, databaseUrl, databasePort);
} catch (Exception e) {
log.info("fail to make ssh tunneling");
this.closeSSH();
e.printStackTrace();
exit(1);
}
return forwardedPort;
}
}
해당 부분의 코드는 ssh 로 연결을 해주기 위한 클래스이다.
@Component로 등록이 되어있어 Spring Context가 실행될 때, Spring 이 실행될 때 자동으로 로드된다. 이를 통해서 dataSource를 연결할 계획
이런식으로 해주어야 하는 이유는 private ip 이면 ec2 내부에서는 RDS 접근하여 디비에 담을 수 있으나, 로컬에서는 실행 할 수 없다. 그래서 ssh 방식을 통해서 dataSource에 접근하는 것이다.
package com.realworld.global.config;
import com.realworld.global.config.ssh.SshTunnelingInitializer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import javax.sql.DataSource;
@Slf4j
@Profile("local")
@Configuration
@RequiredArgsConstructor
public class SshDataSourceConfig {
private final SshTunnelingInitializer initializer;
@Bean("dataSource")
@Primary
public DataSource dataSource(DataSourceProperties properties) {
Integer forwardPort = initializer.buildSshConnection();
String url = properties.getUrl().replace("[forwardedPort]", Integer.toString(forwardPort));
log.info("url={}",url);
return DataSourceBuilder.create()
.url(url)
.username(properties.getUsername())
.password(properties.getPassword())
.driverClassName(properties.getDriverClassName())
.build();
}
}
DataSource에 해당하는 코드를 작성해주었다.
'photocard backend server 개발일기' 카테고리의 다른 글
🖥️ [모니터링 툴] AWS EC2 docker-compose 그라파냐, 프로메테우스 설치 (1) | 2024.12.26 |
---|---|
정적 코드 분석 AWS EC2 SonarQube 사용하여 Github Action CI 하기 (2) | 2024.12.20 |
[AWS] EC2 , Docker 서버 용량 최적화하기 (0) | 2024.12.16 |
[프리티어] 포토카드 DB AWS RDS + Mysql 구현하기 설정편 (0) | 2024.12.16 |
STOMP, JWT 인증을 사용한 채팅 구현 (4) | 2024.09.03 |