Search
Duplicate
📌

Istio overview: Architecture, Traffic Management

Category
as S/W 엔지니어
Tags
Envoy
Istio
Service Mesh
Cilium
k8s
Kubernetes
Traffic Management
Created time
2024/04/27

Introduction

대표적 Service Mesh 제품인 Istio에 대한 overview로 Kubernetes를 배경으로 설명한다.
이 중 Service Mesh의 개요 및 아키텍처, 그리고 features 중 Traffic Management에 대해 논한다(이후 Istio overview: Observability, Istio overview: Security, Istio overview: Extensibility, Etc. 로 이어진다).

Service Mesh란

일단, 정의는 Wikipedia에서 가져왔다.
프록시를 사용하여 서비스 또는 마이크로서비스 간 서비스 간 통신을 촉진하는 전용 인프라 계층
Service Mesh는 pod 수준의 L7 traffic 처리를 위한 일종의 overlay network이다. sidecar 등의 기법으로 각 pod에 붙은 proxy가 모든 pod에 대한 in/outbound traffic를 제어함으로, 각종 부가적 features를 추가한다. API Gateway를 cluster 전체에 대한 proxy라 한다면, Service Mesh는 pod에 대한 proxy, 그리고 이들 proxy 간의 연합이라 볼 수 있다.

Architecture

윗 그림은 앞선 구조 관점의 Istio의 정의를 나타냄과 동시에 Istio가 없는 traffic 흐름과의 차이를 보여준다.
Istio가 없는 상단 traffic은 kube-proxy에 의해 L4에서 routing되는 반면(L4 load balancing), Istio 기반의 하단 traffic은 kube-proxy 없이 L7에서 routing되어(L7 load balancing), kube-proxy 의 개입 없이 destination pod로 직접 전달된다. 참고로 Istio의 default LB algorithm은 Least Request로, 일반적으로 kube-proxy의 random 방식보다 났다고.
Control plane인 istiod 는 앞선 routing에 필요한 pod IP를 포함한 cluster 정보를 각각의 Istio proxy에 동기화함과 동시에 각종 control message를 전달한다.
참고: sidecar-less Service Mesh 근래에 sidecar 없는 아키텍처의 Service Mesh가 부각되었는데, Istio는 Ambient Mesh라 하여 Daemon Set(ztunnel)과 Deployment(waypoint)로 envoy proxy의 역할을 나누고, Cilium은 eBPF 기반으로 DaemonSet을 사용한다. 하지만 sidecar만 없을 뿐 개념적으로는 기존과 동일하다.
이 아키텍처의 목적은 sidecar pattern의 리소스 과다 사용, 성능 저하, 아키텍처 복잡도 증대 등의 단점 개선으로, 24.05.13 에 alpha에서 beta로 버전 업데이트되었다.
이에 대해서는 Istio Internals: Ambient mode 에서 다루며, Istio overview 글 전체에서 특별한 언급이 없는 이상 모두 sidecar mode를 상정한다.

타 아키텍처 대비 비교 우위점

Service Mesh의 부가 가치는 크게 세 영역, 즉 Traffic Management, Observability, Security로 나눌 수 있으며 이들은 모두 cross cutting concerns에 해당한다. 이들은 그간 app에서 SDK, Monkey patching, bytecode injection, 또는 agent 등을 통해서 구현하거나 아예 이루지 못한 것들이다.
이 cross cutting concerns 제공 관점에서 볼 때, Service Mesh는 이들 기존 방안에 비해 아키텍처에서 특히 우위를 점한다. 아래 그림은 이를 단적으로 표현하는데, 좌측은 Service Mesh를 사용하지 않았을 경우를 우측은 사용했을 경우의 아키텍처를 나타낸다.
Service Mesh를 사용했을 경우(우측)와 그렇지 않을 경우(좌측)의 아키텍처
Service Mesh는 application source code / process에 대한 의존성이 없음과 동시에, 단일 runtime 하에 이들 feature 모두를 제공한다. 반면 기존 방안의 경우 feature 별로 각기 다른 provider와 방식으로 구현되어 feature 간의 간섭 발생 및 일관성을 잃을 가능성이 높아짐과 동시에, 이들 방법 중 상당 수는 application source code / process에 대한 의존성을 갖는다.
정리하자면, Service Mesh는 이를 사용하지 않는 방안에 비해 낮은 복잡도(높은 응집성과 낮은 결합성) 와 적은 관리 지점의 장점을 갖는다는 뜻이다. 아키텍처는 복잡할수록 취약하다.
이어지는 내용은 위에서 언급한 Service Mesh의 부가 가치인 Traffic Management, Observability, Security 각각에 대해 Istio가 제공하는 features이다. 참고로, Istio이 지원하는 프로토콜은 TCP, TLS, HTTP1.1, HTTP2, HTTPS, gRPC, gRPC-web의 범용 프로토콜 이외에도, mongo, mysql, redis의 유명 제품 프로토콜도 포함한다(참고).

Traffic Management

한마디로 표현하다면 Kubernetes Service에 대한 L7 기반의 제어로서, Kubernetes Service가 사실 상 L4 Load Balancer임을 고려한다면 Service Mesh는 L7 Load Balancer 및 이들을 전체 또는 부분적으로 제어하는 controller라고 보아도 크게 틀리지 않다.
구체적으로 제공하는 feature는 아래와 같이 Traffic Control, Resilience, DNS Proxying 으로 나눌 수 있다.

Traffic Control

앞서 논한 L7 기반 제어의 직접적인 응용에 해당한다.
Traffic routing: 예컨데, path나 HTTP header 값에 따라 특정 service로 traffic을 분류한다. A/B Testing, Dark release 등 구현을 가능하게 한다.
Traffic splitting(shifting): Traffic을 가중치를 두어 여러 service로 분산한다. Canary, Blue/Green deployment 등 구현에 유용한데, Canary는 Kubernetes Service만 갖고는 불가능하다는 점에서 특별히 의미있다.
Traffic mirroring(shadowing): traffic을 복제하여 다수의 service로 전달한다. 예컨데, 이를 통해 운영 환경에서 새로운 기능이 정상 동작하는지를 release되지 않은 새로운 service에서 사전에 검토할 수 있다. mirroring된 request에 대한 response는 client로 전달되지 않는다(fire and forget).
Ingress / Egress Gateway: service mesh 전체에 대한 in/outbound traffic 관리(Ingress, Egress)로 이 중 inbound traffic 관리 feature는 사실 상 API Gateway로서, 여기에는 Redis 지원의 rate limiting도 포함된다.

Resilience

Microservice는 Monolith 대비 높은 아키텍처 복잡도로 인하여 필연적으로 취약하다. 단적으로 Monolith의 function call 대비 Microservice의 API call은 network로 인해 실패률이 급속히 올라간다. 회복탄력성으로 번역되는 Resilience는 이에 대한 대비이다.
Timeout: 지정한 timeout까지 service로부터 response가 없으면, timeout response를 반환한다. 어떤 이유에서건 application level에서 적절한 timeout이 지정되지 않은 경우에 대한 대응과 응답 시간을 예측 가능하게 한다.
Retry: 최초 호출에 실패했을 경우 지정한 횟수만큼 재연결을 시도한다. 분산 시스템에서는 network 이슈, 순간적 부하 등으로 인한 서비스 오류는 상시 있기 마련이고 호출 재시도만으로 해결되는 경우가 많다.
Circuit breaking: Circuit breaking은 계단식 실패(Cascading Failure)의 대표적 해결안으로, 지정한 기준을 넘어서면 문제의 service로 traffic이 유입되지 않도록 사전에 차단한다.
Fault Injection: Service에 관계없이 지정한 지연, 비율, 오류 코드로 응답한다. client의 오류 대응 테스트에 유용하다.
Locality Load Balancing: 다양한 수준의 지역적(Locality) 단위, 즉 Region(e.g. 국가), Zone(e.g. 지역), Subzone(e.g. 서버 랙)에 따라 load balancing이 가능하다. 이는 지역적 관점의 load balancing 뿐 아니라 disaster recovery, 즉 failover의 주요 수단이 된다.

DNS Proxying

Istio 자체적으로 Kubernetes Service와 ServiceEntry Istio resource를 통한 외부 서비스 DNS 를 관리하여, application의 coreDNS 등으로의 DNS lookup 연산을 “drastically(공식 문서 표현)” 감소시킨다. 이는 FQDN 미사용으로 인한 DNS lookup 횟수 증가 이슈를 처리할 뿐 아니라, istiod가 DNS entry를 제공함으로 클러스터 내 서비스로의 DNS lookup 연산을 제거하기 때문이다.
Istio overview: Observability 로 이어집니다.

References

본 글 작성에 주로 참조한 문서이다.