또한 전체 문서와 NGINX를 사용하여 마이크로서비스를 구현하는 방법에 대한 정보를 전자책으로 다운로드할 수도 있습니다
- 마이크로서비스: 설계부터 배포까지. 또한 새로운 마이크로서비스 솔루션 페이지도 살펴보세요.
이 글은 마이크로서비스 아키텍처로 애플리케이션을 구축하는 방법에 대한 시리즈의 세 번째 글입니다.
첫 번째 문서에서는 마이크로서비스 아키텍처 패턴을 소개하고 이를 모놀리식 아키텍처 패턴과 비교하며
마이크로서비스 사용의 장점과 단점에 대해 논의합니다.
두 번째 글에서는 애플리케이션의 클라이언트가 API 게이트웨이라는 중개자를 통해 마이크로서비스와 통신하는 방법에 대해 설명합니다.
이 문서에서는 시스템 내의 서비스들이 서로 통신하는 방법을 살펴봅니다.
네 번째 글에서는 서비스 검색과 밀접한 관련이 있는 문제를 살펴봅니다.
소개
모놀리식 애플리케이션에서 구성 요소는 언어 수준의 메서드나 함수 호출을 통해 서로를 호출합니다.
이와 대조적으로 마이크로서비스 기반 애플리케이션은 여러 컴퓨터에서 실행되는 분산 시스템입니다.
각 서비스 인스턴스는 일반적으로 하나의 프로세스입니다.
따라서 다음 다이어그램에서 볼 수 있듯이 서비스는 프로세스 간 통신(IPC) 메커니즘을 사용하여 상호 작용해야 합니다.
나중에 구체적인 IPC 기술을 살펴보겠지만, 먼저 다양한 디자인 문제를 살펴보겠습니다.
상호 작용 스타일
서비스에 대한 IPC 메커니즘을 선택할 때는 먼저 서비스 상호 작용 방식을 고려하는 것이 유용합니다.
클라이언트⇔서비스 상호 작용 스타일은 다양합니다.
두 가지 차원으로 분류할 수 있습니다.
첫 번째 차원은 상호 작용이 일대일인지 일대다인지 여부입니다:
일대일 - 각 클라이언트 요청이 정확히 하나의 서비스 인스턴스에 의해 처리됩니다.
일대다 - 각 요청이 여러 서비스 인스턴스에 의해 처리됩니다.
두 번째 차원은 상호 작용이 동기식인지 비동기식인지 여부입니다:
동기식 - 클라이언트는 서비스에서 적시에 응답을 기대하며 기다리는 동안 차단할 수도 있습니다.
비동기식 - 클라이언트가 응답을 기다리는 동안 차단하지 않으며 응답이 있는 경우 반드시 즉시 전송되지 않습니다.
다음 표는 다양한 상호 작용 스타일을 보여줍니다.
동기식
요청/응답
-
비동기
알림
게시/구독
요청/비동기 응답
게시/비동기 응답
일대일 상호작용에는 다음과 같은 종류가 있습니다:
요청/응답 - 클라이언트가 서비스에 요청을 하고 응답을 기다립니다. 클라이언트는 응답이 적시에 도착하기를 기대합니다. 스레드 기반 애플리케이션에서는 요청을 하는 스레드가 대기하는 동안 차단될 수도 있습니다.
알림(단방향 요청이라고도 함)- 클라이언트가 서비스에 요청을 보냈지만 응답이 예상되거나 전송되지 않은 경우입니다. 요청/비동기 응답 - 클라이언트가 서비스에 요청을 보내면 비동기적으로 응답합니다.
클라이언트는 대기하는 동안 차단되지 않으며 응답이 한동안 도착하지 않을 수 있다는 가정 하에 설계되었습니다.
일대다 상호 작용에는 다음과 같은 종류가 있습니다:
게시/구독 - 클라이언트가 알림 메시지를 게시하면 0개 이상의 관심 서비스에서 이를 소비합니다.
응답 게시/비동기화 - 클라이언트가 요청 메시지를 게시한 다음 관심 있는 서비스의 응답을 일정 시간 동안 기다립니다.
각 서비스는 일반적으로 이러한 상호 작용 스타일을 조합하여 사용합니다.
일부 서비스의 경우 단일 IPC 메커니즘으로 충분합니다.
다른 서비스에서는 여러 IPC 메커니즘을 조합하여 사용해야 할 수도 있습니다.
다음 다이어그램은 사용자가 차량 호출을 요청할 때 택시 호출 애플리케이션의 서비스가 상호 작용하는 방식을 보여줍니다.
서비스는 알림, 요청/응답, 게시/구독의 조합을 사용합니다.
예를 들어, 승객의 스마트폰이 트립 관리 서비스에 알림을 전송하여 픽업을 요청합니다.
여행 관리 서비스는 요청/응답을 사용하여 승객 서비스를 호출하여 승객의 계정이 활성화되어 있는지 확인합니다.
그런 다음 여행 관리 서비스는 여행을 생성하고 게시/구독을 사용하여
사용 가능한 드라이버를 찾는 Dispatcher를 비롯한 다른 서비스에 알립니다.
이제 상호작용 스타일을 살펴보았으니 API를 정의하는 방법을 살펴보겠습니다.
API 정의하기
서비스의 API는 서비스와 클라이언트 간의 계약입니다.
어떤 IPC 메커니즘을 선택하든 일종의 인터페이스 정의 언어(IDL)를 사용하여 서비스의 API를 정확하게 정의하는 것이 중요합니다.
서비스를 정의할 때 API 우선 접근 방식을 사용하는 것이 좋다는 주장도 있습니다.
인터페이스 정의를 작성하고 클라이언트 개발자와 함께 검토하는 것으로 서비스 개발을 시작합니다.
API 정의에 대한 반복 작업을 거친 후에야 서비스를 구현할 수 있습니다.
이 설계를 미리 수행하면 클라이언트의 요구 사항을 충족하는 서비스를 구축할 가능성이 높아집니다.
이 글의 뒷부분에서 살펴보겠지만 API 정의의 성격은 사용 중인 IPC 메커니즘에 따라 달라집니다.
메시징을 사용하는 경우 API는 메시지 채널과 메시지 유형으로 구성됩니다.
HTTP를 사용하는 경우 API는 URL과 요청 및 응답 형식으로 구성됩니다.
나중에 몇 가지 IDL에 대해 더 자세히 설명하겠습니다.
진화하는 API
서비스의 API는 시간이 지남에 따라 항상 변합니다.
모놀리식 애플리케이션에서는 일반적으로 API를 변경하고 모든 호출자를 업데이트하는 것이 간단합니다.
마이크로서비스 기반 애플리케이션에서는 API의 모든 소비자가 동일한 애플리케이션의 다른 서비스라고 하더라도 훨씬 더 어렵습니다.
일반적으로 모든 클라이언트를 서비스와 함께 강제로 업그레이드할 수는 없습니다.
또한 서비스의 이전 버전과 새 버전이 동시에 실행되도록 서비스의 새 버전을 점진적으로 배포할 수도 있습니다.
이러한 문제를 처리하기 위한 전략을 세우는 것이 중요합니다.
API 변경을 처리하는 방법은 변경의 규모에 따라 다릅니다.
일부 변경 사항은 경미하며 이전 버전과 역호환됩니다.
예를 들어 요청이나 응답에 속성을 추가할 수 있습니다.
클라이언트와 서비스가 강건성 원칙을 준수하도록 설계하는 것이 좋습니다.
이전 API를 사용하는 클라이언트는 새 버전의 서비스에서 계속 작업해야 합니다.
서비스에서는 누락된 요청 속성에 대한 기본값을 제공하며 클라이언트는 추가 응답 속성을 무시합니다.
API를 쉽게 발전시킬 수 있는 IPC 메커니즘과 메시징 형식을 사용하는 것이 중요합니다.
하지만 때로는 호환되지 않는 API를 크게 변경해야 하는 경우도 있습니다.
클라이언트가 즉시 업그레이드하도록 강제할 수 없으므로 서비스에서 일정 기간 동안 이전 버전의 API를 지원해야 합니다.
REST와 같은 HTTP 기반 메커니즘을 사용하는 경우 URL에 버전 번호를 포함시키는 것도 한 가지 방법입니다.
각 서비스 인스턴스는 여러 버전을 동시에 처리할 수 있습니다.
또는 각각 특정 버전을 처리하는 다른 인스턴스를 배포할 수도 있습니다.
부분 장애 처리하기
API 게이트웨이에 대한 이전 문서인 .htmla<.htmla< 에서 언급했듯이
분산 시스템에서는 부분 장애의 위험이 항상 존재합니다.
클라이언트와 서비스는 별개의 프로세스이므로 서비스가 클라이언트의 요청에 적시에 응답하지 못할 수 있습니다.
장애 또는 유지보수로 인해 서비스가 다운될 수 있습니다.
또는 서비스가 과부하되어 요청에 매우 느리게 응답하고 있을 수 있습니다.
예를 들어 해당 문서의 제품 세부 정보 시나리오를 생각해 보세요.
추천 서비스가 응답하지 않는다고 가정해 봅시다.
클라이언트를 순진하게 구현하면 응답을 기다리며 무기한 차단될 수 있습니다.
이는 사용자 경험을 저하시킬 뿐만 아니라 많은 애플리케이션에서 스레드와 같은 귀중한 리소스를 소모하게 됩니다.
결국 다음 그림과 같이 런타임에 스레드가 부족하여 응답하지 않게 됩니다.
이 문제를 방지하려면 부분적인 장애를 처리하도록 서비스를 설계하는 것이 필수적입니다.
넷플릭스에서 설명하는 에 따라 접근하는 것이 좋습니다.
부분 장애를 처리하기 위한 전략은 다음과 같습니다:
네트워크 타임아웃 - 무한정 차단하지 말고 응답을 기다릴 때는 항상 타임아웃을 사용하세요.
타임아웃을 사용하면 리소스가 무한정 묶이지 않습니다.
미결 요청 수 제한하기 - 클라이언트가 특정 서비스에 대해 가질 수 있는 미결 요청 수에 상한선을 설정합니다.
한도에 도달한 경우 추가 요청을 하는 것은 무의미하며 이러한 시도는 즉시 실패해야 합니다.
서킷 차단기 패턴 - 성공 및 실패 요청 횟수를 추적합니다. 오류율이 구성된 임계값을 초과하면 회로 차단기를 트립하여
추가 시도가 즉시 실패하도록 합니다. 많은 수의 요청이 실패하는 경우 서비스를 사용할 수 없으며
요청을 보내는 것이 무의미하다는 의미입니다.
시간 초과 기간이 지나면 클라이언트는 다시 시도하고 성공하면 회로 차단기를 닫아야 합니다.
폴백 제공 - 요청이 실패할 때 폴백 로직을 수행합니다.
예를 들어 캐시된 데이터 또는 빈 추천 세트와 같은 기본값을 반환합니다.
넷플릭스 Hystrix는 이러한 패턴과 기타 패턴을 구현하는 오픈 소스 라이브러리입니다.
JVM을 사용하는 경우 Hystrix 사용을 반드시 고려해야 합니다.
또한, JVM이 아닌 환경에서 실행하는 경우 동등한 라이브러리를 사용해야 합니다.
IPC 기술
선택할 수 있는 다양한 IPC 기술이 있습니다.
서비스는 HTTP 기반 REST 또는 Thrift와 같은 동기식 요청/응답 기반 통신 메커니즘을 사용할 수 있습니다.
또는 AMQP나 STOMP와 같은 비동기 메시지 기반 통신 메커니즘을 사용할 수도 있습니다.
다양한 메시지 형식도 있습니다.
서비스는 JSON 또는 XML과 같이 사람이 읽을 수 있는 텍스트 기반 형식을 사용할 수 있습니다.
또는 Avro나 프로토콜 버퍼와 같은 이진 형식(더 효율적)을 사용할 수도 있습니다.
나중에 동기식 IPC 메커니즘에 대해 살펴보겠지만 먼저 비동기식 IPC 메커니즘에 대해 알아보겠습니다.
비동기 메시지 기반 통신
메시징을 사용할 때 프로세스는 비동기적으로 메시지를 교환하여 통신합니다.
클라이언트는 서비스에 메시지를 전송하여 요청을 합니다.
서비스에서 응답이 예상되면 클라이언트에 별도의 메시지를 다시 전송하여 응답합니다.
통신은 비동기식이기 때문에 클라이언트는 응답 대기를 차단하지 않습니다.
대신 클라이언트는 응답이 즉시 수신되지 않을 것을 가정하여 작성됩니다.
메시지는 헤더(보낸 사람 등의 메타데이터)와 메시지 본문으로 구성됩니다.
메시지는 채널을 통해 교환됩니다. 채널에 메시지를 보낼 수 있는 프로듀서의 수는 제한이 없습니다.
마찬가지로 채널에서 메시지를 받는 소비자도 얼마든지 가능합니다.
채널에는 point-to-point와 publish-subscribe의 두 가지 종류가 있습니다.
지점 간 채널은 채널에서 읽고 있는 소비자 중 정확히 한 명에게 메시지를 전달합니다.
서비스는 앞서 설명한 일대일 상호 작용 스타일에 지점 간 채널을 사용합니다.
게시-구독 채널은 연결된 모든 소비자에게 각 메시지를 전달합니다.
서비스는 위에서 설명한 일대다 상호 작용 스타일에 게시-구독 채널을 사용합니다.
다음 다이어그램은 택시 호출 애플리케이션에서 게시-구독 채널을 사용하는 방법을 보여줍니다.
트립 관리 서비스는 게시-구독 채널에 트립 생성 메시지를 작성하여 디스패처와 같은 관심 있는 서비스에 새 트립에 대해 알립니다.
디스패처는 사용 가능한 드라이버를 찾아 다른 서비스에 드라이버 제안 메시지를 게시-구독 채널에 작성하여 알립니다.
선택할 수 있는 메시징 시스템은 여러 가지가 있습니다. 다양한 프로그래밍 언어를 지원하는 시스템을 선택해야 합니다.
일부 메시징 시스템은 AMQP 및 STOMP와 같은 표준 프로토콜을 지원합니다.
다른 메시징 시스템에는 독점적이지만 문서화된 프로토콜이 있습니다.
RabbitMQ, 아파치 및 카프카, 아파치 및 액티브MQ, NSQ 등 수많은 오픈 소스 메시징 시스템 중에서 선택할 수 있습니다.
높은 수준에서는 모두 어떤 형태의 메시지와 채널을 지원합니다.
모두 안정적이고 성능이 뛰어나며 확장성을 갖추기 위해 노력합니다.
그러나 각 브로커의 메시징 모델 세부 사항에는 상당한 차이가 있습니다.
메시징을 사용하면 많은 장점이 있습니다:
클라이언트와 서비스 분리 - 클라이언트는 적절한 채널에 메시지를 보내기만 하면 요청을 할 수 있습니다.
클라이언트는 서비스 인스턴스를 전혀 알지 못합니다.
서비스 인스턴스의 위치를 확인하기 위해 검색 메커니즘을 사용할 필요가 없습니다.
메시지 버퍼링 - HTTP와 같은 동기식 요청/응답 프로토콜의 경우 클라이언트와 서비스 모두 교환이 진행되는 동안 사용할 수 있어야 합니다.
이와 달리 메시지 브로커는 채널에 쓰여진 메시지를 소비자가 처리할 수 있을 때까지 대기열에 대기시킵니다.
예를 들어, 온라인 스토어는 주문 처리 시스템이 느리거나 사용할 수 없는 경우에도
고객의 주문을 받을 수 있습니다. 주문 메시지가 대기열에 대기하기만 하면 됩니다.
유연한 클라이언트-서비스 상호 작용 - 메시징은 앞서 설명한 모든 상호 작용 스타일을 지원합니다.
명시적 프로세스 간 통신 - RPC 기반 메커니즘은 원격 서비스 호출을 로컬 서비스 호출과 동일하게 보이게 하려고 시도합니다
그러나 물리 법칙과 부분적인 실패 가능성으로 인해 실제로는 상당히 다릅니다. 메시징은 이러한 차이를 매우 명확하게 보여주기 때문에 개발자가 보안에 대한 잘못된 인식을 갖지 않도록 합니다.
하지만 메시징 사용에는 몇 가지 단점도 있습니다:
- 추가적인 운영 복잡성 - 메시징 시스템은 설치, 구성 및 운영해야 하는 또 다른 시스템 구성 요소입니다. 메시지 브로커의 가용성이 높아야 하며, 그렇지 않으면 시스템 안정성에 영향을 미칩니다.
- 요청/응답 기반 상호 작용 구현의 복잡성 - 요청/응답 스타일 상호 작용을 구현하려면 약간의 작업이 필요합니다. 각 요청 메시지에는 응답 채널 식별자와 상관관계 식별자가 포함되어야 합니다. 서비스는 상관관계 ID가 포함된 응답 메시지를 회신 채널에 씁니다. 클라이언트는 상관관계 ID를 사용하여 응답을 요청과 일치시킵니다. 요청/응답을 직접 지원하는 IPC 메커니즘을 사용하는 것이 더 쉬운 경우가 많습니다. 메시징 기반 IPC 사용에 대해 살펴봤으니 이제 요청/응답 기반 IPC에 대해 살펴보겠습니다.
동기식 요청/응답 IPC
동기식 요청/응답 기반 IPC 메커니즘을 사용하는 경우 클라이언트는 서비스에 요청을 보냅니다.
서비스는 요청을 처리하고 응답을 다시 보냅니다.
많은 클라이언트에서 요청을 만드는 스레드는 응답을 기다리는 동안 차단됩니다.
다른 클라이언트는 선물 또는 Rx Observables로 캡슐화된 비동기 이벤트 중심 클라이언트 코드를 사용할 수도 있습니다.
그러나 메시징을 사용할 때와 달리 클라이언트는 응답이 적시에 도착할 것이라고 가정합니다.
선택할 수 있는 프로토콜은 다양합니다. 널리 사용되는 두 가지 프로토콜은 REST와 중고품입니다.
먼저 REST에 대해 살펴보겠습니다.
REST
오늘날에는 RESTful 스타일로 API를 개발하는 것이 유행입니다.
REST는 (거의 항상) HTTP를 사용하는 IPC 메커니즘입니다.
REST의 핵심 개념은 리소스이며, 일반적으로 고객이나 제품과 같은 비즈니스 개체 또는 비즈니스 개체 모음을 나타냅니다.
REST는 URL을 사용하여 참조되는 리소스를 조작하기 위해 HTTP 동사를 사용합니다.
예를 들어, GET 요청은 리소스의 표현을 반환하며, 이는 XML 문서 또는 JSON 객체의 형태일 수 있습니다.
POST 요청은 새 리소스를 생성하고 PUT 요청은 리소스를 업데이트합니다.
REST의 창시자인 Roy 필딩의 말을 인용하면 다음과 같습니다:
"REST는 전체적으로 적용될 때 구성 요소 상호 작용의 확장성, 인터페이스의 일반성, 구성 요소의 독립적인 배포, 상호 작용 지연 시간을 줄이고 보안을 강화하며 레거시 시스템을 캡슐화하기 위한 중개 구성 요소를 강조하는 일련의 아키텍처 제약 조건을 제공합니다."
다음 다이어그램은 택시 호출 애플리케이션에서 REST를 사용할 수 있는 방법 중 하나를 보여줍니다.
승객의 스마트폰이 여행 관리 서비스의 POST 리소스에 /trips 요청을 하여 여행을 요청합니다.
이 서비스는 승객에 대한 정보를 요청하는 GET 요청을 승객 관리 서비스로 전송하여 요청을 처리합니다.
승객이 여행을 생성할 권한이 있는지 확인한 후, 여행 관리 서비스는 여행을 생성하고 스마트폰에 201 응답을 반환합니다.
많은 개발자가 자신의 HTTP 기반 API가 RESTful이라고 주장합니다.
하지만 Fielding이 이 블로그 게시물에서 설명한 것처럼 실제로는 모두 그런 것은 아닙니다.
Leonard Richardson(관계 없음)은 다음 단계로 구성된 매우 유용한 rest 성숙도 모델을 정의합니다.
레벨 0 - 레벨 0 API의 클라이언트는 유일한 URL 엔드포인트에 HTTP POST 요청을 보내 서비스를 호출합니다.
각 요청은 수행할 작업, 작업 대상(예: 비즈니스 개체) 및 모든 매개변수를 지정합니다.
레벨 1 - 레벨 1 API는 리소스라는 개념을 지원합니다. 리소스에 대한 작업을 수행하려면
클라이언트는 수행할 작업과 매개 변수를 지정하는 POST 요청을 합니다.
레벨 2 - 레벨 2 API는 HTTP 동사를 사용하여 작업을 수행합니다: GET은 검색, POST는 생성, PUT는 업데이트에 사용됩니다. 요청 쿼리 매개변수와 본문(있는 경우)은 작업의 매개변수를 지정합니다. 이를 통해 서비스는 GET 요청에 대한 캐싱과 같은 웹 인프라를 활용할 수 있습니다.
레벨 3 - 레벨 3 API의 설계는 끔찍한 이름의 HATEOAS(Hypertext As The Engine Of Application State) 원칙을 기반으로 합니다. 기본 개념은 GET 요청에 의해 반환되는 리소스의 표현에 해당 리소스에서 허용되는 작업을 수행하기 위한 링크가 포함되어 있다는 것입니다. 예를 들어, 클라이언트는 주문을 검색하기 위해 전송된 GET 요청에 대한 응답으로 반환된 주문 표현의 링크를 사용하여 주문을 취소할 수 있습니다. HATEOAS의 이점에는 더 이상 URL을 클라이언트 코드에 하드 와이어할 필요가 없다는 점이 포함됩니다. 또 다른 장점은 리소스의 표현에 허용되는 작업에 대한 링크가 포함되어 있기 때문에 클라이언트가 현재 상태의 리소스에 대해 어떤 작업을 수행할 수 있는지 추측할 필요가 없다는 것입니다.
HTTP 기반 프로토콜을 사용하면 많은 이점이 있습니다:
HTTP는 간단하고 친숙합니다.
브라우저 내에서 Postman과 같은 확장 프로그램을 사용하거나
명령줄에서 curl(JSON 또는 다른 텍스트 형식이 사용된다는 가정 하에)를 사용하여 HTTP API를 테스트할 수 있습니다.
요청/응답 스타일의 통신을 직접 지원합니다.
물론 HTTP는 방화벽 친화적입니다.
중간 브로커가 필요하지 않으므로 시스템 아키텍처가 간소화됩니다.
HTTP 사용에는 몇 가지 단점이 있습니다:
요청/응답 방식의 상호작용만 직접적으로 지원한다는 점입니다. 알림에 HTTP를 사용할 수 있지만 서버는 항상 HTTP 응답을 보내야 합니다.
클라이언트와 서비스는 메시지를 버퍼링하는 중개자 없이 직접 통신하기 때문에 교환이 진행되는 동안 둘 다 실행 중이어야 합니다.
클라이언트는 각 서비스 인스턴스의 위치(즉, URL)를 알고 있어야 합니다. API 게이트웨이에 대한 이전 문서 에 설명된 대로 이는 최신 애플리케이션에서 사소한 문제가 아닙니다. 클라이언트는 서비스 인스턴스를 찾기 위해 서비스 검색 메커니즘을 사용해야 합니다.
개발자 커뮤니티는 최근 RESTful API를 위한 인터페이스 정의 언어의 가치를 재발견했습니다.
RAML 및 Swagger 등 몇 가지 옵션이 있습니다.
Swagger와 같은 일부 IDL을 사용하면 요청 및 응답 메시지의 형식을 정의할 수 있습니다.
RAML과 같은 다른 IDL은 JSON 스키마와 같은 별도의 사양을 사용해야 합니다.
API를 설명할 뿐만 아니라 IDL에는 일반적으로 인터페이스 정의에서 클라이언트 스텁과 서버 골격을 생성하는 도구가 있습니다.
중고품
아파치 중고품는 REST의 흥미로운 대안입니다. 크로스 언어 RPC 클라이언트와 서버를 작성하기 위한 프레임워크입니다.
Thrift는 API를 정의하기 위한 C 스타일 IDL을 제공합니다.
Thrift 컴파일러를 사용해 클라이언트 측 스텁과 서버 측 스켈레톤을 생성할 수 있습니다.
컴파일러는 C++, Java, Python, PHP, Ruby, Erlang, Node.js 등 다양한 언어에 대한 코드를 생성합니다.
중고품 인터페이스는 하나 이상의 서비스로 구성됩니다. 서비스 정의는 Java 인터페이스와 유사합니다.
강력한 타입의 메서드 모음입니다. 중고품 메서드는 (무효일 수 있는) 값을 반환하거나 단방향으로 정의할 수 있습니다.
값을 반환하는 메서드는 요청/응답 스타일의 상호작용을 구현합니다. 클라이언트는 응답을 기다리며 예외를 발생시킬 수 있습니다.
단방향 메서드는 상호 작용의 알림 스타일에 해당합니다.
서버가 응답을 보내지 않습니다.
중고품은 다양한 메시지 형식을 지원합니다: JSON, 바이너리, 압축 바이너리.
바이너리는 디코딩 속도가 빠르기 때문에 JSON보다 효율적입니다.
그리고 이름에서 알 수 있듯이 압축 바이너리는 공간 효율적인 형식입니다.
물론 JSON은 인간과 브라우저 친화적입니다.
또한 Thrift는 원시 TCP와 HTTP를 포함한 전송 프로토콜을 선택할 수 있습니다.
원시 TCP가 HTTP보다 더 효율적일 가능성이 높습니다. 하지만 HTTP는 방화벽, 브라우저, 인간 친화적입니다.
메시지 형식
HTTP와 중고품에 대해 살펴봤으니 이제 메시지 형식에 대해 살펴봅시다.
메시징 시스템이나 REST를 사용하는 경우 메시지 형식을 선택할 수 있습니다.
Thrift와 같은 다른 IPC 메커니즘은 소수의 메시지 형식만 지원할 수도 있습니다.
어떤 경우든 언어 간 메시지 형식을 사용하는 것이 중요합니다.
현재 단일 언어로 마이크로서비스를 작성하고 있더라도 향후에는 다른 언어를 사용할 가능성이 높습니다.
메시지 형식에는 텍스트와 바이너리의 두 가지 주요 유형이 있습니다.
텍스트 기반 형식의 예로는 JSON과 XML이 있습니다.
이러한 형식의 장점은 사람이 읽을 수 있을 뿐만 아니라 자체적으로 설명할 수 있다는 것입니다.
JSON에서 객체의 속성은 이름-값 쌍의 컬렉션으로 표현됩니다.
마찬가지로 XML에서는 속성이 명명된 요소와 값으로 표현됩니다.
이를 통해 메시지 소비자는 관심 있는 값만 골라내고 나머지는 무시할 수 있습니다.
따라서 메시지 형식의 사소한 변경 사항도 쉽게 이전 버전과 호환될 수 있습니다.
XML 문서의 구조는 XML 스키마에 의해 지정됩니다.
시간이 지남에 따라 개발자 커뮤니티는 JSON에도 유사한 메커니즘이 필요하다는 사실을 깨닫게 되었습니다.
한 가지 옵션은 독립적으로 또는 Swagger와 같은 IDL의 일부로 JSON 스키마를 사용하는 것입니다.
텍스트 기반 메시지 형식을 사용할 때의 단점은 메시지가 장황한 경향이 있다는 것입니다(특히 XML).
메시지가 자체적으로 설명되기 때문에 모든 메시지에는 값과 함께 속성 이름이 포함됩니다.
또 다른 단점은 텍스트 구문 분석의 오버헤드입니다. 따라서 바이너리 형식 사용을 고려할 수 있습니다.
선택할 수 있는 바이너리 형식은 여러 가지가 있습니다. 중고품 RPC를 사용하는 경우 바이너리 중고품을 사용할 수 있습니다.
메시지 형식을 선택할 때 많이 사용되는 옵션으로는 Protocol Buffers와 Apache Avro가 있습니다.
이 두 형식 모두 메시지 구조를 정의하기 위한 유형화된 IDL을 제공합니다.
그러나 한 가지 차이점은 프로토콜 버퍼는 태그가 지정된 필드를 사용하는 반면,
Avro 소비자는 메시지를 해석하기 위해 스키마를 알아야 한다는 점입니다.
따라서 API 진화는 Avro보다 프로토콜 버퍼를 사용하는 것이 더 쉽습니다.
이 블로그 게시물은 Thrift, Protocol, Buffers, Avro를 비교한 훌륭한 글입니다.
요약
마이크로서비스는 프로세스 간 통신 메커니즘을 사용하여 통신해야 합니다.
서비스의 통신 방식을 설계할 때는 서비스 상호 작용 방식, 각 서비스의 API를 지정하는 방법, API를 발전시키는 방법,
부분 장애를 처리하는 방법 등 다양한 문제를 고려해야 합니다.
마이크로서비스가 사용할 수 있는 IPC 메커니즘에는 비동기 메시징과 동기 요청/응답의 두 가지 종류가 있습니다.
시리즈의 다음 글에서는 마이크로서비스 아키텍처에서 서비스 검색 문제를 살펴보겠습니다.
편집자 - 이제 이 7부작 시리즈 기사가 완료되었습니다:
마이크로서비스 소개
마이크로서비스 구축하기: API 게이트웨이 사용
마이크로서비스 구축하기: 마이크로서비스 아키텍처의 프로세스 간 통신(이 문서)
마이크로서비스 아키텍처에서의 서비스 검색
마이크로서비스를 위한 이벤트 중심 데이터 관리
마이크로서비스 배포 전략 선택
모놀리스를 마이크로서비스로 리팩토링
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
쿠버네티스는 Google에서 클러스터에서 컨테이너화된 마이크로서비스 기반 애플리케이션을 실행하고
관리하기 위해 개발한 오픈 소스 시스템입니다. 쿠버네티스를 사용하는 사람들은
종종 쿠버네티스에서 만든 서비스를 쿠버네티스 클러스터 외부에서 액세스할 수 있도록 해야 합니다.
Kubernetes는 아래의 내장 솔루션을 사용하여 Kubernetes 서비스 노출 에서
설명한 대로 서비스를 노출하기 위한 내장 솔루션을 제공 하지만 ,
해당 솔루션은 레이어 4 부하 분산 또는 라운드 로빈 HTTP 부하 분산으로 제한됩니다.
이 게시물에서는 클라우드에서 Kubernetes를 실행하든 자체 인프라에서 실행하든
Kubernetes 서비스를 인터넷에 노출하기 위한 고급 Layer 7 로드 밸런싱 솔루션으로 NGINX Plus를 사용하는 방법을 보여줍니다 .
Kubernetes(포드, 서비스, 복제 컨트롤러 및 레이블)와 실행 중인 Kubernetes 클러스터에 대한 기본적인 이해가 있다고 가정합니다.
Kubernetes에 대해 자세히 알아보려면 공식 Kubernetes 사용자 가이드를 참조하세요 .
내장 솔루션을 사용하여 Kubernetes 서비스 노출
쿠버네티스는 서비스를 노출하기 위한 여러 옵션을 제공합니다 .
그 중 두 가지(NodePort와 LoadBalancer)는 특정 유형의 서비스에 해당합니다.
세 번째 옵션인 Ingress API는 쿠버네티스 릴리스 1.1에서 베타로 제공되었습니다.
노드포트
서비스 유형을 NodePort 로 지정하면 각 Kubernetes 노드에서 동일한 포트에서 서비스를 사용할 수 있습니다.
서비스를 인터넷에 노출하려면 해당 포트에서 하나 이상의 노드를 노출합니다.
고가용성을 위해 여러 노드를 노출하고 DNS 기반 로드 밸런싱을 사용하여
트래픽을 분산하거나 노드를 선택한 로드 밸런서 뒤에 배치할 수 있습니다.
들어오는 트래픽이 포트의 노드에 도달하면 서비스의 포드 간에 로드 밸런싱이 이루어집니다.
kube-proxy모든 노드에서 실행되는 Kubernetes 네트워크 프록시( )가 수행하는 로드 밸런싱은 TCP/UDP 로드 밸런싱으로 제한됩니다.
로드 밸런서
서비스 유형을 LoadBalancer 로 지정하면 서비스의 Pod 간에 수신 트래픽을 분산하는 클라우드 로드 밸런서가 할당됩니다.
LoadBalancer 솔루션은 특정 클라우드 공급자와 Google Container Engine 에서만 지원되며
자체 인프라에서 Kubernetes를 실행하는 경우 사용할 수 없습니다.
또한 Kubernetes에서는 클라우드 로드 밸런서에 세션 지속성이나
요청 매핑과 같은 고급 기능이 있더라도 라운드 로빈 TCP 로드 밸런싱만 구성할 수 있습니다.
인그레스 API
Ingress 리소스를 생성하면 사용자 지정 URL(예: URL /foo 에서 서비스 A , URL /bar 에서 서비스 B )과
여러 가상 호스트 이름(예: 한 서비스 그룹의 경우 foo.example.com , 다른 그룹의 경우 bar.example.com )에서
서비스를 인터넷에 노출할 수 있습니다.
Ingress 컨트롤러는 Ingress 리소스를 사용하고 외부 로드 밸런서를 설정합니다.
Ingress 컨트롤러는 표준 Kubernetes 배포의 일부가 아닙니다.
필요에 가장 적합한 컨트롤러를 선택하거나 직접 구현하여 Kubernetes 클러스터에 추가해야 합니다.
많은 컨트롤러 구현이 곧 나타날 것으로 예상되지만 현재 유일하게 사용 가능한 구현은
Google Compute Engine HTTP Load Balancer용 컨트롤러로 ,
Google Compute Engine 또는 Google Container Engine 에서 Kubernetes를 실행하는 경우에만 작동합니다.
Ingress API는 실제 로드 밸런서가 고급 기능을 지원하더라도 라운드 로빈 HTTP 로드 밸런싱만 지원합니다.
이 글을 쓰는 시점에서 Ingress API와 Google Compute Engine HTTP 부하 분산 장치용 컨트롤러는 모두 베타 버전입니다.
업데이트 – NGINX와 NGINX Plus를 위한 NGINX Ingress Controller가 이제 GitHub 저장소 에서 제공됩니다 .
제품 세부 정보는 NGINX Ingress Controller를 참조하세요 .
위에서 언급한 솔루션은 설정이 간단하고 바로 사용할 수 있지만
특히 7계층 부하 분산과 관련된 기능을 비롯하여 고급 기능을 제공하지 않습니다.
NGINX Plus로 Kubernetes 서비스 노출
[편집자 - 이 섹션은 원래 여기에서 논의된 별도의 동적 구성 모듈을 대체하고 더 이상 사용되지 않는 NGINX Plus API를 참조하도록 업데이트되었습니다 .]
NGINX Plus를 Kubernetes와 통합하려면 NGINX Plus 구성이 Kubernetes와 동기화되어
Pod 추가 또는 삭제와 같은 Kubernetes 서비스의 변경 사항을 반영해야 합니다.
NGINX Open Source를 사용하면 NGINX 구성 파일을 수동으로 수정하고 구성을 다시 로드할 수 있습니다.
NGINX Plus를 사용하면 구성을 동적으로 업데이트하는 두 가지 방법이 있습니다.
API 사용 - 이 방법은 NGINX Plus API를 사용하여 NGINX Plus 구성에서
Kubernetes 포드에 대한 항목을 추가 및 제거하고 Kubernetes API를 사용하여 포드의 IP 주소를 검색합니다. 이 방법을 사용하려면 코드를 작성해야 하며 여기서는 자세히 설명하지 않습니다. 자세한 내용은 Kelsey Hightower의 웨비나 Bringing Kubernetes to the Edge with NGINX Plus를 시청하세요 . 여기서 그는 API를 탐색하고 이를 활용하는 애플리케이션을 만듭니다. DNS 이름을 다시 확인 하여 – 이 방법은 다음 섹션에 설명된 대로 NGINX Plus의 적절한 일회성 구성만 필요합니다.
DNS 기반 재구성 활용
이미 실행 중인 Kubernetes 클러스터와 kubectl클러스터를 관리하는 데
사용할 수 있는 유틸리티가 있는 호스트가 있다고 가정합니다.
지침은 클러스터 유형에 대한 Kubernetes 시작 가이드를 참조하세요 .
또한 NGINX Plus Docker 이미지를 빌드해야 하며,
지침은 블로그의 Docker를 사용하여 NGINX 및 NGINX Plus 배포 에서 확인할 수 있습니다.
우리가 할 일의 개요는 다음과 같습니다.
2단계에서 생성한 서비스를 노출하고 부하를 분산하기 위해 NGINX Plus Pod를 구성합니다.
우리의 서비스로 간단한 웹 애플리케이션을 만들어 보겠습니다.
서비스를 확장하거나 축소하면서 NGINX Plus가 자동으로 재구성되는 모습을 살펴보세요.
참고 사항: 이 블로그에 설명된 솔루션을 Google Compute Engine에서 실행되는
Kubernetes 1.0.6 과 로컬 Vagrant 설정(아래에서 사용)으로 테스트했습니다.
명령에서 Kubernetes 설정에 따라 다를 수 있는 값은 기울임꼴로 표시됩니다.
NGINX Plus Pod 구성
우리는 인터넷에 노출된 노드의 Kubernetes 포드에 NGINX Plus를 넣고 있습니다.
우리의 포드는 우리가 또한 설정하고 있는 복제 컨트롤러에 의해 생성됩니다.
우리의 Kubernetes 특정 NGINX Plus 구성 파일은 NGINX Plus 포드와 노드 간
공유되는 폴더에 상주하여 유지 관리가 더 간단합니다.
NGINX Plus Pod를 호스팅할 노드 선택
NGINX Plus pod가 실행되는 노드를 지정하기 위해 해당 노드에 레이블을 추가합니다.
다음을 실행하여 모든 노드 목록을 가져옵니다.
$ kubectl get nodesNAME LABELS STATUS 10.245.1.3 Kubernetes.io/hostname=10.245.1.3 Ready 10.245.1.4 Kubernetes.io/hostname=10.245.1.4 Ready 10.245.1.5 Kubernetes.io/hostname=10.245.1.5 Ready
첫 번째 노드를 선택하고 다음을 실행하여 레이블을 추가합니다.
$ kubectl label node 10.245.1.3 role=nginxplus
NGINX Plus Pod에 대한 복제 컨트롤러 구성
우리는 NGINX Plus 포드를 직접 생성하지 않고 복제 컨트롤러를 통해 생성합니다.
nginxplus-rc.yaml 이라는 Kubernetes 선언 파일에서 NGINX Plus 포드에 대한 복제 컨트롤러를 구성합니다 .
replicasNGINX Plus Pod가 항상 실행되도록 하려면 Pod 개수를 하나로 설정했습니다 .
Pod에 장애가 발생하면 새로운 Pod로 교체합니다.
필드 에서 nodeSelectorNGINX Plus Pod가 레이블이 지정된 노드에 생성되도록 지정합니다 role: nginxplus.
NGINX Plus 컨테이너는 80과 8080이라는 두 개의 포트를 노출하며, 이 두 포트와 노드의 80과 8080 포트 간의 매핑을 설정합니다.
NGINX Plus 컨테이너는 노드에 있는 /etc/nginx/conf.d 폴더도 공유합니다.
아래 NGINX Plus 구성 에서 자세히 설명했듯이, 폴더를 공유하면 컨테이너 이미지를 다시 빌드하지 않고도 NGINX Plus를 재구성할 수 있습니다.
이제 노드에서 사용할 수 있도록 합니다. 단순성을 위해 개인 Docker 저장소를 사용하지 않고
이미지를 노드에 수동으로 로드합니다.
Docker 이미지를 빌드한 호스트에서 다음 명령을 실행하여 이미지를 파일에 저장합니다.
$ docker save -o nginxplus.tar nginxplus
nginxplus.tar를 노드로 전송하고 , 노드에서 다음 명령을 실행하여 파일에서 이미지를 로드합니다.
$ docker load -i nginxplus.tar
NGINX Plus 구성
NGINX Plus 컨테이너의 /etc/nginx 폴더에서 NGINX Plus 패키지와 함께 제공되는 기본 주 nginx.conf 구성 파일을 유지합니다.
기본 파일의 지시문은 /etc/nginx/conf.dinclude 폴더 에서 다른 구성 파일을 읽습니다 .
NGINX Plus 복제 컨트롤러( nginxplus-rc.yaml ) 의 선언 파일 에 지정된 대로
NGINX Plus 노드의 /etc/nginx/conf.d 폴더를 컨테이너와 공유합니다.
공유는 컨테이너에서 직접 폴더를 만든 경우 해야 하는 NGINX Plus Docker 이미지를 다시 빌드하지 않고도
폴더(노드)에 저장된 구성 파일을 변경할 수 있음을 의미합니다.
공유 폴더에 Kubernetes 특정 구성 파일( backend.conf )을 넣습니다.
먼저 노드에 /etc/nginx/conf.d 폴더를 만들어 보겠습니다 .
$ sudo mkdir -p /etc/nginx/conf.d
그런 다음 해당 위치에 backend.conf 파일을 만들고 다음 지침을 포함합니다.
resolver – NGINX Plus가 업스트림 서버를 식별하는 데 사용하는 도메인 이름을 주기적으로 재확인하는 데 사용하는 DNS 서버를 정의합니다(다음 글머리 기호에서 설명하는 블록 server내부의 지시문 ). 이 DNS 서버를 도메인 이름인 kube-dns.kube-system.svc.cluster.localupstream 로 식별합니다 . 이 매개변수는 NGINX Plus에 5초마다 재확인 요청을 보내라고 지시합니다.valid
(이 지시어에 대한 확인 프로세스는 업스트림 서버의 확인 프로세스와 다릅니다. 이 도메인 이름은 NGINX가 시작되거나 다시 로드될 때만 확인되고, NGINX Plus는 /etc/resolv.conf 파일에 정의된 시스템 DNS 서버를 사용하여 이를 확인합니다.)
upstream– 우리가 노출하는 Kubernetes 서비스를 제공하는 서버를 포함하는 백엔드 라는 업스트림 그룹을 만듭니다 . 서버를 개별적으로 나열하는 대신, 단일 server지시문에서 완전히 정규화된 호스트 이름으로 식별합니다. 이 resolve매개변수는 NGINX Plus에 지시문으로 지정된 설정에 따라 런타임에 호스트 이름을 다시 확인하도록 지시합니다 resolver.
Kubernetes DNS와 NGINX Plus(R10 이상)는 모두 DNS 서비스( SRV) 레코드를 지원하므로 NGINX Plus는 DNS를 통해 업스트림 서버의 포트 번호를 가져올 수 있습니다. serviceNGINX Plus 요청 레코드를 갖도록 매개변수를 포함하여 서비스에서 노출된 포트에 대한 SRV이름( _http)과 프로토콜( )을 지정합니다. 아래 서비스에 대한 복제 컨트롤러 생성 에서 설명한 webapp-svc.yaml_tcp 파일 에 해당 값을 선언합니다 .
DNS를 사용한 서비스 검색에 대한 자세한 내용은 블로그의 NGINX 및 NGINX Plus에서 DNS를 사용하여 서비스 검색을 참조하세요.
server(2회) – 두 개의 가상 서버를 정의합니다.
첫 번째 서버는 포트 80에서 수신하고 /webapp (우리 서비스)에 대한 들어오는 요청을 서비스 인스턴스를 실행하는 포드 간에 로드 밸런싱합니다. 또한 활성 상태 검사를 설정합니다 .
두 번째 서버는 포트 8080에서 수신합니다. 여기서 NGINX Plus의 라이브 활동 모니터링을 설정합니다 .
나중에 NGINX Plus가 제대로 재구성되었는지 확인하는 데 사용합니다. [편집자 - 이 두 번째 서버의 구성은 원래 사용되었던 별도의 상태 모듈을 대체하고 더 이상 사용되지 않는 NGINX Plus API를 사용하도록 업데이트되었습니다 .]
또한 전체 문서와 NGINX를 사용한 마이크로서비스 구현에 대한 정보를 전자책으로 다운로드할 수도 있습니다.
- 마이크로서비스: 설계부터 배포까지. 마이크로서비스 참조 아키텍처 및 마이크로서비스 솔루션 페이지에서 시리즈를 참조하세요.
이 글은 마이크로서비스로 애플리케이션 구축에 대한 시리즈의 다섯 번째 글입니다.
첫 번째 글에서는 마이크로서비스 아키텍처 패턴을 소개하고 마이크로서비스 사용의 장점과 단점에 대해 설명합니다.
두 번째 글과 세 번째 글에서는 마이크로서비스 아키텍처 내 커뮤니케이션의 다양한 측면에 대해 설명합니다.
네 번째 글에서는 서비스 검색과 밀접하게 관련된 문제를 살펴봅니다.
이 글에서는 주제를 바꿔 마이크로서비스 아키텍처에서 발생하는 분산 데이터 관리 문제를 살펴봅니다.
마이크로서비스와 분산 데이터 관리의 문제
모놀리식 애플리케이션에는 일반적으로 단일 관계형 데이터베이스가 있습니다.
관계형 데이터베이스 사용의 주요 이점은 애플리케이션에서
몇 가지 중요한 보증을 제공하는 ACID 트랜잭션을 사용할 수 있다는 것입니다:
원자성 -변경이 원자 단위로 이루어짐
일관성 -데이터베이스의 상태가 항상 일관됩니다.
격리성 트랜잭션이 동시에 실행되더라도 순차적으로 실행되는 것처럼 보입니다.
내구성 - 트랜잭션이 커밋되면 취소할 수 없습니다.
따라서 애플리케이션에서 간단히 트랜잭션을 시작하고,
여러 행을 변경(삽입, 업데이트, 삭제)하고, 트랜잭션을 커밋할 수 있습니다.
관계형 데이터베이스 사용의 또 다른 큰 장점은 풍부하고 선언적이며 표준화된 쿼리 언어인 SQL을 제공한다는 점입니다.
여러 테이블의 데이터를 결합하는 쿼리를 쉽게 작성할 수 있습니다.
그러면 RDBMS 쿼리 플래너가 쿼리를 실행하는 가장 최적의 방법을 결정합니다.
데이터베이스에 액세스하는 방법과 같은 낮은 수준의 세부 사항에 대해 걱정할 필요가 없습니다.
또한 애플리케이션의 모든 데이터가 하나의 데이터베이스에 있으므로 쿼리하기가 쉽습니다.
하지만 마이크로서비스 아키텍처로 전환하면 데이터 액세스가 훨씬 더 복잡해집니다.
각 마이크로서비스가 소유하는 데이터는 해당 마이크로서비스의 비공개 데이터이며
해당 마이크로서비스의 API를 통해서만 액세스할 수 있기 때문입니다.
데이터를 캡슐화하면 마이크로서비스가 느슨하게 결합되어 서로 독립적으로 발전할 수 있습니다.
여러 서비스가 동일한 데이터에 액세스하는 경우 스키마를 업데이트하려면
모든 서비스에 대한 조율된 업데이트가 필요하고 시간이 오래 걸립니다.
설상가상으로 마이크로서비스마다 서로 다른 종류의 데이터베이스를 사용하는 경우가 많습니다.
최신 애플리케이션은 다양한 종류의 데이터를 저장하고 처리하며,
관계형 데이터베이스가 항상 최선의 선택은 아닙니다.
일부 사용 사례의 경우, 특정 NoSQL 데이터베이스가 더 편리한 데이터 모델을 가지고 있고
훨씬 더 나은 성능과 확장성을 제공할 수 있습니다.
예를 들어, 텍스트를 저장하고 쿼리하는 서비스에서는 Elasticsearch와 같은 텍스트 검색 엔진을 사용하는 것이 합리적입니다.
마찬가지로 소셜 그래프 데이터를 저장하는 서비스는 아마도 Neo4j와 같은 그래프 데이터베이스를 사용해야 할 것입니다.
따라서 마이크로서비스 기반 애플리케이션은 종종 SQL 데이터베이스와 NoSQL 데이터베이스를 혼합하여 사용하는데,
이를 소위 폴리글롯 지속성 접근 방식이라고 합니다.
데이터 저장을 위한 분할된 다중 언어 지속성 아키텍처는 느슨하게 결합된 서비스,
더 나은 성능 및 확장성 등 많은 이점이 있습니다.
하지만 몇 가지 분산 데이터 관리 문제를 야기하기도 합니다.
첫 번째 과제는 여러 서비스에서 일관성을 유지하는 비즈니스 트랜잭션을 구현하는 방법입니다.
이것이 왜 문제인지 알아보기 위해 온라인 B2B 스토어의 예를 살펴보겠습니다.
고객 서비스는 신용 한도를 포함하여 고객에 대한 정보를 유지 관리합니다.
주문 서비스는 주문을 관리하며 새 주문이 고객의 신용 한도를 초과하지 않는지 확인해야 합니다.
이 애플리케이션의 모놀리식 버전에서는 주문 서비스에서 ACID 트랜잭션을 사용하여
사용 가능한 크레딧을 확인하고 주문을 생성할 수 있습니다.
반면, 마이크로서비스 아키텍처에서는 다음 다이어그램에서 볼 수 있듯이
ORDER 및 CUSTOMER 테이블이 각 서비스에 대해 비공개입니다.
주문 서비스는 고객 테이블에 직접 액세스할 수 없습니다.
고객 서비스에서 제공하는 API만 사용할 수 있습니다.
주문 서비스에서는 2단계 커밋(2PC)이라고도 하는 분산 트랜잭션을 사용할 수 있습니다(데이터-dl-uid="86">분산 트랜잭션).
그러나 2PC는 일반적으로 최신 애플리케이션에서는 실행 가능한 옵션이 아닙니다.
CAP 정리에 따르면 가용성과 ACID 스타일의 일관성 중에서 선택해야 하며,
일반적으로 가용성이 더 나은 선택입니다.
게다가 대부분의 NoSQL 데이터베이스와 같은 많은 최신 기술은 2PC를 지원하지 않습니다.
서비스와 데이터베이스 전반에서 데이터 일관성을 유지하는 것은 필수적이므로 다른 솔루션이 필요합니다.
두 번째 과제는 여러 서비스에서 데이터를 검색하는 쿼리를 구현하는 방법입니다.
예를 들어 애플리케이션에서 고객과 그의 최근 주문을 표시해야 한다고 가정해 보겠습니다.
주문 서비스가 고객의 주문을 검색하기 위한 API를 제공하는 경우
애플리케이션 측 조인을 사용하여 이 데이터를 검색할 수 있습니다.
애플리케이션은 고객 서비스에서 고객을 검색하고 주문 서비스에서 고객의 주문을 검색합니다.
그러나 주문 서비스가 기본 키로 주문 조회만 지원한다고 가정해 보겠습니다
(기본 키 기반 검색만 지원하는 NoSQL 데이터베이스를 사용할 수도 있습니다).
이 상황에서는 필요한 데이터를 검색할 수 있는 뚜렷한 방법이 없습니다.
이벤트 기반 아키텍처
많은 애플리케이션에서 해결책은 이벤트 중심 아키텍처를 사용하는 것입니다.
이 아키텍처에서는 마이크로서비스가 비즈니스 엔티티를 업데이트할 때와 같이 주목할 만한 일이 발생하면 이벤트를 게시합니다.
다른 마이크로서비스는 이러한 이벤트를 구독합니다.
마이크로서비스가 이벤트를 수신하면 자체 비즈니스 엔티티를 업데이트할 수 있으며,
이로 인해 더 많은 이벤트가 게시될 수 있습니다.
이벤트를 사용하여 여러 서비스에 걸친 비즈니스 트랜잭션을 구현할 수 있습니다. 트랜잭션은 일련의 단계로 구성됩니다.
각 단계는 비즈니스 엔티티를 업데이트하고 다음 단계를 트리거하는 이벤트를 게시하는 마이크로서비스로 구성됩니다.
다음 다이어그램은 주문을 생성할 때 사용 가능한 크레딧을 확인하기 위해 이벤트 기반 접근 방식을 사용하는 방법을 보여줍니다.
마이크로서비스는 메시지 브로커를 통해 이벤트를 교환합니다.
주문 서비스는 신규 상태의 주문을 생성하고 주문 생성됨 이벤트를 게시합니다.
고객 서비스에서 주문 생성 이벤트를 소비하고 주문에 대한 크레딧을 예약한 후 크레딧 예약 이벤트를 게시합니다.
주문 서비스에서 크레딧 예약 이벤트를 소비하고 주문 상태를 '진행 중'으로 변경합니다.
더 복잡한 시나리오에서는 고객의 크레딧이 확인되는 동시에 재고를 예약하는 등의 추가 단계가 포함될 수 있습니다.
(a) 각 서비스가 데이터베이스를 원자적으로 업데이트하고 나중에 이벤트를 게시하고
(b) 메시지 브로커가 이벤트가 적어도 한 번 이상 전달되도록 보장한다면
여러 서비스에 걸친 비즈니스 트랜잭션을 구현할 수 있습니다.
이러한 트랜잭션은 ACID 트랜잭션이 아니라는 점에 유의하는 것이 중요합니다.
일시적 일관성과 같이 훨씬 약한 보장을 제공합니다. 이 트랜잭션 모델을 BASE 모델이라고 합니다.
이벤트를 사용하여 여러 마이크로서비스에서 소유한 데이터를 미리 조인하는 구체화된 보기를 유지할 수도 있습니다.
뷰를 유지 관리하는 서비스는 관련 이벤트를 구독하고 뷰를 업데이트합니다.
예를 들어 고객 주문 보기를 유지 관리하는 고객 주문 보기 업데이트 서비스는
고객 서비스 및 주문 서비스에서 게시하는 이벤트를 구독합니다.
고객 주문 보기 업데이터 서비스는 고객 또는 주문 이벤트를 수신하면
고객 주문 보기 데이터스토어를 업데이트합니다.
MongoDB와 같은 문서 데이터베이스를 사용하여 고객 주문 보기를 구현하고
각 고객에 대해 하나의 문서를 저장할 수 있습니다.
고객 주문 보기 쿼리 서비스는 고객 주문 보기 데이터 저장소를 쿼리하여
고객 및 최근 주문에 대한 요청을 처리합니다.
이벤트 중심 아키텍처에는 몇 가지 장점과 단점이 있습니다.
여러 서비스에 걸친 트랜잭션을 구현할 수 있고 궁극적으로 일관성을 제공할 수 있습니다.
또 다른 장점은 애플리케이션이 구체화된 보기를 유지할 수 있다는 것입니다.
한 가지 단점은 프로그래밍 모델이 ACID 트랜잭션을 사용할 때보다 더 복잡하다는 것입니다.
예를 들어 신용 확인에 실패하면 주문을 취소해야 하는 등 애플리케이션 수준의 오류를 복구하기 위해
보상 트랜잭션을 구현해야 하는 경우가 많습니다.
또한 애플리케이션은 일관되지 않은 데이터를 처리해야 합니다.
이는 기내 트랜잭션으로 인한 변경 사항이 표시되기 때문입니다.
또한 애플리케이션이 아직 업데이트되지 않은 구체화된 보기에서 읽으면 불일치를 볼 수 있습니다.
또 다른 단점은 구독자가 중복 이벤트를 감지하고 무시해야 한다는 것입니다.
원자성 달성하기
이벤트 중심 아키텍처에서는 데이터베이스를 원자적으로 업데이트하고 이벤트를 게시하는 문제도 있습니다.
예를 들어, 주문 서비스는 ORDER 테이블에 행을 삽입하고 주문 생성 이벤트를 게시해야 합니다.
이 두 작업은 원자적으로 수행되는 것이 중요합니다.
데이터베이스를 업데이트한 후 이벤트를 게시하기 전에 서비스가 충돌하면 시스템이 일관성을 잃게 됩니다.
원자성을 보장하는 표준 방법은 데이터베이스와 메시지 브로커를 포함하는 분산 트랜잭션을 사용하는 것입니다.
그러나 CAP 정리와 같이 위에서 설명한 이유로 인해 이 방법은 우리가 원하지 않는 방식입니다.
로컬 트랜잭션을 사용하여 이벤트 게시
원자성을 달성하는 한 가지 방법은 애플리케이션이 로컬 트랜잭션만 포함하는 다단계 프로세스를 사용하여 이벤트를 게시하는 것입니다. 비결은 비즈니스 엔티티의 상태를 저장하는 데이터베이스에 메시지 큐로 작동하는 EVENT 테이블을 만드는 것입니다. 애플리케이션은 (로컬) 데이터베이스 트랜잭션을 시작하고, 비즈니스 엔티티의 상태를 업데이트하고, EVENT 테이블에 이벤트를 삽입하고, 트랜잭션을 커밋합니다. 별도의 애플리케이션 스레드 또는 프로세스가 EVENT 테이블을 쿼리하고 이벤트를 메시지 브로커에 게시한 다음 로컬 트랜잭션을 사용하여 이벤트를 게시된 것으로 표시합니다. 다음 다이어그램은 이러한 설계를 보여줍니다.
주문 서비스는 ORDER 테이블에 행을 삽입하고 주문 생성 이벤트를 EVENT 테이블에 삽입합니다.
이벤트 게시자 스레드 또는 프로세스는 EVENT 테이블에서 게시되지 않은 이벤트를 쿼리하고
이벤트를 게시한 다음 EVENT 테이블을 업데이트하여 이벤트를 게시된 것으로 표시합니다.
이 접근 방식에는 몇 가지 장점과 단점이 있습니다.
한 가지 장점은 2PC에 의존하지 않고 각 업데이트에 대해 이벤트가 게시되도록 보장한다는 것입니다.
또한 애플리케이션이 비즈니스 수준 이벤트를 게시하므로 이벤트를 유추할 필요가 없습니다.
이 접근 방식의 한 가지 단점은 개발자가 이벤트를 게시하는 것을 기억해야 하므로 오류가 발생할 가능성이 높다는 것입니다.
이 접근 방식의 한계는 트랜잭션 및 쿼리 기능이 제한되어 있는 일부 NoSQL 데이터베이스를 사용할 때 구현하기가 어렵다는 것입니다.
이 접근 방식은 애플리케이션이 로컬 트랜잭션을 사용하여 상태를 업데이트하고
이벤트를 게시하도록 함으로써 2PC가 필요하지 않습니다.
이제 애플리케이션이 단순히 상태를 업데이트하도록 하여 원자성을 달성하는 접근 방식을 살펴보겠습니다.
데이터베이스 트랜잭션 로그 마이닝
2PC 없이 원자성을 달성하는 또 다른 방법은 데이터베이스의 트랜잭션 또는
커밋 로그를 마이닝하는 스레드나 프로세스에서 이벤트를 게시하는 것입니다.
애플리케이션이 데이터베이스를 업데이트하면 데이터베이스의 트랜잭션 로그에 변경 사항이 기록됩니다.
트랜잭션 로그 마이너 스레드 또는 프로세스는 트랜잭션 로그를 읽고 이벤트를 메시지 브로커에 게시합니다.
다음 다이어그램은 그 설계를 보여줍니다.
이 접근 방식의 예로 오픈 소스 링크드인 데이터버스 프로젝트를 들 수 있습니다.
Databus는 Oracle 트랜잭션 로그를 마이닝하고 변경 사항에 해당하는 이벤트를 게시합니다.
LinkedIn은 Databus를 사용하여 다양한 파생 데이터 저장소를 기록 시스템과 일관되게 유지합니다.
또 다른 예로는 관리형 NoSQL 데이터베이스인 AWS의 스트림 메커니즘인 DynamoDB가 있습니다.
DynamoDB 스트림에는 지난 24시간 동안 DynamoDB 테이블의 항목에 대해
수행된 변경(만들기, 업데이트, 삭제 작업)의 시간 순서대로 정렬된 순서가 포함되어 있습니다.
애플리케이션은 스트림에서 이러한 변경 사항을 읽고 예를 들어 이벤트로 게시할 수 있습니다.
트랜잭션 로그 마이닝에는 다양한 장점과 단점이 있습니다.
한 가지 장점은 2PC를 사용하지 않고도 각 업데이트에 대해 이벤트가 게시되도록 보장한다는 것입니다.
트랜잭션 로그 마이닝은 또한 애플리케이션의 비즈니스 로직에서
이벤트 게시를 분리함으로써 애플리케이션을 단순화할 수 있습니다.
가장 큰 단점은 트랜잭션 로그의 형식이 각 데이터베이스마다 고유하며
데이터베이스 버전 간에 변경될 수도 있다는 것입니다.
또한 트랜잭션 로그에 기록된 낮은 수준의 업데이트에서
높은 수준의 비즈니스 이벤트를 리버스 엔지니어링하는 것이 어려울 수 있습니다.
트랜잭션 로그 마이닝은 애플리케이션이 데이터베이스 업데이트라는 한 가지 작업을 수행하도록 함으로써 2PC의 필요성을 제거합니다.
이제 업데이트를 없애고 이벤트에만 의존하는 다른 접근 방식을 살펴보겠습니다.
이벤트 소싱 사용
이벤트 소싱는 비즈니스 엔티티를 지속하는데 근본적으로 다른 이벤트 중심 접근 방식을 사용하여 2PC 없이 원자성을 달성합니다.
이 애플리케이션은 엔티티의 현재 상태를 저장하는 대신 상태 변경 이벤트 시퀀스를 저장합니다.
애플리케이션은 이벤트를 재생하여 엔티티의 현재 상태를 재구성합니다.
비즈니스 엔티티의 상태가 변경될 때마다 새 이벤트가 이벤트 목록에 추가됩니다.
이벤트 저장은 단일 작업이므로 본질적으로 원자적인 작업입니다.
이벤트 소싱이 어떻게 작동하는지 보려면 Order 엔티티를 예로 들어 보겠습니다.
기존 접근 방식에서는 각 주문이 ORDER 테이블의 행에 매핑되고 예를 들어 ORDER_LINE_ITEM 테이블의 행에 매핑됩니다.
그러나 이벤트 소싱을 사용할 때 주문 서비스는 주문을 상태 변경 이벤트의 형태로 저장합니다:
생성됨, 승인됨, 배송됨, 취소됨.
각 이벤트에는 주문의 상태를 재구성하기에 충분한 데이터가 포함되어 있습니다.
이벤트는 이벤트 데이터베이스인 이벤트 스토어에서 지속됩니다.
이 스토어에는 엔티티의 이벤트를 추가하고 검색하기 위한 API가 있습니다.
이벤트 스토어는 앞서 설명한 아키텍처의 메시지 브로커처럼 작동하기도 합니다.
이벤트 스토어는 서비스가 이벤트를 구독할 수 있는 API를 제공합니다.
이벤트 스토어는 관심 있는 모든 구독자에게 모든 이벤트를 제공합니다.
이벤트 스토어는 이벤트 중심 마이크로서비스 아키텍처의 중추입니다.
이벤트 소싱에는 여러 가지 이점이 있습니다.
이벤트 기반 아키텍처 구현의 핵심 문제 중 하나를 해결하고 상태가 변경될 때마다
이벤트를 안정적으로 게시할 수 있습니다. 결과적으로 마이크로서비스 아키텍처에서 데이터 일관성 문제를 해결합니다.
또한 도메인 객체가 아닌 이벤트를 유지하므로 <데이터-dl-uid="119">객체-관계형 임피던스 불일치 문제를 대부분 피할 수 있습니다.
또한 이벤트 소싱은 비즈니스 엔티티에 대한 변경 사항에 대해 100% 신뢰할 수 있는 감사 로그를 제공하며,
특정 시점의 엔티티 상태를 결정하는 임시 쿼리를 구현할 수 있게 해줍니다.
이벤트 소싱의 또 다른 주요 이점은 비즈니스 로직이 이벤트를 교환하는 느슨하게 연결된 비즈니스 엔티티로 구성되어 있다는 것입니다.
따라서 모놀리식 애플리케이션에서 마이크로서비스 아키텍처로 훨씬 쉽게 마이그레이션할 수 있습니다.
이벤트 소싱에는 몇 가지 단점도 있습니다.
익숙하지 않은 다른 스타일의 프로그래밍이므로 학습 곡선이 있습니다.
이벤트 스토어는 기본 키로 비즈니스 엔티티를 직접 조회하는 기능만 지원합니다.
쿼리를 구현하려면 명령 쿼리 책임 분리(CQRS)를 사용해야 합니다.
결과적으로 애플리케이션은 최종적으로 일관된 데이터를 처리해야 합니다.
요약
마이크로서비스 아키텍처에서 각 마이크로서비스에는 자체 프라이빗 데이터스토어가 있습니다.
마이크로서비스마다 서로 다른 SQL 및 NoSQL 데이터베이스를 사용할 수 있습니다.
이러한 데이터베이스 아키텍처에는 상당한 이점이 있지만, 분산된 데이터 관리 문제가 발생합니다.
첫 번째 과제는 여러 서비스에서 일관성을 유지하는 비즈니스 트랜잭션을 구현하는 방법입니다.
두 번째 과제는 여러 서비스에서 데이터를 검색하는 쿼리를 구현하는 방법입니다.
많은 애플리케이션의 경우 이벤트 기반 아키텍처를 사용하는 것이 해결책입니다.
이벤트 중심 아키텍처를 구현할 때 한 가지 과제는 상태를 원자적으로 업데이트하는 방법과 이벤트를 게시하는 방법입니다.
데이터베이스를 메시지 큐로 사용하는 방법, 트랜잭션 로그 마이닝, 이벤트 소싱 등 몇 가지 방법을 통해 이를 수행할 수 있습니다.
향후 블로그 게시물에서는 마이크로서비스의 다른 측면에 대해 계속 자세히 살펴보겠습니다.
편집자 - 이제 7부로 구성된 이 시리즈 기사가 완료되었습니다:
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
Ingress Controller 선택에 대한 가이드의 처음 두 부분을 읽은 후에는 하나를 선택할 준비가 거의 되었습니다. 지금까지 우리가 어디에 있었는지 요약해 보겠습니다.
1부에서는 성능, 예산, 사용 사례, 아키텍처 및 소유권을 포함한 요구 사항을 식별하는 방법에 대해 설명합니다.
2부에서는 잘못된 수신 컨트롤러를 선택할 경우 발생할 수 있는 위험에 대해 설명하고 향후 선택을 보장할 수 있는 주요 영역을 간략하게 설명합니다.
수신 컨트롤러는 오픈 소스, 기본 및 상업의 세 가지 범주로 나뉩니다. 각각에는 사용 사례가 있으며 선택하기 전에 단기 및 장기 요구 사항을 명확히 하는 것이 중요합니다. 이 블로그에서는 각 카테고리의 장단점을 다룹니다.
Open Source Ingress Controllers
많은 오픈 소스 수신 컨트롤러는 사용자 및 자원 봉사 개발자 커뮤니티에 의해 유지 관리되지만 일부는 전담 엔지니어링 팀도 있습니다. 가장 인기 있는 오픈 소스 수신 컨트롤러 중 두 개는 NGINX를 기반으로 하며, 하나는 쿠버네티스 커뮤니티에서 유지 관리하고, 다른 하나는 핵심 NGINX 엔지니어링 팀이 주도하고 오픈 소스입니다. NGINX 기반 수신 컨트롤러에 대한 자세한 비교는 시리즈의 4부를 참조하세요.
프로:
무료 및 커뮤니티 기반 – 많은 사람들과 조직이 타의 추종을 불허하는 가격(무료!)뿐만 아니라 커뮤니티에서 개발한 기술을 선호하기 때문에 오픈 소스 프로젝트를 선택합니다.
기능 속도 – 이러한 수신 컨트롤러는 기능 혁신의 최첨단에 있을 가능성이 더 높습니다.
단점 (일반적으로 오픈 소스 프로젝트와 공유) :
비용(시간) – 쉬운 설정과 확장성을 위한 "즉시 사용 가능한" 도구가 없기 때문에 특정 요구 사항에 대한 사용자 지정 및 해결 방법에 시간을 소비하게 됩니다.
위험 – 안정성, 보안 및 신뢰성에 문제가 있을 수 있습니다(기능 속도와 기여자의 자발적 특성에 대한 강조로 인해). CVE(Common Vulnerabilities and Exposures)에 대한 패치는 절대 오지 않거나 CVE가 공개된 후 몇 달 후에 도착할 수 있으므로 해커가 수신 컨트롤러를 공격할 수 있는 충분한 시간을 제공합니다.
지원이 최소화되거나 없음 – 대부분은 "자체 해결"입니다... 그것은 단지 당신과 문서입니다. 스스로 해결할 수 없는 문제에 부딪히면 도움을 받는 것이 어려울 수 있습니다 (또는 불가능할 수 있습니다) - 거의 유일한 선택은 커뮤니티 포럼에 문제를 게시하고 커뮤니티의 다른 구성원이 (a) 귀찮게 응답하고 (b) 해결책을 알기를 바라는 것입니다.
요약: 조직이 쿠버네티스를 처음 실험하기 시작할 때, 편리함을 위해 또는 무료로 빠르게 시작하고 실행할 수 있다고 약속하는 문서 때문에 오픈 소스 수신 컨트롤러를 선택하는 경우가 많습니다. 이는 시작하거나, 테스트하거나, 소량 생산을 실행할 때 매우 효과적일 수 있습니다.
기본 Ingress 컨트롤러
많은 기본 수신 컨트롤러는 오픈 소스 기술을 기반으로 하지만, 전체 Kubernetes 플랫폼을 제공하고 종종 관리를 지원하는 회사에서 개발 및 유지 관리하기 때문에 별도로 분류합니다. 이 범주의 예로는 퍼블릭 클라우드 수신 컨트롤러, Rancher 및 Red Hat OpenShift 라우터가 있습니다.
프로:
무료 또는 저렴한 비용 – 저렴한 가격표는 이러한 제품을 사용하는 강력한 이유입니다. 그들은 이미 플랫폼에 통합되어 있으므로 처음 시작할 때 확실한 시간을 절약할 수 있습니다.
신뢰성 및 지원 – 전담 엔지니어링 팀에서 유지 관리하기 때문에 커뮤니티에서 유지 관리하는 Ingress 컨트롤러보다 더 안정적일 수 있습니다. 상업적 지원은 일반적으로 포함되거나 추가 비용으로 제공됩니다.
Cons:
인프라 종속 – 기본 수신 컨트롤러는 인프라에 구애받지 않으므로 클라우드에서 클라우드로 컨트롤러 또는 구성을 가져올 수 없습니다. 즉, 각 배포 환경에 대해 서로 다른 수신 컨트롤러가 필요하며, 이로 인해 도구가 무분별하게 확장되고 팀의 학습 곡선이 증가하며 수신 컨트롤러를 보호하기가 더 어려워집니다.
기본 기능 – 일반적으로 대규모 배포에 필요한 고급 트래픽 관리 및 보안 기능이 부족합니다.
예측할 수 없는 비용(시간 및 비용) – 초기 비용은 전혀 없거나 낮지만 애플리케이션이 성장함에 따라 급격히 예측할 수 없을 정도로 증가할 수 있습니다. 이는 수신 컨트롤러의 최소 기능 집합에서 누락된 기능을 앱에 빌드하는 데 필요한 시간의 형태를 취할 수 있으며, 물론 앱을 업데이트할 때마다 해당 기능을 회귀 테스트해야 합니다. 일부 기본 도구의 또 다른 단점은 처음에는 무해해 보이는 처리량 비용으로 인해 앱이 인기를 얻음에 따라 클라우드 요금이 크게 증가한다는 것입니다.
요약: 기본 수신 컨트롤러는 Kubernetes를 처음 사용하고 Amazon EKS(Elastic Kubernetes Service), GKE(Google Kubernetes Engine), AKS(Microsoft Azure Kubernetes Service), Rancher 및 Red Hat OpenShift Container Platform과 같은 관리형 플랫폼을 사용하는 팀에 널리 사용됩니다. 앱이 완성되고 팀이 성장함에 따라 조직은 기본 도구를 대체하는 대신 엔터프라이즈급 수신 컨트롤러를 스택에 추가하기로 선택하는 경우가 많습니다.
프로:
대규모 기능 세트 – Commercial Ingress 컨트롤러에는 대규모 배포를 위한 고급 트래픽 관리 및 확장성을 지원하는 강력한 기능 세트가 포함되어 있습니다. WAF 또는 서비스 메시와 같은 다른 프로덕션 등급 제품과의 통합이 있을 수 있습니다.
확장성 – 조직은 사용자 지정이나 해결 방법이 필요하지 않은 "즉시 사용 가능한" 기능이 더 많은 경향이 있기 때문에 이러한 옵션을 통해 시간을 절약할 수 있는 경우가 많습니다. 자동화 파이프라인에 쉽게 추가할 수 있으므로 필요에 따라 인프라를 확장할 수 있습니다.
신뢰성 및 지원 – 상용 제품의 주요 이점 중 하나는 안정적이라는 것인데, 이는 각 릴리스에서 광범위한 테스트를 거치고 필요에 따라 정기적인 소프트웨어 업데이트 및 보안 패치를 제공한다는 것을 의미합니다. 완전한 상업적 지원은 일반적으로 다양한 계층에서 제공되므로 심각한 문제가 발생한 후 몇 분 또는 몇 시간 이내에 기밀 지원을 받을 수 있는 경우가 많습니다.
Cons:
느린 개발 – 상용 Ingress 컨트롤러의 경우 안정성이 중요하기 때문에 기능 속도가 오픈 소스 컨트롤러보다 약간 느릴 수 있습니다.
비용(돈) – 상업용 제품의 현실은 돈이 든다는 것입니다. 현금보다 개발자 주기가 더 많은 조직의 경우 상황이 바뀔 때까지 비용이 거래 중단이 될 수 있습니다.
요약: 조직이 확장됨에 따라 수신 컨트롤러의 선택은 팀과 앱의 복잡성에 따라 더욱 중요해집니다. 조직이 높은 수준의 복잡성에 도달하면 관리 복잡성을 줄이고 새로운 제품 기능의 출시 시간을 단축할 수 있기 때문에 상용 수신 컨트롤러가 적합합니다.
여정의 이 단계에서는 요구 사항을 충족할 수 없는 옵션을 제거하여 시도하기 위해 일부 수신 컨트롤러를 사용할 준비가 되었습니다. 높은 수준의 기능 비교를 시작하기에 좋은 곳 중 하나는 learnk8s이며, 이 도구는 평가한 수신 컨트롤러의 무료 비교 표를 제공합니다.
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
CNCF(Cloud Native Computing Foundation)의 2020년 설문조사에 따르면 NGINX는 쿠버네티스용 인그레스 컨트롤러에서 가장 일반적으로 사용되는 데이터 플레인이지만, "NGINX 인그레스 컨트롤러"가 두 개 이상 있다는 사실을 알고 계셨나요?
2018년에 Wait, What NGINX Ingress Controller for Kubernetes Am I Using?이라는 제목으로 게시된 이 블로그의 이전 버전은 NGINX를 사용하는 두 가지 인기 있는 Ingress 컨트롤러의 존재에 대한 커뮤니티 회원과의 대화에서 촉발되었습니다.
왜 혼란이 있었는지(그리고 여전히 혼란이 있는지) 쉽게 알 수 있습니다. 두 수신 컨트롤러는 모두 다음과 같습니다.
"NGINX Ingress Controller"라고 합니다.
오픈 소스
매우 유사한 리포지토리 이름으로 GitHub에서 호스팅됩니다.
비슷한 시기에 시작된 프로젝트의 결과
물론 가장 큰 공통점은 동일한 기능을 구현한다는 것입니다.
NGINX vs. 쿠버네티스 커뮤니티 수신 컨트롤러
명확성을 위해 다음과 같이 두 버전을 구분합니다.
커뮤니티 버전 – GitHub의 kubernetes/ingress-nginx 리포지토리에서 찾을 수 있는 커뮤니티 수신 컨트롤러는 Kubernetes.io 에 대한 문서가 있는 NGINX 오픈 소스를 기반으로 합니다. 쿠버네티스 커뮤니티에서 유지 관리한다.
NGINX 버전 – GitHub의 nginxinc/kubernetes-ingress 리포지토리에서 찾을 수 있는 NGINX Ingress Controller는 F5 NGINX에서 docs.nginx.com 에 대한 문서와 함께 개발 및 유지 관리합니다. 두 가지 버전으로 제공됩니다.
NGINX 오픈 소스 기반(무료 및 오픈 소스 옵션)
NGINX Plus 기반(상용 옵션)
Kong과 같이 NGINX를 기반으로 하는 다른 Ingress 컨트롤러도 많이 있지만 다행히도 이름을 쉽게 구별할 수 있습니다. 사용 중인 NGINX 수신 컨트롤러가 무엇인지 확실하지 않은 경우 실행 중인 수신 컨트롤러의 컨테이너 이미지를 확인한 다음, Docker 이미지 이름을 위에 나열된 리포지토리와 비교합니다.
NGINX Ingress 컨트롤러 목표 및 우선 순위
NGINX 수신 컨트롤러와 커뮤니티 수신 컨트롤러(NGINX 오픈 소스를 기반으로 하는 다른 수신 컨트롤러와 함께)의 주요 차이점은 개발 및 배포 모델이며, 이는 차례로 서로 다른 목표와 우선 순위를 기반으로 합니다.
개발 철학 – 모든 NGINX 프로젝트 및 제품에 대한 우리의 최우선 순위는 장기적인 안정성과 일관성을 갖춘 빠르고 가벼운 도구를 제공하는 것입니다. 우리는 릴리스 간의 동작 변경, 특히 이전 버전과의 호환성을 손상시키는 변경을 피하기 위해 가능한 모든 노력을 기울입니다. 업그레이드할 때 예상치 못한 놀라움을 못할 것임을 약속드립니다. 또한 선택의 여지가 있다고 믿기 때문에 모든 솔루션은 베어메탈, 컨테이너, VM, 퍼블릭, 프라이빗, 하이브리드 클라우드를 포함한 모든 플랫폼에 배포할 수 있습니다.
통합 코드베이스 – NGINX Ingress Controller는 로드 밸런싱을 위해 100% 순수 NGINX 오픈 소스 또는 NGINX Plus 인스턴스를 사용하여 기본 NGINX 기능만 사용하여 모범 사례 구성을 적용합니다. 상호 운용성 테스트의 이점을 얻지 못한 타사 모듈이나 Lua 코드에 의존하지 않습니다. 우리는 많은 타사 저장소에서 Ingress 컨트롤러를 조립하지 않습니다. 로드 밸런서 (NGINX 및 NGINX Plus) 및 Ingress 컨트롤러 소프트웨어 (Go 애플리케이션)를 직접 개발하고 유지 관리합니다. 우리는 Ingress 컨트롤러의 모든 구성 요소에 대한 단일 기관입니다.
고급 트래픽 관리 – 표준 Kubernetes Ingress 리소스의 제한 사항 중 하나는 주석, ConfigMaps 및 고객 템플릿과 같은 보조 기능을 사용하여 고급 기능으로 사용자 지정해야 한다는 것입니다. NGINX 수신 리소스는 TCP/UDP, 회로 차단, A/B 테스트, 청록색 배포, 헤더 조작, mTLS(상호 TLS 인증) 및 WAF(웹 애플리케이션 방화벽)를 포함한 수신 부하 분산 기능의 구현을 간소화하는 네이티브, 형식 안전 및 들여쓰기된 구성 스타일을 제공합니다.
지속적인 생산 준비 – 모든 릴리스는 지원 가능한 생산 표준에 따라 구축되고 유지 관리됩니다. 이 "엔터프라이즈급" 초점은 NGINX 오픈 소스 기반 버전을 사용하든 NGINX Plus 기반 버전을 사용하든 동일하게 이점을 누릴 수 있습니다. NGINX 오픈 소스 사용자는 GitHub에서 엔지니어링 팀의 질문에 대한 답변을 받을 수 있으며, NGINX Plus 구독자는 동급 최고의 지원을 받을 수 있습니다. 어느 쪽이든 DevOps 팀에 NGINX 개발자가 있는 것과 같습니다!
NGINX 오픈 소스 대 NGINX Plus – 커머셜 에디션으로 업그레이드하는 이유는 무엇입니까?
여기에서 NGINX Plus 기반 NGINX 수신 컨트롤러에서 얻을 수 있는 몇 가지 주요 이점을 검토해 보겠습니다. 쿠버네티스 수신 컨트롤러를 선택하는 방법, 3부: 오픈 소스 vs. 기본 vs. 상용에서 논의한 바와 같이, 오픈 소스와 상용 인그레스 컨트롤러 사이에는 상당한 차이점이 있다. 프로덕션에서 대규모 Kubernetes 배포 및 복잡한 앱을 계획하는 경우 상용 수신 컨트롤러가 일부 주요 영역에서 시간과 비용을 절약한다는 것을 알게 될 것입니다.
보안 및 규정 준수
많은 조직이 프로덕션 환경에서 쿠버네티스 앱을 제공하지 못하는 주된 이유 중 하나는 보안 및 규정 준수를 유지하기 어렵기 때문입니다. NGINX Plus 기반 NGINX Ingress Controller는 앱과 고객을 안전하게 보호하는 데 중요한 5가지 사용 사례를 제공합니다.
엣지 보안 – 잘 설계된 쿠버네티스 배포에서 수신 컨트롤러는 쿠버네티스 내에서 실행되는 서비스로 흐르는 데이터 플레인 트래픽의 유일한 진입점 이므로 웹 애플리케이션 방화벽(WAF)에 이상적인 위치입니다. NGINX App Protect는 NGINX Ingress Controller<.htmla>와 통합되어 OWASP Top 10 및 기타 여러 취약점으로부터 Kubernetes 앱을 보호하고, PCI DSS 규정 준수를 보장하며, ModSecurity를 능가합니다.
인증 및 권한 부여 중앙 집중화 – OAuth 2.0 프레임워크를 기반으로 구축된 OIDC(OpenID Connect) 및 JWT(JSON Web Token) 인증을 사용하여 수신 지점에서 인증 및 SSO(Single Sign-On) 계층을 구현할 수 있습니다.
엔드투엔드 암호화 구현 – 서비스 간 트래픽을 보호해야 하는 경우 서비스 메시를 찾을 수 있습니다. 항상 무료로 제공되는 NGINX 서비스 메시는 NGINX 수신 컨트롤러와 원활하게 통합 되므로 다른 메시 보다 짧은 대기 시간을 최소화하면서 수신 및 송신 mTLS 트래픽을 모두 효율적으로 제어할 수 있습니다.
사전 예방적인 패치 알림 받기 – CVE가 보고되면 가입자는 사전 예방적으로 정보를 받고 신속하게 패치를 받습니다. GitHub에서 업데이트를 확인하거나 패치가 릴리스될 때까지 몇 주(심지어 몇 달)를 기다릴 필요 없이 악용 위험을 줄이기 위해 패치를 즉시 적용할 수 있습니다.
FIPS 규정 준수 – FIPS 모드를 활성화하여 NGINX Plus와 통신하는 클라이언트가 신뢰할 수 있는 구현과 함께 강력한 암호를 사용하고 있는지 확인할 수 있습니다.
독일의 거대 자동차 회사인 아우디(Audi)가 NGINX를 통해 Audi의 미래 경쟁력 있는 기술 비전과 애플리케이션 혁신에서 Red Hat OpenShift 앱을 어떻게 보호 했는지 알아보세요.
응용 프로그램 성능 및 복원력
가동 시간과 앱 속도는 개발자와 Platform Ops 팀을 위한 핵심 성과 지표(KPI)인 경우가 많습니다. NGINX Plus 기반 NGINX Ingress Controller는 쿠버네티스의 약속을 이행하는 데 도움이 되는 5가지 사용 사례를 제공합니다.
실시간 모니터링 – NGINX Plus 대시보드에는 수백 개의 주요 로드 및 성능 메트릭이 표시되므로 앱 느린(또는 다운!) 앱의 원인을 신속하게 해결할 수 있습니다.
더 빠른 장애 감지 및 해결 – TCP 및 UDP 업스트림 서버의 상태를 사전에 모니터링 하는 활성 상태 확인을 통해 회로 차단기를 구현합니다.
재시작 없이 재구성 – 더 빠르고 중단 없는 재구성을 통해 오픈 소스 대안보다 일관된 성능과 리소스 사용량, 더 짧은 대기 시간으로 애플리케이션을 제공할 수 있습니다.
새로운 기능 및 배포를 철저하게 테스트 – 키-값 저장소를 활용하여 다시 로드할 필요 없이 백분율을 변경 함으로써 A/B 테스트 및 블루-그린 배포를 더 쉽게 실행할 수 있습니다.
신속한 지원 요구 사항 해결 – 기밀 및 상업적 지원은 커뮤니티가 질문에 답변할 때까지 기다릴 수 없거나 민감한 데이터가 노출될 위험이 없는 조직에 필수적 입니다. NGINX 지원은 요구 사항에 맞게 여러 계층에서 사용할 수 있으며 설치, 배포, 디버깅 및 오류 수정에 대한 지원을 포함합니다. 무언가가 "옳지 않은" 것처럼 보일 때도 도움을 받을 수 있습니다.
비즈니스 문자 메시지 회사인 Zipwhip이 NGINX를 사용하여 Amazon EKS의 보안 및 트래픽 가시성 강화에서 SaaS 앱의 99.99% 가동 시간을 달성한 방법을 알아보세요.
다음 단계: NGINX Ingress 컨트롤러 사용해 보기
오픈 소스 수신 컨트롤러가 앱에 적합한 선택이라고 결정한 경우 GitHub 리포지토리에서 빠르게 시작할 수 있습니다.
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
바로 RedHat OpenShift Container Platform(OCP)과 Kubernetes입니다.
OpenShift는 Kubernetes를 기반으로 구축된 플랫폼으로,
다양한 컨테이너 오케스트레이션 솔루션에서 Kubernetes를 사용하는 것이 일반적입니다.
그러나 외부 트래픽을 Kubernetes 또는 OpenShift 환경으로 라우팅하는 것은 항상 두 가지 측면에서 약간 복잡할 수 있습니다.
하나는 Kubernetes 내에 배포된 서비스를 외부 세계에 노출하는 문제입니다. 이를 해결하기 위한 솔루션 중 하나는 NGINX Plus Ingress Controller와 같은 Ingress 컨트롤러입니다. OpenShift에서 NGINX Ingress Operator를 사용하는 방법에 대한 자세한 내용은 관련 블로그에서 확인할 수 있습니다.
다른 하나는 Kubernetes 노드에서 트래픽을 로드 밸런싱하는 문제입니다. 이를 해결하려면 외부 하드웨어 또는 가상 로드 밸런서, 또는 클라우드 네이티브 솔루션을 사용할 수 있습니다. 그러나 NGINX Plus를 외부 로드 밸런서로 사용하여 성능을 개선하고 기술 투자를 단순화할 수 있습니다.
이 블로그에서는 간단하고 효율적이며 애플리케이션 개발 팀이 Kubernetes 내부의 Ingress 구성과
외부 로드 밸런서 구성을 모두 관리할 수 있도록 NGINX Plus를 사용하는 방법에 대해 설명합니다.
이를 위한 참조 아키텍처로 GitHub에서 nginx-lb-operator 프로젝트를 제공합니다.
NGINX Load Balancer Operator(NGINX-LB-Operator)는 Red Hat Operator Framework와
SDK를 사용하여 만든 NGINX Controller용 Ansible 기반 연산자입니다.
이 연산자는 Kubernetes 클러스터 내에서 새로운 서비스가 추가되거나 Pod가 변경되거나 배포가 확장될 때
외부 NGINX Plus 로드 밸런서의 구성을 업데이트하기 위해 NGINX Controller의 선언적 API를 구동합니다.
NGINX-LB-Operator는 NGINX Plus 또는 NGINX Controller의 지원 계약에 포함되지 않으며,
GitHub에서 버그 보고나 문제 해결 지원을 받을 수 있습니다.
Kubernetes 및 NGINX 기술 – 리뷰
NGINX-LB-Operator는 여러 Kubernetes와 NGINX 기술에 의존하므로 이를 간단히 살펴보겠습니다.
이미 익숙하다면 NGINX Load Balancer Operator 부분으로 넘어가셔도 좋습니다.
Kubernetes 컨트롤러 및 운영자
Kubernetes는 느슨하게 결합된 중앙 API를 중심으로 구축된 오케스트레이션 플랫폼입니다.
이 API는 리소스 정의와 컨트롤러를 제공하며, 이를 통해 리소스를 모니터링하고 관리합니다.
Kubernetes는 확장 가능한 플랫폼으로, 오퍼레이터를 사용하여 기능을 확장할 수 있습니다.
컨트롤러는 Kubernetes 시스템에서 핵심적인 역할을 하며, 특정 리소스를 감시하고 상태 변화에 따라 원하는 상태를 유지하기 위해 필요한 작업을 수행합니다. 가장 흔히 다뤄지는 Kubernetes 컨트롤러 중 하나는 "Ingress 컨트롤러"입니다.
운영자는 사용자 정의 리소스 정의(CRD)를 사용하여 애플리케이션과 그 구성 요소를 관리하는 커스터마이즈된 컨트롤러입니다.
Kubernetes용 NGINX Ingress 컨트롤러
NGINX에는 두 가지 주요 Ingress 컨트롤러가 있습니다.
첫 번째는 kubernetes/ingress-nginx로, Kubernetes 오픈 소스 커뮤니티에서 지원하는 Ingress 컨트롤러입니다.
두 번째는 nginxinc/kubernetes-ingress로, F5의 NGINX 팀에서 유지 관리하며 NGINX Open Source 및 NGINX Plus 버전이 있습니다.
이 두 가지는 비슷한 이름으로 구별하기 어려울 수 있습니다.
Ingress 컨트롤러의 주요 차이점은 Kubernetes API를 확장하여 고급 로드 밸런싱 기능과 블루그린 배포,
카나리아 릴리스 등 다양한 기능을 제공합니다.
NGINX 컨트롤러
NGINX Controller는 여러 환경에서 NGINX Plus 인스턴스를 관리하고, 성능 및 오류 상태에 대한 통찰력을 제공합니다.
이 컨트롤러는 클라우드 독립적인 제어 평면으로, NGINX Plus 인스턴스를 관리하고,
로드 밸런싱 및 API 관리를 위한 중앙 집중식 구성을 제공합니다.
Kubernetes 환경에서 NGINX Controller는 리버스 프록시 또는 API 게이트웨이로 배포된 NGINX Plus 인스턴스를 관리할 수 있지만,
Ingress Controller 자체는 관리하지 않습니다.
Ingress Controller는 Kubernetes 리소스에 대한 제어 루프를 수행하는 도구이므로 Kubernetes 네이티브 방식으로 관리해야 합니다.
외부 로드 밸런서
Kubernetes용 NGINX Plus Ingress Controller는 Kubernetes 내의 서비스를 외부 세계에 노출하는 훌륭한 방법이지만,
Kubernetes 노드나 클러스터로의 트래픽을 관리하려면 외부 로드 밸런서가 필요할 수 있습니다.
퍼블릭 클라우드에서는 NGINX Plus나 F5 BIG-IP LTM 같은 외부 로드 밸런서를 사용하거나
클라우드 네이티브 솔루션을 선택할 수 있습니다.
온프레미스나 프라이빗 클라우드에서는 NGINX Plus 또는 BIG-IP LTM을 사용할 수 있습니다.
외부 로드 밸런서를 관리할 때는 NGINX Controller를 사용하여
외부 NGINX Plus 인스턴스를 관리할 수 있습니다.
이를 통해 선언적 API를 사용해 인프라를 코드로 추상화하고, CI/CD 파이프라인과 통합할 수 있습니다.
선언적 API는 CI/CD 파이프라인과 인터페이싱하는 목적으로 설계되었으며, 이를 사용하여 각 애플리케이션 구성 요소를 배포할 수 있습니다.
하지만 Ingress 계층이 확장 가능하거나 동적으로 할당된 Kubernetes NodePorts를 사용 하거나
OpenShift Routes가 변경될 수 있는 경우는 어떻게 될까요?
이런 경우, 외부 로드 밸런서 구성을 Kubernetes 상태와 병합하고
Kubernetes Operator를 통해 NGINX Controller API를 구동하고 싶을 것입니다.
다이어그램은 외부 로드 밸런서를 관리하기 위한 그런 연산자( NGINX-LB-Operator )만 포함하는 샘플 배포를 보여주고,
NGINX Plus Ingress Controller와 NGINX Controller의 차이점을 강조합니다.
Ingress 리소스(파란색 상자) – 표준 Ingress 리소스와 NGINX VirtualServer 리소스가 프로젝트 네임스페이스에 정의되어 있습니다.
파란색 화살표 – Ingress 리소스는 Kubernetes API에서 생성되고, 다른 네임스페이스에서 실행되는 NGINX Plus Ingress Controller에서 선택됩니다.
사용자 정의 리소스(녹색 상자) – NGINX-LB-Operator 와 함께 설치된 CRD의 인스턴스인 사용자 정의 리소스는 프로젝트의 네임스페이스에서 정의되며 동일한 네임스페이스에서 실행되는 NGINX-LB-Operator 에서 사용됩니다.
녹색 화살표 - 리소스는 API에서 생성되고 NGINX-LB-Operator 에서 수집됩니다 . 동일한 Pod에서 실행되는 로컬 NGINX Plus 인스턴스를 구성하는 Ingress Controller와 달리 NGINX-LB-Operator는 NGINX Controller에 API 호출을 합니다.
주황색 화살표 – NGINX Controller는 외부 NGINX Plus 인스턴스를 구성하여 NGINX Plus Ingress Controller에 부하를 분산합니다.
이 토폴로지에서 사용자 지정 리소스는 외부 로드 밸런서의 원하는 상태를 포함하고
업스트림(워크로드 그룹)을 NGINX Plus Ingress Controller로 설정합니다.
NGINX-LB-Operator는 Ingress Pod에 대한 정보를 수집하고
해당 정보를 원하는 상태와 병합한 다음 NGINX Controller API로 전송합니다.
NGINX-LB-Operator
Kubernetes용 Operator를 작성하는 것은 어려운 작업처럼 보일 수 있지만,
Red Hat과 Kubernetes 오픈 소스 커뮤니티에서 제공하는 Operator Framework는 이를 쉽게 만들어줍니다.
Operator SDK를 사용하면 누구나 Go, Ansible 또는 Helm을 사용하여 Kubernetes Operator를 만들 수 있습니다.
F5에서는 NGINX Controller용 인증 컬렉션을 포함하여 여러 제품에 대한 Ansible 컬렉션을 이미 게시했으므로
외부 NGINX Plus 인스턴스를 관리하고 NGINX Controller와 인터페이스하는 Operator를 빌드하는 것은 매우 간단합니다.
이는 Namespace 또는 Cluster Scope로 배포할 수 있으며 소수의 사용자 정의 리소스를 감시합니다.
사용자 정의 리소스는 NGINX Controller 객체(Certificate, Gateway, Application 및 Component)에
직접 매핑되므로 Kubernetes에서 NGINX Controller의 애플리케이션 중심 모델을 직접 나타냅니다.
Kubernetes에서 구성된 사용자 정의 리소스는 NGINX-LB-Operator 에서 수집한 다음 NGINX Controller에서 동등한 리소스를 생성합니다.
NGINX-LB-Operator를 사용하면 NGINX Controller의 선언적 API를 사용하여
외부 NGINX Plus 인스턴스의 구성을 관리할 수 있습니다.
NGINX Controller가 외부 인스턴스를 관리하기 때문에
모니터링 및 알림의 추가 이점과 NGINX Controller가 제공하는 심층적인 애플리케이션 통찰력을 얻을 수 있습니다.
이 다이어그램은 다음 사항을 보여줍니다.
프로젝트 네임스페이스에서 Kubernetes API로 전송되는 사용자 지정 리소스를 만듭니다.
NGINX-LB-Operator는 새로 구성된 리소스를 확인하고 Ingress 네임스페이스의 Ingress 컨트롤러에서 구성 요소의 원하는 상태와 배포 정보를 수집합니다.
정의와 Ingress 컨트롤러의 현재 상태에서 병합된 구성이 NGINX 컨트롤러로 전송됩니다.
구성은 요청된 NGINX Plus 인스턴스에 전달되고 NGINX Controller는 새 애플리케이션에 대한 메트릭 수집을 시작합니다.
자세한 배포 지침과 샘플 애플리케이션은 GitHub 에 제공됩니다 .
롤 플레이를 좋아하지 않거나 TL;DR 버전을 위해 여기 왔다면 지금 바로 가보세요.
샘플 배포
자, 이제 롤플레이를 해봅시다. 나는 수잔이고, 당신은 데이브가 될 수 있어요.
데이브로서, 당신은 좋아하는 상상의 대기업에서 비즈니스 라인을 운영하고 있습니다.
최신 트렌드도 잘 파악하고, 젊은 세대와도 잘 어울리며, 애플리케이션과 마이크로서비스를 모두 OpenShift에 배포합니다.
그리고 Ingress로는 Kubernetes용 NGINX Plus Ingress Controller를 사용합니다.
모든 애플리케이션은 OpenShift 프로젝트(네임스페이스)로 배포되고,
NGINX Plus Ingress Controller는 자체적인 Ingress 네임스페이스에서 실행됩니다.
기본적인 Ingress 사양에서 제공하는 기능에 만족하지 못했고, ConfigMap과 Annotations은 다소 번거롭다고 생각했죠.
그래서 NGINX가 NGINX Plus Ingress Controller에서 자체 CRD 지원을 시작한다고 발표했을 때 아주 기뻤습니다.
오늘날, 애플리케이션 개발자들은 VirtualServer와 VirtualServerRoute 리소스를 사용하여
NGINX Plus Ingress Controller에 애플리케이션을 배포하고, OpenShift 내에서 내부 라우팅과 오류 처리를 구성하고 있습니다.
때때로 NGINX Plus Ingress Controller는 TransportServer라는 사용자 정의 리소스를 사용해 HTTP가 아닌 서비스를 노출하기도 합니다.
개발자들은 자신만의 프로젝트 네임스페이스에서 이러한 사용자 정의 리소스를 정의하고,
NGINX Plus Ingress Controller가 이를 선택하여 즉시 적용할 수 있습니다.
정말 멋지긴 하지만, OpenShift 클러스터의 가장자리에서
외부 네트워크 로드 밸런서를 쉽게 관리할 수 있으면 좋겠다고 생각하셨을 겁니다.
Ingress 계층을 확장해야 할 때마다 늘 고민이 생기죠.
어느 토요일 밤, 디스코에서 신나게 춤을 추고 있어야 할 시간인데, 어제는 Ingress 계층을 다시 조정해야 해서 허리가 아파옵니다.
그때 갑자기 연기 구름 속에서 요정 대모인 수잔이 나타납니다.
"안녕, 데이브!" 그녀가 말합니다.
당신은 놀라며 대답합니다. "당신은 누구야? 내 페르시아 카펫에 무슨 짓을 한 거야?"
수잔은 당신의 반응을 무시한 채, GitHub에서 사용할 수 있는 NGINX-LB-Operator에 대해 이야기하기 시작합니다.
그녀는 OpenShift의 가장자리에 배치된 NGINX Plus 클러스터를 NGINX Controller를 사용해 애플리케이션 중심으로 관리하며,
이를 통해 NGINX Plus 로드 밸런서를 구성하는 방법을 정의하는 사용자 정의 리소스를 만들 수 있다는 점을 설명합니다.
NGINX -LB-Operator는 이러한 리소스를 감시하고 이를 사용하여 애플리케이션 중심 구성을 NGINX Controller로 전송합니다.
그러면 NGINX Controller가 필요한 NGINX Plus 구성을 생성하여 외부 NGINX Plus 로드 밸런서로 푸시합니다.
최종 사용자는 귀하의 애플리케이션에 즉시 액세스할 수 있으며,
귀하는 외부 NGINX Plus 로드 밸런서를 수정해야 하는 변경 사항을 제어할 수 있습니다!
NGINX Controller는 외부 NGINX Plus 로드 밸런서에서 메트릭을 수집하여 이미 즐기고 있는 동일한 애플리케이션 중심 관점에서 제공합니다. 그리고 다음에 NGINX Plus Ingress 계층을 확장할 때 NGINX-LB-Operator가 NGINX Controller와 외부 NGINX Plus 로드 밸런서를 자동으로 업데이트합니다. 더 이상 허리 통증이 없습니다!
결론
쿠버네티스는 컨테이너화된 애플리케이션을 관리하기 위해 구축된 플랫폼입니다.
NGINX Controller는 애플리케이션 로드 밸런싱을 생각하고 관리하기 위한 애플리케이션 중심 모델을 제공합니다.
NGINX-LB-Operator는 두 가지를 결합하여 기본 인프라에 대해 걱정할 필요 없이 전체 스택을 엔드투엔드로 관리할 수 있도록 합니다.
NGINX-LB-Operator 에 대한 자세한 기술 정보 와 전체 샘플 워크스루는 GitHub 로 이동하세요 .
당사의 솔루션에 대해 자세히 알아보세요:
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
최근 몇 개의 블로그 게시물에서 애플리케이션을 마이크로서비스의 집합으로 개발 및 배포하는
4계층 애플리케이션 아키텍처를 채택하는 것이 중요한 이유를 설명한 바 있습니다.
10년 전에도 잘 작동했던 개발 프로세스와 애플리케이션 아키텍처를 계속 사용한다면
점점 더 많은 앱 중에서 선택할 수 있는 모바일 사용자의 관심을 사로잡고 유지할 수 없다는 사실이 점점 더 분명해지고 있습니다.
마이크로서비스 아키텍처로 전환하면 기업들은 시장에서 흥미로운 기회를 창출할 수 있습니다.
시스템 설계자와 개발자에게는 고객에게 혁신적인 새로운 웹 경험을 제공할 때 전례 없는 수준의 제어와 속도를 약속합니다.
하지만 이렇게 숨 가쁜 속도에서는 오류가 발생할 여지가 많지 않은 것처럼 느껴질 수 있습니다.
현실에서는 앱 개발과 배포를 중단할 수 없으므로 이를 위한 프로세스를 재구축해야 합니다.
미래의 성공이 마이크로서비스 아키텍처로의 전환에 달려 있다는 것을 알고 있지만
실제로는 어떻게 해야 할까요?
다행히도 마이크로서비스의 여러 얼리어답터들이 공개 코드뿐만 아니라
컨퍼런스 프레젠테이션과 블로그 게시물을 통해
오픈 소스 정신에 입각하여 전문 지식을 아낌없이 공유하고 있습니다.
Netflix가 대표적인 예입니다. 웹 엔지니어링 디렉터와 클라우드 아키텍트를 역임한
Adrian Cockcroft는 100명의 엔지니어가 모놀리식 DVD 대여 애플리케이션을 제작하는
기존 개발 모델에서 매일 수백만 명의 Netflix 고객에게 디지털 엔터테인먼트를 스트리밍하는
수백 개의 마이크로서비스 엔드투엔드 개발을 담당하는 여러 소규모 팀이 함께 일하는
마이크로서비스 아키텍처로 전환하는 과정을 감독했습니다.
현재 배터리 벤처스의 기술 펠로우인 콕크로프트는 마이크로서비스 및 클라우드 네이티브 아키텍처의 저명한 전도사이며
NGINX 기술 자문위원회에서 활동하고 있습니다.
2부로 구성된 블로그 게시물 시리즈에서는 작년 10월에 열린 첫 번째 연례 NGINX 컨퍼런스와
몇 달 전 실리콘밸리 마이크로서비스 밋업에서 콕크로프트가 발표한 두 강연의 주요 내용을 소개합니다.
(전체 동영상 녹화본도 시청할 가치가 있습니다.)
마이크로서비스 아키텍처란 무엇인가요?
콕크로프트는 마이크로서비스 아키텍처를 경계가 있는 느슨하게 결합된 요소로 구성된 서비스 지향 아키텍처로 정의합니다.
<느슨하게 결합되어 있다는 것은 서비스를 독립적으로 업데이트할 수 있고, 한 서비스를 업데이트해도
다른 서비스를 변경할 필요가 없다는 것을 의미합니다.
소규모의 전문화된 서비스가 여러 개 있지만 함께 업데이트해야 하는 경우
느슨하게 결합되어 있지 않으므로 마이크로 서비스가 아닙니다.
마이크로서비스 아키텍처로 전환할 때 사람들이 간과하기 쉬운 결합 유형 중 하나는 데이터베이스 결합으로,
모든 서비스가 동일한 데이터베이스에 연결되고 서비스를 업데이트하려면 스키마를 변경해야 합니다.
데이터베이스를 분할하고 비정규화해야 합니다.
바운드 컨텍스트라는 개념은 Eric Evans의 도메인 중심 설계라는 책에서 유래했습니다.
컨텍스트가 올바르게 바인딩된 마이크로서비스는 소프트웨어 개발 목적에 따라 독립적입니다.
마이크로서비스와 그 동료는 API를 통해 엄격하게 상호 작용하므로
데이터 구조, 데이터베이스 스키마 또는 기타 객체의 내부 표현을 공유하지 않으므로
동료의 내부에 대해 전혀 몰라도 마이크로서비스의 코드를 이해하고 업데이트할 수 있습니다.
인터넷용 애플리케이션을 개발해 본 적이 있다면 이름만 다르지 실제로는 이러한 개념에 이미 익숙할 것입니다.
대부분의 모바일 앱은 사용자가 앱의 컨텍스트 내에서
Facebook에서 공유하고, Google 지도에서 길을 찾고, Foursquare에서 레스토랑을 찾는 등의
작업을 수행할 수 있도록 꽤 많은 백엔드 서비스와 통신합니다.
모바일 앱이 이러한 서비스와 긴밀하게 연결되어 있다면
업데이트를 릴리스하기 전에 모든 개발 팀과 상의하여 변경 사항으로 인해 서비스가 중단되지 않는지 확인해야 합니다.
마이크로서비스 아키텍처로 작업할 때는 인터넷 백엔드와 같은 다른 내부 개발 팀을
마이크로서비스가 API를 통해 상호 작용하는 외부 서비스로 생각하면 됩니다.
마이크로서비스 간에 일반적으로 이해되는 '계약'은 API가 안정적이고 앞으로 호환된다는 것입니다.
Google 지도 API가 사용자에게 피해를 주는 방식으로 경고 없이 변경되는 것이 허용되지 않는 것처럼,
API는 발전할 수 있지만 이전 버전과 호환성을 유지해야 합니다.
마이크로서비스 아키텍처 설계를 위한 모범 사례
콕크로프트는 넷플릭스에서 클라우드 아키텍트로서 자신의 역할은 아키텍처를 제어하는 것이 아니라
넷플릭스 엔지니어들이 아키텍처를 구축하면서 떠오른 아키텍처를 발견하고 공식화하는 것이라고 설명합니다.
넷플릭스 개발팀은 마이크로서비스 아키텍처를 설계하고 구현하기 위한 몇 가지 모범 사례를 확립했습니다.
각 마이크로서비스에 대해 별도의 데이터 저장소 만들기
여러 마이크로서비스에서 동일한 백엔드 데이터 저장소를 사용하지 마세요.
각 마이크로서비스의 팀이 해당 서비스에 가장 적합한 데이터베이스를 선택하도록 해야 합니다.
게다가 단일 데이터 저장소를 사용하면 서로 다른 팀에서 작성한 마이크로서비스가 작업 중복을 줄인다는 명목으로
데이터베이스 구조를 공유하기가 너무 쉽습니다.
결국 한 팀이 데이터베이스 구조를 업데이트하면 해당 구조를 사용하는
다른 서비스도 함께 변경해야 하는 상황이 발생하게 됩니다.
데이터를 분리하면 별도의 저장 시스템이 더 쉽게 동기화되지 않거나 일관성이 없어지고
외래 키가 예기치 않게 변경될 수 있기 때문에 데이터 관리가 더 복잡해질 수 있습니다.
불일치를 찾아 수정하려면 백그라운드에서 작동하여 마스터 데이터 관리(MDM)를 수행하는 도구를 추가해야 합니다.
예를 들어, 가입자 ID를 저장하는 모든 데이터베이스를 검사하여
모든 데이터베이스에 동일한 ID가 존재하는지(한 데이터베이스에 누락되거나 여분의 ID가 없는지) 확인할 수 있습니다.
직접 도구를 작성하거나 도구를 구입할 수 있습니다.
많은 상용 관계형 데이터베이스 관리 시스템(RDBMS)이 이러한 종류의 검사를 수행하지만,
일반적으로 결합에 너무 많은 요구 사항을 부과하므로 확장되지 않습니다.
코드의 성숙도를 비슷한 수준으로 유지
마이크로서비스의 모든 코드를 비슷한 수준의 성숙도와 안정성으로 유지하세요.
즉, 잘 작동하는 배포된 마이크로서비스에서 일부 코드를 추가하거나 다시 작성해야 하는 경우
일반적으로 가장 좋은 방법은 기존 마이크로서비스는 그대로 두고
새 코드 또는 변경된 코드에 대한 새 마이크로서비스를 만드는 것입니다.
[편집자; - 이를 불변 인프라 원칙이라고도 합니다.]
이렇게 하면 기존 마이크로서비스에 장애나 성능 저하가 발생할 위험 없이 새 코드가 버그가 없고
최대한 효율적이 될 때까지 반복적으로 배포하고 테스트할 수 있습니다.
새 마이크로서비스가 기존 마이크로서비스만큼 안정적이면
두 마이크로서비스가 실제로 하나의 기능을 함께 수행하거나
결합을 통해 다른 효율성이 있는 경우 다시 병합할 수 있습니다.
하지만 콕크로프트의 경험에 따르면 마이크로서비스가 너무 커져서 분리해야 한다는 사실을 깨닫는 경우가 훨씬 더 흔합니다.
각 마이크로서비스에 대해 별도의 빌드 수행
각 마이크로서비스에 대해 별도의 빌드를 수행하여
리포지토리에서 해당 리비전 레벨에 맞는 컴포넌트 파일을 가져올 수 있도록 하세요.
이로 인해 여러 마이크로서비스가 비슷한 파일 집합을 가져오지만
서로 다른 리비전 레벨에서 가져오는 상황이 발생하기도 합니다.
이 경우 이전 파일 버전을 폐기하여 코드베이스를 정리하기가 더 어려워질 수 있지만
(리비전이 더 이상 사용되지 않는지 더 주의 깊게 확인해야 하므로),
새 마이크로서비스를 구축하면서 새 파일을 추가하는 것이 더 쉬워진다는 점을 감안하면 감수할 수 있는 절충안이 될 수 있습니다.
새로운 마이크로서비스, 파일 또는 함수를 도입하는 것이 위험하지 않고 쉽기를 바라는 의도적인 비대칭성입니다.
컨테이너에 배포
컨테이너에 마이크로서비스를 배포하는 것이 중요한 이유는 하나의 도구만 있으면
모든 것을 배포할 수 있기 때문입니다. 마이크로서비스가 컨테이너에 있는 한, 도구는 배포 방법을 알고 있습니다.
컨테이너가 무엇이든 상관없습니다. 그렇긴 하지만 Docker는 컨테이너의 사실상 표준으로 빠르게 자리 잡은 것 같습니다.
서버를 상태 비저장 상태로 취급
서버, 특히 고객 대면 코드를 실행하는 서버는 그룹의 상호 교환 가능한 멤버로 취급하세요.
서버는 모두 동일한 기능을 수행하므로 개별적으로 신경 쓸 필요가 없습니다.
필요한 작업량을 생산하기에 충분한 개수만 있으면 되고, 자동 스케일링을 사용하여 숫자를 위아래로 조정할 수 있습니다.
한 서버가 작동을 멈추면 자동으로 다른 서버로 대체됩니다.
특수 기능을 수행하기 위해 개별 서버에 의존하는 '눈송이' 시스템은 피하세요.
콕크로프트의 비유를 빌리자면 서버를 애완동물이 아닌 가축처럼 생각해야 한다는 것입니다.
특수한 기능을 수행하는 기계가 있고 이름만 들어도 알 수 있고,
그 기계가 고장 나면 모두가 슬퍼한다면 그 기계는 애완동물과 같이 소중해집니다.
대신 서버를 젖소통처럼 생각해야 합니다.
여러분은 몇 갤런의 우유가 나오는지를 신경씁니다.
어느 날 평소보다 우유가 적게 나오는 것을 발견하면 어떤 젖소가 잘 생산되지 않는지 알아내어 교체합니다.
NGINX를 기반으로 구축된 넷플릭스 전송 아키텍처
넷플릭스는 NGINX 오픈 소스의 오랜 사용자였으며 2011년 통합 이후 NGINX의 첫 번째 고객이 되었습니다.
실제로 넷플릭스는 전송 인프라의 핵심으로 세계 최대 규모의 콘텐츠 전송 네트워크(CDN) 중
하나인 Open Connect의 핵심으로 NGINX를 선택했습니다.
초당 수천, 때로는 수백만 건의 요청을 처리할 수 있는 NGINX와 NGINX;Plus는
고성능 HTTP 전송을 위한 최적의 솔루션으로 넷플릭스와 같은 기업이
매일 수백만 명의 고객에게 고품질 디지털 경험을 제공할 수 있도록 지원합니다.
nginx.conf 2014, 2014년 10월
마이크로서비스로 마이그레이션, 2부
실리콘밸리 마이크로서비스 밋업, 2014년 8월
마이크로서비스로 마이그레이션, 2부
실리콘밸리 마이크로서비스 밋업, 2014년 8월
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요.
전문가에게 상담받기
편집자 - 이제 7부로 구성된 이 시리즈 기사가 완성되었습니다.
또한 전체 문서와 NGINX를 사용하여 마이크로서비스를 구현하는 방법에 대한 정보를 전자책으로 다운로드할 수도 있습니다
- 마이크로서비스: 설계부터 배포까지. 또한 새로운 마이크로서비스 솔루션 페이지도 살펴보세요.
이 글은 마이크로서비스 아키텍처로 애플리케이션을 구축하는 방법에 대한 시리즈의 세 번째 글입니다.
첫 번째 문서에서는 마이크로서비스 아키텍처 패턴을 소개하고 이를 모놀리식 아키텍처 패턴과 비교하며
마이크로서비스 사용의 장점과 단점에 대해 논의합니다.
두 번째 글에서는 애플리케이션의 클라이언트가 API 게이트웨이라는 중개자를 통해 마이크로서비스와 통신하는 방법에 대해 설명합니다.
이 문서에서는 시스템 내의 서비스들이 서로 통신하는 방법을 살펴봅니다.
네 번째 글에서는 서비스 검색과 밀접한 관련이 있는 문제를 살펴봅니다.
소개
모놀리식 애플리케이션에서 구성 요소는 언어 수준의 메서드나 함수 호출을 통해 서로를 호출합니다.
이와 대조적으로 마이크로서비스 기반 애플리케이션은 여러 컴퓨터에서 실행되는 분산 시스템입니다.
각 서비스 인스턴스는 일반적으로 하나의 프로세스입니다.
따라서 다음 다이어그램에서 볼 수 있듯이 서비스는 프로세스 간 통신(IPC) 메커니즘을 사용하여 상호 작용해야 합니다.
나중에 구체적인 IPC 기술을 살펴보겠지만, 먼저 다양한 디자인 문제를 살펴보겠습니다.
상호 작용 스타일
서비스에 대한 IPC 메커니즘을 선택할 때는 먼저 서비스 상호 작용 방식을 고려하는 것이 유용합니다.
클라이언트⇔서비스 상호 작용 스타일은 다양합니다.
두 가지 차원으로 분류할 수 있습니다.
첫 번째 차원은 상호 작용이 일대일인지 일대다인지 여부입니다:
두 번째 차원은 상호 작용이 동기식인지 비동기식인지 여부입니다:
다음 표는 다양한 상호 작용 스타일을 보여줍니다.
일대일 상호작용에는 다음과 같은 종류가 있습니다:
요청/응답 - 클라이언트가 서비스에 요청을 하고 응답을 기다립니다.클라이언트는 응답이 적시에 도착하기를 기대합니다.
스레드 기반 애플리케이션에서는 요청을 하는 스레드가 대기하는 동안 차단될 수도 있습니다.
요청/비동기 응답 - 클라이언트가 서비스에 요청을 보내면 비동기적으로 응답합니다.
일대다 상호 작용에는 다음과 같은 종류가 있습니다:
각 서비스는 일반적으로 이러한 상호 작용 스타일을 조합하여 사용합니다.
일부 서비스의 경우 단일 IPC 메커니즘으로 충분합니다.
다른 서비스에서는 여러 IPC 메커니즘을 조합하여 사용해야 할 수도 있습니다.
다음 다이어그램은 사용자가 차량 호출을 요청할 때 택시 호출 애플리케이션의 서비스가 상호 작용하는 방식을 보여줍니다.
서비스는 알림, 요청/응답, 게시/구독의 조합을 사용합니다.
예를 들어, 승객의 스마트폰이 트립 관리 서비스에 알림을 전송하여 픽업을 요청합니다.
여행 관리 서비스는 요청/응답을 사용하여 승객 서비스를 호출하여 승객의 계정이 활성화되어 있는지 확인합니다.
그런 다음 여행 관리 서비스는 여행을 생성하고 게시/구독을 사용하여
사용 가능한 드라이버를 찾는 Dispatcher를 비롯한 다른 서비스에 알립니다.
이제 상호작용 스타일을 살펴보았으니 API를 정의하는 방법을 살펴보겠습니다.
API 정의하기
서비스의 API는 서비스와 클라이언트 간의 계약입니다.
어떤 IPC 메커니즘을 선택하든 일종의 인터페이스 정의 언어(IDL)를 사용하여 서비스의 API를 정확하게 정의하는 것이 중요합니다.
서비스를 정의할 때 API 우선 접근 방식을 사용하는 것이 좋다는 주장도 있습니다.
인터페이스 정의를 작성하고 클라이언트 개발자와 함께 검토하는 것으로 서비스 개발을 시작합니다.
API 정의에 대한 반복 작업을 거친 후에야 서비스를 구현할 수 있습니다.
이 설계를 미리 수행하면 클라이언트의 요구 사항을 충족하는 서비스를 구축할 가능성이 높아집니다.
이 글의 뒷부분에서 살펴보겠지만 API 정의의 성격은 사용 중인 IPC 메커니즘에 따라 달라집니다.
메시징을 사용하는 경우 API는 메시지 채널과 메시지 유형으로 구성됩니다.
HTTP를 사용하는 경우 API는 URL과 요청 및 응답 형식으로 구성됩니다.
나중에 몇 가지 IDL에 대해 더 자세히 설명하겠습니다.
진화하는 API
서비스의 API는 시간이 지남에 따라 항상 변합니다.
모놀리식 애플리케이션에서는 일반적으로 API를 변경하고 모든 호출자를 업데이트하는 것이 간단합니다.
마이크로서비스 기반 애플리케이션에서는 API의 모든 소비자가 동일한 애플리케이션의 다른 서비스라고 하더라도 훨씬 더 어렵습니다.
일반적으로 모든 클라이언트를 서비스와 함께 강제로 업그레이드할 수는 없습니다.
또한 서비스의 이전 버전과 새 버전이 동시에 실행되도록 서비스의 새 버전을 점진적으로 배포할 수도 있습니다.
이러한 문제를 처리하기 위한 전략을 세우는 것이 중요합니다.
API 변경을 처리하는 방법은 변경의 규모에 따라 다릅니다.
일부 변경 사항은 경미하며 이전 버전과 역호환됩니다.
예를 들어 요청이나 응답에 속성을 추가할 수 있습니다.
클라이언트와 서비스가 강건성 원칙을 준수하도록 설계하는 것이 좋습니다.
이전 API를 사용하는 클라이언트는 새 버전의 서비스에서 계속 작업해야 합니다.
서비스에서는 누락된 요청 속성에 대한 기본값을 제공하며 클라이언트는 추가 응답 속성을 무시합니다.
API를 쉽게 발전시킬 수 있는 IPC 메커니즘과 메시징 형식을 사용하는 것이 중요합니다.
하지만 때로는 호환되지 않는 API를 크게 변경해야 하는 경우도 있습니다.
클라이언트가 즉시 업그레이드하도록 강제할 수 없으므로 서비스에서 일정 기간 동안 이전 버전의 API를 지원해야 합니다.
REST와 같은 HTTP 기반 메커니즘을 사용하는 경우 URL에 버전 번호를 포함시키는 것도 한 가지 방법입니다.
각 서비스 인스턴스는 여러 버전을 동시에 처리할 수 있습니다.
또는 각각 특정 버전을 처리하는 다른 인스턴스를 배포할 수도 있습니다.
부분 장애 처리하기
API 게이트웨이에 대한 이전 문서인 .htmla<.htmla< 에서 언급했듯이
분산 시스템에서는 부분 장애의 위험이 항상 존재합니다.
클라이언트와 서비스는 별개의 프로세스이므로 서비스가 클라이언트의 요청에 적시에 응답하지 못할 수 있습니다.
장애 또는 유지보수로 인해 서비스가 다운될 수 있습니다.
또는 서비스가 과부하되어 요청에 매우 느리게 응답하고 있을 수 있습니다.
예를 들어 해당 문서의 제품 세부 정보 시나리오를 생각해 보세요.
추천 서비스가 응답하지 않는다고 가정해 봅시다.
클라이언트를 순진하게 구현하면 응답을 기다리며 무기한 차단될 수 있습니다.
이는 사용자 경험을 저하시킬 뿐만 아니라 많은 애플리케이션에서 스레드와 같은 귀중한 리소스를 소모하게 됩니다.
결국 다음 그림과 같이 런타임에 스레드가 부족하여 응답하지 않게 됩니다.
이 문제를 방지하려면 부분적인 장애를 처리하도록 서비스를 설계하는 것이 필수적입니다.
넷플릭스에서 설명하는 에 따라 접근하는 것이 좋습니다.
부분 장애를 처리하기 위한 전략은 다음과 같습니다:
넷플릭스 Hystrix는 이러한 패턴과 기타 패턴을 구현하는 오픈 소스 라이브러리입니다.
JVM을 사용하는 경우 Hystrix 사용을 반드시 고려해야 합니다.
또한, JVM이 아닌 환경에서 실행하는 경우 동등한 라이브러리를 사용해야 합니다.
IPC 기술
선택할 수 있는 다양한 IPC 기술이 있습니다.
서비스는 HTTP 기반 REST 또는 Thrift와 같은 동기식 요청/응답 기반 통신 메커니즘을 사용할 수 있습니다.
또는 AMQP나 STOMP와 같은 비동기 메시지 기반 통신 메커니즘을 사용할 수도 있습니다.
다양한 메시지 형식도 있습니다.
서비스는 JSON 또는 XML과 같이 사람이 읽을 수 있는 텍스트 기반 형식을 사용할 수 있습니다.
또는 Avro나 프로토콜 버퍼와 같은 이진 형식(더 효율적)을 사용할 수도 있습니다.
나중에 동기식 IPC 메커니즘에 대해 살펴보겠지만 먼저 비동기식 IPC 메커니즘에 대해 알아보겠습니다.
비동기 메시지 기반 통신
메시징을 사용할 때 프로세스는 비동기적으로 메시지를 교환하여 통신합니다.
클라이언트는 서비스에 메시지를 전송하여 요청을 합니다.
서비스에서 응답이 예상되면 클라이언트에 별도의 메시지를 다시 전송하여 응답합니다.
통신은 비동기식이기 때문에 클라이언트는 응답 대기를 차단하지 않습니다.
대신 클라이언트는 응답이 즉시 수신되지 않을 것을 가정하여 작성됩니다.
메시지는 헤더(보낸 사람 등의 메타데이터)와 메시지 본문으로 구성됩니다.
메시지는 채널을 통해 교환됩니다. 채널에 메시지를 보낼 수 있는 프로듀서의 수는 제한이 없습니다.
마찬가지로 채널에서 메시지를 받는 소비자도 얼마든지 가능합니다.
채널에는 point-to-point와 publish-subscribe의 두 가지 종류가 있습니다.
지점 간 채널은 채널에서 읽고 있는 소비자 중 정확히 한 명에게 메시지를 전달합니다.
서비스는 앞서 설명한 일대일 상호 작용 스타일에 지점 간 채널을 사용합니다.
게시-구독 채널은 연결된 모든 소비자에게 각 메시지를 전달합니다.
서비스는 위에서 설명한 일대다 상호 작용 스타일에 게시-구독 채널을 사용합니다.
다음 다이어그램은 택시 호출 애플리케이션에서 게시-구독 채널을 사용하는 방법을 보여줍니다.
트립 관리 서비스는 게시-구독 채널에 트립 생성 메시지를 작성하여 디스패처와 같은 관심 있는 서비스에 새 트립에 대해 알립니다.
디스패처는 사용 가능한 드라이버를 찾아 다른 서비스에 드라이버 제안 메시지를 게시-구독 채널에 작성하여 알립니다.
선택할 수 있는 메시징 시스템은 여러 가지가 있습니다. 다양한 프로그래밍 언어를 지원하는 시스템을 선택해야 합니다.
일부 메시징 시스템은 AMQP 및 STOMP와 같은 표준 프로토콜을 지원합니다.
다른 메시징 시스템에는 독점적이지만 문서화된 프로토콜이 있습니다.
RabbitMQ, 아파치 및 카프카, 아파치 및 액티브MQ, NSQ 등 수많은 오픈 소스 메시징 시스템 중에서 선택할 수 있습니다.
높은 수준에서는 모두 어떤 형태의 메시지와 채널을 지원합니다.
모두 안정적이고 성능이 뛰어나며 확장성을 갖추기 위해 노력합니다.
그러나 각 브로커의 메시징 모델 세부 사항에는 상당한 차이가 있습니다.
메시징을 사용하면 많은 장점이 있습니다:
메시징은 이러한 차이를 매우 명확하게 보여주기 때문에 개발자가 보안에 대한 잘못된 인식을 갖지 않도록 합니다.
메시지 브로커의 가용성이 높아야 하며, 그렇지 않으면 시스템 안정성에 영향을 미칩니다.
각 요청 메시지에는 응답 채널 식별자와 상관관계 식별자가 포함되어야 합니다.
서비스는 상관관계 ID가 포함된 응답 메시지를 회신 채널에 씁니다.
클라이언트는 상관관계 ID를 사용하여 응답을 요청과 일치시킵니다.
요청/응답을 직접 지원하는 IPC 메커니즘을 사용하는 것이 더 쉬운 경우가 많습니다. 메시징 기반 IPC 사용에 대해 살펴봤으니 이제 요청/응답 기반 IPC에 대해 살펴보겠습니다.
동기식 요청/응답 기반 IPC 메커니즘을 사용하는 경우 클라이언트는 서비스에 요청을 보냅니다.
서비스는 요청을 처리하고 응답을 다시 보냅니다.
많은 클라이언트에서 요청을 만드는 스레드는 응답을 기다리는 동안 차단됩니다.
다른 클라이언트는 선물 또는 Rx Observables로 캡슐화된 비동기 이벤트 중심 클라이언트 코드를 사용할 수도 있습니다.
그러나 메시징을 사용할 때와 달리 클라이언트는 응답이 적시에 도착할 것이라고 가정합니다.
선택할 수 있는 프로토콜은 다양합니다. 널리 사용되는 두 가지 프로토콜은 REST와 중고품입니다.
먼저 REST에 대해 살펴보겠습니다.
REST
오늘날에는 RESTful 스타일로 API를 개발하는 것이 유행입니다.
REST는 (거의 항상) HTTP를 사용하는 IPC 메커니즘입니다.
REST의 핵심 개념은 리소스이며, 일반적으로 고객이나 제품과 같은 비즈니스 개체 또는 비즈니스 개체 모음을 나타냅니다.
REST는 URL을 사용하여 참조되는 리소스를 조작하기 위해 HTTP 동사를 사용합니다.
예를 들어, GET 요청은 리소스의 표현을 반환하며, 이는 XML 문서 또는 JSON 객체의 형태일 수 있습니다.
POST 요청은 새 리소스를 생성하고 PUT 요청은 리소스를 업데이트합니다.
REST의 창시자인 Roy 필딩의 말을 인용하면 다음과 같습니다:
다음 다이어그램은 택시 호출 애플리케이션에서 REST를 사용할 수 있는 방법 중 하나를 보여줍니다.
승객의 스마트폰이 여행 관리 서비스의 POST 리소스에 /trips 요청을 하여 여행을 요청합니다.
이 서비스는 승객에 대한 정보를 요청하는 GET 요청을 승객 관리 서비스로 전송하여 요청을 처리합니다.
승객이 여행을 생성할 권한이 있는지 확인한 후, 여행 관리 서비스는 여행을 생성하고 스마트폰에 201 응답을 반환합니다.
많은 개발자가 자신의 HTTP 기반 API가 RESTful이라고 주장합니다.
하지만 Fielding이 이 블로그 게시물에서 설명한 것처럼 실제로는 모두 그런 것은 아닙니다.
Leonard Richardson(관계 없음)은 다음 단계로 구성된 매우 유용한 rest 성숙도 모델을 정의합니다.
HTTP 기반 프로토콜을 사용하면 많은 이점이 있습니다:
HTTP 사용에는 몇 가지 단점이 있습니다:
개발자 커뮤니티는 최근 RESTful API를 위한 인터페이스 정의 언어의 가치를 재발견했습니다.
RAML 및 Swagger 등 몇 가지 옵션이 있습니다.
Swagger와 같은 일부 IDL을 사용하면 요청 및 응답 메시지의 형식을 정의할 수 있습니다.
RAML과 같은 다른 IDL은 JSON 스키마와 같은 별도의 사양을 사용해야 합니다.
API를 설명할 뿐만 아니라 IDL에는 일반적으로 인터페이스 정의에서 클라이언트 스텁과 서버 골격을 생성하는 도구가 있습니다.
중고품
아파치 중고품는 REST의 흥미로운 대안입니다. 크로스 언어 RPC 클라이언트와 서버를 작성하기 위한 프레임워크입니다.
Thrift는 API를 정의하기 위한 C 스타일 IDL을 제공합니다.
Thrift 컴파일러를 사용해 클라이언트 측 스텁과 서버 측 스켈레톤을 생성할 수 있습니다.
컴파일러는 C++, Java, Python, PHP, Ruby, Erlang, Node.js 등 다양한 언어에 대한 코드를 생성합니다.
중고품 인터페이스는 하나 이상의 서비스로 구성됩니다. 서비스 정의는 Java 인터페이스와 유사합니다.
강력한 타입의 메서드 모음입니다. 중고품 메서드는 (무효일 수 있는) 값을 반환하거나 단방향으로 정의할 수 있습니다.
값을 반환하는 메서드는 요청/응답 스타일의 상호작용을 구현합니다. 클라이언트는 응답을 기다리며 예외를 발생시킬 수 있습니다.
단방향 메서드는 상호 작용의 알림 스타일에 해당합니다.
서버가 응답을 보내지 않습니다.
중고품은 다양한 메시지 형식을 지원합니다: JSON, 바이너리, 압축 바이너리.
바이너리는 디코딩 속도가 빠르기 때문에 JSON보다 효율적입니다.
그리고 이름에서 알 수 있듯이 압축 바이너리는 공간 효율적인 형식입니다.
물론 JSON은 인간과 브라우저 친화적입니다.
또한 Thrift는 원시 TCP와 HTTP를 포함한 전송 프로토콜을 선택할 수 있습니다.
원시 TCP가 HTTP보다 더 효율적일 가능성이 높습니다. 하지만 HTTP는 방화벽, 브라우저, 인간 친화적입니다.
메시지 형식
HTTP와 중고품에 대해 살펴봤으니 이제 메시지 형식에 대해 살펴봅시다.
메시징 시스템이나 REST를 사용하는 경우 메시지 형식을 선택할 수 있습니다.
Thrift와 같은 다른 IPC 메커니즘은 소수의 메시지 형식만 지원할 수도 있습니다.
어떤 경우든 언어 간 메시지 형식을 사용하는 것이 중요합니다.
현재 단일 언어로 마이크로서비스를 작성하고 있더라도 향후에는 다른 언어를 사용할 가능성이 높습니다.
메시지 형식에는 텍스트와 바이너리의 두 가지 주요 유형이 있습니다.
텍스트 기반 형식의 예로는 JSON과 XML이 있습니다.
이러한 형식의 장점은 사람이 읽을 수 있을 뿐만 아니라 자체적으로 설명할 수 있다는 것입니다.
JSON에서 객체의 속성은 이름-값 쌍의 컬렉션으로 표현됩니다.
마찬가지로 XML에서는 속성이 명명된 요소와 값으로 표현됩니다.
이를 통해 메시지 소비자는 관심 있는 값만 골라내고 나머지는 무시할 수 있습니다.
따라서 메시지 형식의 사소한 변경 사항도 쉽게 이전 버전과 호환될 수 있습니다.
XML 문서의 구조는 XML 스키마에 의해 지정됩니다.
시간이 지남에 따라 개발자 커뮤니티는 JSON에도 유사한 메커니즘이 필요하다는 사실을 깨닫게 되었습니다.
한 가지 옵션은 독립적으로 또는 Swagger와 같은 IDL의 일부로 JSON 스키마를 사용하는 것입니다.
텍스트 기반 메시지 형식을 사용할 때의 단점은 메시지가 장황한 경향이 있다는 것입니다(특히 XML).
메시지가 자체적으로 설명되기 때문에 모든 메시지에는 값과 함께 속성 이름이 포함됩니다.
또 다른 단점은 텍스트 구문 분석의 오버헤드입니다. 따라서 바이너리 형식 사용을 고려할 수 있습니다.
선택할 수 있는 바이너리 형식은 여러 가지가 있습니다. 중고품 RPC를 사용하는 경우 바이너리 중고품을 사용할 수 있습니다.
메시지 형식을 선택할 때 많이 사용되는 옵션으로는 Protocol Buffers와 Apache Avro가 있습니다.
이 두 형식 모두 메시지 구조를 정의하기 위한 유형화된 IDL을 제공합니다.
그러나 한 가지 차이점은 프로토콜 버퍼는 태그가 지정된 필드를 사용하는 반면,
Avro 소비자는 메시지를 해석하기 위해 스키마를 알아야 한다는 점입니다.
따라서 API 진화는 Avro보다 프로토콜 버퍼를 사용하는 것이 더 쉽습니다.
이 블로그 게시물은 Thrift, Protocol, Buffers, Avro를 비교한 훌륭한 글입니다.
요약
마이크로서비스는 프로세스 간 통신 메커니즘을 사용하여 통신해야 합니다.
서비스의 통신 방식을 설계할 때는 서비스 상호 작용 방식, 각 서비스의 API를 지정하는 방법, API를 발전시키는 방법,
부분 장애를 처리하는 방법 등 다양한 문제를 고려해야 합니다.
마이크로서비스가 사용할 수 있는 IPC 메커니즘에는 비동기 메시징과 동기 요청/응답의 두 가지 종류가 있습니다.
시리즈의 다음 글에서는 마이크로서비스 아키텍처에서 서비스 검색 문제를 살펴보겠습니다.
편집자 - 이제 이 7부작 시리즈 기사가 완료되었습니다:
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
전문가에게 상담받기
'
쿠버네티스는 Google에서 클러스터에서 컨테이너화된 마이크로서비스 기반 애플리케이션을 실행하고
관리하기 위해 개발한 오픈 소스 시스템입니다. 쿠버네티스를 사용하는 사람들은
종종 쿠버네티스에서 만든 서비스를 쿠버네티스 클러스터 외부에서 액세스할 수 있도록 해야 합니다.
Kubernetes는 아래의 내장 솔루션을 사용하여 Kubernetes 서비스 노출 에서
설명한 대로 서비스를 노출하기 위한 내장 솔루션을 제공 하지만 ,
해당 솔루션은 레이어 4 부하 분산 또는 라운드 로빈 HTTP 부하 분산으로 제한됩니다.
이 게시물에서는 클라우드에서 Kubernetes를 실행하든 자체 인프라에서 실행하든
Kubernetes 서비스를 인터넷에 노출하기 위한 고급 Layer 7 로드 밸런싱 솔루션으로 NGINX Plus를 사용하는 방법을 보여줍니다 .
Kubernetes(포드, 서비스, 복제 컨트롤러 및 레이블)와 실행 중인 Kubernetes 클러스터에 대한 기본적인 이해가 있다고 가정합니다.
Kubernetes에 대해 자세히 알아보려면 공식 Kubernetes 사용자 가이드를 참조하세요 .
내장 솔루션을 사용하여 Kubernetes 서비스 노출
쿠버네티스는 서비스를 노출하기 위한 여러 옵션을 제공합니다 .
그 중 두 가지(NodePort와 LoadBalancer)는 특정 유형의 서비스에 해당합니다.
세 번째 옵션인 Ingress API는 쿠버네티스 릴리스 1.1에서 베타로 제공되었습니다.
노드포트
서비스 유형을 NodePort 로 지정하면 각 Kubernetes 노드에서 동일한 포트에서 서비스를 사용할 수 있습니다.
서비스를 인터넷에 노출하려면 해당 포트에서 하나 이상의 노드를 노출합니다.
고가용성을 위해 여러 노드를 노출하고 DNS 기반 로드 밸런싱을 사용하여
트래픽을 분산하거나 노드를 선택한 로드 밸런서 뒤에 배치할 수 있습니다.
들어오는 트래픽이 포트의 노드에 도달하면 서비스의 포드 간에 로드 밸런싱이 이루어집니다.
kube-proxy모든 노드에서 실행되는 Kubernetes 네트워크 프록시( )가 수행하는 로드 밸런싱은 TCP/UDP 로드 밸런싱으로 제한됩니다.
로드 밸런서
서비스 유형을 LoadBalancer 로 지정하면 서비스의 Pod 간에 수신 트래픽을 분산하는 클라우드 로드 밸런서가 할당됩니다.
LoadBalancer 솔루션은 특정 클라우드 공급자와 Google Container Engine 에서만 지원되며
자체 인프라에서 Kubernetes를 실행하는 경우 사용할 수 없습니다.
또한 Kubernetes에서는 클라우드 로드 밸런서에 세션 지속성이나
요청 매핑과 같은 고급 기능이 있더라도 라운드 로빈 TCP 로드 밸런싱만 구성할 수 있습니다.
인그레스 API
Ingress 리소스를 생성하면 사용자 지정 URL(예: URL /foo 에서 서비스 A , URL /bar 에서 서비스 B )과
여러 가상 호스트 이름(예: 한 서비스 그룹의 경우 foo.example.com , 다른 그룹의 경우 bar.example.com )에서
서비스를 인터넷에 노출할 수 있습니다.
Ingress 컨트롤러는 Ingress 리소스를 사용하고 외부 로드 밸런서를 설정합니다.
Ingress 컨트롤러는 표준 Kubernetes 배포의 일부가 아닙니다.
필요에 가장 적합한 컨트롤러를 선택하거나 직접 구현하여 Kubernetes 클러스터에 추가해야 합니다.
많은 컨트롤러 구현이 곧 나타날 것으로 예상되지만 현재 유일하게 사용 가능한 구현은
Google Compute Engine HTTP Load Balancer용 컨트롤러로 ,
Google Compute Engine 또는 Google Container Engine 에서 Kubernetes를 실행하는 경우에만 작동합니다.
Ingress API는 실제 로드 밸런서가 고급 기능을 지원하더라도 라운드 로빈 HTTP 로드 밸런싱만 지원합니다.
이 글을 쓰는 시점에서 Ingress API와 Google Compute Engine HTTP 부하 분산 장치용 컨트롤러는 모두 베타 버전입니다.
업데이트 – NGINX와 NGINX Plus를 위한 NGINX Ingress Controller가 이제 GitHub 저장소 에서 제공됩니다 .
제품 세부 정보는 NGINX Ingress Controller를 참조하세요 .
위에서 언급한 솔루션은 설정이 간단하고 바로 사용할 수 있지만
특히 7계층 부하 분산과 관련된 기능을 비롯하여 고급 기능을 제공하지 않습니다.
NGINX Plus로 Kubernetes 서비스 노출
[편집자 - 이 섹션은 원래 여기에서 논의된 별도의 동적 구성 모듈을 대체하고 더 이상 사용되지 않는 NGINX Plus API를 참조하도록 업데이트되었습니다 .]
NGINX Plus를 Kubernetes와 통합하려면 NGINX Plus 구성이 Kubernetes와 동기화되어
Pod 추가 또는 삭제와 같은 Kubernetes 서비스의 변경 사항을 반영해야 합니다.
NGINX Open Source를 사용하면 NGINX 구성 파일을 수동으로 수정하고 구성을 다시 로드할 수 있습니다.
NGINX Plus를 사용하면 구성을 동적으로 업데이트하는 두 가지 방법이 있습니다.
API 사용 - 이 방법은 NGINX Plus API를 사용하여 NGINX Plus 구성에서Kubernetes API를 사용하여 포드의 IP 주소를 검색합니다.
이 방법을 사용하려면 코드를 작성해야 하며 여기서는 자세히 설명하지 않습니다.
자세한 내용은 Kelsey Hightower의 웨비나 Bringing Kubernetes to the Edge with NGINX Plus를 시청하세요 .
여기서 그는 API를 탐색하고 이를 활용하는 애플리케이션을 만듭니다.
DNS 이름을 다시 확인 하여 – 이 방법은 다음 섹션에 설명된 대로 NGINX Plus의 적절한 일회성 구성만 필요합니다.
DNS 기반 재구성 활용
이미 실행 중인 Kubernetes 클러스터와 kubectl클러스터를 관리하는 데
사용할 수 있는 유틸리티가 있는 호스트가 있다고 가정합니다.
지침은 클러스터 유형에 대한 Kubernetes 시작 가이드를 참조하세요 .
또한 NGINX Plus Docker 이미지를 빌드해야 하며,
지침은 블로그의 Docker를 사용하여 NGINX 및 NGINX Plus 배포 에서 확인할 수 있습니다.
우리가 할 일의 개요는 다음과 같습니다.
참고 사항: 이 블로그에 설명된 솔루션을 Google Compute Engine에서 실행되는
Kubernetes 1.0.6 과 로컬 Vagrant 설정(아래에서 사용)으로 테스트했습니다.
명령에서 Kubernetes 설정에 따라 다를 수 있는 값은 기울임꼴로 표시됩니다.
NGINX Plus Pod 구성
우리는 인터넷에 노출된 노드의 Kubernetes 포드에 NGINX Plus를 넣고 있습니다.
우리의 포드는 우리가 또한 설정하고 있는 복제 컨트롤러에 의해 생성됩니다.
우리의 Kubernetes 특정 NGINX Plus 구성 파일은 NGINX Plus 포드와 노드 간
공유되는 폴더에 상주하여 유지 관리가 더 간단합니다.
NGINX Plus Pod를 호스팅할 노드 선택
NGINX Plus pod가 실행되는 노드를 지정하기 위해 해당 노드에 레이블을 추가합니다.
다음을 실행하여 모든 노드 목록을 가져옵니다.
첫 번째 노드를 선택하고 다음을 실행하여 레이블을 추가합니다.
$ kubectl label node 10.245.1.3 role=nginxplusNGINX Plus Pod에 대한 복제 컨트롤러 구성
우리는 NGINX Plus 포드를 직접 생성하지 않고 복제 컨트롤러를 통해 생성합니다.
nginxplus-rc.yaml 이라는 Kubernetes 선언 파일에서 NGINX Plus 포드에 대한 복제 컨트롤러를 구성합니다 .
폴더를 공유하면 컨테이너 이미지를 다시 빌드하지 않고도 NGINX Plus를 재구성할 수 있습니다.
apiVersion: v1kind: ReplicationController metadata: name: webapp-rc spec: replicas: 2 selector: app: webapp template: metadata: labels: app: webapp spec: containers: - name: hello image: nginxdemos/hello ports: - containerPort: 80노드에서 NGINX Plus Docker 이미지 사용 가능
위에서 말했듯이, 우리는 이미 NGINX Plus Docker 이미지를 빌드했습니다.
이제 노드에서 사용할 수 있도록 합니다. 단순성을 위해 개인 Docker 저장소를 사용하지 않고
이미지를 노드에 수동으로 로드합니다.
Docker 이미지를 빌드한 호스트에서 다음 명령을 실행하여 이미지를 파일에 저장합니다.
$ docker save -o nginxplus.tar nginxplusnginxplus.tar를 노드로 전송하고 , 노드에서 다음 명령을 실행하여 파일에서 이미지를 로드합니다.
$ docker load -i nginxplus.tarNGINX Plus 구성
NGINX Plus 컨테이너의 /etc/nginx 폴더에서 NGINX Plus 패키지와 함께 제공되는 기본 주 nginx.conf 구성 파일을 유지합니다.
기본 파일의 지시문은 /etc/nginx/conf.dinclude 폴더 에서 다른 구성 파일을 읽습니다 .
NGINX Plus 복제 컨트롤러( nginxplus-rc.yaml ) 의 선언 파일 에 지정된 대로
NGINX Plus 노드의 /etc/nginx/conf.d 폴더를 컨테이너와 공유합니다.
공유는 컨테이너에서 직접 폴더를 만든 경우 해야 하는 NGINX Plus Docker 이미지를 다시 빌드하지 않고도
폴더(노드)에 저장된 구성 파일을 변경할 수 있음을 의미합니다.
공유 폴더에 Kubernetes 특정 구성 파일( backend.conf )을 넣습니다.
먼저 노드에 /etc/nginx/conf.d 폴더를 만들어 보겠습니다 .
$ sudo mkdir -p /etc/nginx/conf.d그런 다음 해당 위치에 backend.conf 파일을 만들고 다음 지침을 포함합니다.
resolver – NGINX Plus가 업스트림 서버를 식별하는 데 사용하는 도메인 이름을 주기적으로 재확인하는 데 사용하는 DNS 서버를 정의합니다(다음 글머리 기호에서 설명하는 블록 server내부의 지시문 ). 이 DNS 서버를 도메인 이름인 kube-dns.kube-system.svc.cluster.localupstream 로 식별합니다 . 이 매개변수는 NGINX Plus에 5초마다 재확인 요청을 보내라고 지시합니다.valid
(이 지시어에 대한 확인 프로세스는 업스트림 서버의 확인 프로세스와 다릅니다. 이 도메인 이름은 NGINX가 시작되거나 다시 로드될 때만 확인되고, NGINX Plus는 /etc/resolv.conf 파일에 정의된 시스템 DNS 서버를 사용하여 이를 확인합니다.)
upstream– 우리가 노출하는 Kubernetes 서비스를 제공하는 서버를 포함하는 백엔드 라는 업스트림 그룹을 만듭니다 . 서버를 개별적으로 나열하는 대신, 단일 server지시문에서 완전히 정규화된 호스트 이름으로 식별합니다. 이 resolve매개변수는 NGINX Plus에 지시문으로 지정된 설정에 따라 런타임에 호스트 이름을 다시 확인하도록 지시합니다 resolver.
Kubernetes DNS와 NGINX Plus(R10 이상)는 모두 DNS 서비스( SRV) 레코드를 지원하므로 NGINX Plus는 DNS를 통해 업스트림 서버의 포트 번호를 가져올 수 있습니다. serviceNGINX Plus 요청 레코드를 갖도록 매개변수를 포함하여 서비스에서 노출된 포트에 대한 SRV이름( _http)과 프로토콜( )을 지정합니다. 아래 서비스에 대한 복제 컨트롤러 생성 에서 설명한 webapp-svc.yaml_tcp 파일 에 해당 값을 선언합니다 .
DNS를 사용한 서비스 검색에 대한 자세한 내용은 블로그의 NGINX 및 NGINX Plus에서 DNS를 사용하여 서비스 검색을 참조하세요.
server(2회) – 두 개의 가상 서버를 정의합니다.
첫 번째 서버는 포트 80에서 수신하고 /webapp (우리 서비스)에 대한 들어오는 요청을 서비스 인스턴스를 실행하는 포드 간에 로드 밸런싱합니다. 또한 활성 상태 검사를 설정합니다 .
두 번째 서버는 포트 8080에서 수신합니다. 여기서 NGINX Plus의 라이브 활동 모니터링을 설정합니다 .
나중에 NGINX Plus가 제대로 재구성되었는지 확인하는 데 사용합니다.
[편집자 - 이 두 번째 서버의 구성은 원래 사용되었던 별도의 상태 모듈을 대체하고 더 이상 사용되지 않는 NGINX Plus API를 사용하도록 업데이트되었습니다 .]
복제 컨트롤러 생성
이제 다음 명령을 실행하여 복제 컨트롤러를 생성할 준비가 되었습니다.
$ kubectl create -f nginxplus-rc.yamlNGINX Plus Pod가 생성되었는지 확인하려면 다음을 실행합니다.
$ kubectl get pods NAME READY STATUS RESTARTS AGE nginxplus-rc-0ts5t 1/1 Running 0 17s로컬 Vagrant 설정에서 Kubernetes를 실행하고 있으므로 노드의 외부 IP 주소가 10.245.1.3임을 알고 있으며
이 예제의 나머지 부분에서 해당 주소를 사용할 것입니다.
클라우드 공급자에서 Kubernetes를 실행하는 경우 다음을 실행하여 노드의 외부 IP 주소를 가져올 수 있습니다.
클라우드에서 실행 중이라면 NGINX Plus 노드가 들어오는 트래픽을 허용하도록 방화벽 규칙을 설정하는 것을 잊지 마세요.
클라우드 제공자의 설명서를 참조하세요.
NGINX Plus pod가 작동 중인지 확인하려면 노드의 외부 IP 주소(예: http://10.245.1.3:8080/dashboard.html )에서
포트 8080에서 사용할 수 있는 NGINX Plus 라이브 활동 모니터링 대시보드를 보면 됩니다.
하지만 이 지점을 살펴보면 아직 서비스를 만들지 않았기 때문에 서비스에 대한 서버가 보이지 않습니다.
간단한 쿠버네티스 서비스 만들기
이제 Kubernetes 서비스를 만들 시간입니다. 저희 서비스는 두 개의 웹 서버로 구성되어 있으며,
각각은 실행 중인 컨테이너에 대한 정보가 있는 웹 페이지를 제공합니다.
서비스에 대한 복제 컨트롤러 생성
먼저 복제 컨트롤러를 생성하여 Kubernetes가 지정된 수의 웹 서버 복제본(포드)이 클러스터에서 항상 실행되도록 합니다.
다음은 선언 파일( webapp-rc.yaml )입니다.
apiVersion: v1kind: ReplicationController metadata: name: webapp-rc spec: replicas: 2 selector: app: webapp template: metadata: labels: app: webapp spec: containers: - name: hello image: nginxdemos/hello ports: - containerPort: 80컨트롤러는 두 개의 웹 서버로 구성되어 있습니다.
단일 컨테이너가 있는 포드로 구성된 컨트롤러를 선언하고 포트 80을 노출합니다.
nginxdemos/hello 이미지는 Docker Hub에서 가져옵니다.
복제 컨트롤러를 생성하려면 다음 명령을 실행합니다.
$ kubectl create -f webapp-rc.yaml포드가 생성되었는지 확인하려면 다음 명령을 실행할 수 있습니다.
레이블 선택기를 사용하여 app=webapp이전 단계에서 복제 컨트롤러가 생성한 포드만 가져옵니다.
서비스 생성
다음으로 복제 컨트롤러가 만든 포드에 대한 서비스를 만듭니다.
다음 파일( webapp-service.yaml )로 서비스를 선언합니다.
apiVersion: v1kind: Service metadata: name: webapp-svc spec: clusterIP: None ports: - port: 80 targetPort: 80 protocol: TCP name: http selector: app: webapp여기서는 필드를 .으로 설정하여 특별한 헤드리스 서비스를 선언합니다.
이 유형의 서비스에서는 클러스터 IP 주소가 할당되지 않고 kube 프록시를 통해 서비스를 사용할 수 없습니다.
Kubernetes DNS에 대한 DNS 쿼리는 여러 레코드(포드의 IP 주소)를 반환합니다.ClusterIPNoneA
또한 NGINX Plus가 포드를 연결하는 데 사용할 포트를 선언합니다.
포트와 대상 포트 번호를 지정하는 것 외에도 이름( http)과 프로토콜( TCP)을 지정합니다.
NGINX Plus 구성 파일에서 해당 값을 사용하여 NGINX Plus에 레코드를 사용하여
DNS를 통해 포드의 포트 번호를 가져오라고 지시합니다 SRV.
selector필드를 로 설정하면 app: webapp, 서비스에 속하는 Pod,
즉 NGINX 복제 컨트롤러( webapp-rc.yaml 에 정의됨 )에서 생성된 Pod를 선언합니다.
다음 명령을 실행하면 서비스가 생성됩니다.
$ kubectl create -f webapp-service.yaml이제 대시보드 페이지를 새로 고치고 오른쪽 상단 모서리에 있는 업스트림 탭을 클릭하면 추가한 두 개의 서버를 볼 수 있습니다.
NGINX Plus가 서비스의 포드 간에 트래픽을 로드 밸런싱하는지 확인할 수도 있습니다.
그렇다면 브라우저에서 http://10.245.1.3/webapp/ 에 액세스하면
해당 페이지에 호스트 이름과 IP 주소와 같이 웹 서버가 실행 중인 컨테이너에 대한 정보가 표시됩니다.
이 페이지를 여러 번 새로 고치고 상태 대시보드를 살펴보면 요청이 두 개의 상위 서버에 어떻게 분산되는지 확인할 수 있습니다.
쿠버네티스 서비스 확장
[편집자 - 이 섹션은 원래 사용되었던 별도의 상태 모듈을 대체하고 더 이상 사용하지 않는 NGINX Plus API를 사용하도록 업데이트되었습니다 .]
이제 서비스에 두 개의 포드를 더 추가하고 NGINX Plus 구성이 다시 자동으로 업데이트되는지 확인해 보겠습니다.
복제 컨트롤러를 확장하여 포드 수를 4개로 변경하기 위해 이 명령을 실행합니다.
$ kubectl scale rc webapp-rc --replicas=4 scaledNGINX Plus가 재구성되었는지 확인하기 위해 대시보드를 다시 볼 수 있지만
이번에는 대신 NGINX Plus API를10.245.1.3 사용합니다.
NGINX Plus 노드의 외부 IP 주소와 NGINX Plus API3 의 버전을 사용 하여 다음 명령을 실행합니다 .
JSON 출력을 깔끔하게 포맷하기 위해 .으로 파이프합니다.
$$ curl -s 10.245.1.3:8080/api/3/http/upstreams/backend/servers | jq{ "peers": [ { "id": 1, "server": "10.0.0.1:80", "backup": false, "weight": 1, "state": "unhealthy", "active": 0, "requests": 1, "responses": { "1xx": 0, "2xx": 0, "3xx": 0, "4xx": 0, "5xx": 0, "total": 0 }, "sent": 0, "received": 0, "fails": 0, "unavail": 0, "health_checks": { "checks": 1, "fails": 1, "unhealthy": 1, "last_passed": false }, "downtime": 33965, "downstart": 1445378182275, "selected": 1445378131000 }, { "id": 2, "server": "10.246.1.6:80", ... }, { "id": 3, "server": "10.246.3.2:80", ... { "id": 4, "server": "10.0.0.2:80", ... } ], "keepalive": 0 }JSON 출력의 배열 peers에는 웹 서버별로 하나씩, 총 4개의 요소가 정확히 있습니다.
이제 Pod 수를 4개에서 1개로 줄이고 NGINX Plus 상태를 다시 확인해 보겠습니다.
$ kubectl scale rc webapp-rc --replicas=1scaled $ curl -s 10.245.1.3:8080/api/3/http/upstreams/backend/servers | jq이제 peersJSON 출력의 배열에는 요소가 하나만 포함됩니다(출력은 이전 샘플 명령에서 ID가 1인 피어의 경우와 동일합니다).
이제 NGINX Plus를 구동하므로 세션 지속성 , SSL/TLS 종료 , 요청 라우팅 , 고급 모니터링 등 고급 기능 을 활용할 수 있습니다 .
요약
NGINX Plus에서 제공되는 즉석 재구성 옵션을 사용하면 API를 통한 프로그래밍 방식이나
DNS를 통한 완전한 방식으로 Kubernetes와 쉽게 통합할 수 있습니다.
NGINX Plus를 사용하여 Kubernetes 서비스를 인터넷에 노출하면
현재 기본 제공 Kubernetes 로드 밸런싱 솔루션에 없는 많은 기능을 제공합니다.
NGINX Plus가 Kubernetes와 함께 작동하는 방식을 알아보려면
오늘 무료 30일 평가판을 시작하거나 당사에 문의하여 사용 사례에 대해 논의하세요.
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요.
전문가에게 상담받기
또한 전체 문서와 NGINX를 사용한 마이크로서비스 구현에 대한 정보를 전자책으로 다운로드할 수도 있습니다.
- 마이크로서비스: 설계부터 배포까지. 마이크로서비스 참조 아키텍처 및 마이크로서비스 솔루션 페이지에서 시리즈를 참조하세요.
이 글은 마이크로서비스로 애플리케이션 구축에 대한 시리즈의 다섯 번째 글입니다.
첫 번째 글에서는 마이크로서비스 아키텍처 패턴을 소개하고 마이크로서비스 사용의 장점과 단점에 대해 설명합니다.
두 번째 글과 세 번째 글에서는 마이크로서비스 아키텍처 내 커뮤니케이션의 다양한 측면에 대해 설명합니다.
네 번째 글에서는 서비스 검색과 밀접하게 관련된 문제를 살펴봅니다.
이 글에서는 주제를 바꿔 마이크로서비스 아키텍처에서 발생하는 분산 데이터 관리 문제를 살펴봅니다.
마이크로서비스와 분산 데이터 관리의 문제
모놀리식 애플리케이션에는 일반적으로 단일 관계형 데이터베이스가 있습니다.
관계형 데이터베이스 사용의 주요 이점은 애플리케이션에서
몇 가지 중요한 보증을 제공하는 ACID 트랜잭션을 사용할 수 있다는 것입니다:
따라서 애플리케이션에서 간단히 트랜잭션을 시작하고,
여러 행을 변경(삽입, 업데이트, 삭제)하고, 트랜잭션을 커밋할 수 있습니다.
관계형 데이터베이스 사용의 또 다른 큰 장점은 풍부하고 선언적이며 표준화된 쿼리 언어인 SQL을 제공한다는 점입니다.
여러 테이블의 데이터를 결합하는 쿼리를 쉽게 작성할 수 있습니다.
그러면 RDBMS 쿼리 플래너가 쿼리를 실행하는 가장 최적의 방법을 결정합니다.
데이터베이스에 액세스하는 방법과 같은 낮은 수준의 세부 사항에 대해 걱정할 필요가 없습니다.
또한 애플리케이션의 모든 데이터가 하나의 데이터베이스에 있으므로 쿼리하기가 쉽습니다.
하지만 마이크로서비스 아키텍처로 전환하면 데이터 액세스가 훨씬 더 복잡해집니다.
각 마이크로서비스가 소유하는 데이터는 해당 마이크로서비스의 비공개 데이터이며
해당 마이크로서비스의 API를 통해서만 액세스할 수 있기 때문입니다.
데이터를 캡슐화하면 마이크로서비스가 느슨하게 결합되어 서로 독립적으로 발전할 수 있습니다.
여러 서비스가 동일한 데이터에 액세스하는 경우 스키마를 업데이트하려면
모든 서비스에 대한 조율된 업데이트가 필요하고 시간이 오래 걸립니다.
설상가상으로 마이크로서비스마다 서로 다른 종류의 데이터베이스를 사용하는 경우가 많습니다.
최신 애플리케이션은 다양한 종류의 데이터를 저장하고 처리하며,
관계형 데이터베이스가 항상 최선의 선택은 아닙니다.
일부 사용 사례의 경우, 특정 NoSQL 데이터베이스가 더 편리한 데이터 모델을 가지고 있고
훨씬 더 나은 성능과 확장성을 제공할 수 있습니다.
예를 들어, 텍스트를 저장하고 쿼리하는 서비스에서는 Elasticsearch와 같은 텍스트 검색 엔진을 사용하는 것이 합리적입니다.
마찬가지로 소셜 그래프 데이터를 저장하는 서비스는 아마도 Neo4j와 같은 그래프 데이터베이스를 사용해야 할 것입니다.
따라서 마이크로서비스 기반 애플리케이션은 종종 SQL 데이터베이스와 NoSQL 데이터베이스를 혼합하여 사용하는데,
이를 소위 폴리글롯 지속성 접근 방식이라고 합니다.
데이터 저장을 위한 분할된 다중 언어 지속성 아키텍처는 느슨하게 결합된 서비스,
더 나은 성능 및 확장성 등 많은 이점이 있습니다.
하지만 몇 가지 분산 데이터 관리 문제를 야기하기도 합니다.
첫 번째 과제는 여러 서비스에서 일관성을 유지하는 비즈니스 트랜잭션을 구현하는 방법입니다.
이것이 왜 문제인지 알아보기 위해 온라인 B2B 스토어의 예를 살펴보겠습니다.
고객 서비스는 신용 한도를 포함하여 고객에 대한 정보를 유지 관리합니다.
주문 서비스는 주문을 관리하며 새 주문이 고객의 신용 한도를 초과하지 않는지 확인해야 합니다.
이 애플리케이션의 모놀리식 버전에서는 주문 서비스에서 ACID 트랜잭션을 사용하여
사용 가능한 크레딧을 확인하고 주문을 생성할 수 있습니다.
반면, 마이크로서비스 아키텍처에서는 다음 다이어그램에서 볼 수 있듯이
ORDER 및 CUSTOMER 테이블이 각 서비스에 대해 비공개입니다.
주문 서비스는 고객 테이블에 직접 액세스할 수 없습니다.
고객 서비스에서 제공하는 API만 사용할 수 있습니다.
주문 서비스에서는 2단계 커밋(2PC)이라고도 하는 분산 트랜잭션을 사용할 수 있습니다(데이터-dl-uid="86">분산 트랜잭션).
그러나 2PC는 일반적으로 최신 애플리케이션에서는 실행 가능한 옵션이 아닙니다.
CAP 정리에 따르면 가용성과 ACID 스타일의 일관성 중에서 선택해야 하며,
일반적으로 가용성이 더 나은 선택입니다.
게다가 대부분의 NoSQL 데이터베이스와 같은 많은 최신 기술은 2PC를 지원하지 않습니다.
서비스와 데이터베이스 전반에서 데이터 일관성을 유지하는 것은 필수적이므로 다른 솔루션이 필요합니다.
두 번째 과제는 여러 서비스에서 데이터를 검색하는 쿼리를 구현하는 방법입니다.
예를 들어 애플리케이션에서 고객과 그의 최근 주문을 표시해야 한다고 가정해 보겠습니다.
주문 서비스가 고객의 주문을 검색하기 위한 API를 제공하는 경우
애플리케이션 측 조인을 사용하여 이 데이터를 검색할 수 있습니다.
애플리케이션은 고객 서비스에서 고객을 검색하고 주문 서비스에서 고객의 주문을 검색합니다.
그러나 주문 서비스가 기본 키로 주문 조회만 지원한다고 가정해 보겠습니다
(기본 키 기반 검색만 지원하는 NoSQL 데이터베이스를 사용할 수도 있습니다).
이 상황에서는 필요한 데이터를 검색할 수 있는 뚜렷한 방법이 없습니다.
이벤트 기반 아키텍처
많은 애플리케이션에서 해결책은 이벤트 중심 아키텍처를 사용하는 것입니다.
이 아키텍처에서는 마이크로서비스가 비즈니스 엔티티를 업데이트할 때와 같이 주목할 만한 일이 발생하면 이벤트를 게시합니다.
다른 마이크로서비스는 이러한 이벤트를 구독합니다.
마이크로서비스가 이벤트를 수신하면 자체 비즈니스 엔티티를 업데이트할 수 있으며,
이로 인해 더 많은 이벤트가 게시될 수 있습니다.
이벤트를 사용하여 여러 서비스에 걸친 비즈니스 트랜잭션을 구현할 수 있습니다. 트랜잭션은 일련의 단계로 구성됩니다.
각 단계는 비즈니스 엔티티를 업데이트하고 다음 단계를 트리거하는 이벤트를 게시하는 마이크로서비스로 구성됩니다.
다음 다이어그램은 주문을 생성할 때 사용 가능한 크레딧을 확인하기 위해 이벤트 기반 접근 방식을 사용하는 방법을 보여줍니다.
마이크로서비스는 메시지 브로커를 통해 이벤트를 교환합니다.
주문 서비스는 신규 상태의 주문을 생성하고 주문 생성됨 이벤트를 게시합니다.
고객 서비스에서 주문 생성 이벤트를 소비하고 주문에 대한 크레딧을 예약한 후 크레딧 예약 이벤트를 게시합니다.
주문 서비스에서 크레딧 예약 이벤트를 소비하고 주문 상태를 '진행 중'으로 변경합니다.
더 복잡한 시나리오에서는 고객의 크레딧이 확인되는 동시에 재고를 예약하는 등의 추가 단계가 포함될 수 있습니다.
(a) 각 서비스가 데이터베이스를 원자적으로 업데이트하고 나중에 이벤트를 게시하고
(b) 메시지 브로커가 이벤트가 적어도 한 번 이상 전달되도록 보장한다면
여러 서비스에 걸친 비즈니스 트랜잭션을 구현할 수 있습니다.
이러한 트랜잭션은 ACID 트랜잭션이 아니라는 점에 유의하는 것이 중요합니다.
일시적 일관성과 같이 훨씬 약한 보장을 제공합니다. 이 트랜잭션 모델을 BASE 모델이라고 합니다.
이벤트를 사용하여 여러 마이크로서비스에서 소유한 데이터를 미리 조인하는 구체화된 보기를 유지할 수도 있습니다.
뷰를 유지 관리하는 서비스는 관련 이벤트를 구독하고 뷰를 업데이트합니다.
예를 들어 고객 주문 보기를 유지 관리하는 고객 주문 보기 업데이트 서비스는
고객 서비스 및 주문 서비스에서 게시하는 이벤트를 구독합니다.
고객 주문 보기 업데이터 서비스는 고객 또는 주문 이벤트를 수신하면
고객 주문 보기 데이터스토어를 업데이트합니다.
MongoDB와 같은 문서 데이터베이스를 사용하여 고객 주문 보기를 구현하고
각 고객에 대해 하나의 문서를 저장할 수 있습니다.
고객 주문 보기 쿼리 서비스는 고객 주문 보기 데이터 저장소를 쿼리하여
고객 및 최근 주문에 대한 요청을 처리합니다.
이벤트 중심 아키텍처에는 몇 가지 장점과 단점이 있습니다.
여러 서비스에 걸친 트랜잭션을 구현할 수 있고 궁극적으로 일관성을 제공할 수 있습니다.
또 다른 장점은 애플리케이션이 구체화된 보기를 유지할 수 있다는 것입니다.
한 가지 단점은 프로그래밍 모델이 ACID 트랜잭션을 사용할 때보다 더 복잡하다는 것입니다.
예를 들어 신용 확인에 실패하면 주문을 취소해야 하는 등 애플리케이션 수준의 오류를 복구하기 위해
보상 트랜잭션을 구현해야 하는 경우가 많습니다.
또한 애플리케이션은 일관되지 않은 데이터를 처리해야 합니다.
이는 기내 트랜잭션으로 인한 변경 사항이 표시되기 때문입니다.
또한 애플리케이션이 아직 업데이트되지 않은 구체화된 보기에서 읽으면 불일치를 볼 수 있습니다.
또 다른 단점은 구독자가 중복 이벤트를 감지하고 무시해야 한다는 것입니다.
원자성 달성하기
이벤트 중심 아키텍처에서는 데이터베이스를 원자적으로 업데이트하고 이벤트를 게시하는 문제도 있습니다.
예를 들어, 주문 서비스는 ORDER 테이블에 행을 삽입하고 주문 생성 이벤트를 게시해야 합니다.
이 두 작업은 원자적으로 수행되는 것이 중요합니다.
데이터베이스를 업데이트한 후 이벤트를 게시하기 전에 서비스가 충돌하면 시스템이 일관성을 잃게 됩니다.
원자성을 보장하는 표준 방법은 데이터베이스와 메시지 브로커를 포함하는 분산 트랜잭션을 사용하는 것입니다.
그러나 CAP 정리와 같이 위에서 설명한 이유로 인해 이 방법은 우리가 원하지 않는 방식입니다.
로컬 트랜잭션을 사용하여 이벤트 게시
원자성을 달성하는 한 가지 방법은 애플리케이션이 로컬 트랜잭션만 포함하는 다단계 프로세스를 사용하여 이벤트를 게시하는 것입니다. 비결은 비즈니스 엔티티의 상태를 저장하는 데이터베이스에 메시지 큐로 작동하는 EVENT 테이블을 만드는 것입니다. 애플리케이션은 (로컬) 데이터베이스 트랜잭션을 시작하고, 비즈니스 엔티티의 상태를 업데이트하고, EVENT 테이블에 이벤트를 삽입하고, 트랜잭션을 커밋합니다. 별도의 애플리케이션 스레드 또는 프로세스가 EVENT 테이블을 쿼리하고 이벤트를 메시지 브로커에 게시한 다음 로컬 트랜잭션을 사용하여 이벤트를 게시된 것으로 표시합니다. 다음 다이어그램은 이러한 설계를 보여줍니다.
주문 서비스는 ORDER 테이블에 행을 삽입하고 주문 생성 이벤트를 EVENT 테이블에 삽입합니다.
이벤트 게시자 스레드 또는 프로세스는 EVENT 테이블에서 게시되지 않은 이벤트를 쿼리하고
이벤트를 게시한 다음 EVENT 테이블을 업데이트하여 이벤트를 게시된 것으로 표시합니다.
이 접근 방식에는 몇 가지 장점과 단점이 있습니다.
한 가지 장점은 2PC에 의존하지 않고 각 업데이트에 대해 이벤트가 게시되도록 보장한다는 것입니다.
또한 애플리케이션이 비즈니스 수준 이벤트를 게시하므로 이벤트를 유추할 필요가 없습니다.
이 접근 방식의 한 가지 단점은 개발자가 이벤트를 게시하는 것을 기억해야 하므로 오류가 발생할 가능성이 높다는 것입니다.
이 접근 방식의 한계는 트랜잭션 및 쿼리 기능이 제한되어 있는 일부 NoSQL 데이터베이스를 사용할 때 구현하기가 어렵다는 것입니다.
이 접근 방식은 애플리케이션이 로컬 트랜잭션을 사용하여 상태를 업데이트하고
이벤트를 게시하도록 함으로써 2PC가 필요하지 않습니다.
이제 애플리케이션이 단순히 상태를 업데이트하도록 하여 원자성을 달성하는 접근 방식을 살펴보겠습니다.
데이터베이스 트랜잭션 로그 마이닝
2PC 없이 원자성을 달성하는 또 다른 방법은 데이터베이스의 트랜잭션 또는
커밋 로그를 마이닝하는 스레드나 프로세스에서 이벤트를 게시하는 것입니다.
애플리케이션이 데이터베이스를 업데이트하면 데이터베이스의 트랜잭션 로그에 변경 사항이 기록됩니다.
트랜잭션 로그 마이너 스레드 또는 프로세스는 트랜잭션 로그를 읽고 이벤트를 메시지 브로커에 게시합니다.
다음 다이어그램은 그 설계를 보여줍니다.
이 접근 방식의 예로 오픈 소스 링크드인 데이터버스 프로젝트를 들 수 있습니다.
Databus는 Oracle 트랜잭션 로그를 마이닝하고 변경 사항에 해당하는 이벤트를 게시합니다.
LinkedIn은 Databus를 사용하여 다양한 파생 데이터 저장소를 기록 시스템과 일관되게 유지합니다.
또 다른 예로는 관리형 NoSQL 데이터베이스인 AWS의 스트림 메커니즘인 DynamoDB가 있습니다.
DynamoDB 스트림에는 지난 24시간 동안 DynamoDB 테이블의 항목에 대해
수행된 변경(만들기, 업데이트, 삭제 작업)의 시간 순서대로 정렬된 순서가 포함되어 있습니다.
애플리케이션은 스트림에서 이러한 변경 사항을 읽고 예를 들어 이벤트로 게시할 수 있습니다.
트랜잭션 로그 마이닝에는 다양한 장점과 단점이 있습니다.
한 가지 장점은 2PC를 사용하지 않고도 각 업데이트에 대해 이벤트가 게시되도록 보장한다는 것입니다.
트랜잭션 로그 마이닝은 또한 애플리케이션의 비즈니스 로직에서
이벤트 게시를 분리함으로써 애플리케이션을 단순화할 수 있습니다.
가장 큰 단점은 트랜잭션 로그의 형식이 각 데이터베이스마다 고유하며
데이터베이스 버전 간에 변경될 수도 있다는 것입니다.
또한 트랜잭션 로그에 기록된 낮은 수준의 업데이트에서
높은 수준의 비즈니스 이벤트를 리버스 엔지니어링하는 것이 어려울 수 있습니다.
트랜잭션 로그 마이닝은 애플리케이션이 데이터베이스 업데이트라는 한 가지 작업을 수행하도록 함으로써 2PC의 필요성을 제거합니다.
이제 업데이트를 없애고 이벤트에만 의존하는 다른 접근 방식을 살펴보겠습니다.
이벤트 소싱 사용
이벤트 소싱는 비즈니스 엔티티를 지속하는데 근본적으로 다른 이벤트 중심 접근 방식을 사용하여 2PC 없이 원자성을 달성합니다.
이 애플리케이션은 엔티티의 현재 상태를 저장하는 대신 상태 변경 이벤트 시퀀스를 저장합니다.
애플리케이션은 이벤트를 재생하여 엔티티의 현재 상태를 재구성합니다.
비즈니스 엔티티의 상태가 변경될 때마다 새 이벤트가 이벤트 목록에 추가됩니다.
이벤트 저장은 단일 작업이므로 본질적으로 원자적인 작업입니다.
이벤트 소싱이 어떻게 작동하는지 보려면 Order 엔티티를 예로 들어 보겠습니다.
기존 접근 방식에서는 각 주문이 ORDER 테이블의 행에 매핑되고 예를 들어 ORDER_LINE_ITEM 테이블의 행에 매핑됩니다.
그러나 이벤트 소싱을 사용할 때 주문 서비스는 주문을 상태 변경 이벤트의 형태로 저장합니다:
생성됨, 승인됨, 배송됨, 취소됨.
각 이벤트에는 주문의 상태를 재구성하기에 충분한 데이터가 포함되어 있습니다.
이벤트는 이벤트 데이터베이스인 이벤트 스토어에서 지속됩니다.
이 스토어에는 엔티티의 이벤트를 추가하고 검색하기 위한 API가 있습니다.
또한 도메인 객체가 아닌 이벤트를 유지하므로 <데이터-dl-uid="119">객체-관계형 임피던스 불일치 문제를 대부분 피할 수 있습니다.
또한 이벤트 소싱은 비즈니스 엔티티에 대한 변경 사항에 대해 100% 신뢰할 수 있는 감사 로그를 제공하며,
특정 시점의 엔티티 상태를 결정하는 임시 쿼리를 구현할 수 있게 해줍니다.
이벤트 소싱의 또 다른 주요 이점은 비즈니스 로직이 이벤트를 교환하는 느슨하게 연결된 비즈니스 엔티티로 구성되어 있다는 것입니다.
따라서 모놀리식 애플리케이션에서 마이크로서비스 아키텍처로 훨씬 쉽게 마이그레이션할 수 있습니다.
이벤트 소싱에는 몇 가지 단점도 있습니다.
익숙하지 않은 다른 스타일의 프로그래밍이므로 학습 곡선이 있습니다.
이벤트 스토어는 기본 키로 비즈니스 엔티티를 직접 조회하는 기능만 지원합니다.
쿼리를 구현하려면 명령 쿼리 책임 분리(CQRS)를 사용해야 합니다.
결과적으로 애플리케이션은 최종적으로 일관된 데이터를 처리해야 합니다.
요약
마이크로서비스 아키텍처에서 각 마이크로서비스에는 자체 프라이빗 데이터스토어가 있습니다.
마이크로서비스마다 서로 다른 SQL 및 NoSQL 데이터베이스를 사용할 수 있습니다.
이러한 데이터베이스 아키텍처에는 상당한 이점이 있지만, 분산된 데이터 관리 문제가 발생합니다.
첫 번째 과제는 여러 서비스에서 일관성을 유지하는 비즈니스 트랜잭션을 구현하는 방법입니다.
두 번째 과제는 여러 서비스에서 데이터를 검색하는 쿼리를 구현하는 방법입니다.
많은 애플리케이션의 경우 이벤트 기반 아키텍처를 사용하는 것이 해결책입니다.
이벤트 중심 아키텍처를 구현할 때 한 가지 과제는 상태를 원자적으로 업데이트하는 방법과 이벤트를 게시하는 방법입니다.
데이터베이스를 메시지 큐로 사용하는 방법, 트랜잭션 로그 마이닝, 이벤트 소싱 등 몇 가지 방법을 통해 이를 수행할 수 있습니다.
향후 블로그 게시물에서는 마이크로서비스의 다른 측면에 대해 계속 자세히 살펴보겠습니다.
편집자 - 이제 7부로 구성된 이 시리즈 기사가 완료되었습니다:
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
전문가에게 상담받기
또한 전체 문서와 NGINX를 사용한 마이크로서비스 구현에 대한 정보를 전자책으로 다운로드할 수도 있습니다
- 마이크로서비스: 설계부터 배포까지. 마이크로서비스 참조 아키텍처 및 마이크로서비스 솔루션 페이지에서 시리즈를 참조하세요.
이 글은 마이크로서비스로 애플리케이션 구축에 대한 시리즈의 여섯 번째 글입니다.
첫 번째 글에서는 마이크로서비스 아키텍처 패턴을 소개하고 마이크로서비스 사용의 장점과 단점에 대해 설명합니다.
다음 문서에서는 마이크로서비스 아키텍처의 다양한 측면에 대해 설명합니다:
API 및 게이트웨이 사용, 프로세스 간 통신, 서비스 및 검색, 이벤트 중심 데이터 관리에 대해 설명합니다.
이 문서에서는 마이크로서비스를 배포하기 위한 전략을 살펴봅니다.
동기 부여
모놀리식 애플리케이션을 배포한다는 것은 일반적으로 큰 단일 애플리케이션의 동일한 복사본을 여러 개 실행하는 것을 의미합니다.
일반적으로 N개의 서버(물리적 또는 가상)를 프로비저닝하고 각 서버에서 애플리케이션의 M개 인스턴스를 실행합니다.
모놀리식 애플리케이션을 배포하는 것이 항상 완전히 간단한 것은 아니지만,
마이크로서비스 애플리케이션을 배포하는 것보다 훨씬 간단합니다.
마이크로서비스 애플리케이션은 수십 개 또는 수백 개의 서비스로 구성됩니다.
서비스는 다양한 언어와 프레임워크로 작성됩니다.
각 서비스는 고유한 배포, 리소스, 확장 및 모니터링 요구 사항이 있는 미니 애플리케이션입니다.
예를 들어 서비스 수요에 따라 각 서비스의 인스턴스를 일정 수만큼 실행해야 합니다.
또한 각 서비스 인스턴스에는 적절한 CPU, 메모리, I/O 리소스가 제공되어야 합니다.
더욱 어려운 점은 이러한 복잡성에도 불구하고 서비스를 배포하는 것이 빠르고 안정적이며 비용 효율적이어야 한다는 것입니다.
몇 가지 마이크로서비스 배포 패턴이 있습니다.
먼저 호스트당 여러 서비스 인스턴스 패턴을 살펴보겠습니다.
호스트당 여러 서비스 인스턴스 패턴
마이크로서비스를 배포하는 한 가지 방법은 호스트당 여러 서비스 인스턴스 패턴을 사용하는 것입니다.
이 패턴을 사용할 때는 하나 이상의 물리적 또는 가상 호스트를 프로비저닝하고
각 호스트에서 여러 서비스 인스턴스를 실행합니다.
이는 여러 면에서 애플리케이션 배포에 대한 전통적인 접근 방식입니다.
각 서비스 인스턴스는 하나 이상의 호스트에서 잘 알려진 포트에서 실행됩니다.
호스트 머신은 일반적으로 애완동물처럼 취급됩니다.
다음 다이어그램은 이 패턴의 구조를 보여줍니다.
이 패턴에는 몇 가지 변형이 있습니다.
한 가지 변형은 각 서비스 인스턴스가 프로세스 또는 프로세스 그룹이 되는 것입니다.
예를 들어, Apache Tomcat 서버에 Java 서비스 인스턴스를 웹 애플리케이션으로 배포할 수 있습니다.
Node.js 서비스 인스턴스는 부모 프로세스와 하나 이상의 자식 프로세스로 구성될 수 있습니다.
이 패턴의 다른 변형은 동일한 프로세스 또는 프로세스 그룹에서 여러 서비스 인스턴스를 실행하는 것입니다.
예를 들어, 동일한 Apache Tomcat 서버에 여러 Java 웹 애플리케이션을 배포하거나
동일한 OSGI 컨테이너에서 여러 OSGI 번들을 실행할 수 있습니다.
호스트당 여러 서비스 인스턴스 패턴에는 장점과 단점이 모두 있습니다.
한 가지 주요 장점은 리소스 사용량이 상대적으로 효율적이라는 점입니다.
여러 서비스 인스턴스가 서버와 운영 체제를 공유합니다.
프로세스 또는 프로세스 그룹이 여러 서비스 인스턴스를 실행하는 경우,
예를 들어 여러 웹 애플리케이션이 동일한 Apache 및 Tomcat 서버와 JVM을 공유하는 경우 훨씬 더 효율적입니다.
이 패턴의 또 다른 장점은 서비스 인스턴스를 비교적 빠르게 배포할 수 있다는 점입니다.
서비스를 호스트에 복사하고 시작하기만 하면 됩니다.
서비스가 Java로 작성된 경우 JAR 또는 WAR 파일을 복사합니다.
Node.js 또는 Ruby와 같은 다른 언어의 경우 소스 코드를 복사합니다.
두 경우 모두 네트워크를 통해 복사되는 바이트 수가 상대적으로 적습니다.
또한 오버헤드가 없기 때문에 일반적으로 서비스를 시작하는 속도가 매우 빠릅니다.
서비스가 자체 프로세스인 경우 간단히 시작하면 됩니다.
그렇지 않고 서비스가 동일한 컨테이너 프로세스 또는 프로세스 그룹에서 실행되는 여러 인스턴스 중 하나라면
컨테이너에 동적으로 배포하거나 컨테이너를 다시 시작해야 합니다.
호스트당 여러 서비스 인스턴스 패턴의 매력에도 불구하고 몇 가지 중요한 단점이 있습니다.
한 가지 주요 단점은 각 서비스 인스턴스가 별도의 프로세스가 아닌 한 서비스 인스턴스가 격리되지 않는다는 것입니다.
각 서비스 인스턴스의 리소스 사용량을 정확하게 모니터링할 수는 있지만
각 인스턴스가 사용하는 리소스를 제한할 수는 없습니다.
오작동하는 서비스 인스턴스가 호스트의 모든 메모리 또는 CPU를 사용할 수 있습니다.
여러 서비스 인스턴스가 동일한 프로세스에서 실행되는 경우 전혀 격리되지 않습니다.
예를 들어 모든 인스턴스가 동일한 JVM 힙을 공유할 수 있습니다.
서비스 인스턴스가 잘못 동작하면 같은 프로세스에서 실행 중인 다른 서비스가 쉽게 중단될 수 있습니다.
또한 각 서비스 인스턴스에서 사용하는 리소스를 모니터링할 방법이 없습니다.
이 접근 방식의 또 다른 중요한 문제는 서비스를 배포하는 운영팀이 서비스 배포 방법에 대한
구체적인 세부 사항을 알고 있어야 한다는 것입니다.
서비스는 다양한 언어와 프레임워크로 작성될 수 있으므로 개발팀이 운영팀과 공유해야 할 세부 사항이 많습니다.
이러한 복잡성은 배포 중 오류의 위험을 증가시킵니다.
보시다시피 호스트당 다중 서비스 인스턴스 패턴은 친숙함에도 불구하고 몇 가지 중요한 단점이 있습니다.
이제 이러한 문제를 피할 수 있는 다른 마이크로서비스 배포 방법을 살펴보겠습니다.
호스트별 서비스 인스턴스 패턴
마이크로서비스를 배포하는 또 다른 방법은 호스트별 서비스 인스턴스 패턴입니다.
이 패턴을 사용하면 각 서비스 인스턴스를 자체 호스트에서 독립적으로 실행합니다.
이 패턴에는 두 가지 다른 전문화가 있습니다:
가상 머신당 서비스 인스턴스 및 컨테이너당 서비스 인스턴스입니다.
가상 머신당 서비스 인스턴스 패턴
가상 머신당 서비스 인스턴스 패턴을 사용하는 경우, 각 서비스를
아마존 EC2 AMI와 같은 가상 머신(VM) 이미지로 패키징합니다.
각 서비스 인스턴스는 해당 VM 이미지를 사용하여 실행되는 VM(예: EC2 인스턴스)입니다.
다음 다이어그램은 이 패턴의 구조를 보여줍니다:
이것은 Netflix가 비디오 스트리밍 서비스를 배포하는 데 사용하는 기본 접근 방식입니다.
넷플릭스는 Aminator를 사용하여 각 서비스를 EC2 AMI로 패키징합니다.
실행 중인 각 서비스 인스턴스는 EC2 인스턴스입니다.
자체 가상 머신을 구축하는 데 사용할 수 있는 다양한 도구가 있습니다.
지속적 통합(CI) 서버(예: Jenkins)를 구성하여 Aminator를 호출하여 서비스를 EC2 AMI로 패키징할 수 있습니다.
Packer.io는 자동화된 VM 이미지 생성을 위한 또 다른 옵션입니다.
Aminator와 달리 EC2, DigitalOcean, VirtualBox, VMware 등 다양한 가상화 기술을 지원합니다.
Boxfuse라는 회사는 아래에서 설명하는 VM의 단점을 극복하는 강력한 VM 이미지 구축 방법을 제공합니다.
Boxfuse는 Java 애플리케이션을 최소한의 VM 이미지로 패키징합니다.
이러한 이미지는 빠르게 빌드하고 빠르게 부팅할 수 있으며 공격 표면이 제한되어 있어 더욱 안전합니다.
CloudNative라는 회사는 EC2 및 AMI 생성을 위한 SaaS 서비스인 Bakery를 제공합니다.
마이크로서비스 테스트가 통과된 후 베이커리를 호출하도록 CI 서버를 구성할 수 있습니다.
그러면 베이커리가 서비스를 AMI로 패키징합니다.
베이커리와 같은 SaaS 제품을 사용하면 AMI 생성 인프라를 설정하는 데 귀중한 시간을 낭비할 필요가 없습니다.
가상 머신당 서비스 인스턴스 패턴에는 여러 가지 이점이 있습니다.
VM의 가장 큰 장점은 각 서비스 인스턴스가 완전히 격리된 상태로 실행된다는 점입니다.
고정된 양의 CPU와 메모리가 있으며 다른 서비스에서 리소스를 훔칠 수 없습니다.
마이크로서비스를 가상 머신으로 배포할 때의 또 다른 이점은 성숙한 클라우드 인프라를 활용할 수 있다는 점입니다.
AWS와 같은 클라우드는 로드 밸런싱 및 자동 확장 등의 유용한 기능을 제공합니다.
서비스를 가상 머신으로 배포할 때의 또 다른 큰 장점은 서비스의 구현 기술을 캡슐화할 수 있다는 것입니다.
서비스가 VM으로 패키징되면 블랙박스가 됩니다.
VM의 관리 API가 서비스 배포를 위한 API가 됩니다.
배포가 훨씬 더 간단하고 안정적으로 이루어집니다.
그러나 가상 머신당 서비스 인스턴스 패턴에는 몇 가지 단점이 있습니다.
한 가지 단점은 리소스 활용 효율성이 떨어진다는 점입니다.
각 서비스 인스턴스에는 운영 체제를 포함한 전체 VM의 오버헤드가 있습니다.
또한, 일반적인 퍼블릭 IaaS에서는 VM이 고정된 크기로 제공되므로 VM의 활용도가 낮을 수 있습니다.
또한, 퍼블릭 IaaS는 일반적으로 사용 중인지 유휴 상태인지에 관계없이 VM에 대해 요금을 부과합니다.
AWS와 같은 IaaS는 자동 확장을 제공하지만 수요 변화에 신속하게 대응하기는 어렵습니다< data-dl-uid="95">.
따라서 VM을 오버프로비저닝해야 하는 경우가 많으며, 이로 인해 배포 비용이 증가합니다.
이 접근 방식의 또 다른 단점은 일반적으로 새 버전의 서비스를 배포하는 속도가 느리다는 것입니다.
VM 이미지는 일반적으로 크기 때문에 빌드 속도가 느립니다.
또한 VM은 일반적으로 크기 때문에 인스턴스화 속도가 느립니다.
또한 일반적으로 운영 체제를 시작하는 데 시간이 다소 걸립니다.
그러나 Boxfuse에서 구축한 것과 같은 경량 가상 머신이 존재하기 때문에
이것이 보편적으로 적용되는 것은 아닙니다.
가상 머신당 서비스 인스턴스 패턴의 또 다른 단점은 일반적으로 사용자(또는 조직의 다른 누군가)가
차별화되지 않은 많은 무거운 작업을 담당한다는 것입니다.
가상 머신 구축 및 관리의 오버헤드를 처리하는 Boxfuse와 같은 도구를 사용하지 않는 한,
이 작업은 모두 사용자의 책임입니다. 이 필요하지만 시간이 많이 걸리는 작업은 핵심 비즈니스에 방해가 됩니다.
이제 더 가벼우면서도 VM의 많은 이점을 누릴 수 있는 마이크로서비스를 배포하는 다른 방법을 살펴보겠습니다.
컨테이너 패턴별 서비스 인스턴스
컨테이너별 서비스 인스턴스 패턴을 사용하는 경우 각 서비스 인스턴스는 자체 컨테이너에서 실행됩니다.
컨테이너는 운영 체제 수준에서 가상화 메커니즘입니다.
컨테이너는 샌드박스에서 실행되는 하나 이상의 프로세스로 구성됩니다.
프로세스의 관점에서 보면 자체 포트 네임스페이스와 루트 파일시스템이 있습니다.
컨테이너의 메모리와 CPU 리소스를 제한할 수 있습니다. 일부 컨테이너 구현에는 I/O 속도 제한도 있습니다.
컨테이너 기술의 예로는 Docker 및 Solaris Zones가 있습니다.
다음 다이어그램은 이 패턴의 구조를 보여줍니다:
이 패턴을 사용하려면 서비스를 컨테이너 이미지로 패키징합니다.
컨테이너 이미지는 서비스를 실행하는 데 필요한 애플리케이션 및 라이브러리로 구성된 파일 시스템 이미지입니다.
일부 컨테이너 이미지는 완전한 Linux 루트 파일 시스템으로 구성됩니다.
다른 컨테이너 이미지는 더 가볍습니다.
예를 들어 Java 서비스를 배포하려면 Java 런타임, Apache Tomcat 서버,
컴파일된 Java 애플리케이션이 포함된 컨테이너 이미지를 빌드합니다.
서비스를 컨테이너 이미지로 패키징한 후에는 하나 이상의 컨테이너를 시작합니다.
일반적으로 각 물리적 또는 가상 호스트에서 여러 개의 컨테이너를 실행합니다.
Kubernetes 또는 Marathon과 같은 클러스터 매니저를 사용하여 컨테이너를 관리할 수 있습니다.
클러스터 관리자는 호스트를 리소스 풀로 취급합니다.
컨테이너에 필요한 리소스와 각 호스트에서 사용 가능한 리소스를 기반으로 각 컨테이너를 배치할 위치를 결정합니다.
컨테이너당 서비스 인스턴스 패턴에는 장점과 단점이 모두 있습니다.
컨테이너의 장점은 VM의 장점과 유사합니다. 컨테이너는 서비스 인스턴스를 서로 격리합니다.
각 컨테이너에서 소비되는 리소스를 쉽게 모니터링할 수 있습니다.
또한 VM과 마찬가지로 컨테이너는 서비스를 구현하는 데 사용되는 기술을 캡슐화합니다.
컨테이너 관리 API는 서비스 관리를 위한 API 역할도 합니다.
그러나 VM과 달리 컨테이너는 경량 기술입니다.
컨테이너 이미지는 일반적으로 빌드 속도가 매우 빠릅니다.
예를 들어, 제 노트북에서는 <데이터-dl-uid="112">Spring Boot 애플리케이션을 Docker 컨테이너로 패키징하는 데 5초밖에 걸리지 않습니다.
또한 컨테이너는 긴 OS 부팅 메커니즘이 없기 때문에 매우 빠르게 시작됩니다.
컨테이너가 시작되면 실행되는 것은 서비스입니다.
컨테이너 사용에는 몇 가지 단점이 있습니다.
컨테이너 인프라는 빠르게 발전하고 있지만, VM 인프라만큼 성숙하지는 않습니다.
또한 컨테이너는 호스트 OS의 커널을 서로 공유하기 때문에 컨테이너는 VM만큼 안전하지 않습니다.
컨테이너의 또 다른 단점은 컨테이너 이미지 관리의 차별화되지 않은 무거운 작업을 사용자가 책임져야 한다는 점입니다.
또한 Google 컨테이너 엔진 또는 Amazon EC2 컨테이너 서비스(ECS) 같은 호스팅 컨테이너 솔루션을 사용하지 않는다면
컨테이너 인프라 및 해당 인프라에서 실행되는 VM 인프라를 관리해야 할 수 있습니다.
또한 컨테이너는 종종 VM당 가격이 책정되는 인프라에 배포됩니다.
따라서 앞서 설명한 대로 부하 급증을 처리하기 위해 VM을 오버프로비저닝하는 데 추가 비용이 발생할 가능성이 높습니다.
흥미로운 점은 컨테이너와 VM의 구분이 모호해질 가능성이 높다는 점입니다.
앞서 언급했듯이 Boxfuse는 VM을 빠르게 빌드하고 시작할 수 있습니다.
클리어 컨테이너 프로젝트는 경량 가상 머신을 만드는 것을 목표로 합니다.
[편집자주 - 2017년 12월에 발표한 바와 같이, 현재 오픈소스 Kata 프로젝트에서 클리어 컨테이너의 개발이 계속되고 있습니다.]
유니커널에 대한 관심도 높아지고 있으며, 최근 유니커널 시스템을 인수했습니다.
또한 서버리스 배포라는 새롭고 점점 인기를 얻고 있는 개념이 있는데,
이는 컨테이너 또는 가상 머신에 서비스를 배포해야 하는 문제를 피할 수 있는 접근 방식입니다.
이에 대해 다음에서 살펴보겠습니다.
서버리스 배포
AWS는 서버리스 배포 기술의 한 예입니다.
Java, Node.js, Python 서비스를 지원합니다.
마이크로서비스를 배포하려면 마이크로서비스를 ZIP 파일로 패키징하여 AWS Lambda에 업로드합니다.
또한 요청을 처리하기 위해 호출되는 함수의 이름(일명 이벤트)을 지정하는 메타데이터를 제공합니다.
AWS는 요청을 처리하기에 충분한 마이크로서비스 인스턴스를 자동으로 실행합니다.
소요된 시간과 소비된 메모리에 따라 각 요청에 대한 요금만 청구됩니다.
물론 세부 사항에는 악마가 숨어 있으며 AWS의 Lambda에도 한계가 있다는 것을 곧 알게 될 것입니다.
하지만 개발자나 조직의 어느 누구도 서버, 가상 머신 또는 컨테이너의 어떤 측면에 대해서도 걱정할 필요가 없다는 점은 매우 매력적입니다.
Lambda 함수는 상태 저장소 없는 서비스입니다.
일반적으로 AWS 서비스를 호출하여 요청을 처리합니다.
예를 들어, 이미지가 S3 버킷에 업로드될 때 호출되는 Lambda 함수는 DynamoDB 이미지 테이블에 항목을 삽입하고
Kinesis 스트림에 메시지를 게시하여 이미지 처리를 트리거할 수 있습니다.
Lambda 함수는 타사 웹 서비스를 호출할 수도 있습니다.
람다 함수를 호출하는 방법에는 네 가지가 있습니다:
보시다시피, AWS의 Lambda는 마이크로서비스를 배포하는 편리한 방법입니다.
요청 기반 요금제는 서비스가 실제로 수행한 작업에 대해서만 비용을 지불한다는 의미입니다.
또한 IT 인프라에 대한 책임이 없으므로 애플리케이션 개발에 집중할 수 있습니다.
하지만 몇 가지 중요한 제한 사항이 있습니다. 타사 메시지 브로커에서 메시지를 소비하는 서비스와 같이
장기간 실행되는 서비스를 배포하는 데는 사용할 수 없습니다.
요청은 300초 이내에 완료되어야 합니다.
이론상 AWS Lambda는 각 요청에 대해 별도의 인스턴스를 실행할 수 있으므로 서비스는 상태 비저장형이어야 합니다.
지원되는 언어 중 하나로 작성되어야 합니다.
그렇지 않으면 시간이 초과되어 종료될 수 있으므로 서비스도 빠르게 시작해야 합니다.
요약
마이크로서비스 애플리케이션을 배포하는 것은 쉽지 않습니다.
다양한 언어와 프레임워크로 작성된 수십, 수백 개의 서비스가 있습니다.
각 서비스는 고유한 배포, 리소스, 확장 및 모니터링 요구 사항이 있는 미니 애플리케이션입니다.
가상 머신당 서비스 인스턴스 및 컨테이너당 서비스 인스턴스를 비롯한 여러 마이크로서비스 배포 패턴이 있습니다.
마이크로서비스 배포를 위한 또 다른 흥미로운 옵션은 서버리스 접근 방식인 AWS Lambda입니다.
이 시리즈의 다음이자 마지막 파트에서는 모놀리식 애플리케이션을
마이크로서비스 아키텍처로 마이그레이션하는 방법을 살펴보겠습니다.
편집자 - 이제 7부로 구성된 이 시리즈 기사가 완료되었습니다:
게스트 블로거 크리스 리처드슨은 초기 Amazon EC2용 Java PaaS(서비스형 플랫폼)인 CloudFoundry.com의 창립자입니다.
현재는 애플리케이션 개발 및 배포 방식을 개선하기 위해 조직과 컨설팅을 진행하고 있습니다.
또한 마이크로서비스에 대한 블로그를 https://microservices.io에 정기적으로 게시하고 있습니다.
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
전문가에게 상담받기
이제 AWS Marketplace for Containers 에서 NGINX App Protect가 있거나 없는
NGINX Ingress Controller 의 NGINX Plus 기반 버전을 직접 구매할 수 있다는 소식을 알려드리게 되어 기쁩니다.
이 마켓플레이스를 통해 AWS와의 파트너십을 계속 강화하여 고성능 있클라우드 네이티브 앱을 손쉽게 제공할 수 있습니다.

NGINX는 Kubernetes 배포를 프로덕션 수준으로 만들기 위한 두 가지 옵션을 제공합니다 .
빠른 확장성을 가능하게 하고, 셀프 서비스를 지원하는 Ingress 컨트롤러를 추가하는 것입니다 . 30일 동안 무료로 사용해 보세요 .
Kubernetes 앱이 성숙해짐에 따라 침해 및 단일 장애 지점의 위험을 줄이기 위해 보안을 강화해야 합니다.
Ingress 지점에 유연한 웹 애플리케이션 방화벽(WAF) 을 배포하면 WAF가 Kubernetes 앱에 더 가까워지고 별도의 WAF 장치가 필요 없게 됩니다.
30일 동안 무료로 사용해 보세요 .
AWS의 This is My Architecture 비디오 시리즈 의 이번 에피소드를 시청하면 NGINX Ingress Controller가
Elastic Kubernetes Service (EKS)를 사용하여 트래픽을 라우팅하고 보호하는 방법과
Elastic Container Registry (ECR)와 함께 Infrastructure-as-Code를 사용하여
애플리케이션 배포 및 버전 관리를 위한 자동화된 파이프라인을 구축하는 방법을 알아볼 수 있습니다.
지원 옵션
당사의 오퍼링은 F5의 Kubernetes 전문가가 지원합니다. 다음 지원 계층 중에서 선택할 수 있습니다 .
AWS에서 NGINX에 대해 자세히 알아보기
사이징 가이드 검토 – 특정 AWS 인스턴스 유형에서 달성할 수 있는 성능 수준 과 예상 월별 비용에 대한 개요를 확인하세요 .
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
전문가에게 상담받기
Ingress Controller 선택에 대한 가이드의 처음 두 부분을 읽은 후에는 하나를 선택할 준비가 거의 되었습니다. 지금까지 우리가 어디에 있었는지 요약해 보겠습니다.
수신 컨트롤러는 오픈 소스, 기본 및 상업의 세 가지 범주로 나뉩니다. 각각에는 사용 사례가 있으며 선택하기 전에 단기 및 장기 요구 사항을 명확히 하는 것이 중요합니다. 이 블로그에서는 각 카테고리의 장단점을 다룹니다.
Open Source Ingress Controllers
많은 오픈 소스 수신 컨트롤러는 사용자 및 자원 봉사 개발자 커뮤니티에 의해 유지 관리되지만 일부는 전담 엔지니어링 팀도 있습니다. 가장 인기 있는 오픈 소스 수신 컨트롤러 중 두 개는 NGINX를 기반으로 하며, 하나는 쿠버네티스 커뮤니티에서 유지 관리하고, 다른 하나는 핵심 NGINX 엔지니어링 팀이 주도하고 오픈 소스입니다. NGINX 기반 수신 컨트롤러에 대한 자세한 비교는 시리즈의 4부를 참조하세요.
기본 Ingress 컨트롤러
많은 기본 수신 컨트롤러는 오픈 소스 기술을 기반으로 하지만, 전체 Kubernetes 플랫폼을 제공하고 종종 관리를 지원하는 회사에서 개발 및 유지 관리하기 때문에 별도로 분류합니다. 이 범주의 예로는 퍼블릭 클라우드 수신 컨트롤러, Rancher 및 Red Hat OpenShift 라우터가 있습니다.
여정의 이 단계에서는 요구 사항을 충족할 수 없는 옵션을 제거하여 시도하기 위해 일부 수신 컨트롤러를 사용할 준비가 되었습니다. 높은 수준의 기능 비교를 시작하기에 좋은 곳 중 하나는 learnk8s이며, 이 도구는 평가한 수신 컨트롤러의 무료 비교 표를 제공합니다.
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
전문가에게 상담받기
CNCF(Cloud Native Computing Foundation)의 2020년 설문조사에 따르면 NGINX는 쿠버네티스용 인그레스 컨트롤러에서 가장 일반적으로 사용되는 데이터 플레인이지만, "NGINX 인그레스 컨트롤러"가 두 개 이상 있다는 사실을 알고 계셨나요?
2018년에 Wait, What NGINX Ingress Controller for Kubernetes Am I Using?이라는 제목으로 게시된 이 블로그의 이전 버전은 NGINX를 사용하는 두 가지 인기 있는 Ingress 컨트롤러의 존재에 대한 커뮤니티 회원과의 대화에서 촉발되었습니다.
왜 혼란이 있었는지(그리고 여전히 혼란이 있는지) 쉽게 알 수 있습니다. 두 수신 컨트롤러는 모두 다음과 같습니다.
물론 가장 큰 공통점은 동일한 기능을 구현한다는 것입니다.
NGINX vs. 쿠버네티스 커뮤니티 수신 컨트롤러
명확성을 위해 다음과 같이 두 버전을 구분합니다.
Kong과 같이 NGINX를 기반으로 하는 다른 Ingress 컨트롤러도 많이 있지만 다행히도 이름을 쉽게 구별할 수 있습니다. 사용 중인 NGINX 수신 컨트롤러가 무엇인지 확실하지 않은 경우 실행 중인 수신 컨트롤러의 컨테이너 이미지를 확인한 다음, Docker 이미지 이름을 위에 나열된 리포지토리와 비교합니다.
NGINX Ingress 컨트롤러 목표 및 우선 순위
NGINX 수신 컨트롤러와 커뮤니티 수신 컨트롤러(NGINX 오픈 소스를 기반으로 하는 다른 수신 컨트롤러와 함께)의 주요 차이점은 개발 및 배포 모델이며, 이는 차례로 서로 다른 목표와 우선 순위를 기반으로 합니다.
NGINX 오픈 소스 대 NGINX Plus – 커머셜 에디션으로 업그레이드하는 이유는 무엇입니까?
여기에서 NGINX Plus 기반 NGINX 수신 컨트롤러에서 얻을 수 있는 몇 가지 주요 이점을 검토해 보겠습니다. 쿠버네티스 수신 컨트롤러를 선택하는 방법, 3부: 오픈 소스 vs. 기본 vs. 상용에서 논의한 바와 같이, 오픈 소스와 상용 인그레스 컨트롤러 사이에는 상당한 차이점이 있다. 프로덕션에서 대규모 Kubernetes 배포 및 복잡한 앱을 계획하는 경우 상용 수신 컨트롤러가 일부 주요 영역에서 시간과 비용을 절약한다는 것을 알게 될 것입니다.
보안 및 규정 준수
많은 조직이 프로덕션 환경에서 쿠버네티스 앱을 제공하지 못하는 주된 이유 중 하나는 보안 및 규정 준수를 유지하기 어렵기 때문입니다. NGINX Plus 기반 NGINX Ingress Controller는 앱과 고객을 안전하게 보호하는 데 중요한 5가지 사용 사례를 제공합니다.
독일의 거대 자동차 회사인 아우디(Audi)가 NGINX를 통해 Audi의 미래 경쟁력 있는 기술 비전과 애플리케이션 혁신에서 Red Hat OpenShift 앱을 어떻게 보호 했는지 알아보세요.
응용 프로그램 성능 및 복원력
가동 시간과 앱 속도는 개발자와 Platform Ops 팀을 위한 핵심 성과 지표(KPI)인 경우가 많습니다. NGINX Plus 기반 NGINX Ingress Controller는 쿠버네티스의 약속을 이행하는 데 도움이 되는 5가지 사용 사례를 제공합니다.
비즈니스 문자 메시지 회사인 Zipwhip이 NGINX를 사용하여 Amazon EKS의 보안 및 트래픽 가시성 강화에서 SaaS 앱의 99.99% 가동 시간을 달성한 방법을 알아보세요.
다음 단계: NGINX Ingress 컨트롤러 사용해 보기
오픈 소스 수신 컨트롤러가 앱에 적합한 선택이라고 결정한 경우 GitHub 리포지토리에서 빠르게 시작할 수 있습니다.
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
전문가에게 상담받기
머신 클러스터 전반에 걸쳐 컨테이너에서 마이크로서비스 애플리케이션을 대규모로 실행하고 관리하는 것은 어려운 작업입니다.
Kubernetes는 컨테이너 오케스트레이션을 위한 강력한 솔루션을 제공하여 이러한 과제를 해결하는 데 도움이 됩니다.
여기에는 장애 허용, 자동 확장, 롤링 업데이트, 스토리지, 서비스 검색 및 로드 밸런싱과 같은 여러 가지 중요한 기능이 포함되어 있습니다.
이 블로그 게시물에서는 HTTP 트래픽을 위한 내장 Kubernetes 로드 밸런싱 프레임워크인 Ingress 와 함께
NGINX Open Source 또는 NGINX Plus를 사용하는 방법을 설명합니다.
Ingress를 사용하면 Kubernetes 클러스터의 서비스로의 외부 트래픽 라우팅을 제어하는 규칙을 구성할 수 있습니다.
Kubernetes와 로드 밸런서를 통합하기 위해 클러스터에 배포하는
소프트웨어인 Ingress 컨트롤러를 제공하는 모든 로드 밸런서를 선택할 수 있습니다 .
여기서는 Ingress와 NGINX Plus 및 NGINX에 대해 제공하는 Ingress 컨트롤러를 사용하여
마이크로서비스 애플리케이션에 대한 로드 밸런싱을 구성하는 방법을 보여드립니다.
[편집자 - 이전에 NGINX 및 NGINX Plus에 대해 분리되어 있던 컨트롤러가 두 가지 모두에 대한 단일 Ingress 컨트롤러 로 병합되었습니다 .]
이 블로그 게시물에서는 Ingress를 사용한 Kubernetes의 HTTP 로드 밸런싱만 살펴봅니다.
다른 로드 밸런싱 옵션에 대해 자세히 알아보려면 블로그에서 NGINX Plus를 사용한 Kubernetes 서비스 로드 밸런싱을 참조하세요.
참고: 이 블로그 게시물에서 논의된 절차에 대한 전체 지침은 GitHub 저장소 에서 제공됩니다 .
이 게시물은 모든 필수 단계를 다루지는 않지만 대신 해당 지침에 대한 링크를 제공합니다.
NGINX 및 NGINX Plus용 Ingress 컨트롤러
샘플 애플리케이션을 배포하고 이에 대한 부하 분산을 구성하기 전에
부하 분산 장치를 선택하고 해당 Ingress 컨트롤러를 배포해야 합니다.
Ingress 컨트롤러는 특정 로드 밸런서를 Kubernetes와 통합하는 소프트웨어입니다.
저희는 NGINX Open Source와 NGINX Plus를 위한 Ingress 컨트롤러를 개발했으며, 이제 GitHub 저장소 에서 사용할 수 있습니다 .
타사에서 만든 다른 구현도 있습니다. 자세한 내용은 Kubernetes용 GitHub 저장소의 Ingress 컨트롤러 페이지를 방문하세요.
클러스터에 NGINX 또는 NGINX Plus Ingress 컨트롤러를 배포하는 방법에 대한 전체 지침은 GitHub 저장소를 참조하세요 .
샘플 마이크로서비스 애플리케이션
샘플 애플리케이션은 각각 별도로 배포되는 여러 서비스로 구성된 전형적인 마이크로서비스 웹 애플리케이션입니다.
cafe 라는 애플리케이션을 사용하면 티 서비스를 통해 차를 주문하거나 커피 서비스 를 통해 커피를 주문할 수 있습니다 .
HTTP 요청의 URI로 음료 선호도를 표시합니다. /tea 로 끝나는 URI는 차를 제공하고 /coffee 로 끝나는 URI는 커피를 제공합니다.
애플리케이션에 대한 연결은 SSL/TLS로 보안해야 합니다.
아래 다이어그램은 NGINX Plus 로드 밸런서가 클라이언트 요청을 적절한 서비스로 라우팅하고 SSL/TLS를 사용하여
클라이언트 연결을 보호하는 중요한 역할을 수행하는 애플리케이션을 개념적으로 보여줍니다.
클러스터에 애플리케이션을 배포하려면 GitHub 저장소 의 지침을 따르세요 .
Ingress를 통한 Kubernetes 로드 밸런싱 구성
카페 앱 에서는 로드 밸런서가 두 가지 기능을 제공해야 합니다.
Ingress로 로드 밸런싱을 구성하려면 Ingress 리소스 에서 규칙을 정의합니다 .
규칙은 클러스터의 서비스로 외부 트래픽을 라우팅하는 방법을 지정합니다.
리소스에서 여러 가상 서버를 정의할 수 있으며, 각각 다른 도메인 이름에 대해 정의할 수 있습니다.
가상 서버는 일반적으로 클러스터에 배포된 단일 마이크로서비스 애플리케이션에 해당합니다.
각 서버에 대해 다음을 수행할 수 있습니다.
Ingress에 대한 더 자세한 설명과 예제는 Ingress 문서 페이지 에서 확인할 수 있습니다 .
cafe 앱 의 Ingress 리소스( cafe‑ingress.yaml )는 다음과 같습니다 .
줄별로 살펴보면 다음과 같습니다.
6-9행에서 SSL/TLS 종료를 설정합니다.
13-21행에서 두 개의 경로 기반 규칙을 정의합니다.
클러스터에 Ingress 및 Secret 리소스를 배포하는 방법에 대한 전체 지침은 GitHub 저장소를 참조하세요 .
애플리케이션 테스트
NGINX Plus Ingress Controller와 함께 제공되는 샘플 애플리케이션과 리소스를 배포하면
Kubernetes 환경에서 로드 밸런싱과 애플리케이션 동작을 테스트할 수 있습니다.
예를 들어, 브라우저에서 /tea URI로 요청을 보내면 티 서비스에서 생성된 페이지가 표시됩니다.
이 샘플 애플리케이션은 실제로 음료를 제공하지 않지만, 요청 세부 정보와 컨테이너에 대한 정보를 포함한 페이지를 반환합니다.
여기에는 컨테이너의 호스트 이름과 IP 주소, 요청 URI, 클라이언트 IP 주소 등이 포함되며,
페이지를 새로고침할 때마다 다른 컨테이너가 응답을 제공해 로드 밸런싱의 동작을 확인할 수 있습니다.
또한, NGINX Plus의 라이브 활동 모니터링 대시보드를 통해 각 애플리케이션 컨테이너와
NGINX Plus의 실시간 로드 밸런싱 지표를 확인할 수 있습니다.
이러한 기능은 Kubernetes와 NGINX Plus Ingress Controller 설정을 테스트하거나 디버깅하는 데 유용하며,
마이크로서비스 아키텍처와 NGINX Plus의 고급 기능을 이해하는 데 도움을 줍니다.
Ingress 컨트롤러 확장
Ingress는 기본 HTTP 로드 밸런싱 기능을 제공합니다.
그러나 애플리케이션의 로드 밸런싱 요구 사항이 더 복잡하여 Ingress에서 지원하지 않는 경우가 많습니다.
이러한 요구 사항 중 일부를 해결하기 위해 Ingress 컨트롤러에 여러 확장 기능을 추가했습니다.
이렇게 하면 Kubernetes 리소스를 사용하여 로드 밸런싱을 구성하는 이점을
계속 활용할 수 있지만(로드 밸런서를 직접 구성하는 것과는 대조적으로) 고급 로드 밸런싱 기능을 활용할 수 있습니다.
사용 가능한 확장 기능의 전체 목록은 GitHub 저장소에서 확인하세요 .
또한, Config Maps 리소스 또는 Annotations를 통해 Kubernetes 리소스를 통해
NGINX 구성을 사용자 정의하는proxy_connect_timeout 메커니즘을 제공합니다.
예를 들어, 또는 proxy_read_timeout지시문의 값을 사용자 정의할 수 있습니다.
로드 밸런싱 요구 사항이 Ingress와 확장 프로그램에서 지원하는 범위를 넘어서는 경우
Ingress 컨트롤러를 사용하지 않는 NGINX Plus 배포 및 구성에 대한 다른 접근 방식을 제안합니다.
자세한 내용은 블로그에서 NGINX Plus를 사용한 Kubernetes 서비스 로드 밸런싱을 읽어보세요.
컨트롤러가 포함된 NGINX Plus의 이점
NGINX Plus를 사용하면 Ingress 컨트롤러는 NGINX를 통해 얻을 수 있는 이점 외에도 다음과 같은 이점을 제공합니다.
매우 동적인 환경에서의 안정성 – Ingress를 통해 노출되는 서비스 포드 수가 변경될 때마다
Ingress 컨트롤러는 NGINX 또는 NGINX Plus 구성을 업데이트하여 변경 사항을 반영해야 합니다.
NGINX Plus를 사용하면 동적 재구성 API를 사용하여 구성 파일을 다시 로드하지 않고도 구성을 업데이트할 수 있습니다.
이렇게 하면 구성 다시 로드가 매우 빈번할 때 발생할 수 있는 잠재적인 메모리 사용량 증가 및 전체 시스템 오버로드를 방지할 수 있습니다.
요약
Kubernetes는 Ingress를 사용하여 클러스터의 서비스로 외부 트래픽을 라우팅하기 위한 내장 HTTP 로드 밸런싱을 제공합니다.
NGINX 및 NGINX Plus는 Kubernetes 로드 밸런싱과 통합되어 Ingress 기능을 완벽하게 지원하고
확장된 로드 밸런싱 요구 사항을 지원하는 확장 기능도 제공합니다.
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
전문가에게 상담받기
컨테이너 오케스트레이션 플랫폼의 세계에서 두 가지 주요 이름을 자주 마주치게 됩니다.
바로 RedHat OpenShift Container Platform(OCP)과 Kubernetes입니다.
OpenShift는 Kubernetes를 기반으로 구축된 플랫폼으로,
다양한 컨테이너 오케스트레이션 솔루션에서 Kubernetes를 사용하는 것이 일반적입니다.
그러나 외부 트래픽을 Kubernetes 또는 OpenShift 환경으로 라우팅하는 것은 항상 두 가지 측면에서 약간 복잡할 수 있습니다.
이 블로그에서는 간단하고 효율적이며 애플리케이션 개발 팀이 Kubernetes 내부의 Ingress 구성과
외부 로드 밸런서 구성을 모두 관리할 수 있도록 NGINX Plus를 사용하는 방법에 대해 설명합니다.
이를 위한 참조 아키텍처로 GitHub에서 nginx-lb-operator 프로젝트를 제공합니다.
NGINX Load Balancer Operator(NGINX-LB-Operator)는 Red Hat Operator Framework와
SDK를 사용하여 만든 NGINX Controller용 Ansible 기반 연산자입니다.
이 연산자는 Kubernetes 클러스터 내에서 새로운 서비스가 추가되거나 Pod가 변경되거나 배포가 확장될 때
외부 NGINX Plus 로드 밸런서의 구성을 업데이트하기 위해 NGINX Controller의 선언적 API를 구동합니다.
NGINX-LB-Operator는 NGINX Plus 또는 NGINX Controller의 지원 계약에 포함되지 않으며,
GitHub에서 버그 보고나 문제 해결 지원을 받을 수 있습니다.
Kubernetes 및 NGINX 기술 – 리뷰
NGINX-LB-Operator는 여러 Kubernetes와 NGINX 기술에 의존하므로 이를 간단히 살펴보겠습니다.
이미 익숙하다면 NGINX Load Balancer Operator 부분으로 넘어가셔도 좋습니다.
Kubernetes 컨트롤러 및 운영자
Kubernetes는 느슨하게 결합된 중앙 API를 중심으로 구축된 오케스트레이션 플랫폼입니다.
이 API는 리소스 정의와 컨트롤러를 제공하며, 이를 통해 리소스를 모니터링하고 관리합니다.
Kubernetes는 확장 가능한 플랫폼으로, 오퍼레이터를 사용하여 기능을 확장할 수 있습니다.
Kubernetes용 NGINX Ingress 컨트롤러
NGINX에는 두 가지 주요 Ingress 컨트롤러가 있습니다.
첫 번째는 kubernetes/ingress-nginx로, Kubernetes 오픈 소스 커뮤니티에서 지원하는 Ingress 컨트롤러입니다.
두 번째는 nginxinc/kubernetes-ingress로, F5의 NGINX 팀에서 유지 관리하며 NGINX Open Source 및 NGINX Plus 버전이 있습니다.
이 두 가지는 비슷한 이름으로 구별하기 어려울 수 있습니다.
Ingress 컨트롤러의 주요 차이점은 Kubernetes API를 확장하여 고급 로드 밸런싱 기능과 블루그린 배포,
카나리아 릴리스 등 다양한 기능을 제공합니다.
NGINX 컨트롤러
NGINX Controller는 여러 환경에서 NGINX Plus 인스턴스를 관리하고, 성능 및 오류 상태에 대한 통찰력을 제공합니다.
이 컨트롤러는 클라우드 독립적인 제어 평면으로, NGINX Plus 인스턴스를 관리하고,
로드 밸런싱 및 API 관리를 위한 중앙 집중식 구성을 제공합니다.
Kubernetes 환경에서 NGINX Controller는 리버스 프록시 또는 API 게이트웨이로 배포된 NGINX Plus 인스턴스를 관리할 수 있지만,
Ingress Controller 자체는 관리하지 않습니다.
Ingress Controller는 Kubernetes 리소스에 대한 제어 루프를 수행하는 도구이므로 Kubernetes 네이티브 방식으로 관리해야 합니다.
외부 로드 밸런서
Kubernetes용 NGINX Plus Ingress Controller는 Kubernetes 내의 서비스를 외부 세계에 노출하는 훌륭한 방법이지만,
Kubernetes 노드나 클러스터로의 트래픽을 관리하려면 외부 로드 밸런서가 필요할 수 있습니다.
퍼블릭 클라우드에서는 NGINX Plus나 F5 BIG-IP LTM 같은 외부 로드 밸런서를 사용하거나
클라우드 네이티브 솔루션을 선택할 수 있습니다.
온프레미스나 프라이빗 클라우드에서는 NGINX Plus 또는 BIG-IP LTM을 사용할 수 있습니다.
외부 로드 밸런서를 관리할 때는 NGINX Controller를 사용하여
외부 NGINX Plus 인스턴스를 관리할 수 있습니다.
이를 통해 선언적 API를 사용해 인프라를 코드로 추상화하고, CI/CD 파이프라인과 통합할 수 있습니다.
선언적 API는 CI/CD 파이프라인과 인터페이싱하는 목적으로 설계되었으며, 이를 사용하여 각 애플리케이션 구성 요소를 배포할 수 있습니다.
하지만 Ingress 계층이 확장 가능하거나 동적으로 할당된 Kubernetes NodePorts를 사용 하거나
OpenShift Routes가 변경될 수 있는 경우는 어떻게 될까요?
이런 경우, 외부 로드 밸런서 구성을 Kubernetes 상태와 병합하고
Kubernetes Operator를 통해 NGINX Controller API를 구동하고 싶을 것입니다.
다이어그램은 외부 로드 밸런서를 관리하기 위한 그런 연산자( NGINX-LB-Operator )만 포함하는 샘플 배포를 보여주고,
NGINX Plus Ingress Controller와 NGINX Controller의 차이점을 강조합니다.
이 토폴로지에서 사용자 지정 리소스는 외부 로드 밸런서의 원하는 상태를 포함하고
업스트림(워크로드 그룹)을 NGINX Plus Ingress Controller로 설정합니다.
NGINX-LB-Operator는 Ingress Pod에 대한 정보를 수집하고
해당 정보를 원하는 상태와 병합한 다음 NGINX Controller API로 전송합니다.
NGINX-LB-Operator
Kubernetes용 Operator를 작성하는 것은 어려운 작업처럼 보일 수 있지만,
Red Hat과 Kubernetes 오픈 소스 커뮤니티에서 제공하는 Operator Framework는 이를 쉽게 만들어줍니다.
Operator SDK를 사용하면 누구나 Go, Ansible 또는 Helm을 사용하여 Kubernetes Operator를 만들 수 있습니다.
F5에서는 NGINX Controller용 인증 컬렉션을 포함하여 여러 제품에 대한 Ansible 컬렉션을 이미 게시했으므로
외부 NGINX Plus 인스턴스를 관리하고 NGINX Controller와 인터페이스하는 Operator를 빌드하는 것은 매우 간단합니다.
이는 Namespace 또는 Cluster Scope로 배포할 수 있으며 소수의 사용자 정의 리소스를 감시합니다.
사용자 정의 리소스는 NGINX Controller 객체(Certificate, Gateway, Application 및 Component)에
직접 매핑되므로 Kubernetes에서 NGINX Controller의 애플리케이션 중심 모델을 직접 나타냅니다.
Kubernetes에서 구성된 사용자 정의 리소스는 NGINX-LB-Operator 에서 수집한 다음 NGINX Controller에서 동등한 리소스를 생성합니다.
NGINX-LB-Operator를 사용하면 NGINX Controller의 선언적 API를 사용하여
외부 NGINX Plus 인스턴스의 구성을 관리할 수 있습니다.
NGINX Controller가 외부 인스턴스를 관리하기 때문에
모니터링 및 알림의 추가 이점과 NGINX Controller가 제공하는 심층적인 애플리케이션 통찰력을 얻을 수 있습니다.
이 다이어그램은 다음 사항을 보여줍니다.
자세한 배포 지침과 샘플 애플리케이션은 GitHub 에 제공됩니다 .
롤 플레이를 좋아하지 않거나 TL;DR 버전을 위해 여기 왔다면 지금 바로 가보세요.
샘플 배포
자, 이제 롤플레이를 해봅시다. 나는 수잔이고, 당신은 데이브가 될 수 있어요.
데이브로서, 당신은 좋아하는 상상의 대기업에서 비즈니스 라인을 운영하고 있습니다.
최신 트렌드도 잘 파악하고, 젊은 세대와도 잘 어울리며, 애플리케이션과 마이크로서비스를 모두 OpenShift에 배포합니다.
그리고 Ingress로는 Kubernetes용 NGINX Plus Ingress Controller를 사용합니다.
모든 애플리케이션은 OpenShift 프로젝트(네임스페이스)로 배포되고,
NGINX Plus Ingress Controller는 자체적인 Ingress 네임스페이스에서 실행됩니다.
기본적인 Ingress 사양에서 제공하는 기능에 만족하지 못했고, ConfigMap과 Annotations은 다소 번거롭다고 생각했죠.
그래서 NGINX가 NGINX Plus Ingress Controller에서 자체 CRD 지원을 시작한다고 발표했을 때 아주 기뻤습니다.
오늘날, 애플리케이션 개발자들은 VirtualServer와 VirtualServerRoute 리소스를 사용하여
NGINX Plus Ingress Controller에 애플리케이션을 배포하고, OpenShift 내에서 내부 라우팅과 오류 처리를 구성하고 있습니다.
때때로 NGINX Plus Ingress Controller는 TransportServer라는 사용자 정의 리소스를 사용해 HTTP가 아닌 서비스를 노출하기도 합니다.
개발자들은 자신만의 프로젝트 네임스페이스에서 이러한 사용자 정의 리소스를 정의하고,
NGINX Plus Ingress Controller가 이를 선택하여 즉시 적용할 수 있습니다.
정말 멋지긴 하지만, OpenShift 클러스터의 가장자리에서
외부 네트워크 로드 밸런서를 쉽게 관리할 수 있으면 좋겠다고 생각하셨을 겁니다.
Ingress 계층을 확장해야 할 때마다 늘 고민이 생기죠.
어느 토요일 밤, 디스코에서 신나게 춤을 추고 있어야 할 시간인데, 어제는 Ingress 계층을 다시 조정해야 해서 허리가 아파옵니다.
그때 갑자기 연기 구름 속에서 요정 대모인 수잔이 나타납니다.
"안녕, 데이브!" 그녀가 말합니다.
당신은 놀라며 대답합니다. "당신은 누구야? 내 페르시아 카펫에 무슨 짓을 한 거야?"
수잔은 당신의 반응을 무시한 채, GitHub에서 사용할 수 있는 NGINX-LB-Operator에 대해 이야기하기 시작합니다.
그녀는 OpenShift의 가장자리에 배치된 NGINX Plus 클러스터를 NGINX Controller를 사용해 애플리케이션 중심으로 관리하며,
이를 통해 NGINX Plus 로드 밸런서를 구성하는 방법을 정의하는 사용자 정의 리소스를 만들 수 있다는 점을 설명합니다.
NGINX -LB-Operator는 이러한 리소스를 감시하고 이를 사용하여 애플리케이션 중심 구성을 NGINX Controller로 전송합니다.
그러면 NGINX Controller가 필요한 NGINX Plus 구성을 생성하여 외부 NGINX Plus 로드 밸런서로 푸시합니다.
최종 사용자는 귀하의 애플리케이션에 즉시 액세스할 수 있으며,
귀하는 외부 NGINX Plus 로드 밸런서를 수정해야 하는 변경 사항을 제어할 수 있습니다!
NGINX Controller는 외부 NGINX Plus 로드 밸런서에서 메트릭을 수집하여 이미 즐기고 있는 동일한 애플리케이션 중심 관점에서 제공합니다. 그리고 다음에 NGINX Plus Ingress 계층을 확장할 때 NGINX-LB-Operator가 NGINX Controller와 외부 NGINX Plus 로드 밸런서를 자동으로 업데이트합니다. 더 이상 허리 통증이 없습니다!
결론
쿠버네티스는 컨테이너화된 애플리케이션을 관리하기 위해 구축된 플랫폼입니다.
NGINX Controller는 애플리케이션 로드 밸런싱을 생각하고 관리하기 위한 애플리케이션 중심 모델을 제공합니다.
NGINX-LB-Operator는 두 가지를 결합하여 기본 인프라에 대해 걱정할 필요 없이 전체 스택을 엔드투엔드로 관리할 수 있도록 합니다.
NGINX-LB-Operator 에 대한 자세한 기술 정보 와 전체 샘플 워크스루는 GitHub 로 이동하세요 .
당사의 솔루션에 대해 자세히 알아보세요:
위 내용과 같이 NGINX Ingress Controller 를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요
전문가에게 상담받기