[Project] MSA 적용 방식

mDev_97·2023년 12월 18일

Goormthon-Project

목록 보기
3/4
post-thumbnail

이전 게시글에서 우리 프로젝트에서는 Spring Cloud와 Kubernetes를 어떻게 도입할 것인지에 대해서 고민하였고,
결론은 다음과 같이 적용하는 것이다.

위의 표를 설명하자면 다음과 같다.

API Gateway

쿠버네티스에서는 Spring Cloud API와 비슷한 동작을 하는 Ingress라는 리소스를 제공한다.
API Gateway와 Ingress는 L7 레이어에서 라우팅하는 역할을 수행한다.

하지만, API Gateway를 사용한다면, Custom Filter, Path Rewrite 기능을 사용할 수 있다.

이에 어차피 동일한 기능을 수행하는 것이라면 더 많은 기능을 제공하는 Spring Cloud API Gateway를 사용하자.

내부 통신

내부 통신(서비스간 통신)은 Spring Cloud에서 OpenFeign을 제공한다.
OpenFeign의 경우 코드 레벨이기 때문에 개발자 친화적으로 간편하게 적용할 수 있다.
반면, 플랫폼 레벨인 쿠버네티스에서 제공하는 비슷한 기능들을 사용하기 어렵다.

이에 내부 통신은 간편하고, 빠르게 구현할 수 있도록 Spring Cloud OpenFeign을 사용한다.

OpenFeign을 사용하기 위해서는 아래의 의존성을 추가해주어야 한다.

implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'

서비스 레지스트리 & 서비스 디스커버리

서비스 레지스트리와 서비스 디스커버리는 단순하게 쿠버네티스에 배포할 때만을 고려해서는 안된다.
분명히 개발을 하면서도 직접 동작을 시켜보던지, 또는 작성한 테스트 케이스를 확인해보아야 한다.

이에 Local 환경에서는 Spring Cloud Eureka를 사용하여 서비스 레지스트리 및 디스커버리를 적용하고,
쿠버네티스에서는 Service 리소스를 최대한으로 사용하기로 하였다.

이처럼 로컬 환경에서 서비스 레지스트리 및 디스커버리를 적용하기 위해서는 아래의 의존성을 추가해주어야 하며,

implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'

쿠버네티스 상에서 Service 리소스를 사용하여 서비스 레지스트리 및 디스커버리를 하기 위해서는
아래의 의존성을 추가해주어야 한다.

implementation 'org.springframework.cloud:spring-cloud-starter-kubernetes-client-all'
implementation 'org.springframework.cloud:spring-cloud-starter-loadbalancer'

프로퍼티 파일 관리

프로퍼티 파일 관리 측면에서는 서비스 레지스트리와 디스커버리와 같이
Local과 Kubernetes를 분리하여 생각해야한다.

이는 Local 환경에서 사용하는 Config Server를 어플리케이션과 함께 배포하는 것은
서버 리소스와 비용적인 측면에서 비효율적이기 때문이다.

이에 Local 환경에서는 Spring Cloud Config Server를 사용하고,
kubernetes에서는 ConfigMap과 Secret을 사용하기로 하였다.

Local 환경에서 Spring Cloud Config를 사용하기 위해서는 아래의 의존성을 추가해야하며,

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

Kubernetes 상에서 배포한 어플리케이션이 ConfigMap과 Secret을 사용하기 위한 라이브러리들은
위에서 나온 client-all 라이브러리에 모두 포함되어 있다.

implementation 'org.springframework.cloud:spring-cloud-starter-kubernetes-client-all'

Profile 분리

위에서 정리한 내용들을 보면 Local과 Kubernetes 환경을 별도로 관리하기 때문에
코드의 변경이 있을 것이라고 생각할 수 있다.

하지만, 코드를 수정하지 않으면서, 코드가 로컬이나 쿠버네티스에 의존적이지 않도록 하기 위해서는
Local과 Kubernetes에 맞는 Profile을 별도로 관리해주어야 한다.

간단하게 말하자면 다음과 같다.
Local 환경에서는 Eureka와 Config Server를 사용해야 하고, Kubernetes를 사용하지 않도록 해야하며,
Kubernetes 환경에서는 Eureka와 Config Server를 사용하지 않으면서, Kubernetes를 사용해야 한다는 것이다.

이러한 방식으로 Profile을 관리하기 위해서는 프로퍼티 파일을 다음과 같이 작성해야 한다.

Local 환경을 위해서는 아래와 같다.

  • application.yml
spring:
  application:
    name: <Servie Name>
  config:
    activate:
      on-profile: default
      
eureka:
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka
  • bootstrap.yml
spring:
  config:
    activate:
      on-profile: default
  cloud:
    config:
      uri: http://127.0.0.1:8888
      name: <Property Filename>
    kubernetes:
      enabled: false
      config:
        enabled: false

쿠버네티스 환경을 위해서는 다음과 같다.

  • application-kubernetes.yml
spring:
  application:
    name: <Service Name>
  config:
    activate:
      on-profile: kubernetes

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
    enabled: false
  • bootstrap.yaml
spring:
  config:
    activate:
      on-profile: kubernetes
  cloud:
    config:
      enabled: false
    kubernetes:
      enabled: true
      config:
        enabled: true
        name: <ConfigMap Name>
        namespace: default
      loadbalancer:
        mode: service
profile
안녕하세요. 백엔드, 클라우드, 인프라에 관심과 열정이 있는 김문성입니다. 😊

0개의 댓글