- 스프링 클라우드의 구성 서버는 애플리케이션의 모든 마이크로서비스에 대해 중앙 집중식의 구성(config)를 제공한다.
- 구성 서버를 사용하면 애플리케이션의 모든 구성을 한 곳에서 관리할 수 있다.
구성 공유하기#
- application.yml 또는 application.properties 파일
- 속성만 변경하기 위해 애플리케이션을 재배포해야된다.
- 데이터베이스 비밀번호와 같은 일부속성들은 개발자 조차 접근할 수 없도록 해야한다.
- 자바 시스템 속성이나 운영체제의 환경 변수에 구성 속성을 설정하는 경우
- 속성의 변경으로 인해 애플리케이션이 재시작되어야 한다.
- 데이터베이스 비밀번호와 같은 일부속성들은 개발자 조차 접근할 수 없도록 해야한다.
- 중앙 집중식으로 구성을 관리
- 구성이 더 이상 애플리케이션 코드에 패키징되어 배포되지 않는다.
- 공통적인 구성을 공유하는 마이크로서비스가 자신의 속성 설정으로 유지, 관리하지 않고도 동일한 속성들을 공유할 수 있다.
- 보안에 민감한 구성 속성은 애플리케이션 코드와 별도로 암호화하고 유지, 관리할 수 있다.
구성 서버 실행하기#
- 구성 서버는 클라이언트가 되는 다른 서비스들이 구성 속성을 사용할 수 있도록 REST API를 제공한다.
- Git과 같은 소스 코드 제어 시스템에 구성 속성을 저장함으로써 애플리케이션 소스 코드처럼 구성 속성의 버전, 분기 등을 관리할 수 있다.
- 구성 속성을 사용하는 애플리케이션과 별도로 구성 속성을 유지, 관리하므로 애플리케이션과 독립적으로 버전을 관리할 수 있다.
- 해시코프의 Vault는 보안 처리된 구성 속성을 유지, 관리할 때 유용하다.

구성 서버 활성화하기#
- 스프링 클라우드 구성 서버 스타터 의존성
@EnableConfigServer
애노테이션으로 활성화- 구성 서버의
spring.cloud.config.server.git.uri
속성으로 속성을 관리할 git 저장소 uri 입력 - REST API를 통해서 구성 속성을 요청할 수 있다.
curl localhost:8888/application/default
- 브랜치 명은 생략하면 master가 기본값이 된다.


Git 리퍼지터리에 구성 속성 저장하기#
- Git 리퍼지터리에 저장할 application.yml 파일
curl localhost:8888/someapp/someconfig
의 응답 결과
{
"name": "someapp",
"profiles": [
"someconfig"
],
"label": null,
"version": "95df-cbc3bca106199bd804b27a1de7c3ef5c35e",
"state": null,
"propertySources": [
{
"name": "http://locahost:10080/tacocloud/tacocloud-config/application.yml",
"source": {
"server.port": 0,
"eureka.client.service-url.defaultZone": "http://eureka1:8761/eureka/"
}
}
]
}
- Git 리퍼지터리의 루트 경로가 아니라 서브 디렉터리에 구성 속성을 저장하려면 구성 서버 자체의 속성으로
spring.loud.config.server.git.search-paths
를 추가하면 된다. - 복수 개의 서브 디렉터리도 가능하다.
spring.cloud.config.server.git.default-label
속성을 지정하면 기본 라벨이나 브랜치를 변경할 수 있다.- 아래의 예에서는 sidework 브랜치가 기본 브랜치가 된다.

- Git 리퍼지터리에 접근할 때 인증으로 사용자 이름과 비밀번호를 설정할 수 있다.
공유되는 구성 데이터 사용하기#
- 구성 서버에 접근할 클라이언트 서버 구성 방법
- 의존성 추가
spring.cloud.config.uri
속성에 구성 서버의 위치 지정
- 구성 서버를 서비스 레지스트리(유레카 등)에 등록한 후 클라이언트는 서비스 레지스트리로부터 구성 서버의 위치를 가져오는 방법도 있다.
- 하지만 이 방법은 마이크로서비스가 시작되는 시점에 두 번의 호출이 필요해진다.
- 구성 서버를 발견하기 위해 유레카에 호출
- 구성 데이터를 가져오기 위해 구성 서버에 호출
- 애플리케이션이 시작되면 구성 서버에 요청해서 속성 값을 받고 이를 캐싱한다.
- 따라서 중간에 구성 서버의 실행이 잠깐 중단되더라도 구성 속성을 사용할 수 있다.
애플리케이션이나 프로파일에 특정된 속성 제공하기#
애플리케이션에 특정된 속성 제공하기#
- 애플리케이션 이름과 상관없이 모든 애플리케이션은 application.yml 파일의 구성 속성을 받는다.
- 그러나 각 서비스 애플리케이션의
spring.application.name
속성이 구성 서버에 요청할 때 요청할 때 전송된다, 그리고 이 속성 값과 일치하는 이름의 구성 파일이 있으면 이 파일에 저장된 속성들이 반환된다.- 예: 4개의 마이크로서비스(ingredient-service, order-service, tacoservice, user-service)이 각 서비스 애플리케이션의
spring.application.name
속성에 지정하고, 구성 서버의 Git 백엔드에 ingredient-service.yml, order-service.yml, taco-service.yml, user-service.yml이라는 이름의 YAML 구성 파일들을 생성하면 된다. 
- 만일 application.yml의 공통 속성과 애플리케이션에 특정한 구성 파일의 속성이 중복될 때는 애플리케이션에 특정된 속성들이 우선한다.
프로파일로부터 속성 제공하기#
- 프로파일에 특정된 속성 지원
- 프로파일에 특정된 .properties 파일이 YAML 파일을 제공한다. 예: application-production.yml
- 하나의 YAML 파일 내부에 여러 개의 프로파일 구성 그룹을 포함한다. 3개의 하이픈(—)을 추가하고 그다음에 해당 프로파일의 이름을 나타내는
spring.config.activate.on-profile
속성을 지정한다.
- 애플리케이션이 구성 서버로부터 구성을 가져올 때 활성 프로파일을 production으로 알려주면
- application.yml과 application-production.yml 모두가 반환된다.
- 프로파일과 애플리케이션 모두에 특정된 속성을 지정하려면 ingredient-service-production.yml과 같은 형식으로 구성 파일의 이름을 지정하면 된다.

구성 속성들의 보안 유지하기#
- 구성 서버에 민감한 정보(비밀번호나 보안 토큰 등)를 포함하는 속성들을 제공해야 할 경우가 있다.
- 보안 구성 속성을 사용할 때 두 가지 옵션
- Git 백엔드 리퍼지터리에 저장된 구성 파일에 암호화된 값 쓰기
- Git 백엔드 리퍼지터리에 추가하여 구성 서버의 백엔드 저장소로 해시코프의 Vault 사용하기
Git 백엔드의 속성들 암호화하기#
- 대칭 키를 사용하려면 구성서버 자체 구성의
encrypt.key
속성에 키를 설정하면 된다.- 아래 속성은 자동-구성이 구성 서버를 활성화시키기 전에 로드되어 사용하기 위해 bootstrap.properties나 bootstrap.yml에 설정되어야 한다.

- 한 쌍의 비대칭 RSA나 키스토어의 참조를 사용하도록 구성할 수 있다.
- 암호화하고자 하는 데이터를 구성 서버의 /encrypt 엔드포인트로 POST 요청을 보내면 된다.
- 응답으로 온 암호화된 값을 Git 리퍼지터리에 속성으로 추가하면 된다.
{cipher}
로 시작하면 암호화된 값이라는 것을 구성 서버에 알려주는 것이다.
- 구성 속성을 요청 하게되면 구성 서버가 복호화 해서 응답한다.
- 만일 구성 서버가 복호화하지 않고 그대로 제공하기를 원한다면
spring.cloud.config.server.encrypt.enabled
속성을 false
로 설정하면 된다.
Vault에 보안 속성 저장하기#
- Git 서버와 다르게 Vault가 보안 정보를 자체적으로 처리한다.
- Vault 서버 시작시키기

vault server -dev -dev-root-token-id=roottoken
- Vault 서버를 개발 모드로 시작
- 루트 토큰 ID를 roottoken으로 지정
- 루트 코큰은 관리용 토큰이며, 더 많은 토큰을 생성할 수 있게 한다.
- 루트 토큰은 보안 정보를 읽거나 쓰는 데도 사용할 수 있다.
export VAULT_ADDR='http://127.0.0.1:8200'
- 개발 모드 시작되면 로컬 컴퓨터의 8200 포트를 리스닝한다.
- vault 명령에서 Vault 서버의 위치를 알 수 있도록
VAULT_ADDR
환경 변수를 설정한다.
vault status
- Vault 서버가 실행 중인지 검사
- sealed 상태: 데이터가 암호화되어 봉인된 상태
- 개발 모드에서는 sealed 상태가 되지 않는다.

- 구성 서버와 연계되도록 Vault를 사전 준비시키는 명령
- 구성 서버와 호환되는 secret이라는 이름의 Vault 백엔드를 다시 생성한다.
- 보안 데이터를 Vault에 쓰기

- 저장된 구성 데이터는
vault read
명령을 사용해서 확인할 수 있다. - 지정된 경로에 보안 데이터를 쓸 때는 이전에 해당 경로에 썼던 데이터를 덮어쓰기때문에, 유지하고싶은 데이터는 함께 써야된다.
- 구성 서버에서 Vault 백엔드 활성화하기

- Vault에 대한 모든 요청은 X-Vault-Token 헤더를 포함해야 한다.
- 이때 구성 서버 자체에 해당 토큰을 구성하는 대신, 구성 서버 클라이언트가 구성 서버에 대한 모든 요청의 X-Vault-Token 헤더에 토큰을 포함시켜야 한다. 그러면 구성 서버에서 X-Vault-Token 헤더로 토큰을 받은 후 이토큰을 Vault로 전송하는 요청의 X-Vault-Token 헤더로 복사한다.
- 토큰을 포함하지 않으면 속성 제공을 거부한다.

- 구성 서버 클라이언트에 Vault 토큰 설정하기

spring.cloud.config.token
속성은 지정된 토큰 값을 구성 서버에 대한 모든 요청에 포함하라고 구성 서버 클라이언트에 알려준다.
- 애플리케이션과 프로파일에 특정된 보안 속성 쓰기
- 이름(
spring.application.name
)이 ingredient-service인 애플리케이션에 특정된 보안 속성을 쓴다. - 활성 프로파일이 production인 애플리케이션에만 제공되는 보안 속성을 쓴다.
실시간으로 구성 속성 리프레시하기#
- 2가지 방법을 제공한다.
- 수동식: 구성 서버 클라이언트는 /actuator/refresh의 특별한 액추에이터 엔드포인트를 활성화한다. 그리고 각 서비스에서 이 엔드포인트로 HTTP POST 요청을 하면 구성 클라이언트가 가장 최근의 구성을 백엔드로부터 가져온다.
- 장점: 업데이트 시점을 정확하게 제어할 수 있다.
- 단점: 마이크로서비스의 인스턴스에 대해 개별적인 HTTP 요청이 수행되어야 한다.
- 자동식: 리퍼지터리의 커밋 후크가 모든 서비스의 리프리시를 촉발할 수 있다. 이때는 구성 서버와 이것의 클라이언트 간의 통신을 위해 스프링 클라우드 버스(Spring Cloud Bus)라는 스프링 클라우드 프로젝트가 개입한다.
- 장점: 애플리케이션의 모든 마이크로서비스에 대해 즉시로 변경 구성을 적용한다.
- 단점: 리퍼지터리에 커밋을 할 때 수행되므로 프로젝트에 따라서는 큰 부담이 될 수 있다.
구성 속성을 수동으로 리프레시하기#
- 액추에이터: 런타임 파악 및 로깅 수준과 같은 런타임 상태의 일부 제한적인 제어를 가능하게 해준다.
- 구성 서버의 클라이언트로 애플리케이션을 활성화하면, 구성 속성들을 리프레시하기 위해 자동-구성이 액추에이터 엔드포인트를 구성한다.
- 이 엔드포인트를 사용하려면 구성 클라인언트 의존성과 함깨 액추에이터 스타터 의존성을 프로젝트의 빌드에 포함해야 한다.

- 액추에이터 엔드포인트로 POST 요청을 하면 변경된 속성 이름이 포함된 응답이 온다.

config.client.version
은 현재 구성이 생성된 Git 커밋의 해시 값을 갖는다.
구성 속성을 자동으로 리프레시하기#
- 자동 리프레시 절차
- 웹훅이 Git 리퍼지터리에 생성되어 Git 리퍼지터리에 대한 변경이 생겼음을 구성 서버에 알려준다.
- 구성 서버는 RabbitMQ나 카프카 같은 메시지 브로커를 통하여 변경 관련 메시지를 전파함으로써 웹흑의 POST 요청에 반응한다.
- 알림을 구독하는 구성 서버 클라이언트 애플리케이션은 구성 서버로부터 받은 새로운 속성 값으로 자신의 속성을 리프리세하여 알림 메시지에 반응한다.

- 자동 리프레시를 위해 고려할 사항
- 구성 서버와 클라이언트 간의 메시지 처리를 위한 메시지 브로커가 있어야한다.(RabbitMQ나 카프카)
- 구성 서버에 변경을 알려주기 위해 웹훅이 백엔드 Git 리퍼지터리에 생성되어야한다.
- 구성 서버는 구성 서버 모니터 의존성(웹훅 요청을 처리하는 엔드포인트를 제공함) 및 RabbitMQ나 카프카 스프링 클라우드 스트림 의존성(속성 변경 메시지를 브로커에 전송하기 위해서)과 함께 활성화되어야 한다.
- 메시지 브로커가 기본 설정으로 로컬에서 실행하는 것이 아니라면, 브로커에 연결하기위한 세부 정보를 구성 서버와 이것의 모든 클라이언트에 구성해야 한다.
- 각 구성 서버 클라이언트 애플리케이션에 스프링 클라우드 버스 의존성이 추가되어야 한다.
- 구성 서버에서 웹훅 처리하기
- /monitor 엔드포인트를 활성화 시키는 것은, 스프링 클라우드 구성 모니터 의존성만 추가하면 된다.
- 스프링 클라우드 스트림은 스트림으로부터 처리할 데이터를 받으며, 한위 스트림 서비스가 처리하도록 스트림으로 데이터를 반환하는 프로젝트다.
- 만일 RabbitMQ를 사용하고 있다면, 스프링 클라우드 스트림 RabbitMQ 바인딩 의존성을 구성 서버의 빌드에 포함시켜야 한다.

- 구성 서버 클라이언트에 속성의 자동 리프레시 활성화하기
- 스프링 클라우드 버스 스타터 의존성을 추가만 해주면 된다.