개요
Service Mesh의 필요성과 대표적 솔루션인 Istio에 대해 학습
소개
Istio는 프로그래밍적으로 제어할 수 있는 애플리케이션 중심의 네트워크를 k8s에 구성할 수 있도록 돕는 도구로써 Security, Observability, Reliability를 보장
Service Mesh의 대표적인 예시로는 Istio, Linkerd 등이 존재
•
등장 배경
Service 접근을 위해 내부망 진입점인 Gateway로만 처리하게 되면 많은 동작 처리로 무거워지는 문제가 있으며, 내부망에서 통신에 대한 제어 자체는 어렵다는 문제가 존재
Istio는 MSA 환경의 시스템 전체적인 모니터링의 어려움과 운영에서 장애나 문제가 발생 했을 때 원인 및 병목 구간을 찾는 어려움을 극복하기 위해 등장
동작 원리
등장 배경에서 의식한 문제를 해결하기 위한 기본 기능인 트래픽 모니터링과 트래픽 컨트롤을 모두 지원하는데, 기존 애플리케이션 코드의 수정 없이도 동작시키기 위해 Pod 간 통신 경로에 Proxy를 두는 식으로 동작
기존 통신
Istio
Istio에서는 Proxy를 통신 경로에 둔다고 했는데, 이는 Pod 내에 Sidecar 패턴으로 컨테이너 자체를 주입해서 단일 Pod 내에서 동작
Proxy 컨테이너가 애플리케이션의 트래픽을 가로채기 위해선 Pod에 있는 iptables 규칙을 조작해야 하는데, 클러스터 상에 존재하는 많은 Pod들을 대상으로 이러한 동작이 가능한 배경은 컨트롤 플레인 덕분
기능
트래픽 모니터링, 트래픽 컨트롤이 가능
트래픽 모니터링은 요청의 Error Rate, Latency, Connection Count, Request Count 등 메트릭을 볼 수 있으며, Service 간 특정 요청 경로에 따라 필터링하여 모니터링도 가능하므로 문제 발생 시 원인 파악에 용이
트래픽 컨트롤로는 Traffic Shifting, Circuit Breaker, Fault Injection, Rate Limit을 지원
•
Traffic Shifting : 카나리 배포처럼 비율로 기존 99%, 신규 1%와 같이 특정 엔드 사용자에게만 신규로 전달하도록 트래픽의 단계별 적용이 가능
•
Circuit Breaker : 목적지 MSA에 문제가 발생하는 경우 출발지 Service에 오류를 반환하면서 접속을 차단 시키는 기능인데, 이는 연쇄적인 장애를 방지하고 시스템 전체 장애를 예방하기 위함
•
Fault Injection : 의도적으로 요청 자체를 지연 시키거나 실패 시키도록 구현
•
Rate Limit : 특정 시간 단위 혹은 전체적으로 요청을 처리할 수 있는 수를 제한
내부 구조
트래픽 모니터링과 트래픽 컨트롤이 가능한 이유로는 애플리케이션이 배포되는 Pod마다 Proxy가 Sidecar 패턴으로 추가되기 때문이었는데, 이와 같이 Proxy가 함께 붙어 있는 논리적인 공간을 데이터 플레인이라고 지칭
데이터 플레인에서는 Routing, Service Discovery, Load Balancing, Security, Telemetry 등의 기능을 지원
여기서 언급된 Proxy는 Envoy를 Wrapping 하고 있는 Istio Proxy를 의미하는데, 이는 Envoy Wrapping과 k8s 연동이 쉽도록 Golang으로 개발되었으며 istiod와 직접적으로 통신하여 Istio의 기능을 제공
또한 데이터 플레인에서 Proxy가 적절히 기능을 수행할 수 있도록 iptables 규칙을 관리해주는 컨트롤 플레인이 존재한다고 했는데, istiod라는 데몬이 해당되며 내부적으로는 Pilot, Galley, Citadel이 포함
컨트롤 플레인에서는 새 Service를 찾아내고, 컨트롤 플레인이 담당하는 Service들의 Traffic Shifting, Circuit Breaking, Load Balancing, Timeout, Security에 해당되는 메타 데이터를 정의하는 역할을 수행
•
Pilot : Sidecar로 추가된 모든 Envoy에서 Proxy Routing 규칙을 관리하여, Service Discovery와 Load Balancing 설정을 제공
•
Galley : Pilot에 필요한 설정을 제공하고, Istio와 k8s 간 연결을 돕는 역할 뿐만 아니라 Service Mesh를 구성하는 데이터를 검증을 수행
•
Citadel : 보안 기능을 담당하여, TLS 인증서 발급과 관리를 통해 Service간 통신에서 암호화를 수행
단점
결국 중요한 점은 통신 과정에 개입하는 것들이 존재한다는 것으로, Service Mesh 자체는 가볍지 않다는 것이 중요
Proxy 자체는 인프라 내에서 강력하고 다양한 기능들을 지원하지만, 결국 리소스가 소모되고 네트워크 지연이 발생할 수 있음
•
Proxy 수가 늘어남에 따라 CPU와 메모리를 소모량이 많아지면서 가용 자원이 고갈되는 경우도 존재
•
단순히 통신 간 1개의 Connection을 이용하는 것이 아니라 Service 간에 위치한 2개의 Proxy로 3개의 Connection을 이용함에 따라 는 더 많은 Connection Pool을 점유하게 되고, 이는 트러블 슈팅 구간의 확장으로 플랫폼 운영자가 감수해야할 것들이 증가하고 엔드 사용자에게 네트워크 지연이라는 간접 영향 존재
Service Mesh에서의 Connection은 아래 그림과 같이 3개를 요구
•
Source Container → Source Proxy
•
Source Proxy → Target Proxy
•
Target Proxy → Target Container
칼럼에서 Linkerd와 리소스 소모를 비교한 결과를 보면 다소 충격적
요약
1.
Istio는 각 Pod 내에서 Sidecar 패턴으로 Envoy Proxy가 추가된 형태로 동작
2.
각 애플리케이션은 Pod 내에 공존하는 Envoy Proxy에 접근하기 위해 localhost에 TCP 접속을 수행
3.
모든 MSA 통신에서는 Envoy를 통과하여 동작하고, 이 과정에서 지표를 수집하고 트래픽을 컨트롤 가능
4.
컨트롤 플레인이 별도로 존재하여 Istio를 통해 정의한 정보를 바탕으로 Envoy의 설정이 이뤄지고, 이 덕분에 트래픽을 컨트롤 하기 위한 규칙이 Envoy에 설정
5.
MSA 내에서 Service 간의 통신을 mTLS (mutual TLS)로 암호화
기타
Istio의 오랜 구조는 Proxy를 두고서 동작하는 것인데, 위에서 확인한 구조적인 단점 때문에 Istio Ambient Mesh라는 모드가 등장하여 최근엔 이를 이용
Istio 1.23.0의 신규 기능으로 강력하게 Ambient를 어필하는데, Sidecar Less Mode여서 전반적인 구조 개선으로 적은 리소스 소모로 상당한 성능 향상을 누릴 수 있게된 업데이트
컨트롤 플레인의 istiod는 그대로 존재하여 원래 역할을 수행하나, 데이터 플레인의 Proxy에 해당되는 컴포넌트가 Ztunnel과 Waypoint로 분리
Ztunnel은 DaemonSet으로 L4를 대응하기 위한 것이고, Waypoint는 Deployment로 L7을 대응하기 위한 것으로 Istio Proxy를 대체하는 컴포넌트
모든 Pod 간의 통신은 Ztunnel은 통과하고, L7 기반의 로직을 처리해야 할 때만 Waypoint를 통과하는 방식으로 동작
Waypoint는 Gateway를 통해 네임스페이스 단위로 생성하는데, 이는 Waypoint가 특정 워크로드에 대해서 Gateway 역할도 수행한다는 것
특징으로는 아직까지는 애플리케이션 트레이싱이 미지원된다는 점, 그리고 istio-cni를 요구하지만 기존 CNI의 확장으로 구현되어 Cilium, Calico와 같은 CNI를 지원한다는 점이 있음