brunch

You can make anything
by writing

C.S.Lewis

by 에디의 기술블로그 Nov 11. 2018

Spring Cloud Config

- 마이크로서비스 외부 구성 저장소 패턴

목차

1. External Configuration Store pattern

2. Spring Boot Properties

3. Spring Cloud Config

4. Spring Cloud Bus


External Configuration Store pattern


중요한 내용이지만 생략한다. 나중에 시간 있을 때 작성하겠다. 


Spring Boot Properties


역시 중요한 내용이지만 깔끔하게 생략한다. 나중에 시간 있을 때 작성하겠다. 


Spring Cloud Config


Spring Cloud Config 는 분산 환경에서 External Configuration Store, 즉 외부화된 컨피그레이션 구성을 구축할 수 있도록 해주는 프로젝트이다. 개발, QA, 실서비스의 모든 환경 구성을 심플하게 관리할 수 있다.  자세한 내용은 스프링 공식 레퍼런스를 참고하자. 필자가 영어를 드럽게 못해서 번역을 할수가 없다.

https://cloud.spring.io/spring-cloud-config/

국내 블로그 중에서는 이 분의 글이 가장 볼만하다. 꼭 읽어보자.

http://blog.leekyoungil.com/?p=352


AS-IS


필자는 이전에 보통 아래와 같은 방식으로 구성 정보를 관리하였다. 

애플리케이션에 구성정보를 포함하여 배포한다.

구성정보는 각 서버에 개별적으로 배포하고, 애플리케이션에서 배포된 구성정보를 읽는다.

필자가 보통 수행하는 개발 프로세스는 아래와 같다. 

개발 -> 테스트 -> 스테이지 -> 실서비스


각각의 과정에서의 구성정보는 모두 다를수도 있기 때문에, 애플리케이션에 구성정보를 모두 포함해서 빌드 하는 방식이 운영 및 배포하기 어려울 수 있다. 그래서, 각 서버에 구성 정보를 개별 배포한 후 애플리케이션을 재시작하는 방식으로 애플리케이션 배포 없이 변경 된 구성 정보를 업데이트할 수 있도록 서비스를 운영하는 편이다. 이 과정에서 애플리케이션 재시작으로 인한 서비스 중단을 방지하기 위해서, 리버스 프록시, 포트포워딩 등의 방식을 사용하여 서비스 무중단 상태에서 배포를 할 수 있도록 운영을 한다. 어쨋든 나쁘지 않은 방법이지만, 애플리케이션 재시작 없이 구성 정보가 실시간으로 변경되도록 구축할 수 있을까??


Spring Cloud Config


서비스 애플리케이션이 스프링 부트 환경이라면 Spring Cloud Config 를 도입하여 구성 정보를 심플하게 관리할 수 있다. 아래 필자가 그린 그림을 보자.

Git 에서 구성 정보를 관리한다. 

Config 서버는 Git 을 바라본다. 

Config 클라이언트는 Config 서버를 바라본다.


아주 심플하다. 바로 코드를 작성해보자. 


Spring Cloud Config Repository


컨피그 서버에서 사용할 git Repository 를 만들어 보자. 필자는 GitHub 에서 신규 Repository 를 생성하였다. 


GitHub 만 테스트를 하였습니다. GitLab 등 다른 애들도 되는지 확인을 못했습니다만, 추측으로는 git 기반이면 전부 될 것 같기는 합니다. 이부분에 대해서 아시는 분은 피드백 부탁드립니다. 


필자는 cafe.properties 라는 이름의 구성 파일을 생성하였고, 아래와 같이 정보를 입력하였다. 


Spring Cloud Config Server


스프링 부트 2.0.6.RELEASE , Gradle 으로 프로젝트를 초기화해보자. 

아래와 같이 @EnableConfigServer 어노테이션을 선언하자. 

아래와 같이 application.properties 파일을 작성하자. spring.cloud.config.server.git.uri 에는 구성정보가 저장되어 있는 git 의 Repository 주소를 넣으면 된다. 

컨피그 서버는 8888 포트로 실행한다.


이게 끝인가?


Spring Cloud Config Client


스프링 부트 2.0.6.RELEASE , Gradle 으로 프로젝트를 초기화해보자. 

resources/bootstrap.properties 파일을 생성한다. 

application.name 에는 cafe 라고 작성하고, spring.cloud.config.uri 에는 컨피그 서버를 지정하면 된다. 


심플하다.

이제 구성 정보를 사용하는 코딩을 해보자. 세상에서 제일 간단한 코드이다. 

필자가 샘플로 자주 사용하는, 커피 예제이다. 커피 관련 유스케이스를 정의하는 CoffeeUseCase 인터페이스를 정의해보자. 

인터페이스의 구현체를 만들자. 

컨트롤러를 만들자.


필자가 아주 간단하게 작성을 하였는데, 이 글을 보는 사람이 있다면 필자처럼 하지 말고 반드시 테스트 코드를 작성하자. 컨피그 서버와 애플리케이션을 실행해보자. git 의 구성파일에 정의된 coffee.order.max-threads 값을 정상적으로 가져오는 것을 확인할 수 있다. 


여기서 잠깐만!!  만약 컨피그 서버가 Down 된 상태이면 어떻게 될까? 

오류 발생한다. 


컨피그 서버는 반드시 고가용성 을 보장해야 한다. 절대 죽으면 안되는 서버!!!


Spring Cloud Config Refresh


애플리케이션이 실행 중에 구성 정보를 업데이트 해보자. 일단 git Repository 에서 coffee.order.max-threads 를 수정해보자. 그리고, 컨피그 클라이언트(애플리케이션) 에 http://localhost:8081/actuator/refresh Post 메서드로 호출하면 된다. 필자는 Postman에서 아래와 같이 호출하였다.

Response 를 보면 변경 된 구성정보를 확인 할 수 있다. 웹에서도 확인해보자. 애플리케이션을 재시작하지 않았는데 실서비스 중에 구성정보가 변경 된 것을 확인할 수 있다. 

생각보다 괜찮다. 



업데이트가 되는 애플리케이션, 즉 컨피그 클라이언트 서버들은 업데이트가 필요한 경우에 항상 /actuator/refresh 를 호출해야만 한다. 하지만... 만약, git 에서 구성정보가 변경되면 바로 서비스에 업데이트가 되도록 구축해야 한다면 어떻게 하면 될까? Spring Cloud Bus 기술을 사용해보자. 



Spring Cloud Bus


Spring Cloud Bus links nodes of a distributed system with a lightweight message broker. This can then be used to broadcast state changes (e.g. configuration changes) or other management instructions. The only implementation currently is with an AMQP broker as the transport, but the same basic feature set (and some more depending on the transport) is on the roadmap for other transports.


영어에 자신이 없어서, 영어 잘하시는 분은 번역 부탁드립니다. 


Spring Cloud Bus 를 사용해서, git Repository 에 구성정보가 변경되는 순간에, 애플리케이션이 실시간으로 업데이트될 수 있도록 구축해보자. 


아키텍처


Spring Cloud Bus 는 RabbitMQ 와 통신한다. RabbitMQ의 Queue, Exchange 생성 및  Queue와 Exchage의 바인등 등에 대해서는 고민할 필요가 없다. Spring Cloud Bus 가 알아서 다 해준다. Git 에서 변경사항이 있으면 Spring Config Server 에 알림을 보내줘야 한다. Git 의 Webhook 기능을 사용하면 된다. 아래 아키텍처를 참고하자. 역시 심플하다.  


RabbitMQ


RabbitMQ 를 설치하자. 설치 방법은 생략한다. 


Spring Cloud Config Server


컨피그 서버를 구축하자. 위에서 구축한 컨피그 서버랑 거의 비슷하다. Spring-Cloud-Bus 를 연동하기 위해서 아래 디펜던시를 추가하자.

spring-cloud-starter-bus-amqp

spring-cloud-config-monitor

메시지브로커, RabbitMQ 연동을 위해 프로퍼티 설정을 추가하자. 


위에서 만든 컨피그 서버와 유사하지만, GitHub webhook 기능을 사용하기 위해, 외부 호스팅 서버에 배포를 하였다. 참고로 필자는 8888 포트로 컨피그 서버를 올리고, Nginx 에서 Reverse Proxy 를 해서 접근하도록 설정하였다. 아래 작업은 굳이 똑같이 하지 않아도 된다. 


단, 컨피그 서버로 접근은 보안 인증이 필수로 적용이 되어야 한다. 필자는 테스트 환경이라서 따로 구현하지는 않았지만, 스프링 시큐리티를 사용할 수 있다. GitHub 에서 webhook 을 요청할 때 id 와 password 를 같이 Request 할 수 있다. 


Spring Cloud Config Client


컨피그 서버를 바라보는, 클라이언트 애플리케이션을 구축하자. 아래와 같이 디펜던시를 추가한다.

필자는 스프링부트 2.0.6.RELEASE 버전으로 테스트를 진행 중이다. 참고로, 2.1.0.RELEASE 로 구축해봤는데, webhook 요청할 때 오류가 발생한다. 

구현 코드는 위에서 구현한 컨피그 클라이언트 애플리케이션과 거의 유사하다. 

단, RabbitMQ 연동을 하기 위한 호스트설정을 추가하자.

그리고 컨피그 서버의 호스트를 localhost:8888 에서 실서비스에 배포한 경로를 설정하자. 필자는 필자의 호스팅 서버를 바라보도록 설정하였다. 


제 호스팅 서버인, sieun.kr 호출하시면 안됩니다. 한달에 3천원짜리 저렴한 호스팅입니다. 과도한 트래픽이 발생되면 서버가 죽을수도 있습니다.  

애플리케이션을 실행해보자. RabbitMQ 에 Exchange 와 Queue 가 자동으로 생성이 되는 것을 확인할 수 있다. 

RabbitMQ Exchange


RabbitMQ Queue

마지막으로 GitHub 에서 webhook 설정을 해야 한다. Settings -> Webhooks 에서 컨피그 서버 경로를 추가하자. 이때 /monitor 엔드포인트를 추가해야 한다. 또한, application/json 을 선택해야 한다. Secret 는 빈 문자열로 남겨주자. 

 

자!! 이제 테스트를 해보자. Repository 에서 속성을 변경해보자. 컨피그 서버에서는 아래와 같이 변경된 사항을 webhook 을 통해서 리스닝 하는 것을 확인 할 수 있다. 

GitHub 에서는 아래와 같이 webhook 전송 히스토리를 확인할 수 있다. 필자의 마지막 업데이트가 정상적으로 성공한 것을 확인할 수 있다. 그 아래는 오류가 발생햇었다. 

클라이언트 애플리케이션에서도 리스닝 정보를 확인할 수 있다.


자!! 컨피그 서버를 보고 있는 각각의 클라이언트 애플리케이션이 별도의 업데이트 요청을 하지 않아도, 자동으로 업데이트가 되는 것을 확인할 수 있었다. 



마무리


이번 글에서는 Spring Cloud Config , Spring Cloud Bus 에 대해서 알아보았다. 관련 소스는 아래 필자의 github을 참고하길 바란다. 끝!!

https://github.com/sieunkr/spring-cloud


레퍼런스


https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

https://www.baeldung.com/properties-with-spring

https://docs.microsoft.com/ko-kr/azure/architecture/patterns/external-configuration-store

http://blog.leekyoungil.com/?p=352

https://springbootdev.com/2018/07/17/spring-cloud-config-refreshing-the-config-changes-with-spring-cloud-bus-part-2/

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari