[Spring Cloud] Spring Cloud Config 정리
Spring Cloud Config 란?
Spring Cloud Config 는 분산 시스템에서 설정 정보(application.yml) 를 외부에 보관할 수 있도록 지원해주는 서비스이다. 이러한 Spring Cloud Config 를 이용했을 때 얻을 수 있는 장점은 다음과 같다.
- 여러 서버의 설정 파일을 중앙 서버에서 관리할 수 있다.
- 서버를 재배포 하지 않고 설정 파일의 변경사항을 반영할 수 있다.
위 도식은 Spring Cloud Config 가 동작하는 과정이다. 조금 간단하게 설명하자면 우선 세 가지 요소로 생각하면 좋다.
실제로 설정파일이 저장되는 Config 저장소(Git Repository, File System 등)가 있고, 이러한 저장소와 연결되어 설정파일을 관리해주는 Spring Cloud Config Server 가 있다. 마지막으로 Spring Cloud Config 를 이용하고 싶은 다양한 Client 들이 존재한다.
Client 가 Spring Cloud Config Server 에게 설정값을 요청하면 Server 는 설정파일이 저장된 Config 저장소에 접근해 조건에 맞는 영역을 탐색한다. 탐색한 결과로 가져온 최신 설정값을 가지고 Client 에게 전달하게 된다.
위 과정은 최초 Client 구동시이고 운영중인 상태에 바뀐 설정 값을 갱신하고 싶다면 /actuator/refresh API 를 호출함으로써 가능하다. Client 가 Server 에게 설정값을 요청하고 이렇게 가져온 최신의 설정 값을 Client 에게 전달하고 이를 통해 변경된 설정정보를 갱신하게 된다.
즉, /actuator/refresh API 를 사용해 서버를 재배포하지 않고도 설정정보를 갱신하는 것이다.
하지만 Spring Cloud Config 를 이용하는 Client 수가 엄청나게 많다고 했을 때 /actuator/refresh API 를 일일히 호출하는 것도 일이 될 수 있다.
Spring Cloud Bus 를 사용해 이러한 문제까지 개선하는 내용을 뒤에서 살펴볼 예정이다.
Spring Cloud Config Server
Spring Cloud Config Server 는 Config 저장소와 연결되어 중간 역할을 수행한다. 간단하게 몇 가지 Dependency 와 설정 정보만 추가하면 된다!
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
위 Dependency 를 추가하고 Spring Boot 의 Auto Configuration 을 이용해 @EnableConfigServer 어노테이션을 선언해주면 된다.
그리고 application.yml 파일에 다음과 같은 설정정보를 입력하면 Spring Cloud Config Server 의 설정은 완료된다.
server:
prot: 8888
spring:
cloud:
config:
server:
git:
uri: {Git Config Repository URI}
username: {Git Config Repository Username}
password: {Git Config Repository Password}
# Spring Cloud Config 는 Remote 에 있는 Git Repository 를 클론해온다.
# 하지만 이전에 클론해와서 로컬에 있는 정보의 폴더구조가 변경되는 등의 문제가 발생하면 제대로 업데이트할 수 없는데,
# 이러한 상황에서 강제로 Git Repository 를 클론하기 위한 설정이다.
force-pull: true
timeout: 30
# Config 저장소 상에서 설정 파일을 탐색할 경로를 지정하는 설정이다.
# {application} 에는 Client 의 spring.application.name 값이 사용된다.
searchPaths:
- '{application}'
- '{application}/*'
위 설정에서는 다양한 설정들을 해줬지만 간단하게 spring.cloud.config.server.git.uri 만 있어도 동작은 한다. 조금 더 디테일적인 부분을 설정해주는 코드라고 생각하면 된다.
이외에도 굉장히 다양한 설정들이 있으니 공식 레퍼런스를 참고하자.
https://cloud.spring.io/spring-cloud-config/reference/html/
하지만 해당 Config Server 를 사용하는 Client 가 여러개라면 searchPaths 설정은 해주는게 좋다고 생각한다. 이를 설정했을 때 Config 저장소에서 Client 별로 디렉토리를 구분지어서 설정 파일을 관리할 수 있기 때문이다.
아니면 spring.cloud.config.server.git.uri = https://github.com/{application} 와 같이 설정해 저장소 자체를 Client 별로 구분하도록 설정할 수도 있다.
searchPaths 에서 사용된 {application} 은 뭘까..?
Client 가 Spring Cloud Config Server 에 설정 값을 요청할 때 다양한 정보를 제공해주는데
- {application} : Client 측의 spring.application.name 에 대한 정보
- {profile} : Client 측의 spring.profiles.active 에 대한 정보
- {label} : 버전을 매긴 설정파일들을 지정하는 Config Server 측의 기능
따라서 Spring Cloud Config Server 는 이러한 정보들을 활용해 설정 값에 사용할 수도 있고, 이를 통해서 적절한 설정 값을 찾아 Client 에게 보내주게 된다.
예를 들면 {application}-{profile}.yml 와 같은 설정 파일을 찾는 것이다.
그러면 Config Server 에서는 {application}.yml, {application}-{profile}.yml 와 같이 여러 설정 파일이 존재할 수 있는데 어떤 우선순위를 가지고 설정 파일을 선택할까?
- {application}-{profile}.yml
- {application}.yml
- application.yml
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
Spring Cloud Config Client
Spring Cloud Config Client 도 Server 못지 않게 몇 가지 Dependecny 와 설정 정보로 충분히 구현이 가능하다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
spring-cloud-starter-config 는 그렇다 치더라도 spring-boot-starter-actuator 는 어떤 역할을 수행하는 걸가? actuator 의 기본적인 역할은 해당 애플리케이션의 상태를 종합적으로 정리해서 Client 에게 제공해주는 역할을 수행한다.
/actuator/health, /actuator/env, /actuator/info 등 다양한 API 로 애플리케이션의 정보를 제공한다.
# actuator 기본 설정
management:
endpoint:
health:
show-details: never
endpoints:
web:
base-path: /servicemanager
exposure:
include: "*"
그 중에서도 /actuator/refresh 는 애플리케이션의 설정 파일을 다시 로딩하는 역할을 수행한다. 즉, Spring Cloud Config 와 결합하여 사용한다면 중앙에 있는 Config 저장소의 값을 변경하고 해당 API 를 실행하게 된다면 재배포 없이도 변경한 설정 정보를 반영할 수 있다는 것이다.
이후 bootstrap.yml 파일에 Spring Cloud Config Server 에 대한 정보를 입력하면 된다.
spring:
profiles: dev
cloud:
config:
uri: "http://config.ch4njun.com:8888"
profile: ${spring.profiles.active}, sample-${spring.profiles.active}
label: develop
---
spring:
profiles: qa
cloud:
config:
uri: "http://config.ch4njun.com:8888"
profile: ${spring.profiles.active}, sample-${spring.profiles.active}
label: develop
spring.cloud.config.profile 에 대한 부분은 찾아도 안나온다. 흐름상 여러 가지 설정파일이 필요한 경우 이용하는 설정값으로 생각된다. 추후 검색해서 찾게되면 추가로 포스팅할 계획이다.
spring.cloud.config.profile 은 Spring Cloud Config Server 에 전달할 Profiles 목록이다!!
Server 는 해당 목록에 해당하는 모든 설정 파일을 Client 에게 보내준다!
Spring Boot 2.4 이후에 달라진점
http://honeymon.io/tech/2021/01/16/spring-boot-config-data-migration.html
Spring Boot 2.4 이후에는 bootstrap.yml 을 기본적으로 애플리케이션이 로딩될 때 Context 초기화 작업이 지원되지 않는다. 즉, 위에서 작성한 설정 정보를 application.yml 보다 먼저 초기화 되는 bootstrap.yml 에 입력할 수 없다.
이를 해결하기 위해 Spring Boot 2.4 부터는
spring.config.import = optional:configserver:http://ch4njun.com:8888 와 같은 설정 정보를 application.yml 파일에 입력하는 방식을 기본적으로 사용한다.
spring:
config:
import: "optional:configserver:http://config.ch4njun.com:8888/"
cloud:
config:
name: my-config
profile: dev
하지만 만약 기존에 사용하던 bootstrap.yml 파일을 통한 설정방법을 이용하고 싶다면 spring-cloud-starter-bootstrap 의 Dependency 를 추가하거나 spring.cloud.bootstrap.enabled = true 설정을 두어 bootstrap.yml 을 활성화해야 한다.
그리고 spring.config.activate.on-profile 을 통해서 profiles 를 지정해야 한다는 점이 다르다. spring.profiles 속성은 Deprecated 되었다!
spring:
config:
activate:
on-profile: dev
cloud:
config:
uri: "http://config.ch4njun.com:8888"
profile: ${spring.profiles.active}, sample-${spring.profiles.active}
label: develop
---
spring:
config:
activate:
on-profile: qa
cloud:
config:
uri: "http://config.ch4njun.com:8888"
profile: ${spring.profiles.active}, sample-${spring.profiles.active}
label: develop