고급 트래픽 관리로 Kubernetes의 복원력을 개선하는 방법

회사가 최신 앱 개발 기술을 성공적으로 사용하고 있지 않다고 말할 수 있는 아주 쉬운 방법이 있습니다. 고객은 소셜 미디어에 빠르게 불평합니다. 그들은 최신의 폭식할 만한 릴리스를 스트리밍할 수 없을 때 불평합회사가 최신 앱 개발 기술을 성공적으로 사용하고 있지 않다는 것을 아주 쉽게 알 수 있는 방법이 있습니다. 고객은 소셜 미디어에서 빠르게 불평합니다. 그들은 최신의 폭식할 만한 릴리스를 스트리밍할 수 없을 때 불평합니다. 또는 온라인 뱅킹에 액세스하십시오. 또는 장바구니가 시간 초과되어 구매하십시오.

고객이 공개적으로 불만을 제기하지 않는다고 해서 나쁜 경험이 결과를 초래하지 않는다는 의미는 아닙니다. 대형 보험사인 고객 중 한 명이 홈페이지가 3초 이내에 로드되지 않으면 고객을 잃는다고 말했습니다.

성능 저하 또는 중단에 대한 모든 사용자 불만은 공통 원인을 가리킵니다. 복원력…또는 복원력 부족입니다. 컨테이너 및 Kubernetes를 포함한 마이크로서비스 기술의 장점은 앱의 복원력을 개선하여 고객 경험을 크게 개선할 수 있다는 것입니다. 어떻게? 아키텍처에 관한 모든 것입니다.

나는 일련의 휴일 조명의 비유를 사용하여 모놀리식 아키텍처와 마이크로서비스 아키텍처의 핵심 차이점을 설명하고 싶습니다. 구식 가닥의 전구가 꺼지면 전체 가닥이 어두워집니다. 전구를 교체할 수 없다면 그 가닥으로 장식할 가치가 있는 유일한 것은 쓰레기통 내부입니다. 이 오래된 스타일의 조명은 구성 요소가 밀접하게 결합되어 있고 구성 요소 하나가 고장나면 실패하는 모놀리식 앱과 같습니다.

그러나 소프트웨어 산업과 마찬가지로 조명 산업은 이러한 문제점을 감지했습니다. 잘 설계된 마이크로서비스 앱이 서비스 인스턴스에 장애가 발생하더라도 계속 작동하는 것처럼 현대적인 조명 가닥에서 전구가 끊어지면 다른 전구도 계속 밝게 빛납니다.

목차

1. 쿠버네티스 트래픽 관리
  1-1. 트래픽 제어(Traffic Control)
  1-2. 트래픽 분할(Traffic Splitting)
2. NGINX가 도움이 되는 방법
  2-1. NGINX Ingress 리소스 및 SMI 사양으로 더 쉬운 구성
  2-2. 고급 사용자 정의로 더욱 정교한 트래픽 제어 및 분할(Splitting)
2-3. 대시보드(Dashboard)로 트래픽 분할(Traffic Splitting) 결과 해석

1. 쿠버네티스 트래픽 관리

컨테이너는 더 작고 개별 구성 요소를 사용하여 애플리케이션을 구축하는 데 이상적으로 적합하기 때문에 마이크로서비스 아키텍처에서 널리 선택됩니다. 컨테이너는 가볍고 휴대 가능하며 확장하기 쉽습니다. Kubernetes는 컨테이너 오케스트레이션의 사실상 표준이지만 Kubernetes를 프로덕션 준비 상태로 만드는 데는 많은 문제가 있습니다. Kubernetes 앱에 대한 제어와 탄력성을 모두 향상시키는 한 가지 요소는 패킷이 아닌 서비스를 제어하고 트래픽 관리 규칙을 동적으로 또는 Kubernetes API로 조정할 수 있는 성숙한 트래픽 관리 전략입니다. 트래픽 관리는 모든 아키텍처에서 중요하지만 고성능 앱의 경우 트래픽 제어와 트래픽 분할이라는 두 가지 트래픽 관리 도구가 필수적입니다.

1-1. 트래픽 제어(Traffic Control)

트래픽 제어(트래픽 라우팅 또는 트래픽 셰이핑이라고도 함)는 트래픽이 어디로 가고 어떻게 도달하는지 제어하는 행위를 말합니다. 이는 공격과 트래픽 급증으로부터 인프라와 앱을 보호할 수 있기 때문에 프로덕션 환경에서 Kubernetes를 실행할 때 필요합니다. 앱 개발 주기에 통합할 두 가지 기술은 속도 제한과 회로 차단입니다.

사용사례(Use Case): 너무 많은 요청을 받지 않도록 서비스를 보호하고 싶습니다.
솔루션(Solution): 속도 제한(Rate limiting)

악의적이든(예: 무차별 암호 대입 및 DDoS 공격) 양성이든(예: 판매를 위해 몰려드는 고객) 많은 양의 HTTP 요청이 서비스를 압도하고 앱이 다운될 수 있습니다. 속도 제한(Rate limiting)은 사용자가 주어진 기간 동안 만들 수 있는 요청 수를 제한합니다. 요청에는 웹사이트 홈페이지에 대한 GET 요청이나 로그인 양식에 대한 POST 요청과 같은 간단한 것이 포함될 수 있습니다. 예를 들어 DDoS 공격을 받는 경우 속도 제한을 사용하여 수신 요청 속도를 실제 사용자에게 일반적인 값으로 제한할 수 있습니다.

사용사례(Use Case): 계단식 오류(cascading failures)를 피하고 싶습니다.
솔루션(Solution): 회로 차단(Circuit breaking)

서비스를 사용할 수 없거나 대기 시간이 길면 들어오는 요청이 시간 초과되고 클라이언트가 오류 응답을 받는 데 오랜 시간이 걸릴 수 있습니다. 시간 초과가 길면 잠재적으로 연쇄 오류가 발생할 수 있으며, 여기서 한 서비스의 중단은 다른 서비스의 시간 초과와 궁극적으로 애플리케이션 전체의 실패로 이어집니다.

회로 차단기는 서비스 장애를 모니터링하여 계단식 장애를 방지합니다. 서비스에 대한 실패한 요청 수가 미리 설정된 임계값을 초과하면 회로 차단기가 트립되어 요청이 도착하는 즉시 클라이언트에 오류 응답을 반환하기 시작하여 서비스에서 트래픽을 효과적으로 제한합니다.

회로 차단기는 제한된 수의 요청이 테스트로 통과하도록 허용하기 전에 정의된 시간 동안 요청을 계속 가로채고 거부합니다. 이러한 요청이 성공하면 회로 차단기가 트래픽 조절을 중지합니다. 그렇지 않으면 시계가 재설정되고 회로 차단기는 정의된 시간에 대한 요청을 다시 거부합니다.

1-2. 트래픽 분할(Traffic Splitting)

트래픽 분할(트래픽 테스트라고도 함)은 트래픽 제어의 하위 범주이며 환경(일반적으로 현재 프로덕션 버전과 업데이트된 버전)에서 동시에 실행되는 백엔드 앱의 다른 버전으로 전달되는 수신 트래픽의 비율을 제어하는 작업을 나타냅니다. 이는 팀이 고객에게 부정적인 영향을 미치지 않으면서 새로운 기능과 버전의 기능과 안정성을 테스트할 수 있도록 하기 때문에 앱 개발 주기의 필수적인 부분입니다. 유용한 배포 시나리오에는 디버그(debug) 라우팅, 카나리(canary) 배포, A/B 테스트(testing) 및 블루-그린(blue-green) 배포(deployments)가 포함됩니다. (업계 전반에 걸쳐 이 네 가지 용어를 사용하는 데 상당한 불일치가 있습니다. 여기에서는 정의를 이해하는 대로 사용합니다.)

사용사례(Use Case): 프로덕션 환경에서 새 버전을 테스트할 준비가 되었습니다.
솔루션(Solution): 디버그 라우팅(Debug routing)

은행 앱이 있고 신용 점수 기능을 추가한다고 가정해 보겠습니다. 고객과 테스트하기 전에 프로덕션 환경에서 성능이 어떤지 확인하고 싶을 것입니다. 디버그 라우팅(Debug routing)을 사용하면 세션 쿠키(session cookie), 세션 ID 또는 그룹 ID와 같은 레이어 7 속성을 기반으로 특정 사용자만 액세스할 수 있도록 허용하여 공개적으로 배포하면서도 실제 사용자로부터 “숨길” 수 있습니다. 예를 들어 관리자 세션 쿠키가 있는 사용자에게만 액세스를 허용할 수 있습니다. 다른 모든 사용자는 안정적인 버전을 계속 사용하는 동안 해당 요청은 신용 점수 기능이 있는 새 버전으로 라우팅됩니다.

사용사례(Use Case): 새 버전이 안정적인지 확인해야 합니다.
솔루션(Solution):
카나리(Canary) 배포

카나리(Canary) 배포의 개념은 광부들이 독성 가스에 대한 조기 경보 역할을 하기 위해 우리에 갇힌 카나리를 탄광으로 가져간 역사적인 광산 관행에서 가져왔습니다. 가스는 광부를 죽이기 전에 카나리를 죽였으므로 신속하게 위험에서 벗어날 수 있습니다. 앱의 세계에서는 새가 다치지 않습니다! Canary 배포는 새로운 기능이나 버전의 안정성을 테스트하는 안전하고 민첩한 방법을 제공합니다. 일반적인 카나리아 배포는 안정적인 버전에서 사용자의 높은 점유율(예: 99%)로 시작하여 작은 그룹(나머지 1%)을 새 버전으로 이동합니다. 새 버전이 실패하는 경우(예: 충돌 또는 클라이언트에 오류 반환) 테스트 그룹을 즉시 안정적인 버전으로 다시 이동할 수 있습니다. 성공하면 사용자를 안정적인 버전에서 새 버전으로 한 번에 전환하거나(일반적인 경우처럼) 점진적이고 제어된 마이그레이션으로 전환할 수 있습니다.

사용사례(Use Case): 고객이 현재 버전보다 새 버전을 더 좋아하는지 확인해야 합니다.
솔루션(Solution): A/B 테스트(testing)

이제 새 기능이 프로덕션 환경에서 작동하는 것을 확인했으므로 클릭 수, 반복 사용자 또는 명시적 등급과 같은 핵심 성과 지표(KPI)를 기반으로 기능의 성공에 대한 고객 피드백을 받고 싶을 수 있습니다. A/B 테스트는 고객 기반 전반에 걸쳐 다양한 제품 또는 앱 버전의 상대적인 성공을 판단하기 위해 사용자 행동을 측정하고 비교하기 위해 여러 산업에서 사용되는 프로세스입니다. 일반적인 A/B 테스트에서 사용자의 50%는 버전 A(현재 앱 버전)를 받고 나머지 50%는 버전 B(새롭지만 안정적인 기능이 있는 버전)를 받습니다. 승자는 전반적으로 더 나은 KPI 세트를 가진 사람입니다.

사용사례(Use Case): 다운타임 없이 사용자를 새 버전으로 이동하고 싶습니다.
루션(Solution):
블루-그린(Blue-green) 배포

이제 은행 앱의 주요 버전 변경이 예정되어 있다고 가정해 보겠습니다. 축하합니다! 과거에는 새 버전을 프로덕션으로 이동하기 전에 이전 버전을 제거해야 했기 때문에 버전 업그레이드는 일반적으로 사용자에게 다운타임을 의미했습니다. 그러나 오늘날의 경쟁 환경에서 업그레이드를 위한 가동 중지 시간은 대부분의 사용자에게 허용되지 않습니다. 블루-그린(Blue-green) 배포는 업그레이드를 위한 가동 중지 시간을 크게 줄이거나 없애기까지 합니다. 동일한 프로덕션 환경에서 동시에 새 버전(녹색)을 배포하면서 동시에 이전 버전(파란색)을 프로덕션에 유지하기만 하면 됩니다.

대부분의 조직은 사용자의 100%를 파란색에서 녹색으로 한 번에 이동하는 것을 원하지 않습니다. 결국, 녹색 버전이 실패하면 어떻게 될까요? 솔루션은 카나리(Canary) 배포를 사용하여 위험 완화 전략에 가장 적합한 증분 단위로 사용자를 이동하는 것입니다. 새 버전이 재난인 경우 몇 번의 키 입력으로 모든 사람을 안정적인 버전으로 쉽게 되돌릴 수 있습니다.

2. NGINX가 도움이 되는 방법

대부분의 Ingress ControllerService Mesh를 사용하여 고급 트래픽 제어 및 분할을 수행할 수 있습니다. 사용할 기술은 앱 아키텍처와 사용 사례에 따라 다릅니다. 예를 들어 Ingress Controller를 사용하는 것은 다음 세 가지 시나리오에서 의미가 있습니다.

  • Kubernetes로 “lifeed and shifted”한 단순 앱 또는 모놀리식 앱과 같이 앱에는 endpoint가 하나만 있습니다.
  • 클러스터에 서비스 간 통신이 없습니다.
  • 서비스 간 통신이 있지만 아직 Service Mesh를 사용하지 않습니다.

개별 마이크로서비스의 테스트 또는 업그레이드를 위한 서비스. 예를 들어, 지리적 위치 마이크로서비스 A배포가 Service Mesh가 필요할 정도로 복잡한 경우 일반적인 사용 사례는 개별 마이크로서비스의 테스트 또는 업그레이드를 위해 서비스 간에 트래픽을 분할하는 것입니다. 예를 들어, 지리적 위치 마이크로서비스 API의 서로 다른 두 버전 간에 모바일 Frontend 뒤에서 카나리(Canary) 배포를 수행할 수 있습니다.

그러나 일부 Ingress Controller 및 Service Mesh를 사용하여 트래픽 분할을 설정하는 것은 다음과 같은 다양한 이유로 시간이 많이 걸리고 오류가 발생하기 쉽습니다.

  • 다양한 공급업체의 Ingress Controller 및 Service Mesh는 다양한 방식으로 Kubernetes 기능을 구현합니다.
  • Kubernetes는 Layer 7 트래픽을 관리하고 이해하도록 설계되지 않았습니다.
  • 일부 Ingress Controller 및 Service Mesh는 정교한 트래픽 관리를 지원하지 않습니다.

NGINX Ingress Controller 및 NGINX Service Mesh를 사용하면 강력한 트래픽 라우팅 및 분할 정책을 몇 초 만에 쉽게 구성할 수 있습니다.

2-1. NGINX Ingress 리소스 및 SMI 사양으로 더 쉬운 구성

이러한 NGINX 기능을 사용하면 구성이 더 쉬워집니다.

NGINX Ingress Controller용 NGINX Ingress 리소스 – 표준 Kubernetes Ingress 리소스를 사용하면 SSL/TLS termination, HTTP 로드 밸런싱 및 Layer 7 라우팅을 쉽게 구성할 수 있지만 회로 차단(circuit breaking), A/ B 테스트(testing) 및 블루-그린(blue-green) 배포. 대신 NGINX가 아닌 사용자는 주석, ConfigMap 및 사용자 지정 템플릿을 사용해야 합니다. 이러한 템플릿은 모두 세밀한 제어 기능이 없고 안전하지 않으며 오류가 발생하기 쉽고 사용하기 어렵습니다.

NGINX Ingress Controller는 표준 Ingress 리소스(역시 지원)의 대안으로 NGINX Ingress 리소스와 함께 제공됩니다. Ingress 로드 밸런싱 구현을 단순화하는 기본, 유형 안전 및 들여쓰기 구성 스타일을 제공합니다. NGINX Ingress 리소스는 기존 NGINX 사용자를 위한 추가 이점이 있습니다. 즉, Kubernetes가 아닌 환경에서 로드 밸런싱 구성을 쉽게 재사용할 수 있으므로 모든 NGINX 로드 밸런서가 동일한 구성을 사용할 수 있습니다.

SMI가 포함된 NGINX Service Mesh – NGINX Service Mesh는 TrafficSplit, TrafficTarget 및 HTTPRouteGroup과 같은 유형이 지정된 리소스를 사용하여 Kubernetes의 Service Mesh에 대한 표준 인터페이스를 정의하는 사양인 SMI(Service Mesh Interface)를 구현합니다. 표준 Kubernetes 구성 방법을 사용하는 NGINX Service Mesh 및 NGINX SMI 확장은 카나리(Canary) 배포와 같은 트래픽 분할 정책을 프로덕션 트래픽에 대한 중단을 최소화하면서 배포를 간단하게 만듭니다. 예를 들어 NGINX Service Mesh로 카나리(Canary) 배포를 정의하는 방법은 다음과 같습니다.

apiVersion: split.smi-spec.io/v1alpha2
kind: TrafficSplit
metadata:
name: target-ts
spec:
service: target-svc
backends:
- service: target-v1-0
    weight: 90
- service: target-v2-0
    weight: 10

2-2. 고급 사용자 정의로 더욱 정교한 트래픽 제어 및 분할(Splitting)

이러한 NGINX 기능을 사용하면 정교한 방식으로 트래픽을 쉽게 제어하고 분할할 수 있습니다.

카나리(Canary) 배포를 위한 키-값 저장소(Key-Value Store) – A/B 테스트(testing) 또는 블루-그린(blue-green) 배포를 수행할 때 특정 증분(예: 0%, 5%, 10%, 25)으로 트래픽을 새 버전으로 전환할 수 있습니다. %, 50% 및 100%. 대부분의 도구에서 이것은 백분율을 편집하고 각 증분에 대한 구성 파일을 다시 로드해야 하기 때문에 매우 수동적인 프로세스입니다. 그 정도의 오버헤드로 인해 5%에서 100%로 곧장 가는 위험을 감수하기로 결정할 수 있습니다. 그러나 NGINX Plus 기반 버전의 NGINX Ingress Controller를 사용하면 다시 로드할 필요 없이 키-값 저장소(Key-Value Store)를 활용하여 백분율을 변경할 수 있습니다.

NGINX Ingress Controller를 사용한 회로 차단(Circuit breaking) – 정교한 회로 차단기는 오류 및 장애 조치를 보다 신속하게 감지하고 비정상적인 업스트림에 대해 형식이 지정된 사용자 지정 오류 페이지를 활성화하여 시간을 절약하고 탄력성을 개선합니다. 예를 들어, 검색 서비스에 대한 회로 차단기는 올바른 형식이지만 비어 있는 검색 결과 집합을 반환하도록 구성될 수 있습니다. 이러한 수준의 정교함을 얻기 위해 NGINX Plus 기반 버전의 NGINX Ingress Controller는 TCP 및 UDP 업스트림 서버의 상태를 사전에 모니터링하는 활성 상태 확인을 사용합니다. 실시간으로 모니터링하기 때문에 클라이언트는 오류를 반환하는 앱을 경험할 가능성이 적습니다.

NGINX Service Mesh를 사용한 회로 차단(Circuit breaking) – NGINX Service Mesh 회로 차단기 사양에는 세 가지 사용자 정의 필드가 있습니다.

  • errors – 회로가 트립되기 전의 오류 수
  • timeoutSeconds – 회로를 트립하기 전에 오류가 발생하는 창과 회로를 닫기 전에 기다려야 하는 시간
  • fallback – 회로가 트립된 후 트래픽이 다시 라우팅되는 Kubernetes 서비스의 이름 및 포트

error 및 timeoutSeconds는 표준 회로 차단기 기능이지만 fallback은 백업 서버를 정의할 수 있도록 하여 탄력성을 더욱 향상시킵니다. 백업 서버 응답이 고유한 경우 클러스터 문제의 조기 지표가 될 수 있으므로 즉시 문제 해결을 시작할 수 있습니다.

2-3. 대시보드(Dashboard)로 트래픽 분할(Traffic Splitting) 결과 해석

트래픽 분할을 구현했습니다. 이제 어떻게 하시겠습니까? 결과를 분석할 차례입니다. 많은 조직이 Kubernetes 트래픽 및 앱의 성능에 대한 핵심 통찰력을 놓치고 있기 때문에 이것이 가장 어려운 부분일 수 있습니다. NGINX는 NGINX Plus 대시보드와 Prometheus Exporter에서 노출된 메트릭을 시각화하는 사전 구축된 Grafana 대시보드를 통해 더 쉽게 인사이트(insights)를 얻을 수 있습니다.