본문 바로가기

SpringFramework/Spring Cloud (스터디)

Spring Cloud - (5장) 컨피그를 사용한 분산 컨피규레이션

분산 컨피규레이션?

애플리케이션의 컨피규레이션을 팻 JAR 파일 안에 제공하게되면, 마이크로서비스 인스턴스를 다시 컴파일하거나 다시 배포해야 하는 문제가 발생하는데, 분산 컨피규레이션을 사용하면 이러한 문제가 해소

 

- 클라우드 네이티브 환경에서 가장 인기 있는 표준

- 분산 시스템에서 외부 컨피규레이션을 위해 서버 측과 클라이언트 측을 지원

- 전체 환경에 걸쳐 애플리케이션을 위한 외부 속성을 관리하는 중앙의 단일 저장소를 두어서 사용

    사용예)

    VCS(버전관리 시스템)

    파일 시스템

    볼트(Vault)

 

- 서버는 단지 HTTP와 자원 기반(Restful API) 인터페이스를 노출하는 것이 전부이며, JSON 혹은 YAML, 속성 형태로 반환

(+ 암호화 복호화 수행 지원)

 

HTTP API 자원의 소개

컨피그 서버는 다양한 방법으로 호출할 수 있는 HTTP API를 제공한다. 아래와 같은 종단점이 제공된다.

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

- {application} : 애플리케이션 이름

- {profile} : active.profile (2.6.x에서는 spring.profiles.active)

- {label} : 선택적인 값으로, git 저장소의 브랜치 정보다. (기본값은 default branch이다)

 

- 기본적으로 스프링 클라우드 컨피그 서버는 컨피규레이션 데이터를 가져오려고 하는데, spring.profiles.active를 native (네이티브 프로파일을 활성화)하여 서버를 시작해야 컨피그 파일을 찾는다. (자동으로 되어있는듯)

classpath:/

classpath:/config

file:./

file:./config

(속성 또는 YAML 파일이 JAR파일 안에 위치할 수 있다는 의미)

VCS (깃백엔드)를 사용한 config 파일 생성 및 HTTP API 호출

- VCS의 주요기능인 commit, revert, branching과 같은 것들을 사용하면 중요한 운영작업들을 매우 쉽게 처리할 수 있다.

- 컨피그 서버 코드와 컨피그 파일을 강제로 분리하여 저장한다. 그리고 spring.cloud.config.server.git.uri 속성에 컨피그 속성 소스들을 볼러오도록 경로를 설정한다.

컨피그 서버와 컨피그 속성파일 저장소가 분리되었고, 컨피그 서버에서 깃 저장소를 설정한 모습.

(!) 예제를 위해 git 계정 인증을 사용하지 않도록 저장소를 설정했지만, 실제로는 username, password 등의 계정정보가 입력되어야 한다.

(!) file:/home/nodo3482/ys-spring-config 와 같이 로컬 저장소를 이용할 수도 있다.

 

- 당연하지만, 원격 VCS서버를 사용하면 모든 인스턴스와 쉽게 공유가 가능하다.

 

 

- Spring Config 서버 (PORT:8888)

https://gitlab.com/nodo3482/ys-spring-cloud/-/tree/main/eureka.config

 

- Spring Config 파일 VCS저장소

https://gitlab.com/nodo3482/ys-spring-config

 

아래의 예제는 컨피그 서버 API 엔드포인트 호출을 VCS저장소에 연동하여 호출해보는 부분을 테스트한 내용이다.

{application-name}/{profile}/{label} 의 엔드포인트가 JSON으로 응답하고있는 모습.
properties 엔드포인트로 호출
yml 엔드포인트로 호출

 

-> spring.config.name=configserver 속성을 사용하게 되면, 해당 속성에 정의된 이름의 .yml 파일을 사용하게 되는데, spring-cloud-config에서 기본적으로 제공하는 configserver.yml 파일을 사용할 수도 있다. (테스트용)

spring-config에서 제공하는 configserver.yml 파일 (ReadOnly)

 

-> 위의 예제처럼 컨피그 서버의 기본 포트는 8888 이지만,

포트를 변경하는 경우에는 클라이언트 애플리케이션에서 bootstrap.yml 파일의 spring.cloud.config.url 속성에 주소를 설정 (http://localhost:8889)해야 한다.

 

(spring boot 2.4이후로는 spring cloud에서 bootstrap.yml 지원을 중단하였으며, 아래의 링크를 참고하여 작성을 하면 된다)

- 참고링크: https://hongdor.dev/112

 

-> 컨피그 서버에서는 spring-cloud-starter-eureka 의존성을 포함해야 한다. (디스커버리 클라이언트 활성)

-> 클라이언트 서버에서는 컨피그 서버의 주소값을 가질 필요가 없으며, 컨피그 서버가 다를 경우에는 Service ID만 설정하면 된다.

spring.cloud.config.discovery.service-id 에 Service ID를 추가한다.

spring.cloud.config.discovery.enabled 를 true로 활성화하여 컨피규레이션 원격 속성 소스를 가져오도록 한다.

클라이언트 서버에서도 컨피그 서버를 이용하려면 spring-cloud-config-server 의존성이 추가되어야 한다.

 

디스커버리 서비스에 클라이언트 서비스와 컨피그 서버가 등록되어있는 모습

파일시스템 백엔드

- 컨피그 파일이 로컬 파일 시스템 또는 클래스 경로에서 로딩하여 속성 소스를 읽어오는 방법. 보통 우리가 흔히 알고있는 프로젝트 resources폴더에 yml, properties 설정파일에 작성하여 사용하는 방법을 말한다.

- 교육용이나 테스트용으로 사용하며, 운영용으로는 잘 사용하지 않는 방법이다.

- spring.cloud.config.server.native.search-locations 속성에 경로를 지정하여 디스크상의 속성 소스를 읽어올 수 있다.

  (file:/home/ys-cloud-config 등..)

- spring.cloud.config.server.native.add-label-locations 속성을 false(default: true)로 하면 위와같은 동작을 비활성화 한다.

URI에 플레이스홀더 사용하기

HTTP API 종단점(=엔드포인트)를 설명하면서 나온 application, profile, label 플레이스홀더를 활용하여 여러가지 방식으로 속성소스들을 가져올 수 있다. 특히, 깃 저장소를 사용할 때 커밋 ID브랜치, 태그명을 가지고 label에 매핑하여 사용할 수 있다.

 

- 컨피그 파일을 수정하고, 커밋ID를 추가하여 변경 이전의 정보를 가져오는 테스트 결과 화면이다.

cliend-service-zone2.yml 이라는 파일에 datasource 내용을 추가
(좌) 최신 내용이 반영되어 출력 / (우) 이전 히스토리를 커밋ID를 통해 내용을 가져옴

 

- 클라이언트에서도 위와같이 label 플레이스홀더를 사용할 수 있다. spring.cloud.config.label 속성에 추가해준다.

실제로 이렇게 사용하려면 깃 저장소 히스토리 관리가 엄격해져야 할 것같다.

- 단일 컨피그 서버에 여러 저장소를 구성할 수도 있다. 설계방식에 따라 사용할 수 있다. spring.cloud.config.server.git.repos 속성에 설정 값을 추가해준다.

=============예시=============

dev: https://giuthub.com/dev/ys-config

pre:

  pattern: pre*/abc*,*pre*/abc*

  url: https://giuthub.com/pre/ys-config

prod:

  pattern: prod*

  url: https://giuthub.com/prod/ys-config

=============================

볼트 (Vault)

: HashiCorp에서 개발된 크로스플랫폼 패스워드 및 인증 관리 시스템이다. 공개되면 안되는 비밀번호나 API Key, 토큰 등의 민감정보들을 저장하고 관리한다.

- 볼트는 docker 환경에서 구동이 가능하고, 필요에 따라 별도의 서버를 두어서 운영할 수도 있을 것이다.

docker run --cap-add=IPC_LOCK -d --name=vault -e 'VAULT_DEV_ROOT_TOKEN_ID=client' -p 8200:8200 vault

    => VAULT_DEV_ROOT_TOKEN_ID: 초기 루트 토큰

 

- 볼트는 서버에 값을 추가하거나 조회할 수 있는 CLI 인터페이스와 HTTP API를 제공해준다.

# 쓰기 CLI
$ vault write secret/hello value=world
# 읽기 CLI
$ vault read secret/hello

 

- API 레퍼런스 공식문서

 

HTTP API | Vault by HashiCorp

Vault has an HTTP API that can be used to control every aspect of Vault.

www.vaultproject.io

 

 

- 컨피그 서버에서 Vault를 사용할 경우, spring.cloud.config.server에 vault 인자를 사용하여 연결해주면 된다.

- 클라이언트 서버에서는 Vault에 access할 수 있는 token정보를 spring.cloud.config.token 속성에 추가해주어야 한다.

그밖에 추가 기능..

1] 시작 시 실패와 재시도

- 컨피그 서버에 접속이 안될 경우 성공할 때까지 접속을 시도하게 할 수 있다. spring.cloud.config.failFast (default:false) 속성을 true로 변경해준다.

- spring.cloud.config.retry.* 속성으로 설정값을 변경할 수 있다.

- initial-interval: 재시도 요청의 초기 시간 간격 (ms)

- max-attempts: 최대 요청 횟수

- max-interval: 재시도 요청의 최대 시간 간격 (ms)

- multiplier: 시간의 간격 곱수를 나타냄. (재시도 요청시 네트워크 연속적인 충돌을 방지하기 위함) 1.2 -> 1.44 -> 1.72 ....

 

2] 클라이언트 안전하게 하기

- 컨피그 서버도 기본 인증을 사용해 안전하게 할 수 있다. 스프링 시큐리티를 사용할 수 있다.

- 이때, 클라이언트 서버들은 username과 password를 설정해두어야 한다.

재시작 없이 동적으로 컨피규레이션 다시 읽기

- 컨피그내용이 변경이 되는경우, 웹혹을 통해 변경을 알려서 스프링 클라우드 버스를 통해 레빗엠큐나 아파치 카프카를 구현하여 메시지 브로커에 전송하고, 클라이언트에서는 @RefreshScope 어노테이션을 통해 컨피규레이션을 다시 읽도록 하는 방법이 있다.

 

- POST - http://localhost:8081/refresh 를 호출하면 컨피그 갱신을 수행한다. (단, 서비스 디스커버리, 컨피그 서버가 활성화되어있어야함)

@Component
@RefreshScope
public class ClientConfiguration {
    @Value("${sample.string.id}")
    private String id;
    
    @Value("${sample.string.name}")
    private String name;
    
    public String toString() {
        return "id: "+this.id+", name: "+this.name;
    }
}

위의 코드처럼 @RefreshScope 어노테이션이 선언된 클래스내 프로퍼티들이 갱신되어서 변경된 값들로 응답을 한다. (재시작이 필요없다)

 

- 중간에 메시지 브로커(RabbitMQ, Apache Kafka)를 통해 변경 프로퍼티를 적용시킨다고 하였는데, 큐시스템 관련한 부분은 학습이 되지않아서 설명이 어렵다 ㅠㅠ.. 이번장에서는 이런 아키텍처로 동작한다는 것만 알아두자.

 

참고자료

= 서적 - 마스터링 스프링 클라우드 제 5장

= https://madplay.github.io/post/introduction-to-spring-cloud-config