[BooTakHae] Spring Cloud Config 도입

Kim Hyen Su·2024년 6월 13일

BooTakHae

목록 보기
16/22
post-thumbnail

Spring Cloud Config


개요

프로젝트 개발 후 각 서비스를 docker 이미지로 빌드한 뒤 dockerhub에 push 해보려고 하는데, 생각해보니 관련 설정 파일들도 이제 git에 함께 관리해줘야 했습니다.

하지만, 내부 민감 정보들이 있어 해당 정보들을 우선 암호화 방식으로 처리할까 했었지만, 서비스들 중 공통으로 설정되는 정보들을 한 곳에서 관리해주는 것이 좋으며, 이러한 정보들은 배포 이후에 서버를 내릴 필요 없이 git에서 관리가 가능하기 위해서 Config Server 도입을 결정했습니다.

이를 구현하기 위해서는 Spring Cloud에서 제공하는 Spring Cloud Config에 대해서 알아봐야 합니다.

Spring Cloud Config

Spring Cloud Config는 분산 시스템에서 외부화된 설정 정보를 서버 및 클라이언트에게 제공하는 시스템입니다. 즉, 외부에서 모든 서비스의 환경에 대한 공통된 정보들을 중앙에서 관리해주는 서버입니다.

  • Spring Cloud Config Server : Config Server
  • Spring Cloud Config Client : Microservices

Spring Cloud Config 사용 시 주의점

  • Git 서버 또는 Config Server의 장애가 전 서버에 전파될 수 있습니다.
  • 설정 정보의 우선순위로 인해 의도치 않은대로 동작할 수 있습니다.

서비스가 실행중일 때에는 메모리 상에 설정 정보들이 로드되어 있기 때문에 문제 없지만, 서비스 시작 시점에 Git 서버 또는 Config Server에 장애가 있다면 다른 서비스에 전파될 수 있습니다. 또한, Config Server에 의해서 장애 단일 지점이 될 수 있으므로 Config Server를 위한 별도의 운영이 추가로 필요하게 될 수 있습니다.

설정 정보도 적용되는 우선순위가 있습니다. 우선순위에 알맞게 작성해줘야 올바른 설정이 Microservice에 적용됩니다.

Spring Cloud Config 설정 파일 적용 우선 순위

application.yml 파일의 네이밍에 따라서 우선순위 설정이 가능합니다.

application.yml > 애플리케이션명.yml > 애플리케이션명-profile.yml

위처럼 우선순위가 선정되며, 특정 profile 설정 또는 애플리케이션명 설정으로 제한하고 싶은경우, config server 에서 설정해주면 해당 프로필에 맞는 설정이 적용됩니다.

ex) 애플리케이션명.yml -> user.yml(회원 서버 관련 설정)

구현

Config Server

Spring Initializr를 사용하여 Config Server 프로젝트를 생성합니다.

Dependency

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

Spring Cloud Config Server 의존성을 추가해줍니다.

application.yml

server:
  port: 8888
spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: file:///C:\project\bootakhae-config-repo

config 서버관련 설정 정보를 입력해줍니다.

  • uri : config 정보가 저장된 위치 경로를 입력해줍니다. 현재 로컬 디렉토리 내 설정 정보가 위치하기 때문에 파일 프로토콜(file://)을 명시해줍니다.

ConfigServerApplication.java

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {

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

}

@EnableConfigServer 어노테이션을 정의하여 Config Server를 활성화 해줍니다.

설정 정보 확인

웹 브라우저에 다음과 같이 URL을 검색하여 설정 정보를 검색합니다.

http://localhost:8888/bootakhae/default

이는 application명칭/profile 형식으로 설정 정보 조회가 가능합니다.

위와 같이 configuration 메타 데이터 조회가 가능합니다.

Config Client

이제 위 설정을 하나의 마이크로 서비스에 적용해보도록 하겠습니다. 우선, jwt 관련 설정이므로 User-Service에 Config Client를 설정해보도록 하겠습니다.

Dependency

	implementation 'org.springframework.cloud:spring-cloud-starter-config'
	implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap'

bootstrap 관련 의존성을 추가한 이유는 Config-Server에서 관리하는 설정 정보가 해당 서버의 application.yml 파일을 읽기 전에 로딩돼야 합니다. 따라서 Config Client 서버 실행과 동시에 bootstrap을 사용하여 설정 정보를 로딩해주기 위해서 사용합니다.

bootstrap.yml

spring:
  cloud:
    config:
      uri: http://localhost:8888
      name: bootakhae

Config Client 서버 실행과 동시에 해당 정보를 통해서 설정 정보를 불러와서 로딩해줍니다.

그 다음으로 기존에 Config Client에 추가되어 있었던 설정 정보를 지워준 다음 서버를 실행해보도록 하겠습니다.

위처럼 콘솔을 통해서 Config 서버의 설정 정보를 가져온 것을 알 수 있습니다.

다음과 같이 메서드를 정의해줍니다.

    /**
     * 헬스 체크 
     */
    @GetMapping("health-check")
    public ResponseEntity<String> healthCheck(){
        String body = String.format("port(local.server.port) :" +  env.getProperty("local.server.port")
        +", port(server.port) :" + env.getProperty("server.port")
        +", with token secret :" + env.getProperty("token.secret")
        +", with token access time : " + env.getProperty("token.access-expired-time")
        +", with token refresh time : " + env.getProperty("token.refresh-expired-time"));
        return ResponseEntity.ok(body);
    }

postman을 사용하여 테스트한 결과 다음과 같은 결과가 출력된 것을 알 수 있습니다.

설정 정보 변경

Config Server를 도입하는 이유 중 하나가 배포 중 설정 정보를 변경하기 위함입니다. 하지만, 현재 구현한 부분까지는 서버를 재시작해야 적용이 됩니다.

이를 해결하기 위해서 Actuator를 활용한 api 통신을 통해 설정 정보를 업데이트 해줄 수 있습니다.

Actuator 사용을 위해서 의존성을 추가해줍니다.

	implementation 'org.springframework.boot:spring-boot-starter-actuator'

그 다음으로 application.yml 파일에 actuator를 통해 사용할 엔드포인트들을 추가해줍니다.

management:
  endpoints:
    web:
      exposure:
        include: refresh

그 다음으로 기존에 설정했던 값들을 수정해준 뒤 git 커밋을 해줍니다.

  • with token access time: 1800 -> 18
  • with token refrsh time: 86400 -> 6

이 때, 서버를 재실행 하지 않는 이상은 postman으로 실제 값을 조회하더라도 변경되지 않은 것을 확인할 수 있습니다.

이 때, user-service 서버에서 actuator의 refresh를 호출하게 되면 값이 변경됩니다.

Config Server에서 관리하는 설정 중 변경된 항목들만 반환해줍니다.

값이 정상적으로 변경되는 것을 확인할 수 있습니다.

결과적으로, actuator의 refresh를 사용하면 서버를 재실행 하지 않아도 설정 수정을 반영할 수 있게 됩니다.

application.yml 테스트

case1_profile 적용

bootakhae.yml

token:
  secret: BQBIp8JxTfqZhpmySSvz29ZE/8gODZCu4PBhOkyFKiIAq8hGZ8f8a9vllqqUJl2362noOfcjE2eNs//SuoSBtP8peNCKxZGsZ3QUpmMKw7fJARiFUN67EcZ02O+XhDdlpOROevsYjfGvfSHeQ4PqaADvYquFvIeUvGwBC3/vQzVZYL8R+JdOxpq3W/mMQ7j6rIK70MkUj7gt90TiJ18eJ45U+J+T4VWtC0+kHEIEFSRs8wTpPicAl5CLlZmJ+GI7R9ZERDsAKwyQ/XacfrHAp3QdLyvkVQ7qp4MrP8X6fwpOZFleerNdRx0oXATpqtN5eYGfG8BVVpgSQoq7ZMP85pm1NQNDlOLjmYdHuOAuESwg+G30ucb5ipynr+GmHK5Nwg4A78BnNvhVAqGqdwT/xVfCkkbCtHd4FYhynrMdhddiEVbzUQMg/PsN/B0AadXV6xwm+Yxgz31qn2wwlW7vMy9tKKVxiso7hQK1qI18r60FTaOB7cWzsYBBCN3KaD0R3tM=
  access-expired-time: 300 #1800
  refresh-expired-time: 86400 #86400

bootakhae-dev.yml

token:
  secret: AQBIp8JxTfqZhpmySSvz29ZE/8gODZCu4PBhOkyFKiIAq8hGZ8f8a9vllqqUJl2362noOfcjE2eNs//SuoSBtP8peNCKxZGsZ3QUpmMKw7fJARiFUN67EcZ02O+XhDdlpOROevsYjfGvfSHeQ4PqaADvYquFvIeUvGwBC3/vQzVZYL8R+JdOxpq3W/mMQ7j6rIK70MkUj7gt90TiJ18eJ45U+J+T4VWtC0+kHEIEFSRs8wTpPicAl5CLlZmJ+GI7R9ZERDsAKwyQ/XacfrHAp3QdLyvkVQ7qp4MrP8X6fwpOZFleerNdRx0oXATpqtN5eYGfG8BVVpgSQoq7ZMP85pm1NQNDlOLjmYdHuOAuESwg+G30ucb5ipynr+GmHK5Nwg4A78BnNvhVAqGqdwT/xVfCkkbCtHd4FYhynrMdhddiEVbzUQMg/PsN/B0AadXV6xwm+Yxgz31qn2wwlW7vMy9tKKVxiso7hQK1qI18r60FTaOB7cWzsYBBCN3KaD0R3tM=
  access-expired-time: 1800 #1800
  refresh-expired-time: 86400 #86400

bootstrap.yml(user-service)

spring:
  cloud:
    config:
      uri: http://localhost:8888
      name: bootakhae
      profile: dev

위처럼 설정한 뒤 postman을 사용하여 API 테스트한 결과, 다음과 같은 결과가 출력됐습니다.

dev profile로 설정했던 값이 저장된 것을 확인했습니다. 위 bootstrap.yml에 설정한 profile을 주석처리한 뒤 출력해보겠습니다.

bootstrap에서 profile 설정을 해줘야 해당 profile이 우선순위를 갖게 됩니다. 설정 정보가 적용되는 과정은 다음과 같습니다.

local application.yml 이 최초 설정 -> bootakhae.yml 이 설정 정보 덮어씌움 -> bootakhae-dev.yml이 설정 정보 덮어씌움(profile 설정한 경우)

위와 같이 어떤 파일에 있는 설정 정보가 반영되는지 이해하고 있어야 합니다.

profile
백엔드 서버 엔지니어

0개의 댓글