[MSA] Config Server 구축

C_Mungi·2024년 9월 20일

MSA

목록 보기
3/8
post-thumbnail

이번 포스트에서는 각 서비스들이 기동할 때 필요한 환경 변수들을 관리하는 Config Server에 대한 설명과 구축 방법에 대해 설명해보고자 합니다.

Config Server란

스프링 클라우드 구성은 분산 시스템에서 외부화된 구성을 위한 서버 및 클라이언트 측 지원을 제공합니다. 
Config 서버를 사용하면 애플리케이션의 환경 변수들을 관리할 수 있는 중앙 위치를 확보할 수 있습니다. 
클라이언트와 서버의 개념은 스프링 환경 및 속성소스 추상화와 동일하게 매핑되므로 스프링 애플리케이션과 
매우 잘 맞지만 모든 언어로 실행되는 모든 애플리케이션에서 사용할 수 있습니다. 
애플리케이션이 배포 파이프라인을 통해 개발자에서 테스트 및 프로덕션으로 이동할 때 해당 환경 간의 구성을 관리하고 
애플리케이션이 마이그레이션할 때 실행하는 데 필요한 모든 것을 갖추고 있는지 확인할 수 있습니다. 
서버 스토리지 백엔드의 기본 구현은 git을 사용하므로 레이블이 지정된 버전의 구성 환경을 쉽게 지원할 뿐만 아니라 
콘텐츠 관리를 위한 광범위한 도구에 액세스할 수 있습니다. 
대체 구현을 추가하고 스프링 구성으로 쉽게 연결할 수 있습니다.

Config Server를 사용함으로써 애플리케이션들의 환경 변수를 한 곳에서 집중 관리가 가능하다고 공식 문서에 언급되어 있습니다. 이를 통해 각 애플리케이션이 기동할 때 Config Server로 요청을 하고 Config Server는 해당 애플리케이션의 환경 변수들을 보내줌으로써 애플리케이션의 실행을 지원하게 됩니다.

자세한 내용은 Spring Config 공식 문서 를 참고바랍니다.


Config server 구축

이전 포스트에서 하위 모듈들을 구축하셨다면 아래와 같은 config-server 모듈이 존재할 것이고 오늘은 이 config-server를 구축해 이후 각 서비스들이 config-server를 통해 환경 변수를 조회 및 관리를 할 수 있도록 하겠습니다.

구축해야 할 내용은 다음과 같습니다.

  1. 의존성 주입 ( build.gradle )
  2. 로직 작성
  3. config server용 git repository 생성
  4. application.yml 수정
  5. 동작 확인

1. 의존성 주입

의존성은 lombok, Spring Cloud Config Server, Spring Security 3가지가 필요하다.


build.gradle

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.cloud:spring-cloud-config-server'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
}

tasks.register("prepareKotlinBuildScriptModel") {}

bootJar {
    enabled = true
}

jar {
    enabled = false
}

Security를 사용하는 이유는 다음과 같습니다.

각 애플리케이션의 환경 변수들을 관리하는 만큼 민감한 정보들을 다루게 됩니다. 민감한 정보들이란, DB의 비밀번호, 외부 API의 키 등입니다.

이처럼 보안이 중요한 요소가 있기에 Spring Security를 활용해 인증된 애플리케이션만 환경 변수들을 가져가도록 합니다.
또한 만일에 대비해 누가 언제 어떠한 설정에 접근했는지 추적을 할 수도 있습니다.

2. 로직 작성

로직은 Security에 대한 작성이 대부분입니다. SecurityConfig를 작성하겠습니다.
username과 password는 보안적인 대책이 필요하므로 따로 환경변수로 입력받게끔 했습니다.
필요하다면 프로젝트 기획에 따라 DB와 연결해 관리자 role을 부여한 계정을 생성하도록 하는 방법도 있지만 학습용이기에 확장하지 않고 사용하는 형태로 작성했습니다.

SecurityConfig.java

@Configuration
@EnableWebSecurity
public class SecurityConfig implements WebMvcConfigurer {
     
    @Value("${config.username}")
    private String username;

    @Value("${config.password}")
    private String password;

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests((auth) -> auth.anyRequest().authenticated())
            .httpBasic(Customizer.withDefaults())
            .build();
    }

    @Bean
    public UserDetailsService userDetailsService() {

        UserDetails admin = User.builder()
            .username(username)
            .password(passwordEncoder().encode(password))
            .roles("ADMIN")
            .build();

        return new InMemoryUserDetailsManager(admin);
    }
}

Security에 대한 작성은 여기까지가 전부이고 ConfigServer를 활성화하기 위해 main클래스에 @EnableConfigServer 어노테이션을 추가해야 합니다.

@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

3. git repository 생성

본래 Config Server에서 환경 변수들을 관리하는 방법은 여러가지 있습니다.

이미지 출처 : https://medium.com/javarevisited/centralized-configuration-for-microservices-using-spring-cloud-config-c7845cbccc34

위의 이미지와 같이 여러 방법들이 존재 하지만 Git 서비스를 가장 많이 사용한다고 합니다.

먼저 GitHub에서 다음 이미지와 같이 리포지토리를 생성을 하는데 꼭 Private로 만들어야 합니다.
위에서 언급했듯이 민감한 정보들을 다루니 Public 리포지토리를 만들어선 안됩니다.
이후, 비대칭 키를 통해서 리포지토리로 접속 할 예정입니다.

3-1. SSH Key 생성

Private로 만들어진 리포지토리를 외부에서 접속할 수 있도록 SSH Key를 생성해 위에서 생성한 리포지토리에 등록을 해야 합니다.

이때 쉘 환경에서 다음 명령어를 통해 생성하면 되는데
Windows 환경의 경우 git bash, Mac 환경의 경우 Terminal을 사용하면 됩니다.

다만 Key를 생성할때엔 많은 사람들이 rsa알고리즘을 사용하기도 하는데 Github에서는 rsa 알고리즘에 대한 보안 취약점이 있어 SHA-1 Error가 발생한다고 합니다. 그래서 저는 ecdsa 알고리즘을 사용하고자 합니다.

ssh-keygen -m PEM -t ecdsa -b 256 -C "임의의 코멘트"

명령어를 실행하면 /사용자/.ssh 경로에 생성 됩니다.

.ssh 경로가 어딘지 모르겠다면 아래 명령어를 실행하면 됩니다.

Mac의 경우

echo $HOME/.ssh

Windows의 경우

echo %userprofile%\.ssh

생성된 SSH Key 중 pub 확장자의 파일에 저장된 키 내용을 복사해주세요.

이후 리포지토리의 Settings > Security 탭의 Deploy keys > Add deploy key 버튼 클릭해주시고 임의의 제목을 입력한 후 Key 란에 복사했던 내용을 붙여넣어 주세요.

저는 이 리포지토리에 설정 파일들에 대한 작성 및 수정이 있을 예정이라 아래 Allow write access 체크박스에 체크를 했습니다. ( 체크를 하지 않는다면 IDE에서 파일 작성, 수정하고 PUSH하게 되면 작성 권한이 없어 에러가 발생합니다. )

Add key 버튼을 누르면 다음과 같이 키가 등록된 것을 확인 할 수 있습니다.

이후, Terminal 또는 Git bash에서 아래의 명령어를 실행하면 해당 SSH Key가 출력이 되는데 설정 파일(yml, properties)에 입력해야하니 현 단계에선 준비까지만 해주세요.

# ex) cat id_ecdsa
cat 생성한 SSH Key 이름

명령어를 실행하면 아래와 같은 값들이 출력이 됩니다.

4. application.yml 수정

프로젝트 또는 모듈을 생성하면 src/main/resoruce 경로에 application.properties 라는 파일이 생성되어 있을텐데 편의상 application.yml로 수정했습니다.

server:
  port: ${CONFIG_SERVER_PORT} # 일반적으로 8888 포트가 많이 사용됩니다.

spring:
  application:
    name: ${CONFIG_APP_NAME}
  cloud:
    config:
      server:
        git:
          uri: ${CONFIG_GIT_URI} # Github의 ssh uri를 복사해서 붙여넣습니다
          search-paths: config-file/**
          default-label: main
          ignore-local-ssh-settings: true
          privateKey: |
            -----BEGIN EC PRIVATE KEY-----
            3번에서 cat 명령어로 출력한 값을 여기에 붙여넣습니다
            -----END EC PRIVATE KEY-----
          host-key: ${GIT_HOST_KEY}
          host-key-algorithm: ${GIT_HOST_ALGORITHM}
config:
  username: ${CONFIG_USERNAME}
  password: ${CONFIG_PASSWORD}

${CONFIG_SEVER_PORT} : 일반적으로 8888 포트 번호를 많이 사용합니다.

${CONFIG_APP_NAME} : 임의의 문자열을 넣으셔도 되고 이름 설정을 하고 싶지 않으시다면 해당 설정을 삭제 하셔도 무방합니다.

${CONFIG_GIT_URI} : 아래와 같이 SSH의 URI를 복사해 붙여넣습니다.

${GIT_HOST_KEY} : 아래 명령어를 실행해서 출력된 값을 base64로 인코딩해 붙여넣습니다.

ssh-keyscan -t ssh-rsa github.com

${GIT_HOST_ALGORITHM} : ecdsa 알고리즘으로 키를 생성했기 때문에 ecdsa-sha2-nistp256 를 적습니다.

${CONFIG_USERNAME}${CONFIG_PASSWORD} 의 경우는 필요에 따라 설정을 하셔도 되고 Security 로직 작성 내용에서 언급했듯이 프로젝트 기획에 따라 대응하면 됩니다.

5. 동작 확인

위에서 작성한 내용이 잘 실행 되는지 로컬 환경에서 Config Server 애플리케이션을 동작해본 결과는 다음과 같습니다.

그리고 실제 웹에서 접속하게되면 입력한 경로에 맞는 설정 파일 내용들을 조회할 수 있습니다.
(※ 아래 이미지는 추후 서비스 애플리케이션의 설정파일들을 Config Server용 리포지토리에 등록하게 되면 확인 가능합니다.)


추가

동작 확인에서 언급했지만 각 서비스 애플리케이션의 설정파일들을 Config Server용 리포지토리에 등록을 해야하는데 다음과 같은 파일명 규칙에 맞춰 push해야만 합니다.

저장소 이름-저장소 환경.properties 또는 저장소 이름-저장소 환경.yml 일것.

위와 같은 규칙에 맞춰 설정 파일 이름이 되어야 아래와 같이 주소 변환이 이루어져 서버에서 동작됩니다.

http:HOST:PORT/저장소 이름/저장소 환경

예를들어 localhost:8888이고 yml의 이름을 accommodation-prod.yml인 경우
http:localhost:8888/accommodation/prod 로 접속이 가능하고 설정 내용들을 조회할 수 있습니다.


다음은 Eureka Server 주제로 포스팅하겠습니다.
profile
백엔드 개발자의 수집상자

0개의 댓글