Spring

[ Spring ] Cloud Config 구축하기(1)

구티맨 2020. 7. 29. 11:20

Spring Cloud Config 를 사용해, Config 서버 구축을 알아보도록 하겠습니다.

 

 

먼저, Config 서버 란 application의 config 파일( property )의 최신 정보를 전달해주는 서버입니다.

 

Config 클라이언트에서는 자체적으로 config 파일 가지고 있지 않고, 서버에 config 파일을 요청합니다.

 

그리고, 변경된 내용이 있으면 클라이언트에서 변경된 내용을 업데이트 할 수 있도록 해줍니다.

 

config 파일의 저장과 버전은 GIT 에서 관리 됩니다.

 

Spring 에서는 Spring Cloud Config 라는 모듈로 이 기능을 제공해 주고 있습니다.

 

대략 그림을 그려보자면 아래와 같습니다.

 

1. Client 에서 property 를 요청합니다.

2 ~ 4. Server 에서 요청 받은 property를 GIT Repo에서 받아와 Client에 전달해줍니다.

5. 개발자가 config 파일을 업데이트하여 GIT에 push를 합니다.

6. 개발자가 Client에 새로운 config 파일이 있으니 업데이트 하라는 요청을 보내면 다시 1번부터 4번까지의 flow 를 진행합니다.

 

Spring Cloud Config에 대해 대략적으로 설명을 했으니, 어떻게 구현을 하는지 알아보겠습니다.

 

Config Server

서버에는 Config 서버로 동작하기 위해 아래의 dependency가 필요합니다.

implementation 'org.springframework.cloud:spring-cloud-config-server'

 

아래의 EnableConfigServer annotation 을 하나만 추가해주면 Config 서버로 구동할 수 있습니다.

@EnableConfigServer
@SpringBootApplication
public class ConfigserverApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigserverApplication.class, args);
    }

}

 

마지막으로, Property 파일에 Config 파일이 저장되어 있는 GIT repo uri 를 명시해줍니다.

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/ggamzang/config.git

 

config.git GIT repo에 config-client.yml 파일이 push 되어 있습니다.

 

서버를 구동하고 난 뒤, config 파일을 요청하는 URI를 브라우저에서 호출해 보면 config 파일의 내용이 응답으로 오는 것을 볼 수 있습니다.

 

propertySources의 name에 요청한 config 파일 uri가 있고, source에는 config 파일에 기록된 property 값이 담겨 있습니다.

 

Config 클라이언트에서는 이 source의 값에 있는 내용을 property 값으로 읽어 사용하게 됩니다.

 

URI 형식은 host:port/applicationName/profile/label 입니다. ( 여기서는 기본 값인 default profile 로 요청하였습니다. )

http://localhost:8888/config-client/default

{
    "name": "config-client",
    "profiles": [
        "default"
    ],
    "label": null,
    "version": "6a58c32ae4669ddcd514a2cd0bb6c8fc04063683",
    "state": null,
    "propertySources": [
        {
            "name": "https://github.com/ggamzang/config.git/config-client.yml",
            "source": {
                "server.port": 8080,
                "my.value": "config client"
            }
        }
    ]
}

 

Config Client

Config Client 로 동작하기 위해서는, 아래의 dependency 가 필요합니다.

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'org.springframework.cloud:spring-cloud-starter-config'
}

 

그리고, property 파일( application.yml ) 을 서버에서 받아와야 하기 때문에 application property 파일 대신에

resources 폴더에 bootstrap.yml 파일을 만들고, 아래 내용을 작성 합니다.

spring:

  application:
    name: "config-client"

  cloud:
    config:
      uri: http://localhost:8888

 

GIT에 저장된 property 파일( config-client.yml )은 아래 내용과 같습니다.

server:
  port: 8080

my:
  value: "config client refreshed2"

management:
  endpoints:
    web:
      exposure:
        include: "refresh"

 

그리고 property 파일을 잘 읽어들었는지 확인 용으로 my.value 값을 읽어 리턴해주는 API 를 하나 추가해줍니다.

@RestController
public class FirstController {

    @Value("${my.value}")
    private String prop;

    @GetMapping("/read")
    public String readProp(){
        return prop;
    }
}

 

application을 구동하고, 브라우저에 http://localhost:8080/read 을 입력하면

my.value의 값인 "config client" 가 리턴되는 것을 확인할 수 있습니다.

 

application이 구동 할 때, http://localhost:8888/config-client/default URL로 config 파일을 요청 및 정상적으로 잘 읽었음을 알 수 있습니다.

Fetching config from server at : http://localhost:8888
Located environment: name=config-client, profiles=[default], label=null, version=6a58c32ae4669ddcd514a2cd0bb6c8fc04063683, state=null
Located property source: [BootstrapPropertySource {name='bootstrapProperties-configClient'}, BootstrapPropertySource {name='bootstrapProperties-https://github.com/ggamzang/config.git/config-client.yml'}]

 

Property Refresh

GIT 에 저장된 property 값이 변경 된 경우, client에서 최신 파일을 다시 받아 값을 refresh 하는 방법을 알아 보겠습니다.

 

먼저, 업데이트 된 property 의 값을 다시 읽을 수 있도록 java code 를 변경합니다.

 

property 값을 다시 읽을 변수가 있는 클래스에 @RefreshScope 를 선언 해주기만 하면 됩니다.

@RefreshScope
@RestController
public class FirstController {

    @Value("${my.value}")
    private String prop;

    @GetMapping("/read")
    public String readProp(){
        return prop;
    }
}

 

client application을 재기동하고, GIT의 property 파일을 수정, 푸시를 해줍니다.

 

그리고 actuator 의 refresh endpoint에 POST 호출 하여 client 에 property 가 업데이트 되었으니 갱신하라고 알려줍니다.

$ curl -XPOST localhost:8080/actuator/refresh
["config.client.version","my.value"]

 

client에 GET /read 를 다시 해보면, 변경된 my.value 의 값이 리턴되는 것을 확인할 수 있습니다.

( 이전 값 : "config client", 갱신된 값 : "config client refreshed" )

 

 

 

그림에서 설명한 내용을 모두 구현 해보았습니다.

이제 client에서 property 내용을 바꾸기 위해 property 파일을 수정하고 재기동 할 필요도 없고,

property 파일에 대한 보안이 좀 더 견고해졌습니다.

 

그런데, client 가 한두개가 아니라면 일일히 refresh endpoint 를 호출을 해주기가 너무 번거롭고

업데이트된 property 를 업데이트는 했는데 refresh endpoint 호출 하는걸 깜박하는 경우도 생길 것입니다.

 

다음 포스팅에서는 이를 모두 자동화 하는 것에 대해 알아보도록 하겠습니다.

 

 

소스코드

github.com/ggamzang/config

github.com/ggamzang/config-client

github.com/ggamzang/config-server

 

참조

cloud.spring.io/spring-cloud-config/reference/html/