티스토리 뷰

Spring

[Spring] Spring Cloud Config 도입하기 및 private 레포지토리 SSL로 연결 설정 및 privateKey 암호화

망나니개발자 2022. 6. 6. 10:00
반응형

이번에는 Spring Cloud Config에 대해 간단히 알아보고, 설정해보도록 하겠습니다.

 

 

 

 

1. Spring Cloud Config란?


[ Spring Cloud Config란? ]

Spring Cloud Config는 분산 시스템에서 외부화된 설정 정보를 서버 및 클라이언트에게 제공하는 시스템이다. 설정 서버는(Config Server)는 외부에서 모든 환경에 대한 정보들을 관리해주는 중앙 서버이다. 기본적으로 설정 정보 저장을 위해 git을 사용하도록 되어있어서 손쉽게 외부 도구들로 접근 가능하고, 버전 관리도 가능하다.

  • Spring Cloud Config Server(설정 서버): 버전 관리 레포지토리로 백업된 중앙 집중식 구성 노출을 지원한다.
  • Spring Cloud Config Client(설정 클라이언트) : 애플리케이션이 설정 서버에 연결하도록 지원한다.

 

 

 

 

[ Spring Cloud Config의 장점과 단점 ]

Spring Cloud Config 는 여러 서비스 들의 설정 파일을 외부로 분리해 하나의 중앙 설정 저장소 처럼 관리 할 수 있도록 해주며 특정 설정 값이 변경시 각각의 서비스를 재기동 할 필요없이 적용이 가능하도록 도와준다.

  • 여러 서버의 설정 파일을 중앙 서버에서 관리할 수 있다. 
  • 서버를 재배포 하지 않고 설정 파일의 변경사항을 반영할 수 있다.

 

 

하지만 이것이 모든 문제를 해결해주지는 않는다. Spring Cloud Config를 이용하면 다음의 문제들을 겪을 수 있으므로 주의해야 한다.

  • Git 서버 또는 설정 서버에 의한 장애가 전파될 수 있다.
  • 우선 순위에 의해 설정 정보가 덮어씌워질 수 있다.

 

이미 서비스가 실행중이라면 메모리에서 설정 정보를 관리해 문제가 없지만, 서비스가 시작될 때 만약 GIT 서버나 설정 서버에 문제가 있다면 서비스들까지 문제가 전파될 수 있다. 또한 설정 서버에 의해 장애 지점이 될 수 있으므로 설정 정보를 관리하기 위한 별도의 서비스 운영이 필요할 수도 있다. 또한 설정 파일이 여러 곳에 있을 수 있어 우선 순위에 주의해야 하는데, 자세히 살펴보도록 하자.

 

 

 

[ Spring Cloud Config 설정 파일 우선 순위 ]

설정 파일은 크게 다음의 위치에 존재할 수 있으며 다음의 순서대로 읽어진다. 나중에 읽어지는 것이 우선순위가 높다.

  • 프로젝트의 application.yaml
  • 설정 저장소의 application.yaml
  • 프로젝트의 application-{profile}.yaml
  • 설정 저장소의 {application name}/{application name}-{profile}

 

 

만약 읽어지는 순서대로 읽다가 동일한 값을 지니는 설정 정보가 있다면 덮어 씌워지므로 주의해야 한다. 예를 들어 'hello'이라는 이름의 애플리케이션에 local 프로파일인 환경변수가 로컬의 appliation.yaml, application-local.yaml에 있고, 설정 저장소의 application.yaml, hello/hello-local.yaml에도 있다면 다음의 순서대로 읽어진다.

  • 프로젝트의 application.yaml
  • 설정 저장소의 application.yaml
  • 프로젝트 application-local.yaml
  • 설정 저장소의 hello/hello-local.yaml

 

 

최종적으로 읽혀 적용되는 환경변수 값은 설정 저장소의 hello/hello-local.yaml 의 값이다. 만약 설정 정보가 산개되어 있다면 오히려 관리가 복잡해질 수 있으며, 동작 과정을 모른다면 장애가 될 수 있으므로 주의하도록 하자.

 

 

 

 

2. Spring Cloud Config 구축하기


[ Spring Cloud Config Server 구축 ]

  1. 설정 파일 저장소 구축
  2. 설정 서버 구축
  3. 설정 서버 실행 및 확인

 

 

1. 설정 파일 저장소 구축

가장 먼저 설정 파일들을 저장할 git 레포지토리를 만들어주도록 하자. 디렉토리 구조는 각자의 환경에 맞는 파일로 지정해주면 된다. 중요한 것은 파일 이름인데, {앱이름}-{프로파일}.yml 의 구조로 작성해주면 된다. 아래와 같은 파일들의 경우 lw-jp1-alpha.yml에서 lw이 앱이름이고, jp1-alpha가 프로파일에 해당한다. 실제 저장소는 깃허브를 참고하도록 하자.

  • lw-jp1-alpha.yml
  • lw-jp1-real.yml
  • nw-kr1-alpha.yml
  • nw-kr1-real.yml

 

 

2. 설정 서버 구축

설정 서버 구성을 위해서는 spring-boot-starter-web에 spring-cloud-config-server 의존성이 필요하다. 클라우드 설정이 전혀 없다면 이를 위해 Gradle을 기준으로 implementation 'org.springframework.cloud:spring-cloud-config-server' 과 함께 ext 부분과 dependencyManagement 부분을 추가해주면 된다. 실제 파일은 깃허브를 참고하도록 하자.

... 생략

ext {
    set('springCloudVersion', "2021.0.2")
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.cloud:spring-cloud-config-server'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

... 생략

 

 

그리고 설정 서버에서 application.yml에 다음과 같이 설정 내용을 추가해주어야 한다.

server:
  port: 8888
spring:
  application:
    name: config
  cloud:
    config:
      server:
        git:
          uri: https://github.com/MangKyu/spring-cloud-config-sample
          search-paths: test-cloud-config-file/**
          default-label: master

 

 

config 서버는 기본적으로 8888번 포트를 사용하므로 맞춰주도록 하자. 그 외에 설정 파일이 있는 위치와 디렉토리 등을 잡아주면 된다.

  • uri: 설정파일이 있는 깃 주소
  • default-label: 깃 주소의 브랜치 이름
  • search-paths: 설정 파일들을 찾을 경로

 

 

마지막으로 메인 클래스에 @EnableConfigServer 을 붙여주면 설정 서버 구성이 끝난다.

@SpringBootApplication
@EnableConfigServer
public class TestCloudConfigServerApplication {

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

}

 

 

 

 

3. 설정 서버 실행 및 확인

서버를 실행하면 설정 파일 저장소를 클론하고 설정 정보를 읽어오는데, spring cloud config server가 갖는 endpoint는 다음과 같다.

  • /{application}/{profile}[/{label}]
  • /{application}-{profile}.yml
  • /{label}/{application}-{profile}.yml
  • /{application}-{profile}.properties
  • /{label}/{application}-{profile}.properties

 

 

그러므로 다음과 같이 localhost:8888/{앱이름}/{프로파일}로 접근하면 정상적으로 동작함을 확인할 수 있다. 만약 private 레포지토리라면 SSL 설정이 추가로 필요하므로 아래에서 다시 살펴보도록 하자.

 

 

 

 

[ Spring Cloud Config Client 구축 ]

  1. 클라이언트 서버 구축
  2. 설정 파일을 읽기 위한 코드 추가
  3. 클라이언트 실행 및 확인

 

 

1. 클라이언트 서버 구축

Spring Cloud Config Client 실행을 위해서는 아래의 의존성이 필요하다. 마찬가지로 처음 Spring Cloud를 도입하는 과정이라면 ext와 dependencyManagements 설정이 필요하다. Gradle 설정 예시는 깃허브를 참고하도록 하자.

 

 

 

2. 설정 파일을 읽기 위한 코드 추가

그 다음 yaml 파일로부터 읽어올 설정 정보들을 작성해주어야 한다.

@Setter
@Getter
@ConfigurationProperties("com.mangkyu")
@RefreshScope
@ToString
public class MyConfig {

    private String profile;
    private String region;

}

 

 

여기서 @RefreshScope는 설정 정보가 바뀌면 다시 불러올 수 있도록 도와주는데, Git 주소에 있는 설정 파일을 수정했을시 /actuator/refesh 엔드포인트를 호출하면 변경된 설정 값이 반영된다. 추가적으로 위의 예시에서는 @ConfigurationProperties를 사용했으므로 당연히 @EnableConfigurationProperties(MyConfig.class)를 설정해주어야 한다.

그리고 클라이언트의 yaml에는 설정 서버의 정보와 애플리케이션 정보를 다음과 같이 입력해주면 된다. 만약 config server와 통신에 실패했을 때 에러를 던지고, 서버 실행을 멈추고 싶다면 "optional:" 부분을 제거해주면 된다.

spring:
  application:
    name: nw
  profiles:
    active: kr1-real
  config:
    import: optional:configserver:http://localhost:8888

 

 

그리고 설정 값이 제대로 불러와졌는지 확인하기 위한 컨트롤러를 만들어 주도록 하자.

import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class ConfigController {

    private final MyConfig myConfig;

    @GetMapping("/config")
    public ResponseEntity<String> config() {
        System.out.println(myConfig);
        return ResponseEntity.ok(myConfig.toString());
    }

}

 

 

 

 

3. 클라이언트 실행 및 확인

설정 클라이언트를 실행해 호출해보면 정상적으로 적용됨을 확인할 수 있다. 하지만 대부분은 private 레포지토리를 사용할 것인데, 이때는 SSL로 연결을 해주어야 한다.

 

 

 

 

 

3. private 레포지토리 SSL로 연결 설정 예시


[ private 레포지토리 SSL로 연결 설정하기 ]

  1. 설정 서버에서 비대칭키 생성하기
  2. public key를 deploy key에 등록하기
  3. 설정 서버의 application.yaml 수정해주기

 

 

1. 설정 서버에서 비대칭키 생성하기

가장 먼저 다음의 명령어로 비대칭키를 생성해주도록 하자. 해당 비대칭키는 설정 서버가 설정 파일 깃 저장소에 연결될 때 사용된다. 보안을 위해 rsa 키 대신 ecdsa을 사용해야 한다. 만약 그렇지 않으면 GitHub SHA-1 error 에러가 발생하면서 원격 저장소의 파일을 읽어오는데 에러가 발생할 수 있다. 참고로 22.03.15 이후로 github 에서 RSA 를 이용한 SHA-1 인증을 더 이상 지원하지 않는다. 또한 Ubuntu 역시 Ubuntu22부터 RSA-SHA1 방식을 지원하지 않는다. 

ssh-keygen -m PEM -t ecdsa -b 256
// ssh-keygen -m PEM -t rsa -b 4096 보안 취약점 때문에 GitHub SHA-1 error가 발생할 수 있음

 

 

2. public key를 deploy key에 등록하기

그 다음 설정 파일 깃 저장소의 deploy key에 공개키를 저장해주어야 한다. 공개키는 비대칭키를 생성한 서버에서 다음으로 조회가능하다.

cat /home1/irteam/.ssh/id_ecdsa.pub

 

 

공개키는 Project Settings의 deploy keys에서 등록가능하다.

 

 

 

3. 설정 서버의 application.yaml 수정해주기

그 다음 Spring Cloud Config 서버의 설정 파일을 수정해주어야 한다. 아래의 설정 파일을 복사한 다음에 개인에 맞게 uri, search-paths, hostKey, hostKeyAlgorithm, privateKey, passphrase 부분을 중점적으로 수정해주면 된다.

server:
  port: 8888
spring:
  cloud:
    config:
      server:
        git:
          default-label: master
          uri: git@github.com:MangKyu/spring-cloud-config-sample.git
          search-paths: test-cloud-config-file/**
          ignoreLocalSshSettings: true
          strictHostKeyChecking: false
          hostKey: hostKey // hostKey를 base64 인코딩한 값
          hostKeyAlgorithm: ecdsa-sha2-nistp256 // 비대칭키 생성 알고리즘
          privateKey: |
            -----BEGIN EC PRIVATE KEY-----
            
            ... 생략
            
            -----END EC PRIVATE KEY-----
          passphrase: passphrase // 비대칭키 생성 시 입력한 값

 

 

 

hostkey는 다음과 같이 설정 서버에서 ssh-keyscan으로 찾은 값을 base64 인코딩해주면 된다.

ssh-keyscan -t ssh-rsa github.com

 

 

개인 키는 다음의 명령어로 조회한 값을 입력해주면 된다. 그런데 주의할 점은 위와 같이 설정 파일에 privateKey를 입력한다면 값에 "|"가 들어가야 하므로 빼먹지 않도록 주의해야 한다는 것이다. 그리고 실행 후 확인해보면 정상적으로 SSL 연결 설정 되었음을 확인할 수 있다.

cat /home1/irteam/.ssh/id_ecdsa

 

 

 

4. privateKey 암호화

보안 상의 이슈로 privateKey를 암호화 해야 할 수 있다. 그런 경우에는 Jasypt를 적용하면 되는데, 이와 관련에서는 다음 포스팅에서 설명하고 있으니 필요한 경우 참고하도록 하자.

 

 

 

 

현재 사내에서 설정 파일이 여러 프로젝트에 중복되어 있는데, 값이 바뀌면 모든 프로젝트들에서 변경해주어야 합니다. 유지 보수가 번거로워 Spring Cloud Config를 도입하게 되었는데, 만약 비슷한 저와 상황이라면 도입을 검토해보시는 것도 좋을 것 같습니다!

또한 현재 기준으로는 원격 저장소의 설정 파일을 변경해도 값이 자동으로 갱신되지 않습니다. 갱신하려면 actuator 의존성을 추가하고 POST로 /actuator/refresh 요청을 보내야 하는데, 모든 서버에서 이것을 호출하는 것은 번거롭습니다. 그러므로 다음 포스팅에서는 변경된 설정 값을 편리하게 자동으로 갱신하는 방법들에 대해 알아보도록 하겠습니다.

그 외에도 Config Server를 사용하면서 주의할 점이 있는데, 관련 내용은 이 포스팅을 참고해주세요!  감사합니다:)

 

 

 

 

관련 포스팅

  1. Spring Cloud Config 도입하기 및 private 레포지토리 SSL로 연결 설정 및 privateKey 암호화
  2. Spring Cloud Config 설정 파일 내용을 갱신하는 방법, Spring Cloud Bus 없이 자동 갱신하기
  3. Spring Cloud Config 사용 시의 주의사항 및 에러 해결 (Internal Server Error, RSA key with SHA-1)

 

 

 

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함