0. 이스티오(Istio)와 엔보이(Envoy)
최신 애플리케이션은 일반적으로 마이크로서비스의 분산 컬렉션으로 설계되며, 각 마이크로서비스 컬렉션은 개별 비즈니스 기능을 수행합니다. 서비스 메시는 애플리케이션에 추가할 수 있는 전용 인프라 계층입니다. 이를 통해 관찰 가능성, 트래픽 관리, 보안과 같은 기능을 자체 코드에 추가하지 않고도 투명하게 추가할 수 있습니다.
Kubernetes 기반 시스템과 같은 분산 서비스 배포의 규모와 복잡성이 증가함에 따라 이해하고 관리하기가 더 어려워질 수 있습니다. 요구 사항에는 검색, 로드 밸런싱, 오류 복구, 메트릭 및 모니터링이 포함될 수 있습니다. 또한 서비스 메시는 A/B 테스트, 카나리아 배포, 속도 제한, 액세스 제어, 암호화 및 엔드투엔드 인증과 같은 보다 복잡한 운영 요구 사항을 해결하는 경우가 많습니다.
이스티오(Istio)는 기존 분산 애플리케이션에 투명하게 계층화되는 오픈 소스 서비스 메시입니다. 이스티오의 강력한 기능은 서비스를 보호하고, 연결하고, 모니터링하는 균일하고 효율적인 방법을 제공합니다. 이스티오는 서비스 코드 변경이 거의 또는 전혀 없이 로드 밸런싱, 서비스 간 인증 및 모니터링을 추가할 수 있죠. 이스티오는 서비스 메시 전체에 대한 관찰 가능성과 운영 제어를 제공함으로써 마이크로서비스 애플리케이션의 다양한 요구 사항을 충족하는 아주 훌륭한 솔루션을 제공합니다.
이스티오에는 데이터 플레인과 컨트롤 플레인이라는 두 가지 주요 구성요소가 있습니다.
데이터 플레인 : 데이터 플레인은 확장된 엔보이(envoy) 프록시 를 사용하여 각 Kubernetes 포드에서 사이드카 컨테이너로 표시되는 프록시 서비스 컬렉션으로 구성됩니다. 이러한 사이드카는 마이크로서비스 간의 모든 네트워크 통신을 중재하고 제어하는 동시에 유용한 메트릭과 로그를 수집하고 보고합니다.
컨트롤 플레인 : 컨트롤 플레인은 상위 수준 라우팅 규칙 및 트래픽 제어 동작을 엔보이 관련 구성으로 변환한 다음 런타임 시 사이드카에 전파하는 역할을 담당하는 istiod라는 단일 바이너리로 구성됩니다. 컨트롤 플레인은 원하는 구성과 서비스 보기를 가져와 프록시 서버를 동적으로 프로그래밍하고 규칙이나 환경이 변경되면 이를 업데이트합니다.
쉽게 요약해 볼까요? 각 서비스의 네트워크 설정을 담은 VirtualService , DestinationRule 등의 리소스가 배포되면 컨트롤 플레인, 즉 istiod는 이 설정들을 모두 모아 엔보이 사이드카에게 쏴주는 역할을 합니다. (그 외에도 많은 역할을 수행합니다.) 엔보이는 애플리케이션에 사이드카 형태로 붙어 애플리케이션 컨테이너로 오가는 모든 패킷을 프록시해 라우팅하는 역할을 하죠. 그 요청들을 어떤 규칙들로 라우팅 하느냐? 바로 아까 istiod가 쏴준 설정 규칙들입니다.
1. 엔보이 프록시…란?
엔보이에 대해 본격적으로 파고들기 전에, 알고 있으면 좋을 몇 가지 정보가 있는데요. 엔보이를 더 잘 이해하려면 다음 개념을 잘 알고 있어야 합니다.
- Out-of-process 아키텍처: 엔보이는 독립적인 프로세스입니다. 엔보이 프록시 간에 투명한 통신 메시가 형성됩니다. 각 애플리케이션은 로컬 호스트로 메시지를 보내거나 로컬 호스트로부터 메시지를 받습니다. 이러한 종류의 메시지 전송은 네트워크 토폴로지와는 관련이 없습니다.
- 단일 프로세스 및 다중 스레드 모델: 이 모델에서 기본 스레드는 사소한 작업을 관리하고 작업자 스레드는 수신, 필터링 및 전달을 구현합니다.
- 다운스트림 호스트: 요청을 보내고 응답을 받는 엔보이 연결 호스트입니다. 즉, 다운스트림 호스트는 요청 발신자입니다.
- 업스트림 호스트: 요청을 받는 호스트입니다.
- 리스너: 포트 또는 명명된 네트워크 주소가 있는 UNIX 도메인 소켓입니다. 이 리스너는 다운스트림 호스트에 연결할 수 있습니다. 엔보이는 다운스트림 호스트에 연결하기 위해 하나 이상의 리스너를 노출합니다. 각 리스너는 레이어 3 및 레이어 4와 같은 특정 네트워크 수준의 필터로 구성됩니다. 리스너가 새 연결 요청을 받으면 구성된 로컬 필터가 인스턴스화되어 후속 이벤트를 처리합니다. 리스너 아키텍처는 쓰로틀링, TLS 클라이언트 인증, HTTP 연결 관리, MongoDB 스니핑, 원본 TCP 프록시 등 다양한 프록시 작업 대부분을 실행합니다.
- 클러스터: 엔보이에 연결된 논리적으로 동일한 업스트림 호스트 그룹입니다.
- xDS 프로토콜: 엔보이에서 xDS 프로토콜은 CDS(Cluster Discovery Service)를 포함한 여러 검색 서비스 프로토콜을 나타냅니다. LDS(리스너 검색 서비스), RDS(경로 검색 서비스), EDS(엔드포인트 검색 서비스) 및 SDS(비밀 검색 서비스)이 있습니다.
엔보이는 서비스 간 통신을 위한 다양한 기능을 제공합니다. 예를 들어 엔보이는 다운스트림 호스트에 연결하기 위해 하나 이상의 리스너를 노출할 수 있으며 포트를 통해 외부 애플리케이션에 리스너를 노출할 수 있습니다. 엔보이는 라우팅 규칙을 정의하여 리스너에서 전송한 트래픽을 처리하고 트래픽을 대상 클러스터로 전달할 수도 있습니다.
클러스터는 기본적으로 엔보이에 연결되어 있고 논리적으로 동일한 업스트림 호스트 그룹입니다. 클라이언트는 백엔드 서비스와 상호작용하는 동안 통신할 인스턴스 또는 IP 주소를 어떻게 알 수 있을까요? 이를 위해 엔보이는 라우팅 기능을 제공합니다. 엔보이는 SDS를 통해 클러스터의 모든 구성원을 검색하고, 각 구성원의 상태를 적극적으로 확인합니다.(헬스 체크) 그런 다음 엔보이는 요청을 정상 구성원에게 라우팅 하는 로드 밸런싱 정책을 구현합니다. 엔보이가 서비스 인스턴스 전체에 로드 밸런싱을 구현할 때 클라이언트는 실제 배포 세부 정보를 알 필요가 없습니다.
2. 엔보이 정적&동적 구성
엔보이는 JSON 또는 YAML 형식의 구성 파일로 구동되는 지능형 프록시입니다. 엔보이는 다양한 구성 버전을 제공합니다.
엔보이의 API 버전구성은 gRPC를 기반으로 합니다. 그 이유는 이러한 API를 호출하면 엔보이가 스트리밍 기능을 통해 구성을 집계하는 데 걸리는 시간을 줄일 수 있기 때문입니다. 이렇게 하면 API 폴링이 제거되고 서버가 주기적인 엔보이 폴링 없이 엔보이에 업데이트를 푸시할 수 있습니다.
엔보이 아키텍처를 사용하면 다양한 유형의 구성 관리 방법을 사용할 수 있습니다. 필요에 따라 배포 방법을 선택할 수 있습니다. 완전한 정적 구성을 통해 간단한 배포를 구현할 수 있습니다. 혹은 복잡한 동적 구성을 점진적으로 추가하여 복잡한 배포를 구현할 수 있습니다.
정적 구성
istio를 사용한다면 엔보이필터(EnvoyFilter)를 사용해 정적으로 라우팅룰을 구성할 수 있습니다. 자세한 내용은 문서를 참고합시다.
동적 구성
엔보이는 API 세트를 사용하여 다운타임이나 재시작 없이 구성을 업데이트할 수 있습니다. 엔보이에는 구성을 적절한 검색 서비스 API로 연결하는 간단한 부트스트랩 구성 파일만 필요합니다. 다른 설정은 동적으로 구성됩니다. 엔보이의 동적 구성 API는 xDS 서비스라고 하며 다음을 포함합니다.
- LDS: 이를 통해 엔보이는 전체 리스너를 쿼리 할 수 있습니다. 이 API를 호출하면 알려진 리스너를 동적으로 추가, 수정, 삭제할 수 있습니다. 각 리스너에는 고유한 이름이 있어야 합니다. 엔보이는 이름이 지정되지 않은 모든 수신기에 대해 UUID(Universally Unique Identifier)를 생성합니다.
- RDS: 이를 통해 엔보이는 경로 구성을 동적으로 검색할 수 있습니다. 경로 구성에는 HTTP 헤더 수정, 가상 호스트 구성 및 각 가상 호스트에 포함된 개별 라우팅 규칙이 포함됩니다. 각 HTTP 연결 관리자는 API를 통해 독립적으로 자체 경로 구성을 검색할 수 있습니다. LDS의 하위 집합인 RDS 구성은 정적 구성과 동적 구성을 사용할 시기와 사용할 경로를 지정합니다.
- CDS: 엔보이가 클러스터 관리 멤버를 동적으로 검색하기 위해 호출하는 선택적 API입니다. 엔보이는 API 응답을 기반으로 클러스터 관리를 조정하고 필요에 따라 알려진 클러스터를 추가, 수정 및 삭제합니다. 엔보이 구성에 정적으로 정의된 클러스터는 CDS API를 통해 수정하거나 삭제할 수 없습니다.
- EDS: 엔보이가 클러스터 구성원을 검색할 수 있게 해주는 gRPC 또는 RESTJSON 기반 API입니다. 이는 CDS의 하위 집합입니다. 엔보이에서는 클러스터 구성원을 엔드포인트라고 합니다. 엔보이는 검색 서비스를 사용하여 각 클러스터의 엔드포인트를 검색합니다. EDS는 선호되는 검색 서비스입니다.
- SDS: 인증서를 배포하는 데 사용되는 API입니다. 인증서 관리를 단순화합니다. SDS가 아닌 Kubernetes 배포에서는 인증서를 키로 생성하고 엔보이 컨테이너에 탑재해야 합니다. 인증서가 만료되면 해당 키를 업데이트하고 엔보이 컨테이너를 다시 배포해야 합니다. SDS를 사용하면 SDS 서버는 모든 엔보이 인스턴스에 인증서를 푸시합니다. 인증서가 만료되면 SDS 서버는 새 인증서를 엔보이 인스턴스에 푸시하기만 하면 됩니다. 그런 다음 엔보이 인스턴스는 재배포 없이 즉시 새 인증서를 적용합니다.
- ADS: 직렬화된 스트림에서 이전 API의 모든 변경 사항을 순서대로 검색하는 데 사용됩니다. 본질적으로 ADS는 xDS 서비스가 아닙니다. 오히려 단일 스트림에서 여러 xDS 서비스에 대한 동기식 액세스를 구현합니다.
구성에 하나 이상의 xDS 서비스를 사용할 수 있습니다. 엔보이의 xDS API는 궁극적인 일관성을 위해 설계되었으며, 적절한 구성은 결국 수렴됩니다. 예를 들어, 엔보이는 결국 새 경로를 사용하여 RDS 업데이트를 검색할 수 있으며, 이 경로는 CDS에서 아직 업데이트되지 않은 클러스터로 트래픽을 전달할 수 있습니다. 결과적으로 CDS가 업데이트될 때까지 라우팅 프로세스에서 라우팅 오류가 발생할 수 있습니다. 엔보이는 이 문제를 해결하기 위해 ADS를 도입했습니다. Istio는 프록시 구성을 수정하는 데 사용할 수 있는 ADS도 구현합니다.
엔보이 XDS 작동 방식에 대해 최종적으로 요약하자면 다음과 같습니다.
- 구성 서버(istiod)는 엔보이 프록시가 서비스 메시에서 트래픽을 라우팅 하는 데 필요한 모든 구성 정보에 대한 중앙 저장소 역할을 합니다.
- 구성 서버는 XDS(검색 서비스) 프로토콜을 통해 엔보이 프록시에 대한 동적 구성 업데이트를 제공합니다. XDS 프로토콜은 gRPC를 사용하여 제어 평면과 데이터 평면 간의 통신을 활성화합니다.
- 서비스 메시에 새 서비스가 추가되거나 기존 서비스가 업데이트되면 구성 서버는 엔보이 프록시에 새 구성 업데이트를 보냅니다.
- 엔보이 프록시는 새 구성 업데이트를 적용하고 새 규칙에 따라 트래픽 라우팅을 시작합니다.
- 또한 구성 서버는 상태 확인 정보를 엔보이에 제공할 수 있으며, 이를 통해 엔보이는 정상적인 서비스 인스턴스로만 트래픽을 라우팅 할 수 있습니다.
- 이러한 방식으로 컨트롤 플레인과 데이터 플레인이 함께 작동하여 서비스 메시에서 동적 서비스 검색 및 트래픽 라우팅을 제공합니다.
3. 엔보이 프록시 처리 단계: 패킷 처리 방법
패킷이 엔보이 프록시에 도착하면 최종 목적지에 도달하기 전에 일련의 단계를 거칩니다. 아래 그림을 참고합시다.
수신 단계에서 엔보이 리스너 컴포넌트는 다운스트림 클라이언트의 특정 포트와 프로토콜(예: TCP, HTTP, HTTPS)에서 들어오는 연결을 수락합니다. 리스너 필터 체인(Listener Filter Chain)은 SNI 및 기타 사전 TLS 세부 정보를 제공하고 대상 IP CIDR 범위, SNI, ALPN, 소스 포트 등을 기반으로 네트워크 필터 체인(Network Filter Chain)과 일치시킵니다. TLS 전송 소켓과 같은 전송 소켓은 보안 통신을 위해 필터 체인과 연결됩니다.
네트워크 필터 체인(Network Filter Chain)은 네트워크 읽기 과정에서 TLS 전송 소켓을 사용하여 TCP 연결의 데이터를 복호화하며, HTTP 연결 관리자 필터(HTTP Filter Chain)는 체인에서 가장 마지막에 위치합니다. HTTP 연결 관리자의 HTTP/2 코덱은 TLS 연결에서 해독된 데이터 스트림을 독립적인 스트림으로 역프레임 화하고 역다중화하여(deframes and demultiplexes) 각 요청과 응답을 처리합니다.
각 HTTP 스트림에 대해 해당 HTTP 필터 체인이 생성되고 실행됩니다. 요청은 그 요청을 읽고 수정할 수 있는 사용자 지정 필터를 통과합니다. 라우터 필터는 체인의 가장 마지막에 위치한 가장 중요한 HTTP 필터로, 수신 요청의 헤더를 기반으로 경로와 클러스터를 선택합니다. 그런 다음 헤더는 해당 클러스터의 업스트림 엔드포인트로 전달됩니다. 라우터 필터는 이 프로세스를 처리하기 위해 클러스터 관리자로부터 일치하는 클러스터에 대한 HTTP 연결 풀을 가져옵니다.
클러스터 특화방식의 로드 밸런싱(Cluster-specific load balancing)이 수행되어 엔드포인트를 찾고, 서킷 브레이커를 확인하여 새 스트림이 허용되는지 확인합니다. 엔드포인트의 연결 풀이 비어 있거나 용량이 부족한 경우 엔드포인트에 대한 새 연결이 만들어집니다. 업스트림 엔드포인트 연결의 HTTP/2 코덱은 요청의 스트림을 단일 TCP 연결을 통해 해당 업스트림으로 가는 다른 스트림과 함께 멀티플렉싱하고 프레임을 구성합니다. 업스트림 엔드포인트 연결의 TLS 전송 소켓은 이러한 바이트를 암호화하여 업스트림 연결을 위한 TCP 소켓에 씁니다.
헤더와 바디, 트레일러로 구성된 요청은 업스트림으로 프록시되고 응답은 다운스트림으로 프록시됩니다. 응답은 라우터 필터에서 시작하여 사용자 지정 필터를 통과한 후 다운스트림으로 전송되기 전에 요청과 반대 순서로 HTTP 필터를 통과합니다. 응답이 완료되면 스트림이 삭제됩니다. 통계 업데이트, 액세스 로그에 쓰기, 추적 범위(trace span) 마무리 등의 요청 후 처리가 수행됩니다.
마지막으로 송신 구성은 전송 프로토콜, 암호화 및 기타 설정을 포함하여 다운스트림 클라이언트에 대한 엔드포인트 정보를 지정합니다. 적절한 프로토콜과 전송 메커니즘을 사용하여 다운스트림 클라이언트로 응답을 전달하도록 엔보이를 구성할 수 있으므로 업스트림 서비스의 응답을 처리하는 필터를 구성하고, 응답 헤더를 추가하고, 쿠키를 설정하고, 캐싱을 수행하는 등의 작업을 수행할 수 있으며, 응답을 기록하는 액세스 로그 필터도 구성할 수 있습니다.
정리하자면, 엔보이 프록시 구성은 고도화 커스터마이징이 가능하며 애플리케이션 아키텍처의 특정 요구 사항을 충족하도록 맞춤 설정할 수 있습니다. 패킷 수명 주기의 각 단계를 신중하게 구성하면 최신 애플리케이션을 위한 고급 트래픽 관리, 통합 가시성, 보안 기능을 확보할 수 있게 되겠죠.
지금까지 엔보이가 패킷을 받아 라우팅 하기까지의 여정을 살펴봤는데요. 2편에서는 엔보이의 컴포넌트 로깅과 액세스 로깅, 엔보이가 일시적인 오류를 처리하는 방법과 핫 리스타트에 대해 알아보겠습니다. 곧 돌아오겠습니다!
참고자료
https://istio.io/latest/docs/tasks/observability/metrics/tcp-metrics/
https://dramasamy.medium.com/life-of-a-packet-in-istio-part-1-8221971d77de
'🏋️♀️ DevOps, SRE' 카테고리의 다른 글
AWS Graviton (그래비톤)은 정말 더 빠르고, 더 성능이 좋고, 더 쌀까 ? (0) | 2024.05.20 |
---|---|
엔보이(envoy) 딥-다이브 (2) : 엔보이 로깅의 2가지 종류 (1) | 2024.02.27 |
Renovate bot을 사용해 argoCD로 배포한 helm 차트 버전을 체계적으로 관리해보자 (1) | 2024.01.09 |
Github Actions Kubernetes에서 self-hosted 설치&운영하기 (0) | 2023.09.05 |
DevOps vs SRE , 차이점과 공통점에 대해 (0) | 2023.08.22 |