본문 바로가기

IT Book Summary/스프링 마이크로 서비스 코딩공작소

Chapter 03 스프링 클라우드 컨피그 서버로 구성 관리

구성정보를 저장하기 위해 저수준의 프로퍼티 파일 (YAML, JSON, XML)을 이용한다.

대부분 구성파일을 소스 관리 시스템에 넣거나 애플리케이션 일부로 배포하는 일 외에는

애플리케이션 구성을 위한 운영작업은 하지 않는다.

 

하지만 많은 마이크로서비스가 운영되는 상황에서는 어떤 구성파일을 어디에 배치할지가 중요한 문제가 된다.

  1. 배포되는 실제 코드에서 애플리케이션 구성을 완전히 분리
  2. 서버 및 애플리케이션을 빌드하고 배포환경에 따라 바뀌지 않는 불변이미지를 빌드
  3. 서버를 시작할 때 환경변수나 애플리케이션의 마이크로서비스가 읽어 올 수 있는 중앙저장소를 이용해
    애플리케이션 구성정보를 주입

3.1 구성(그리고 복잡성) 관리

마이크로서비스 인스턴스는 사람이 최소한으로 개입해 신속하게 시작해야 한다.

따라서 사람이 수동으로 구성해서 구성편차로 인한 장애, 지체시간이 발생하면 문제다.

 

구성관리를 위한 네가지 원칙

  1. 분리
    실제 물리 서비스 배포와 구성정보의 분리

  2. 추상화
    서비스 인터페이스 뒷단에 있는 구성 데이터의 접근방식을 추상화.

  3. 중앙 집중화
    구성정보를 보관하는 저장소 개수를 최소로 줄임

  4. 견고성
    어떤 솔루션을 사용하더라도 고가용성과 다중성을 구현

관리하고 버전제어를 할 외부의존성이 생기는데. 구성정보를 관리할때 중요한 부분이다.

 

1 - 구성관리 아키텍처

 

구성관리의 개념적 아키텍처

  1. 서비스인스턴스가 시작하면 서비스엔드포이트를 호출해 동작중인 환경별 구성정보를 읽어옴. 
  2. 구성 저장소 구현방식은 다양할수 있다. 파일이나 관계형디비, 키-짝 데이터저장소 등.
  3. 배포방식과 독립적으로 구성데이터 관리.
    빌드 및 배포 파이프라인으로 구성관리를 변경하며, 버전 정보 태그를 달아 다른환경에 배포
  4. 서비스는 변경통보를 받고 보유한 데이터 사본을 갱신.

 

2 - 구현 선택

구성관리 시스템을 구현하는 오픈소스 프로젝트

- Etcd, Eureka, Consul, Zookeeper, Spring Cloud Config server

 

스프링 클라우드 서버의 장점

  • 쉽게 설치 사용
  • 스프링부트와 긴밀히 통합. 간편한 어노테이션 사용가능.
  • 구성데이터 저장할 수 있는 여러 백엔드 지원
  • 깃과 직접 통합 가능. 손쉽게 버전관리 가능.

3.2 스프링 클라우드 컨피그 서버구축

 

http://projects.spring.io/spring-cloud-config/

스프링 부트로 만든 REST 기반의 애플리케이션

 

confsvr이라는 새로운 프로젝트 디렉터리를 만들자.

인 안에 스프링 클라우드 컨피그 서버를 시작하는데 필요한 jar파일을 내려받는 메이븐 파일을 생성.

 

중요한 부분은 스프링 클라우드 컨피그의 상위 BOM(Bill Of Meterials)

BOM정의를 사용해 스프링 클라우드와 호환 가능한 하위 프로젝트 버전 사용을 보장.

 

spring-cloud-starter-config

spring-cloud-config-server 

 

resource 디렉토리에 application.yml 파일 생성.

 

이제 구성데이터를 보관할 백엔드 저장소를 지정하자.

 

계층구조로 동작하는 스프링 클라우드 컨피그

세가지 환경 -  기본 default, 개발 dev, 운영 prod

 

각환경에 두가지 구성 프로퍼티 설정

  • 라이선싱 서비스가 직접 사용할 예제 프로퍼티
  • 라이선싱 서비스의 데이터가 저장될 Postgres 데이터베이스를 위한 구성

구축되고나서 서비스 콘텐츠는 HTTP/REST 엔드포인트로 액서스 가능

 

1 - 스프링 클라우드 컨피그 부트스트랩 클래스 설정

 

@EnableConfigServer 는 서비스를 스프링 클라우드 컨피그 서비스로 사용 가능하게 한다.

 

2 - 파일시스템과 스프링 클라우드 컨피그 서버 사용

 

confsvr/src/main/resources/application.yml 파일의 항목을 사용해 애플리케이션 구성데이터를 보관할 저장소를 지정

파일시스템 기반 저장소를 가장 쉽게 만들 수 있다.

 

server:
  port: 8888 -- 스프링클라우드컨피그 서버가 수신 대기하는 포트
spring:
  profiles:
    active: native -- 구성정보 저장 백엔드 저장소
  cloud:
    config:
      server:
        native:
          searchLocations: 
            file:///Users/johncarnell1/book/spmia_code/chapter3_code/confsvr/src/main/
          resources/config/licensingservice --구성파일 저장 경로

 

중요한 매개변수는 searchLocations 프로퍼티

 

컨피그 서버를 시작하고 

 

GET 방식 localhost:8888/licensingservice/default 호출하면 

licensingservice.yml 파일에 포함된 모든 프로퍼티와 함깨 JSON 페이로드가 반환된다.

 

개발dev 환경 라이선싱 서비스를 위한 구성정보는

localhost:8888/licensingservice/dev 엔드포인트를 호출하면 된다.

 

특정 환경의 프로퍼티 파일을 요청하면 해당 환경 프로퍼티 파일과 기본 파일을 회신해줌.

두개의 정보를 제공하는 이유는 스프링 프레임워크가 계층적 메커니즘으로 구현 되었기 때문이다.

 

스프링 프레임워크가 프로퍼티를 찾을때 우선 기본을 찾고 다음 해당환경의 프로퍼티가 있으면 기본 프로퍼티를 대체함.

 


3.3 스프링 클라우드 컨피그와 스프링부트 클라이언트의 통합

 

1 - 스프링 클라우드 컨피그 서버의 의존성 설정

JPA, Postgres JDBC 메이븐에 설정

 

2 - 스프링 클라우드 컨피그를 위한 라이선싱 서비스 구성

스프링 클라우드 서비스가 가용하지 않을 때도 사용할 수 있는 구성 데이터를 application.yml파일에 저장 

일반적으로 bootstrap.yml 파일에 서비스 애플리케이션 이름, 프로파일과 클라우드 컨피그 서버에 접속할 수 있는 URI가 명시된다.

 

bootstrap.yml

spring:
  application:
    name: licensingservice -- 스프링클라우드 컨피그 클라이언트가 어떤 서비스를 조회할지 이름지정
  profiles:
    active:
      default -- 기본프로파일 지정
    cloud:
      config:
        uri: http://localhost:8888 -- 컨피그 서버의 위치를 지정

uri 는 라이선싱 서비스가 접속할 컨피그 서버의 엔드포인트

 

licensingservice 프로젝트를 -D로 프로파일 값을 재정의하고 다른환경 지정하여 JAR 실행할수 있다.

 

java -Dspring.cloud.config.uri=hoop://localhost:8888 \

       -Dspring.profiles.active=dev \

       -jar target/licensing-service-0.0.1-SNAPSHOT.jar

 

3 - 스프링 클라우드 컨피그 서버로 데이터 소스 연결

License 모델 클래스 JPA 엔티티 테이블과 컬럼 매핑

LicenseRepository 클래스로 질의 CRUD 구현

LicenseService 클래스 비지니스 및 데이터 액서스 로직 분리

 

4 - @Value 어노테이션으로 프로퍼티 직접 읽기

 

@Value("{example.property}") 

프로퍼티 속성을 가져와 클래스의 속성에 주입

 

5 - 깃과 스프링 클라우드 컨피그 서버 사용

 

스프링 클라우드 컨피그용 application.yml 파일

server:
  port: 8888
spring:
  cloud:
    config:
      server:
        encrypt.enabled: false
        git: 
          uri: https://github.com/klimtever/config-repo/ -- repo URL 전달
          searchPaths: licensingservice, organizationiservice -- 클라우드 컨피그에 깃경로 전달
          username: native-cloud-apps
          password: 0ffended

 

6 - 스프링 클라우드 컨피그 서버에서 프로퍼티 갱신

 

하부 저장소의 프로퍼티 변경하면 바로 반영

@RefreshScope 어노테이션 제공

/refresh 엔드포인트 사용해 애플리케이션 구성정보를 다시 읽어올 수 있음.

- 사용자 정의 스프링 프로퍼티만 다시 로드할 뿐 디비 구성정보는 다시 로드하지 않음

- 업데이트를 수행하기 위해 http://<server>:8080/actuator/refresh 엔드포인트 호출


3.4 중요한 구성 정보 보호

 

1 - 암호화에 필요한 오라클 JCE jar 파일을 내려받아 설치

  1. $JAVA_HOME/jre/lib/security 디렉터리에 있는 local_policy.jar 와 US_export_policy.jar 파일을 다른위치에 백업
  2. 오라클에서 받은 JCE zip 파일 압축풀기
  3. local_policy.jar 와 US_export_policy.jar 파일을 $JAVA_HOME/jre/lib/security 디렉터리에 복사
  4. 스프링 클라우드 컨피그가 암호화를 사용하도록 구성

2 - 암호화 키 설정

 

대칭 암호화 키 설정하자

ENCRYPT_KEY 라는 운영체제의 환경변수를 사용해 서비스에 전달되는 선택된 문자열

 

ex)

export ENCRYPT_KEY=IMSYMMETRIC

 

  1. 대칭키의 길이는 12자 이상, 불규칙 문자열이 이상적
  2. 분실하면 안됨. 암호화키로 한번 암호화한 것은 그 키 없이는 복호화 불가능

 

3 - 프로퍼티 암호화 및 복호화

 

스프링 클라우드 컨피그 인스턴스가 실행할 때 ENCRYPT_KEY 환경변수가 설정되었음을 감지하고

2개의 새로운 엔드포인트(/encrypt 와 /decrypt)를 컨피그 서비스에 자동으로 추가

 

/encrypt 엔드포인트를 사용해 p0stgr@s 값을 암호화 할 것. 호출은 POST로 수행.

 

복호화를 하려면 /decrypt 엔드포인트를 호출할 때 암호화된 문자열을 입력

 

이제 라이선싱 서비스용 깃헙이나 파일 시스템 기반 구성파일에 암호화된 프로퍼티 추가

spring.datasource.password:"{cipher} b232sdkafkg43g93kjfnsadfanwu433"

 

컨피그 서버에 모든 암호화된 프로퍼티 값 앞에 {cipher}를 붙여야 함. 컨피그 서버에 암호화된 값을 처리하도록 지시.

 

프로퍼티를 암호화 했지만 클라이언트에서 호출하면 평문으로 표시된다.

 

4 - 클라이언트 측에서 암호화하도록 마이크로서비스 구성

 

  1. 서버 측에서 프로퍼티를 복호화하지 못하도록 스프링 클라우드 컨피그를 설정
    서버측 복호화 프로퍼티를 비활성화하는 것.
    spring.cloud.config.server.encrypt.enabled : false
  2. 라이선싱 서버에서 대칭 키를 설정
  3. 라이선싱 서비스 pom.xml 파일에 spring-security-rsa JAR 파일 추가

 


  • 스프링 클라우드 컨피그 서버를 사용하면 애플리케이션 프로퍼티를 환경별로 설정 가능
  • 스프링은 스프링 프로파일을 사용해 스프링 클라우드 컨피그 서비스에서 조회할 환경 프로퍼티를 결정하고 서비스를 시작
  • 스프링 클라우드 컨피그 서비스를 파일이나 깃 기반의 애플리케이션 저장소를 사용해 애플리케이션 프로퍼티를 저장
  • 스프링 클라우드 컨피그 서비스를 대칭 및 비대칭 암호화를 사용해 중요한 정보를 암호화