클라우드 컴퓨팅 & NoSQL/도커 & 쿠버네티스

Istio #1 - 마이크로 서비스와 서비스 매쉬

Terry Cho 2018. 11. 20. 20:25

Istio #1

마이크로 서비스 아키텍처와 서비스 매쉬

조대협 (http://bcho.tistory.com)


마이크로 서비스 아키텍쳐는 여러가지 장점을 가지고 있는 아키텍쳐 스타일이기는 하지만, 많은 단점도 가지고 있다. 마이크로 서비스는 기능을 서비스라는 단위로 잘게 나누다 보니, 전체 시스템이 커질 수 록 서비스가 많아지고, 그로 인해서 서비스간의 연결이 복잡해지고 여러가지 문제를 낳게 된다



<그림. 넷플릭스의 마이크로 서비스 구조 >

출처 : https://www.slideshare.net/BruceWong3/the-case-for-chaos?from_action=save


서비스간의 전체 연결 구조를 파악하기 어려우며 이로 인해서 장애가 났을때, 어느 서비스에서 장애가 났는지 추적이 어려워진다.

또한 특정 서비스의 장애가 다른 서비스에 영향을 주는 문제들을 겪을 수 있다.



예를 들어 클라이언트→ 서비스 A → 서비스 B의 호출 구조가 있다고 하자. 만약 서비스 B가 느려지거나 응답이 없는 상태가 되어 버리면, 서비스 B를 호출 하는 서비스 A 안의 쓰레드는 서비스 B로 부터 응답을 기다리기 위해 대기 상태가 되고, 이 상태에서 클라이언트에서 호출이 계속 되면, 같은 원리로 서비스 A의 다른 쓰레드들도 응답을 받기 위해서 대기 상태가 된다. 이런 상태가 반복되면, 서비스 A에 남은 쓰레드는 없어지고 결과적으로 서비스 A도 응답을 할 수 없는 상태가 되서 장애 상태가 된다. 이런 현상을 장애 전파 현상이라고 한다.  

마이크로 서비스 아키텍쳐 패턴

이런 문제들이 패턴화 되고 이를 풀어내기 위한 방법이 디자인 패턴으로 묶이기 시작하였다.

예를 들어 앞의 문제와 같은 장애 전파의 예는 써킷 브레이커 (Circuit breaker)라는 디자인 패턴으로 해결할 수 있다.



<그림, 써킷 브레이커(Circuit breaker) 패턴 >


서비스 A와 서비스 B에 써킷 브레이커라는 개념을 정의해서, 네트워크 트래픽을 통과 시키도록 하고, 서비스 B가 장애가 나거나 응답이 없을 경우에는 그 네트워크 연결을 끊어서 서비스 A가 바로 에러를 받도록 하는 것이다. 이렇게 하면 서비스 B가 응답이 느리거나 또는 응답을 할 수 없는 상태일 경우에는 써킷 브레이커가 바로 연결을 끊어서, 서비스 A내에서 서비스 B를 호출한 쓰레드가 바로 에러를 받아서 더 이상 서비스 B로 부터 응답을 기다리지 않고, 쓰레드를 풀어주서 서비스 A가 쓰레드 부족으로 장애가 되는 것을 막는다.

이 외에도 분산 시스템에 대한 로그 수집등 다양한 패턴들이 있는데, https://microservices.io/ 를 보면 잘 정리가 되어 있다.

이런 패턴은 디자인 패턴일 뿐이고, 이를 사용하기 위해서는 시스템에서 구현을 해야 하는데, 당연히 구현에 대한 노력이 많이 들어서 구체화 하기가 어려웠는데, 넷플릭스에서 이러한 마이크로 서비스 아키텍쳐 패턴을 오픈소스화 하여 구현하여 공개하였다. 예를 들어 위에서 언급한 써킷 브레이커 패턴의 경우에는 Hystrix (https://github.com/Netflix/hystrix/wiki)라는 오픈 소스로 공개가 되어 있다.

Hystrix 이외에도, 서비스 디스커버리 패턴은 Eureka, 모니터링 서비스인 Turbine 등 다양한 오픈 소스를 공개했다.



<그림. 넷플릭스의 마이크로 서비스 프레임웍 오픈소스 >

출처 : https://jsoftgroup.wordpress.com/2017/05/09/micro-service-using-spring-cloud-and-netflix-oss/


문제는 이렇게 오픈소스로 공개를 했지만, 여전히 그 사용법이 복잡하다는 것이다. Hystrix 하나만을 적용하는데도 많은 노력이 필요한데, 여러개의 프레임웍을 적용하는 것은 여간 어려운 일이 아니다.

그런데 여기서 스프링 프레임웍이 이런 문제를 풀어내는 기여를 한다. 스프링 프레임웍에 넷플릭스의 마이크로 서비스 오픈 소스 프레임웍을 통합 시켜 버린것이다. (http://spring.io/projects/spring-cloud-netflix)

복잡한 부분을 추상화해서 스프링 프레임웍을 적용하면 손쉽게 넷플릭스의 마이크로 서비스 프레임웍을 사용할 수 있게 해줬는데, 마지막 문제가 남게 된다. 스프링은 자바 개발 프레임웍이다. 즉 자바에만 적용이 가능하다.

서비스 매쉬

프록시

이러한 마이크로 서비스의 문제를 풀기 위해서 소프트웨어 계층이 아니라 인프라 측면에서 이를 풀기 위한 노력이 서비스 매쉬라는 아키텍쳐 컨셉이다.

아래와 같이 서비스와 서비스간의 호출이 있을때


이를 직접 서비스들이 호출을 하는 것이 아니라 서비스 마다 프록시를 넣는다.


이렇게 하면 서비스로 들어오거나 나가는 트래픽을 네트워크 단에서 모두 통제가 가능하게 되고, 트래픽에 대한 통제를 통해서 마이크로 서비스의 여러가지 문제를 해결할 수 있다.

예를 들어 앞에서 설명한 써킷 브레이커와 같은 경우에는 호출되는 서비스가 응답이 없을때 프록시에서 이 연결을 끊어서 장애가 전파되지 않도록 하면된다.


또는 서비스가 클라이언트 OS에 따라서 다른 서비스를 호출해야 한다면, 서비스가 다른 서비스를 호출할때, 프록시에서 메세지의 헤더를 보고 “Client”라는 필드가 Android면, 안드로이드 서비스로 라우팅을 하고, “IOS”면 IOS 서비스로 라우팅 하는 지능형 라우팅 서비스를 할 수 있다.


이런 다양한 기능을 수행하기 위해서는 기존의 HA Proxy,nginx, Apache 처럼 TCP 기반의 프록시로는 한계가 있다. 예를 들어서 위에서 언급한 HTTP 헤더 기반의 라우팅이나 조금더 나가면 메세지 본문을 기반으로 하는 라우팅들이 필요하기 때문에, L7 계층의 지능형 라우팅이 필요하다.

서비스 매쉬

그러면 이러한 마이크로 서비스에 대한 문제를 소프트웨어 계층이 아니라, 프록시를 이용해서 인프라 측면에서 풀어낼 수 있다는 것을 알았다. 그렇지만 마이크로 서비스는 한두개의 서비스가 아니라 수백, 수천의 서비스로 구성된다. 프록시를 사용해서 여러 기능을 구성할 수 있지만 문제는 서비스 수에 따라 프록시 수도 증가하기 때문에, 이 프록시에 대한 설정을 하기가 어려워진다는 것이다.



그래서 이런 문제를 해결하기 위해서, 각 프록시에 대한 설정 정보를 중앙 집중화된 컨트롤러가 통제하는 구조를 취할 수 있다. 아래 구조와 같이 되는데,

각 프록시들로 이루어져서 트래픽을 설정값에 따라 트래픽을 컨트롤 하는 부분을 데이타 플레인(Data Plane)이라고 하고, 데이타 플레인의 프록시 설정값들을 저장하고, 프록시들에 설정값을 전달하는 컨트롤러 역할을 하는 부분을 컨트롤 플레인(Control Plane) 이라고 한다.


다음 글에서는 이러한 서비스 매쉬 구조를 구현한 오픈 소스 솔루션인 Istio에 대해서 알아보도록 하겠다.