Programming/Server

[Youtube] 넷플릭스 마이크로 서비스 가이드 3-3

bisi 2020. 4. 18. 16:37

유투브 출처 :  넷플릭스 마이크로 서비스 가이드 - 혼돈의 제왕

강의 순서
1. Introductions 00:00~5:38

2. Microservice Basics 05:39~13:18 


3. Challenges & Solutions 13:19 ~ 43:33
 1) Dependency 13:19 ~ 25: 02
 2) Scale 25:03 ~ 33:33
 3) Varience 33:34 ~ 43:33
 4) Chagne 43:33~ 45:45

4. Organization & Architecture 46:46~53:13


 


 

3. Challenges & Solutions

 

지난 7년간 넷플릭스의 해법과 해법 철학으로 4가지 접근방법이 있다. 

.

1) Dependency

2) Scale

3) Variance, 다양한 아키텍쳐의 수용

4) Change, 변화를 어떻게 처리할지

 

 

 

3) Variance

 

 

다양성은 다양한 아키텍쳐가 서비스 내에 존재하는 것을 의미한다. 서비스에 다양한 아키텍쳐가 존재한다는 것이며, 이건 서비스의 관리를 힘들게 하는 요인이다. 이것과 관련하여 두가지 사례를 볼텐데, 하나는 시간이 흐르면서 발생하는 오퍼레이션의 변화이다. 다른 하나는 작년에 저희가 새로운 언어와 컨테이너를 아키텍쳐에 도입한 것이다. 

 

USE Cases

사례 1. Operational drift
사례 2. Polyglot & containers

 

사례 1. Operational drift

운영의 변화는 강제로 발생하는 것이 아니다. 어떤 목적에 의해 자연스럽게 변화된 것이다. 시간이 흐르면서 발생하는 것의 예는, 알람의 임계점 설정이 변화된 다는 것이 있을수 있으며, 배치 작업의 시간이 점점 길어지거나 하는 등의 이유로 타임 아웃과 같은 설정을 변경해야 할 필요가 있을 것이다. 처리 성능 역시 지속적으로 테스트를 통해 확인하지 않으면 새로운 기능을 추가하는 등의 영향으로 약간씩 느려질 수도 있다. 그리고 여러개의 마이크로 서비스에서도 서비스를 운영하고 유지하는 방법에 굉장히 좋은 패턴을 발견했어도 팀의 절반의 엔지니어만이 이 패턴을 구현하는 경우도 있다. 처음 팀에 가서 "이 문제를 해결해 보자!", "알람을 좀 튜닝해 보자!" , "부하 테스트를 해보자!", "서비스 성능을 개선하고 가용성 높이는 튜닝을 해 보자!" 하고 말하면 그 팀으로 부터 처음엔 아주 긍정적인 반응을 볼 수 있을 겁니다. 하지만 사람은 여기에 필요한 수작업을 반복적으로 하는데 별로 뛰어 나지 않는다. 그래서 보통 다들 다른일을 하고 싶어 한다. 제품을 만드는 본연의 일에 집중하거나, 다음번 배포를 위해 A/B 테스트를 준비하는 것이다. 그리고 그 다음번에 그 팀에 가서 이전과 같은 방식으로 말을 하면, 아마도 그 전보다는 덜 긍정적인 반응을 보일 것이다. 그래서 우리는 사람들이 수동으로 처리하거나, 굳이 생각하지 안하도 알아서 동작하게 하는것이다.

 

 

넷플릭스는 운영하면서 지속적으로 학습하는 내용을 자동화해서 반영하는 방식을 도입했다. 보통 우리는 어떤 사고를 통해 무언가를 학습한다. 어떤 장애가 발생하면 엔지니어들은 콜을 하고, 고객의 문제를 해결 하고자 한다. 사건에 대한 리뷰를 통해 서비스에 무슨 장애가 발생한건지 파악하고 즉시 효과를 볼수 있는 해결책을 강구해서 적용한다. 이후에는 분석을 시작한다. 이것은 새로운 형태인가? 이걸 해결할 수 있는 최적의 방법이 있는가? 또는 서비스에 큰 영향을 미칠 수도 있는 반복적으로 발생하는 문제인가? 그런것들을 알고나면 가능한 모든 부분에 자동화를 시도한다. 그리고 만들어진 자동화를 서비스에 반영한다. 이게 바로 학습이 자동화 된 코드로 만들어지고, 마이크로 서비스에 반영되는 과정이다. 

 수년동안의 경험을 바탕으로 넷플릭스는 "프로덕션 수준으로 준비된"것을 검증하는 방법이 축적되었는데 이건 넷플릭스 고유의 체크리스트 또는 애플리케이션이다. 위의 나열된 부분은 그 위에 자동화 되어 동작하는 것들이며 더 좋은 서비스를 만들기 위해 지속적으로 개선하는 것들 이다. 더 나은 오토스케일링을 위해 알람을 손보거나, Stateless 서비스 검증을 위해 카오스 몽키를 사용하거나 red-black 푸시의 방법을 사용해서 문제가 생기면 롤백을 할 수 있도록 만든다. 가장 중요한 것 중 하나는 배포를 스테이징에 먼저 적용함으로서 나쁜 코드를 전체 리전에 동시에 적용되지 않도록 하는 것이다. 

 

사례2. Polyglot & Containers

다음 주제로 넘어가서 '폴리 글럿'과 '컨테이너'에대해 말해보자. 이 두가지 모두 최근 몇년동안에 나타난 주제들이다. 이것들은 변화가 적용되는 극단적인 모습인데 사람들은 마이크로 서비스에 이 새로운 기술들을 적용하고자 한다.

 

3년전 처음 운영 기술팀을 맡게 되었을때 당시에 고속도록같은 기술들은 이런것들이었다. 이것들은 모두 넷프릭스에서 아주 잘작동하는 도구들이었다. 앞서 말했던 자동화와 끊임 없는 개선이 적용된 도구이자 개발자들은 이 잘 구성된 도구 위에서 빠르게 서비스를 개발함으로서, 매우 효율적인 경험을 할 수 있었다. 자바에 집중했으며, EC2를 쌩으로 사용했는데 이 EC2는 컨테이너와는 반대되는 것이었다. 어쨌든 우리가 자바 기반의 아주 잘동작하는 도구들 덕분에 스스로 자랑스러워 하는 동안 다른 팀의 내부의 엔ㅈ니어 고객들은 오프로드를 달기기 시작했다. 자신들만의 길을 걷는것이다. 어떤 팀은 오퍼레이션 작업에 완벽한 핏을 자랑하는 파이썬을 사용하기 시작했다. 그리고 루비로 만들어진 일부 백오피스 애플리케이션이 있었다. 어느날 웹 팀에서 와서 말하길, '우리 JVM 기반의 애플리케이션을 모두 NodeJS로 다시 개발할거에요'라고 했다.  어떤팀에서는 docker를 구축했으며 점점 더 복잡해지기 시작했다. 이런 다양한 도구와 기술을 사용하는 것은 합리적이며 올바른 선택이었지만 이런 기술들을 서비스의 핵심 부분에 적용하는 것이 현실화하는데 어려움이 있었다. 그래도 이렇게 바꾸어낸건 매우 타탕했는데 그 이유를 지금부터 이야기 하겠다.

우리의 API 게이트웨이는 UI팀의 엔드 포인트로 동작하는 groovy 스크립트와 연동하는 기능이 있었는데 모든 스크립트에 버저닝을 적용해서 각각 변경이 발생할 때마다 프로덕션에 배포를 수행하면 필드에서 동작하는 각각의 장치와 싱크를 수행해서 업데이트된 엔드포인트 정보를 바탕으로 API 게이트웨이와 연동하는 방식이었다. 근데 이게 바로 또 다른 모놀리틱의 사례이다. 프로세스 안에서 동작하는 수많은 코드들, 사람들은 이 서비스에 대한 다른 이해를 바탕으로 수많은 라이브러리를 사용했다. 결국 엔드포인트가 지워지는 일이 발생하거나 특정 스크립트에 서로다른 버전이 많이 생성되거나 API 서비스가 가진 모든 메모리를 잡아먹는 문제도 있었다.

다시 말하지만, 피해야할 모놀리틱 패턴이다. 논리적인 해법은 각가의 엔드포인트를 API 서비스 바깥으로 꺼내는 작업이었고 우리는 아주 작은 nodjs앱을 docker안에 넣어 분리하는 방식으로 구현했다. 이로 인해 API 서비스에 호출을 하는 다른 작은 서비스들로 나눌수 있었고, 문제를 해결할 수 있었다. 여기에 NodeJS 애플리케이션을 사용함으로서 먼저 언급한 문제로 인한 장애를 고립할 수 있게 된 것이다.

 

 

여기서 잊지 말하야 할 것은 이런 다양성을 유지하기 위한 비용이 절대 공짜가 아니라는 점이다. 사실 굉장히 비용이 드는 작업이기 때문에 반드시 생각해 볼 필요가 있다. UI 팀이 사용했던 groovy 스크립트 모델은 개발에 있어서 상당한 효율을 제공 했다. 인프라에 신경쓰는 대신 필요한 코드를 만드는데 집중할 수 있었다.

 그리고 이런 경험을 nodejs와 docker 컨테이너 모델을 도입하기 위해서 엄청난 일을 해야 했다. 컨테이너에 어떤 일이 발생하는지, 그리고 문제가 된 컨테이너를 서비스에서 제외하는 등의 작업을 위해서 CPU와 메모리가 얼마나 사용되는지를 알기 위해서는 기존과는 다른 도구와 다른 지표들을 필요로 했다. 이전의 넷플릭스는 거의 대부분의 애플리케이션에 아주 기본적은 AMI를 사용했는데, 지금은 특화된 더 많은 종류의 AMI 가 존재한다.

 컨테이너 관리는 엄청난 비용이 든다.  오늘날 우리가 클라우드 환경에서 원하는 방향으로 사용할 수 있는 아키텍쳐나 기술을 제공하고 있지않기 때문이다.  그래서 우린 Titus라고 불리는 새로운 계층을 만들어야 했으며, 이건 컨테이너의 오토스케일링을 비롯한 장애 컨테이너의 교체등의 작업 관리를 처리하는 계층이며, 이걸 만들기 위해 넷플릭스는 엄청난 비용을 투자해야 했다.

 그리고 우리가 수년동안 사용했던 JVM 기반의 플랫폼 코드들은 여러가지의 서비스사용을 편리하게 해주던 것들이다. 이런 도구들은 다른 언어로도 동일하게 만들어야 하는지 아닌지 결정과, nodejs를 사용하는 팀이 알아서 REST 호출이나 관리도구 같은 것들을 직접 구현하게 할지 이런 것들이 논의되고 절충되고 있는데, 예를 들면 플랫폼이 제공하는 일부 기능을 nodejs용으로 만든다던가 하는 것이다. 그리고 매번 새로운 기술을 프로덕션에 반영할 때마다, 예를 들면 클라우드로 서비스를 옮긴다던가, 아키텍쳐에 큰 변화를 준다거나 새로운 방법으로 기존의 것을 부수고 다시 만들어야 하는 작업을 해야한다. 따라서 경험이 쌓여 익숙해 지려면 시간이 필요할 것이다.

 

 

이런건 중앙화된 관리 및 자원을 제공하려는 팀에서는 매우 큰 도전이었다. 많은 토론 끝에 정해진 결론은 비용 증가에 대한 인식을 바탕으로 엔지니어들이 아키텍쳐를 선택 할때 다양한 정보를 기반으로 올바른 선택을 하도록 돕는 것이었다. 지원범위를 제하는 것이다. 이를 테면 기본적으로는 JVM에 집중하되 , node나 docker는 매우 필수적이기 때문에 지원을 확대하는 식이다. 그리고 논리적으로 예상되는 규모에 따른 우선순위를 설정하고 적절한 규모의 인력을 배치하며 재사용 가능한 솔루션을 찾는다. 배포(딜리버리)의 경우 매우 일반적이기 때문에 다양한 언어를 지원하는데 별 문제가 없을 것이다.  또 다른 예는 아주 간단한 클라이언트 라이브러리는 자동으로 생성하는 것이다. 자동으로 루비, 자바, 파이썬 버전을 생성해 내는 것이다. 이런 공통적으로 사용할 수 있는 방법을 지속적으로 찾고 있으며 여기에는 모든 경우에 들어맞는 하나의 해결법이 있는 것이 아니기 때문에 이런 예시들이 각각의 처한 상황에 대한 판단을 하는데 도움이 되길 바란다.