MSA Development Project with Spring Boot using Netflix OSS & Istio.io
The term "Microservice Architecture" has sprung up over the last few years to describe a particular way of designing software applications as suites of independently deployable services. While there is no precise definition of this architectural style, there are certain common characteristics around organization around business capability, automated deployment, intelligence in the endpoints, and decentralized control of languages and data. (defined by Martin Fowler, 25 March 2014)
- Netflix는 Circuit Breaker, Edge Routing, Service Discovery, Load Balancing 등의 기능을 위해 Java를 주축으로 하는 일련의 기술을 만들어 이후 Opensource화 했다. (
Netflix OSS
) - 이 시점(2010년~ )만 해도 Virtual Machine이 Cloud에서 application을 실행하기 위해 사실상 유일한 방법이었다. Netflix는 Service Mesh 기능을 위한 언어 Platform으로 Java를 선택했다.
- k8s가 등장하면서 서비스 검색, 로드밸런싱과 같은 기능이 플랫폼의 일부가 되어 사용된 언어에 관계없이 모든 애플리케이션에서 활용할 수 있게 되었다.
- Application 개발 초기에는 기존 application에 최소한의 변경 사항이 있어도 자체 QA(Quality Assurance) 주기에 따라 대규모 update를 해야 했다.
- 전체 application의 source code는 하나의 배포 unit(.war or .ear 등)으로 내장되기 때문에 이런 방식을
Monolithic
이라고 부른다. - 일부 application의 update로 인해 오류가 발생할 경우, 전체를 offline으로 전환하고 운영 규모를 축소시킨 다음 문제를 해결해야 했다. 이러한 방식은 소규모 application션에서 여전히 실행 가능하지만, 성장하는 기업들은 downtime을 감당할 수 없다.
Service Oriented Architecture(SOA)
는 application을 별개의 재사용 가능한 서비스 단위로 분할하며, 이 service들은Enterprise Service Bus(ESB)
를 통해 통신한다.- 특정 Business Process를 기반으로 구성된 개별 서비스가 통신 프로토콜(SOAP, ActiveMQ, Apache Thrift 등)을 준수하며 ESB를 통해 공유된다. 즉, 이러한 서비스 요소가 ESB를 통해 통합되어 하나의 애플리케이션을 구성한다.
- 서비스의 구축, 테스트, 수정을 동시에 수행할 수 있기 때문에 더 이상의 monolithic 개발 주기는 필요가 없다. 그러나 ESB는 전체 시스템의 단일 장애점(single point of failure)을 나타내기 때문에 이러한 방식에서 monolithic 제거는 새로운 monolithic을 만들어낼 뿐이며, 잠재적으로 ESB가 전체 조직의 자체적인 장애 요소로 작용할 수 있다.
Microservice
는 Stateless 방식으로 서로 통신을 할 수 있으므로, 이러한 방식으로 구축된 application은 내결함성이 더 높고 단일 ESB에 대한 의존성은 더 낮다.- Microservice가 programing 언어에 구속 받지 않는 API이기 때문에 개발팀이 자체 tool을 선택할 수도 있다.
- SOA의 본질적 기능을 감안하면 microservice는 완전히 새로운 개념은 아니다. microservice는
Containerized
기술의 발달에 힘입어 유용성이 향상되었다. - Linux Container를 활용해 application의 여러 조각들을 독립적으로 작동시킬 수 있으며, 각 개별 요소 및 lifecycle에 대한 통제력은 훨씬 강화되었다.
- Containerized Microservice는 API 및
DevOps
와 함께 Cloud Native Application의 기반이 된다.
- UI는 HTTP를 통해 API Gateway에 request 한다.이 요청은
Command
또는Query
중 하나이다. - Command은 Command만 수신하는 domain microservice로 전달되며, query를 전혀 허용하지 않는다.
Domain Microservice
는 명령을 수신하여 event를 memory에 유지하고, Event Store Database에 지속할 이벤트를 전송한다. 또한, 이러한 이벤트를 Service Bus에 publish한다.Read Model Microservice
는 이 event에 관심이 있으므로, service bus를 통해 이 이벤트를 수신하고 정규화되지 않은 data의 version을 update하고 query를 준비한다.- 요청이 "query"인 경우 read model microservice로 전송된다.
Web API Controller
는 명령만 허용하며, 명령을 받으면 Command Handler로 전달한다.Command Handler
가 명령을 Aggregate에 보내 명령과 관련된 Business Logic을 실행한다.- Command Handler에 aggregate 작업이 완료되면, event가 지속될 준비가 되었다는 알림이 표시된다.
Event Store Repository
를 통해 이벤트 저장소에 이벤트가 유지되고, 동일한 이벤트가 service bus에 publish되어 다른 서비스에서 사용된다.
Web API Controller
가 query를 수신한다.- controller가 Query Handler에 query를 전달하고, 쿼리 처리기는 데이터 모델에서 쿼리 판독치를 실행하기만 하면 데이터를 반환한다.
-
Container Management
: 개별 service instanece에는 작동할 context가 필요한데 VM, Docker container 또는 조정된 process로 구현된 관리 container는 이러한 기능을 제공한다. instance 관리 및 조정을 제공하고 필요에 따라 개별 인스턴스의 lifecycle를 관리한다. -
External Gateway
: 서비스에 대한 access를 관리하고 traffic 관리 및 보안 정책을 적용하여 microservice 환경을 보호한다. 외부 게이트웨이 기능은 종종 API 관리 제품을 사용하여 구현된다. -
Service Mesh
: 서비스 간의 통신을 느슨하게 결합, 신뢰성 및 유연성을 유지하는 데 도움이되는 기능으로 구성되며, 이러한 기능을 통해 서비스 분리, 버전 관리 전략 지원 및 부하시 탄성 확장성 관리가 가능하다.Service Router
: 클라이언트 응용 프로그램에서 또는 마이크로 서비스 사이의 요청은 구성 및 정책에 따라 올바른 마이크로 서비스로 라우팅해야 한다.Load Balanceing
: 각 마이크로 서비스의 인스턴스는 확장 성을 지원하기 위해로드 밸런싱이 필요하며, 로드 밸런싱의 세밀성 및 구성은 각 서비스를 관리하는 팀에 의해 제어되야 한다.Service Discovery
: 서비스는 느슨하게 결합 된 방식으로 서비스 레지스트리를 사용하여 구현되며, 이 서비스 레지스트리에서 마이크로 서비스 소유자는 런타임에 다른 서비스가 필요로 하는 정보를 등록 및 구성하여 찾아서 호출 할 수 있다. 마이크로 서비스간에 존재할 종속성을 관리하는데 도움을 주며 환경 변화를 관리할 때 중요하다.Config. Store
: 서비스 인스턴스는 마이크로 서비스와 전체 환경과 관련된 구성을 공유해야 한다. 예를 들어, 환경에 배포된 마이크로 서비스에는 서비스 검색 레지스트리의 위치와 로그 이벤트를 내보내는 위치를 파악하는 방법이 필요한데 분산 특성으로 인해 분산 키-값 저장소를 사용하여 구현되는 경우가 많다.Identity Provider
: 서비스 인스턴스는 신뢰할 수 있는 ID를 사용하여 통신하며, 서비스 메시는 이러한 ID를 제공하고 유효성을 검사한다.
-
Service Image Repo
: 사용자 환경의 어딘가에는 빌드되고 테스트된 서비스의 불변 이미지를 저장하는 레지스트리가 있다. 이 저장소에 사용되는 기술은 사용하는 배포 단위에 따라 다른데 코드 저장소(동적으로 생성 된 서비스의 경우), Docker 이미지 레지스트리, 이진 아티팩트 저장소 또는 VM 이미지의 BLOB (Binary Large Object) 기반 저장소 일 수 있다. -
Message Oriented Middleware
: 가장 간단한 MSA 구현은 HTTP와 같은 동기식 프로토콜 또는 gRPC 또는 Thrift와 같은 보다 효율적인 프로토콜을 사용하여 지속 가능할 수 있지만 대부분의 MSA는 이벤트 및 메시지 중심 패턴을 지원하기 위해 비동기 메시징 채널이 필요하다 -
Build/Test Automation
: MSA의 개발 민첩성 이점은 개발 출력 품질을 극대화하고 전달을 간소화하기 위해 개발주기에서 높은 수준의 빌드 및 테스트 자동화가 필요하다. -
Deployment Automation
: 개발 민첩성 이점을 완전히 실현하려면 배포를 자동화 해야 한다. 외부 아키텍처 자체의 변경 자동화 (ex: 배포의 일부로 서비스 라우팅, 로드 균형 조정, 서비스 검색 및 서비스 구성 데이터 업데이트)를 지원해야 한다. -
Platform Automation
: 마이크로 서비스의 런타임 확장성과 적응성 이점을 실현하려면 외부 아키텍처에 기본 플랫폼과 관련된 자동화 기능 지원이 포함 되어야 한다. 여기에는 VM 또는 컨테이너의 프로비저닝 및 각 마이크로 서비스의 실행 중인 인스턴스 관리가 포함된다. -
Monitoring/Alert
: 분산 환경에서 문제가 발생할 때 모니터링 및 경고의 복잡성이 증가된다. 외부 아키텍처는 일관되고 효율적으로 이를 수행 할 수 있는 기능을 제공해야 한다. -
Logging & Diagnotics
: 분산 환경에서 문제가 발생하면 근본 원인을 식별하고 격리하기가 어려울 수 있다. 분산된 프로세스의 추적을 포함하여 자세한 계측 및 진단 분석을 지원함으로써 외부 아키텍처는 마이크로 서비스 팀이 문제를 보다 신속하게 분류하고 해결할 수 있도록 지원한다. -
Identity Provider
: 토큰 기반 서비스를 사용하여 인증 및 권한 부여를 외부화하는 것은 안전한 고객 대 서비스 및 서비스 대 서비스 상호 작용을 보장하는 것이 좋다.
[MSA Components]
-
Microservice Architecture에 대해 4개의 독립된 Layer를 정의하여 각 Layer가 개별적으로 쉽게 변할 수 있다.
-
Gateway Layer
: 버전 관리와 같은 간단한 게이트웨이 라우팅 기능을 제공하여 다른 플랫폼의 장치를 처리한다.- APIs
- Traffic throttle 처리에 필요한 모든 정책
- API 보안
- 올바른 버전으로의 라우팅
- Combine
- 데이터 정규화에 대한 유지
- 클라이언트 형태에 따른 output type의 변형
- Application Domain간의 연결
- APIs
-
Composite layer
: 다수의 Microservice 구성을 처리하는 중요한 중간 Layer이다. 이 계층에서 데이터 처리에 대한 복잡한 라우팅을 수행하고 데이터를 split/aggregate하며 이벤트를 트리거하거나 단순히 전달함으로써 분할/집계된 결과를 다른 마이크로 서비스에 적용한다. 이 계층은 Client로 부터 Microservice의 복잡성을 숨긴다.- MSA 구현 : Microservice에서 사용할 수있는 API를 호출하고 필요에 따라 데이터를 변환하며 해당 내용을 기반으로 담당 Microservice로 데이터를 라우팅한다.
- Event Trigger : 각 서비스간 느슨한 연결을 통해 Event를 유지해야 한다. 비동기 특성으로 인해 최상의 성능을 보장하는 형태를 구현한다. 여기서 이벤트 버스는 Message Broker일 필요는 없지만 모든 형태의 버스가 될 수 있다.
- Caching : REST Architecture는 Caching이 필요하다. 복합 Layer는 비즈니스 연관성이 떨어지므로 캐싱 메커니즘을 적용하여 Stateless를 유지해야 한다.
-
Basic Layer
: 시스템의 기본 구성 요소를 포함한다. 데이터 검색 또는 비즈니스 로직 처리를 처리한다. 각각은 모듈은 모두 독립적이어야 한다.- Anti-corruption layer : 이 계층은 Legacy Application 또는 Microservice가 규칙에 따라 작동하는 인터페이스를 처리한다.
[MSA Layers]
[Service Mesh Tech.]
- Service Mesh는 현재 크게 세가지 유형으로 구분할 수 있다.
-
PaaS(Platform as a Service)의 일부로 서비스 코드에 포함되는 유형
Mesh-Native Code
: Microsoft Azure Servicefabric
, lagom, SENECA 등이 이 유형에 해당되며, 프레임워크 기반의 프로그래밍 모델이기 때문에, 서비스메쉬를 구현하는데에 특화된 코드가 필요하다. -
라이브러리로 구현되어 API 호출을 통해 Service Mesh에 결합되는 유형
Mesh Aware Code
: Spring Cloud,Netflix OSS
(Ribbon/Hystrix/Eureka/Archaius), finagle 등이 이 유형에 해당되며, framework library를 사용하는 형태. 이중 Netfilix의 Prana는 sidecar 형태로 동작하며 서비스 메시를 이해하고 코드를 작성해야 한다. -
Side Car Proxy를 이용하여 Service Mesh를 Microservice에 주입하는 유형
Side Car Proxy
:Istio/Envoy
, Consul, Linkerd 등이 이 유형에 해당되며, Sidecar Proxy 형태로 동작하므로 Service Mesh와 무관하게 Code를 작성할 수 있다. : 최근의 Service Mesh는 Sidecar Pattern이 recommended 되고 있는 추세
--> Netflix 계열 OSS를 사용하기 위해선 동작을 위한 Application Library를 사용해야만 했는데, Kubernetes와 Service Mesh를 이용한 Microservice 관리(Istio/Envoy)시 소스코드 관리나 기존 정책을 바꿀 필요가 없다.
- 모든 응용 program container에 추가로 sidecar container가 배포된다. Sidecar는 서비스에 들어오거나 나가는 모든 네트워크 트래픽을 처리하게 된다.
- business logic이 포함된 실제 service와 sidecar가 병렬로 구성되어, 서비스 호출에서 서비스가 직접 서비스를 호출하는 것이 아니라 proxy를 통해서 호출하게 된다.
- 대규모 MSA 환경이라고 하여도 개발자가 별도의 작업 없이 서비스의 연결 뿐만 아니라, 로깅, 모니터링, 보안, 트래픽 제어와 같은 다양한 이점을 누릴 수 있다.
[Sidecar Pattern]
Library로 구현되어 API 호출을 통해 Service Mesh에 결합되는 Mesh Aware Code
유형에 대한 실습을 진행해 본다.
- microservice #1 :
displays
, port8081
- microservice #2 :
products
, port8082
- Eureka Server :
eureka-server
, port8761
(https://localhost:8761) - Zuul Server :
zuul
, port8765
- Hystrix Dashboard는 앞의 Hystrix 설정에 따른
Circuit Breaker
의 상태를 모니터링 할 수 있는 dashboard를 제공해주는 라이브러리이다. 사실 라이브러리라기 보다는 솔루션에 가깝다고 할 정도로 간단한 설정으로 실행할 수 있다. - Client 요청은 많은 traffic과 다양한 형태(예상하지 못한 형태)의 요청으로 경고없이 운영 이슈 발생 상황에 신속히 대응할 수 있는 시스템 zuul을 개발
- zuul은 이런한 문제를 신속하고, 동적으로 해결하기 위해서 groovy 언어로 작성된 다양한 형태의 Filter를 실행한다.
- Filter에 기능을 정의하고, 이슈사항에 발생시 적절한 filter을 추가함으로써 이슈사항을 대비할 수 있다.
- Authentication and Security : 클라이언트 요청시, 각 리소스에 대한 인증 요구 사항을 식별하고 이를 만족시키지 않는 요청은 거부
- Insights and Monitoring : 의미있는 데이터 및 통계 제공
- Dynamic Routing : 필요에 따라 요청을 다른 클러스터로 동적으로 라우팅
- Stress Testing : 성능 측정을 위해 점차적으로 클러스터 트래픽을 증가
- Load Shedding : 각 유형의 요청에 대해 용량을 할당하고, 초과하는 요청은 제한
- Static Response handling : 클러스터에서 오는 응답을 대신하여 API GATEWAY에서 응답 처리
[Zuul Core Architecture]
- Zuul-Core의 ZuulServlet을 그대로 사용하여, 아래 그림과 같이 Spring MVC 위에서 동작하기 위해 몇 가지를 추가
[Zuul Core]
RouteLocator
은 url path에 대한 routing을 지정한다. 요청이 들어오면 url path로 어떻게 routing 할 것인가를 정의하고 있다.ZuulHandlerMapping
은 org.springframework.web.servlet.handler.AbstractUrlHandlerMapping을 상속받고, RouteLocator에 정의된 url path에 zuulController를 매핑한다. RouteLocator에 정의된 path의 요청이 들어오면 zuulController를 호출하게 된다.ZuulController
은 org.springframework.web.servlet.mvc.ServletWrappingController를 상속받으며, ZuulServlet을 주입시킨다. 그래서 ZuulController로 들어온 모든 요청은 ZuulServlet으로 처리한다.ZuulFilterInitializer
는 filter Map에 정의된 filter를 FilterRegistry에 등록하고, FilterLoader로 로딩한다.
compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix-dashboard')
compile('org.springframework.boot:spring-boot-starter-actuator')
spring:
application:
name: zuul
server:
port: 8765
management:
security:
enabled: false
endpoints:
web:
exposure:
include: hystrix.stream
base-path: /
- Spring Boot Project에 Artifact ID Spring-Cloud-Starter-Zuul를 추가하고 Main Class에
@EnableZuulProxy
또는@EnableZuulServer
를 명시해주면 Zuul 서버가 구축된다.
@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
@EnableHystrixDashboard
@EnableTurbine
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
[Hystrix Dashboard]
[Hystrix Stream]
- 격리 전략이란 일종의 Bulkhead Pattern이며, 각 서비스에 대한 dependency을 격리하고 동시 접근을 제한한다.
- 아래 그림에서 빨간색으로 표기된 상자는 특정 서비스의 호출이 지연되고 있다는 의미이며, 나머지 서비스에는 영향을 주지 않고 있다. 또한, 동시 접근 제한을 서비스별로 다르게 설정하고 있다.
- Isolation의 방법으로는 두 가지가 있다.
- 서비스 호출이 별도의 thread에서 수행된다. 이렇게 하면 네트워크상의 timeout 위에 thread timeout을 둘 수 있다.
- 하지만 별도의 thread를 사용하는 만큼 비용이 드는데 여기서는 이를 가리켜 연산 오버헤드(Computational Overhead)라고 표현한다.
- HystrixCommand를 사용할 때는 Thread isolation을 권장하고 있다.
Semaphore
- 서비스 호출을 위해 별도의 thread를 만들지 않는다. 단지 각 서비스에 대한 동시 호출 수를 제한할 뿐이다.
zuul:
routes:
product:
path: /products/**
serviceId: product
stripPrefix: false
display:
path: /displays/**
serviceId: display
stripPrefix: false
ribbon-isolation-strategy: thread <- "이번 실습에서는 Thread 방식을 사용한다."
thread-pool:
use-separate-thread-pools: true
thread-pool-key-prefix: zuul-
...(중략)...
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 1000
product:
execution:
isolation:
thread:
timeoutInMilliseconds: 10000 <- "Thread에 대한 timeout을 설정한다."
threadpool:
zuul-product:
coreSize: 30
maximumSize: 100
allowMaximumSizeToDivergeFromCoreSize: true
zuul-display:
coreSize: 30
maximumSize: 100
allowMaximumSizeToDivergeFromCoreSize: true
- Zipkin으로 추적할 수 있는 분산 트렌젝션은 HTTP를 기본으로 지원하고, 이외에도 많이 사용되는 리모트 프로토콜인 gRPC를 함께 지원한다.
- Zipkin 클라이언트 SDK는
에 있는데, Zipkin에서 공식적으로 지원하는 라이브러는 아래와 같이 C#, Go, Java, Javascript,Ruby,Scala 등이 있다.
- Zipkin 라이브러리는 수집된 트렌젝션 정보를 zipkin 서버의 collector 모듈로 전송한다. 이 때 다양한 프로토콜을 사용할 수 있는데, 일반적으로 HTTP를 사용하고, 시스템의 규모가 클 경우에는 Kafka Queue를 넣어서 Kafka Protocol로 전송이 가능하다.
- Zipkin Client SDK에 의해서 전송된 정보는 Storage(In-Memory, MySQL, Cassandra, Elastic Serch)에 저장할 수 있다.
- 이렇게 수집된 정보는 Dashboard를 이용하여 시각화가 가능하다. Zipkin Server의 dashboard를 사용할 수 있고, Elastic Search 백앤드를 이용한 경우에는 Kibana를 이용하여 시각화가 가능하다.
[Zipkin Architecture]
- Application에서 Distributed Log Trace를 해보자.
- Spring Boot application을 Zipkin과 연동하기 위해서는
Sleuth
라는 Library를 사용하면 된다. - Java application에서 Trace 정보와 Span 정보를 넘길 때, 여러 class의 method들을 거쳐서 transaction이 완성될때, Trace 정보와 Span 정보 Context가 유지가 되어야 하는데, thread마다 할당되는 thread의 일종의 전역변수인 Thread Local 변수에 이 Trace와 Span Context 정보를 저장하여 유지한다.
- 분산 트렌젝션은 HTTP나 gRPC로 들어오기 때문에, Spring Sleuth는 HTTP request가 들어오는 시점과 HTTP request가 다른 서비스로 나가는 부분을 wrapping하여 Trace와 Span Context를 전달한다.
- 아래 그림과 같이 HTTP로 들어오는 요청의 경우에는 Servlet filter를 이용하여, Trace Id와 Span Id를 받고 (만약에 이 서비스가 맨 처음 호출되는 서비스라서 Trace Id와 Span Id가 없을 경우에는 이를 생성한다.)
- 다른 서비스로 호출을 할 경우,
RestTemplate
을 wrapping하여, Trace Id와 Span Id와 같은 Context 정보를 보낸다.
compile('org.springframework.cloud:spring-cloud-starter-zipkin')
compile('org.springframework.cloud:spring-cloud-starter-sleuth')
spring:
application:
name: display
zipkin:
baseUrl: https://127.0.0.1:9411/
sleuth:
enabled: true
sampler:
probability: 1.0
sample:
zipkin:
enabled: true
public class DisplayController {
@Autowired
RestTemplate restTemplate;
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
@Bean
public Sampler alwaysSampler() {
return Sampler.ALWAYS_SAMPLE;
}
- alwaysSampler() 정의를 통해 Tracing Transaction Rate를 결정 가능
- jar 파일을 다운 받은 후에, java -jar로 서버를 구동하는게 간편하다. ※ 유의사항 : zipkin 서버를 통해서 HTTP로 Trace Log를 받을 때, 별도의 보안이나 인증 메커니즘이 없기 때문에 zipkin 서버는 반드시 방화벽 안에 놓고 서비스 서버로부터만 HTTP 호출을 받을 수 있도록 해야 한다.
> wget -O zipkin.jar <-- Download
> java -jar zipkin.jar <-- Server 구동
- 서비스 구동
https://localhost:9411
Zipkin Server 접속- Find Traces를 통한 개별 Transaction 확인
[Trace Result]
-
자체 SDK를 이용하여 transaction을 추적하는 것도 가능하며, Zipkin client로 부터 log를 수집할 수 있다.
-
개발 server는 Zipkin을 사용하고, backend에는 복잡한 Zipkin 서버 대신 Stack driver trace를 사용하는 방법으로 Zipkin 서버 대신 Zipkin/stack driver collector라는 server를 띄우면(addr/port 변경), 이 server가 Stackdriver로 log를 저장하고 시각화 해준다.
-
Google Cloud뿐만 아니라, local 환경, AWS, Azure, On Prem 등 다양한 환경에 설치가 가능하여 모든 애플리케이션 서비스를 통합해서 Stack driver로 trace가 가능하다.
-
Service별 build.gradle에 dependency 정의
// https://mvnrepository.com/artifact/com.google.cloud.trace.adapters.zipkin/collector
compile('com.google.cloud.trace.adapters.zipkin:collector:0.6.0') // To use StackDriver
- Docker Image 또는 java jar 파일을 download하여 사용한다.
- Google Cloud VM이나 Docker로 실행할 때는 상관 없지만, google cloud 밖에서 Zipkin Stackdriver collector를 실행할 때는 추가 인증 정보를 설정해야 한다.
- Stack driver collector가 Stackdriver server(google cloud)로 log를 전달하기 위해서는 아무 log나 받으면 안되고 추가 인증된 log만 받아야 하는데 google cloud에서는 application 인증을 위해서 Service Account라는 JSON 파일을 사용한다.
- Service Account 파일이 생성되면, 아래와 같이
GOOGLE_APPLICATION_CREDENTAILS
환경 변수에 Service account 파일의 경로를 지정하고 google cloud의 어느 project에 있는 Stack Driver와 연결할지를PROJECT_ID
환경 변수에 Project명을 지정해주면 된다.
export GOOGLE_APPLICATION_CREDENTIALS="c:/zipkin-proxy-dc1792cd9893.json"
export PROJECT_ID="zipkin-proxy"
- 환경변수 설정이 끝나면
java -jar collector-0.6.0.jar
명령으로 collector를 실행한다. (port: 9411) - GCP내 Stackdriver > Trace > Trace List을 통해 세부정보 확인
[Result]
- FindOrderService에서 주문 상세 조립물을 만들기 위해 API를 순차적으로 호출한다면 API가 많으면 많을수록 응답 시간이 길어질 것이다. 예를 들어 OrderService, KitchenService, AccountingService는 각 1초가 걸렸지만 DeliveryService에서 5초가 걸렸다면 결과적으로 응답 시간은 8초가 걸린다.
- 반면 동시에 API를 호출하여 데이터를 조립한다면 상대적으로 응답 시간을 줄일 수 있다.
- Java에서는 동시성을 Thread로 구현한다. Java 5에 도입된
Concurrency API
(java.util.concurrent 패키지)를 사용하여 여러 Thread에 API 호출하는 작업을 할당하여 동시에 실행하는 것을 구현할 수 있다.
- Java 8에서 Concurrency API 향상으로 도입된 것이
CompletableFuture
이다. CompletableFuture는 비동기 작업들을 함께 묶을 수 있으며 더 나아가 단계로 구성할 수 있다. - 어떤 API는 중요한 정보가 아니라서 정해진 시간 이내에 응답이 오지 않으면 무시하고 결과를 전달할 필요가 있다.
- Java 8의 CompletableFuture는 명시적으로 timeout을 지원하지 않는다. 다행히도
Java 9
부터 CompletableFuture는 orTimeou
메소드를 지원한다.
Usage of Swagger 2.0 in Spring Boot Applications to document APIs
- Source Code내에서 annotation을 통해 직접 API를 문서화할 수 있다.
compile('io.springfox:springfox-swagger2:2.9.2')
compile('io.springfox:springfox-swagger-ui:2.9.2')
@EnableSwagger2
...
@Bean
public Docket newsApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("display")
.apiInfo(apiInfo())
.select()
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Micro Service Architecture with Swagger")
.description("Micro Service Architecture with Swagger")
.license("Apache License Version 2.0")
.version("2.0")
.build();
}
...
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Success", response = DisplayApplication.class),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 403, message = "Forbidden"),
@ApiResponse(code = 404, message = "Not Found"),
@ApiResponse(code = 500, message = "Failure")})
[Result]
- MSA는 모든 Application에 적용할 수 있는 것은 아니다.
- MSA로 이동해야 한다면, 기존 Monolith에서 감수해 내야만 하는 것들을 결정해야 한다.
- 매우 드문 경우에만 Monolith의 모듈 그대로를 분리하여 MSA화 할 수 있다. 그 외의 경우에는 기존 프로세스를 유지하지 못한다.(코드 레벨까지 수정 혹은 재개발이 필요하다.)
- MSA가 비즈니스 확장성 및 생산성에 큰 이점이 있는 것은 사실이지만, 어떤 경우에는 Monolith를 그대로 유지하여 개발하고, 운영하는 것이 더 큰 business value를 가져다 주기도 한다.
- Monolith는 단일 객체 그 자체이기 때문에, 해당 architecture에 속해 있는 데이터 모델 및 데이터베이스를 변경하는 것은 매우 어렵거나 거의 불가능에 가깝다. 이를 위해서는 데이터에 대한 Refactoring이 필요하다.
[출처: A Microservices Maturity Model, from “Spring 5.0 Microservices,” 2nd Edition”by Rajesh R V (O’Reilly)]
- 코드의 API화나 Integration 등에 대한 이야기 보다는 종속된 데이터 관계를 어떻게 분리시킬 것인지, 분리된 데이터 관계로 인한 모듈화가 중요하다.
Module에 대한 식별
: 기존 모듈을 유지하거나, 새로운 모듈 작성, 어떤 기능(모듈)을 분리하고 싶은지, 해당 서비스가 어떤 테이블에 연관되어 있는지에 대해 판단한 다음 그 곳에서 부터 변화를 시작해야 한다.DB 재정의
: 각각 모듈에 해당하는 Database table 분리, 서비스로 포장, dependencies 업데이트. 각 모듈의 독립성을 유지하기 위해서는 반드시 데이터가 분리되어야 한다.Code Update
: 새로운 서비스를 호출하기 위해 DB 테이블에 직접 호출했던 코드 업데이트- 더 이상 모듈화 단계를 반복할 수 없을 때까지 이 방법을 지속적으로 강화 및 반복한다. but,
- 현존하는 많은 수의 monolith가 위와 같은 방법으로 깔끔한 모듈화가 어렵다.
- 테이블 간의 정규화, 엔티티 결합, 무결정 제약 조건 등을 유지하기 까다롭다.
- Monolith에 복잡한 Query 코드를 작성했을 때, 어떤 테이블을 어떻게 사용했는지 이해하기 힘들 수 있다.
- 단순하게 모듈을 쪼개는 방식이 아닌 매우 까다롭고 비용이 많이 드는 migration이 있을 수 있다.
- 모듈화를 진행하다 보면, 오히려 쪼개지 않는 쪽에 이점이 많은 지점이 생길 수 있다.
[Migration]
Monolith 판단시 고려사항
- Monolithic code와 DB는 변화하기 매우 어렵다.
- MSA로의 변경은 팀간의 높은 수준의 협업과 커뮤니케이션이 필요하다.
- 우리는 반복적인 분석을 통해 수 없이 많은 테스트를 실시해야 한다. 비즈니스는 안정성이 필수이기 때문이다.
- 완벽한 자동화를 이용하여 새로운 프로세스를 배포해야 한다.
UI 추출시 고려사항
- 이 단계에서 Monolithic Application을 수정하면 안된다. 단순히 Monolith에 포함되어있는 UI를
Copy-Paste로 복사를 하여 분리
시켜야 한다. - 작업을 수행하기 전, UI와 Monolith 사이에 적절한
API Interface 설계
가 되어 있어야 한다. - Ingress 구간이 두 채널이 되기 때문에,
보안에 대한 고려
도 필요하다. - UI와 Monolith 두 구간으로의 트래픽 분산을 위한
Platform 설계
가 돼있어야 한다. 또한 Canary, Blue-green, Rolling Deployment 정책을 수행하기 위한 프로세스도 존재해야 한다.
UI를 Monolith에서 분리시 고려사항
- UI 모듈을 Monolith에서 완전히 제거하는 작업이다.
- 이 작업을 수행하려면 Monolith에 대한 최소한의 변경이 필요하다.
- Routing/Shaping 방식을 사용하여 다운타임 없이 변화를 수행해야 한다.
신규 서비스 도입시 고려사항
- 신규 서비스는 기존 Backend와의 API 디자인 및 Boundary에 대한 우선적인 설계가 될 것이다.
- 이 서비스는 Backend에서 분리된 것이 아니라, 새롭게 작성된 기능이다.
- API 설계를 결정한 후에는, 간단한 Scaffolding 혹은 Place holder를 구현할 것이다.
- 신규 서비스는 자체 데이터 베이스를 가지고 있다.
- 아직 이 단계에서는 서비스에 트래픽이 접근하지 않는다.
신규 서비스와 API 통합시 고려사항
- 신규 서비스는 Monolith의 데이터 모델과 긴밀하게 결합된 모델을 가지고 있다.
- 실 상황에서 Monolith는 데이터를 얻기 위한 API가 설계되어 있지 않을 가능성이 크다.
- Read-only query를 위해 임시적으로 Backend DB에 direct로 접근할 수 있다.
- Monolith의 DB가 수정되는 일은 거의 없다.
신규 서비스의 Dark Launch시 고려사항
- Code path에 신규 서비스를 적용하면 많은 이슈가 발생할 수 있다.
- 신규 서비스의 영향도를 체크하고 모니터링 해야한다.
- 트래픽 제어를 위한
gateway platform
에 대한 구성이 필요하다. - 이 게이트웨이 플랫폼을 이용하여 특정 사람 혹은 집단의 트래픽을 새로운 Backend 서비스로 연결해야 한다.
신규 서비스로 Canary/Rolling 배포시 고려사항
- 바로 이 ‘cohort group’을 식별하고 새로운 Microservice에 실시간 트랜잭션 트래픽을 보낼 수 있어야 한다.
- 트랜잭션이 여전히 두 코드 경로로 진행되는 일정한 기간이 있기 때문에, 여전히 Monolith에 직접 데이터베이스 연결이 필요하다.
- 모든 트래픽을 새로운 버전인 Microservice로 이동 한 후에 그 전 기능을 제거해야 한다.
- 라이브 서비스를 새로운 v2 서비스로 보내면 이전 버전으로 Rollback할 때 이슈가 발생할 수 있다. v1과 v2를 Load-balancing 방식으로 계속 트래픽을 공유하면 안된다.
Offline Data ETL/Migration시 고려사항
- Monolith의 데이터와 Microservice 데이터가 공유 가능한 데이터인지 확인해야 하며, 공유 및 변경이 가능하다면 데이터 소유에 대한 이슈를 해결해야 한다.
Datastore와 연결 해제 및 Decouple시 고려사항
- 신규 서비스의 API Interface를 backend direct로 연결된 것이 아닌 gateway 모듈로 연결하여 완전한 De-coupling 구조로 만든다.
-
Istio를 사용하면 서비스 코드의 코드 변경 없이 로드 밸런싱, 서비스 간 인증, 모니터링 등을 통해 배포된 서비스의 네트워크를 쉽게 생성할 수 있다.
-
Istio는 서비스 네트워크 전체에 걸쳐 다음과 같은 다양한 주요 기능을 제공한다.
Traffic Management
: Istio의 쉬운 규칙 구성 및 트래픽 라우팅을 통해 서비스 간의 트래픽 및 API호출 흐름을 제어할 수 있다. 또한 circuit breakers, timeout 및 재시도와 같은 서비스 레벨 속성의 구성을 단순화하고 A4B test, canary rollout, 백분율 기반 트래픽 분할과 같은 중요한 작업을 쉽게 설정할 수 있다.
Security
: 기본 보안 통신 채널을 제공하고 서비스 통신의 인증, 권한 부여 및 암호화를 규모에 맞게 관리할 수 있다. 기본적으로 envoy를 통해서 통신하는 모든 트래픽을 자동으로 TLS를 이용해서 암호화한다. 즉 서비스간의 통신이 디폴트로 암호화 된다.
-
Policies
: Istio를 사용하면 다음과 같은 규칙을 런타임에 적용하도록 응용 프로그램에 대한 사용자 지정 정책을 구성할 수 있다.- 서비스에 대한 트래픽을 동적으로 제한하는 속도 제한
- 서비스 액세스 제한을 위한 부정, 화이트 리스트 및 블랙 리스트
- 헤더 다시 쓰기 및 리디렉션
-
Observability
: 강력한 추적, 모니터링 및 로깅 기능을 통해 서비스와 서비스 간의 종속성을 관리하며, 트래픽 간의 특성 및 흐름을 파악하여 이슈를 신속하게 파악할 수 있다. -
Platform Support
: Istio는 Cloud, On-premise, Kubernetes, Mesos 등 다양한 기반 환경에서 실행할 수 있도록 설계되었다. 현재는 Kubernetes에 중점을 두고 있지만, 곧 다른 환경을 지원하기 위해 커뮤니티가 진행되고 있다. -
Policy Enforcement
: 서비스 간 상호 작용에 대해 access, role 등의 정책을 설정하여 리소스가 각 서비스에게 공정하게 분배되도록 제어한다. 이 정책 변경에 대한 부분은 application 소스를 직접 수정하는 것이 아니라 mesh로 제어가 된다. -
Integration and Customization
: 정책 집행이 가능한 영역을 확장하기 위하여 mesh의 연결에 대한 부분을 커스터마이징하여 ACLs, Logging, Monitoring, quotas, auditing 등의 기존 솔루션과 통합할 수 있다.
-
Istio Service Mesh는 논리적으로 Data Plane과 Control Plane으로 나뉜다.
-
Data Plane
은 Microservice 사이의 모든 네트워크 통신을 조정하고, 제어하는 Kubernetes의 Application Pod에 Sidecar Container로 배치된 Envoy Proxy로 구성된다. -
Control Plane
은 Pilot, Mixer, Istio-Auth로 구성되어 런타임에 정책을 시행 할뿐만 아니라 트래픽을 라우팅하기 위해 프록시를 관리 및 구성한다.
-
Envoy
- C++로 개발된 고성능 Proxy Sidecar로서 Service Mesh의 모든 서비스에 대한 Inbound/Outbound 트래픽을 처리한다.
- Dynamic Service Discovery, Load Balancing, TLS Termination, HTTP/2 & gRPC Proxying, Circuit Breakers, Health Checks, %-based Traffic Split, Fault Injection, Rich Metrics 등의 기능을 포함한다.
- 동일한 Kubernetes Pod의 Application Service에 Sidecar로 배치된다. 이를 통해 Istio는 트래픽 동작에 대한 데이터를 attribute로 추출할 수 있고, Mixer에서 정책을 관리하는데 사용할 수 있으며, 모니터링 시스템(Prometheus, Grafana 등)에 보내져 전체 Mesh의 동작에 대한 정보를 관리할 수 있다.
-
Mixer
- Service Mesh 전체 영역에서 액세스 제어 및 사용 정책을 정의하고, Envoy Proxy 및 기타 서비스에서 데이터를 원격에서 수집하는 독립 모듈이다.
- Request Level attribute를 추출하여 평가를 위해 Mixer로 데이터를 보낸다.
- Plugin이 가능한 adaptor 구조로, 운영하는 인프라에 맞춰서 logging 및 monitoring system 변경이 가능하다. k8s에서 많이 사용되는 Heapster나 Prometheus에서부터 GCP의 StackDriver, 전문 모니터링 서비스인 Datadog등으로 저장이 가능하다.
-
Pilot
- Envoy Sidecar에 대한 서비스 검색, 지능형 라우팅 (예 : A/B 테스트, Canary 배치 등) 및 Resiliency (timeout, retries, circuit breakers 등)을 위한 트래픽 관리 기능을 제공한다.
- 특정 트래픽 정책을 Envoy Sidecar Container로 전달하여 라우팅 규칙들을 적용시켜준다.
- Pilot은 플랫폼에 종속되지 않고, Envoy Data Plane을 준수하는 모든 Sidecar에 표준 format으로 통합시킨다.
-
Istio-Auth
- Mesh를 관리하기 위한 ID 및 서비스 Authentication을 위해 TLS를 사용한 Service-To-Service Enduser 인증을 제공한다.
- Service Mesh에서 암호화되지 않은 트래픽을 전송하는 데 사용할 수 있으며, 운영자는 네트워크 컨트롤 대신 Service ID를 기반으로 정책을 시행할 수 있다.
- Istio를 설치하기 위해서는 Kubernetes 기반의 Platform이 준비되어야 한다. [
Openshift 3.7(Kubernetes 1.7)
]
$ launch.sh
Waiting for Kubernetes to start...
Kubernetes started
$ kubectl cluster-info
Kubernetes master is running at https://172.17.0.9:6443
KubeDNS is running at https://172.17.0.9:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
- Istio backed services를 관리하고 deploy를 위해 사용할 CLI tooling과 Istio를 지원하기 위한 k8s cluster 설정을 위한 intall 진행
$ curl -L https://git.io/getLatestIstio | ISTIO_VERSION=1.0.0 sh -
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 3015 100 3015 0 0 4028 0 --:--:-- --:--:-- --:--:-- 45000
Downloading istio-1.0.0 from https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz ... % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 635 100 635 0 0 3714 0 --:--:-- --:--:-- --:--:-- 3735
100 14.1M 100 14.1M 0 0 278k 0 0:00:52 0:00:52 --:--:-- 559k
Istio 1.0.0 Download Complete!
Istio has been successfully downloaded into the istio-1.0.0 folder on your system.
- path에 bin 폴더 추가
$ export PATH="$PATH:/root/istio-1.0.0/bin"
$ cd /root/istio-1.0.0
- Custom Resource Definitions (CRD)를 통해 k8s를 확장한다. (crds.yaml)
$ kubectl apply -f install/kubernetes/helm/istio/templates/crds.yaml -n istio-system
- 기본적으로 상호 TLS 인증을 적용한다.
$ kubectl apply -f install/kubernetes/istio-demo-auth.yaml
- Pods로 배포된 모든 서비스 확인한다.
$ kubectl get pods -n istio-system
NAME READY STATUS RESTARTS AGE
grafana-fff7f4b74-gdxqf 1/1 Running 0 96s
istio-citadel-65bf48d985-k4jrs 1/1 Running 0 96s
istio-cleanup-secrets-l5mdj 0/1 Completed 0 98s
istio-egressgateway-bf5775d64-bl5nr 1/1 Running 0 96s
istio-galley-8485bfc668-vlb26 1/1 Running 0 97s
istio-grafana-post-install-vhb7s 0/1 Completed 0 99s
istio-ingressgateway-6796bc5c85-78ksf 1/1 Running 0 96s
istio-pilot-6995fb8f49-4tb8k 2/2 Running 0 96s
istio-policy-77cb84dbd7-qr8cc 2/2 Running 0 96s
istio-security-post-install-dnm6s 0/1 Completed 0 98s
istio-sidecar-injector-7f6fdc7989-nhhsn 1/1 Running 0 95s
istio-statsd-prom-bridge-5b596dfc-7pkd6 1/1 Running 0 97s
istio-telemetry-5d7b78dc5b-74pxl 2/2 Running 0 96s
istio-tracing-c8b67b59c-8m6r2 1/1 Running 0 95s
prometheus-5b77b7d695-zw9l9 1/1 Running 0 96s
servicegraph-57c58d6d6d-x9v5x 1/1 Running 0 96s
- 샘플 BookInfo 애플리케이션 및 대시보드를 외부, 특히 Katacoda에서 사용할 수 있도록 katacoda.yaml을 배포한다.
$ kubectl apply -f /root/katacoda.yaml
service/katacoda-servicegraph created
service/katacoda-grafana created
service/katacoda-jaeger-query created
service/katacoda-prometheus created
service/istio-ingressgateway configured
- Sample Applicationd을 deploy한다.
$ kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml)
service/details created
deployment.extensions/details-v1 created
service/ratings created
deployment.extensions/ratings-v1 created
service/reviews created
deployment.extensions/reviews-v1 created
deployment.extensions/reviews-v2 created
deployment.extensions/reviews-v3 created
service/productpage created
deployment.extensions/productpage-v1 created
- gateway를 deploy한다.
$ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created
- Pods가 시작될 때, container가 생성되며 시작 단계가 발생한다. 이는 istio service mesh 내의 응용 프로그램에 대한 트래픽 관리 및 인증을 처리하기 위한 Envoy sidecar를 구성하는 것이다.
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
details-v1-779c7845c5-6czcm 2/2 Running 0 2m
productpage-v1-64f9bf7767-qmgdk 2/2 Running 0 119s
ratings-v1-596455959-zzgtp 2/2 Running 0 2m
reviews-v1-6bdb55dbdf-hn8gc 2/2 Running 0 119s
reviews-v2-746cc79789-wws69 2/2 Running 0 119s
reviews-v3-58fcf899fc-tw67r 2/2 Running 0 119s
- 기본 대상 규칙 적용 : Istio를 사용하여 Bookinfo 버전 라우팅을 제어하기 전에 대상 규칙에서 하위 집합이라고 하는 사용 가능한 버전을 정의해야 한다.
$ kubectl apply -f samples/bookinfo/networking/destination-rule-all-mtls.yaml
destinationrule.networking.istio.io/productpage created
destinationrule.networking.istio.io/reviews created
destinationrule.networking.istio.io/ratings created
destinationrule.networking.istio.io/details created
- Bookinfo Architecture
- productpage microservice는 홈페이지로, 세부 정보를 사용하여 채워지고 마이크로 서비스를 검토한다.
- details microservice에는 책 정보가 들어 있다.
- reviews microservice에는 서평이 포함되어 있다. 그것은 별 등급에 대한 등급 마이크로 서비스를 사용한다.
- atings microservice에는 서평에 대한 서적 등급이 포함되어 있다.
- Istio의 주요 특징 중 하나는 traffic management다. Microservice architectures의 확장에 따라, 보다 진보된 service-to-service 통신 제어에 대한 요구사항이 있다.
- 트래픽 관리의 한 가지 측면은 사용자 에이전트 문자열, IP 주소 또는 쿠키와 같은 HTTP 요청을 기반으로 트래픽 라우팅을 제어하는 것이다.
$ cat samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
- routing rules은 istioctl을 사용하여 적용할 수 있다.
$ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
virtualservice.networking.istio.io/reviews created
- Productpage 접속 (jason/jason)
- 테스트를 위해 트래픽을 분할하고 변경사항을 롤아웃하는 능력은 중요하며 이를 통해, A/B 변동 테스트 또는 카나리아 릴리즈 배포가 가능하다.
$ cat samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 50
- destination:
host: reviews
subset: v3
weight: 50
$ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml
virtualservice.networking.istio.io/reviews configured
- 위의 접근 방식을 고려할 때 canary release가 성공적이라면 traffic의 100%를 review로 이동시킨다.
$ cat samples/bookinfo/networking/virtual-service-reviews-v3.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v3
$ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-v3.yaml
virtualservice.networking.istio.io/reviews configured
$ istioctl get virtualservices
VIRTUAL-SERVICE NAME GATEWAYS HOSTS #HTTP #TCP NAMESPACE AGE
bookinfo bookinfo-gateway * 1 0 default 17m
reviews reviews 1 0 default 6m
- Grafana를 통해 모니터링하려면 트래픽이 있어야 한다. 응용 프로그램에 요청을 보내기 위해 아래 명령을 실행한다.
$ while true; do
> curl -s https://2886795281-80-elsy06.environments.katacoda.com/productpage > /dev/null
> echo -n .;
> sleep 0.2
> done
- 현재 Istio의 최신 버전은
1.4.4
이다.
$ curl -L https://istio.io/downloadIstio | sh -
$ cd istio-1.4.4
$ export PATH=$PWD/bin:$PATH
Prometheus
: System 모니터링 및 Alert을 위한 Toolkit으로, CNCF(Cloud Native Computing Foundation)의 2번째 호스팅 프로젝트로 선정될 정도로 활발한 오픈소스 모니터링 프로젝트이다. (첫번째는 Kubernetes). 다만, Scale-out이 안되는 구조라 Pod의 Size(CPU/MEM/Disk)를 늘려야 한다.Grafana
: 등록되어 있는 서비스(Application)과 상호작용하는 쿼리, 통신, 상태 등을 시각적으로 보기 좋게 나열해주는 Metrics Visualization 도구이다.Jaeger Tracing
: 등록되어 있는 서비스들의 시계열 데이터를 모아 Tracking을 제공해주는 toolkit으로 troubleshooting, Latency issue 등을 tracing할 수 있는 MSA 환경에서의 분산 트레이싱 도구이다.Kiali
(https://www.kiali.io/) : Istio에 의해서 수집된 각종 지표를 기반으로, 서비스간의 관계를 시각화하여 나타낼 수 있다.
Servicegraph
: Mesh 안에서 서비스들의 그래프를 나타내주는 toolkit이다.
MSA, 조직의 문화가 준비돼 있어야
- MSA를 채택할 때에는 무엇보다 비즈니스를 중심으로 생각해야 한다. 비용은 물론 기술적·조직적 제약 조건을 충족시키는 세밀성과 분해의 올바른 균형을 찾는 것이 목표가 되어야 한다.
- MSA라는 것은 결국 지속적으로 변화가 필요할 때 변화에 빨리 대응하기 위해 도입하는 것이고, 그렇게 해야만 혜택이 생긴다. 그러나 특정 조직이 언제까지 뭔가를 해야 한다는 데드라인을 요구한다면 MSA의 효과를 충족시키지 못하게 된다.
MSA, 만능은 아니지만 준비돼 있다면 가치 크다
- MSA를 기술적인 프로젝트로만 간주해서 진행하면 안 되고, 비즈니스 가치를 제공하기 위한 것이라는 것을 염두에 두고 진행해야 한다
- MSA가 가치를 제공하기 위해서는 지속적인 애플리케이션의 변화를 신속하게 따라가면서 서비스를 선보여야 하는데, 만약 어떤 조직이 애플리케이션을 개발해 놓고 변화 없이 그대로 가는 경우에는 굳이 MSA가 필요 없다
- MSA에서 가치나 효과를 기대하기 위해서는 개발이 신속하게 이뤄져야 하는데, 그 전제조건으로 agile한 개발, DevOps라던가 통합 파이프라인, 테스팅 자동화, 인프라 등이 갖춰져야 한다는 점이다. 이러한 부분이 되지 않으면 전환해봐야 별다른 가치를 갖지 못한다.
- 전환과정이 점진적으로 이뤄져야 한다. monolithic에서 MSA로 가는 부분에 있어 단계별 접근이 필요하다. 처음에는 큰 부분(macro)에서부터 점점 작은 부분(micro)으로 가면서, 효과를 체크하면서 가야 한다. 얻을 수 있는 가치가 적어지기 시작하면 micro로 갈 필요가 없다는 것이다. 때문에 단계적으로 추진해야 한다.
- 결국 MSA를 통해 애플리케이션 개발의 전deployment model을 바꾸는 건데, 이 과정에서 어떤 혜택을 얻으려면 모든 것이
API
에 기반을 두고 이뤄져야만 한다. 그래야 code 등을 변경해도 다른 애플리케이션에는 영향 없이 할 수 있다. 그리고 이 API를 활용해 애플리케이션 코드를 재모듈화(remodulization)해 분해하고, 또 재배포하는 모델을 갖춰야 한다.
현업이 주도하고 위에서 지원…‘목표’ 돼선 안돼
- 어떤 부분들이 우리의 제약 요건인지, 방해 요소인지 파악하고 생각지 않았던 잠재적 이슈나 부작용, 실패 등을 파악해야 한다.
- MSA가 적절한 가치를 산출하려면 비즈니스 가치를 위한 수단이 돼야 한다. 그렇지 않으면 MSA를 남용하거나, 과대평가되고 목표가 돼서 추진될 가능성이 있다.
- Netflix, Amazon, eBay 등 성공사례를 보더라도 이들 역시 굉장히 점진적으로 다양한 Level에서 MSA를 도입, 실행하고 있다. 완전히 MSA를 하기보다는 이렇게 조금씩 하다 보면 그 과정에서 배우는 것이 생기고, 또 기술을 개발하면서 점차 나아가는 게 최선이라고 생각한다.
[Trello]