1W - 서비스 메시와 이스티오

개요

이스티오를 설정하고 관리하는 방법을 공부하기 이전에, 먼저 서비스 메시 툴로서의 이스티오를 명확히 이해해보자.

개념 정리

서비스 메시란


서비스 메시는 다양한 서비스가 그물망처럼 다양하게 얽히고 연결되어 있는 구조, 아키텍처를 말한다.
큰 서비스의 관점에서, 서비스 메시는 네트워크만을 따로 담당하는 추상된 인터페이스 레이어를 가진다는 것이 핵심이다.
서비스 메시는 아키텍처 개념인 만큼 독립된 서비스들을 운용하며 이들을 효율적으로, 장애가 전파되지 않도록 운영하는 기술과 방식도 포함하여 일컫는다.
대표적인 서비스 메시 툴에는 Istio가 있다.

이 개념을 익숙치 않다면, 등장 배경을 먼저 아는 것이 좋다.

용어 정리 - 어플리케이션과 서비스의 차이

클라우드 네이티브가 활성화되면서 어플리케이션과 서비스라는 용어가 많이 나오기 시작했다.
둘 다 비슷한 뜻이기는 하지만, 그래도 서비스 메시를 이해하기 위해서 먼저 두 용어를 간단하게 개념 차이를 짚을 필요가 있다.

먼저 어플리케이션은 어떤 기능을 하는 프로그램이며, 이것을 만드는 사람이 바로 개발자이다.
서비스, 비즈니스 로직이 담긴 프로세스라고 이해해도 좋다.
이 어플리케이션을 실제 사용자가 사용할 수 있도록 구축한 환경을 포함하는 개념이 서비스이다.
어플리케이션을 만들었으면 클라이언트가 이것을 활용할 수 있도록 시스템을 구축해야 한다.
사용할 수 있는 엔드포인트를 노출시키고, 도메인을 등록하거나 적절한 자원을 배치하는 운영적 요소가 결합된, 어플리케이션이 실제로 목적대로 사용될 수 있도록 하는 일련의 모든 과정이 들어간 개념이 서비스라고 할 수 있다.
인프라에 대한 개념이 들어가기 때문에 서비스를 담당하는 것은 운영자이다.

서비스에는 필연적으로 네트워크적인 요소가 들어가게 된다.
이러한 개념 정리 아래, 왜 우리가 마이크로 어플리케이션 아키텍처라고 하지 않고 마이크로서비스 아키텍처라고 하는지도 이해할 수 있다.
작은 기능 단위로 여러 어플리케이션을 책임지는 서비스를 분리하고, 이를 통합적으로 구성하여 궁극적인 시스템을 구축한 것이 바로 마이크로서비스 아키텍처이다.
여기에는 각 어플리케이션들을 네트워크로 긴밀하게 연결하는 과정이 필수적으로 들어가는데, 그렇기에 이 단위들은 서비스라고 부르는 것이 더 바람직하다.

배경 - 마이크로서비스아키텍쳐의 문제

컨테이너 기술이 본격화되며 어플리케이션을 패키징하는 것이 용이해졌고, 이런 컨테이너를 여러 노드에서 통합적으로 관리할 수 있도록 오토스케일링과 자동화 기능을 하는 컨테이너 오케스트레이션(대표적으로 쿠버네티스) 기술이 발달했다.
이로부터 유연한 확장성을 확보할 수 있는 MSA도 자연스럽게 정립됐다.
MSA의 가장 큰 특징 중 하나는 인프라 환경과 어플리케이션의 결합도를 낮춘다는 것으로, 물리적 자원의 제약에서 벗어나 자유롭게 기능을 확장하고 대처하는 것이 가능해졌다.
image.png
그러나 MSA 역시 몇 가지 문제점을 야기한다.
모놀리틱 아키텍처와 비교했을 때, 전체 아키텍쳐가 세분화되기에 구조는 복잡해지고 관리포인트가 늘어나게 된다.
현대 MSA에서 마주칠 수 있는 큰 문제점을 정리해보자.

간단하게 정리했지만, 각각을 더 세분화시켜 문제점으로 삼을 수도 있을 만큼 운영 상에 굵직한 이슈들이라 할 수 있다.

해결 방안과 방향성

그러면 종합해서 현대 MSA에서 마주하는 도전과제들과 이를 위한 방법들도 간단하게 정리해보자.

근데.. 위 요소들을 누가 맡아서 작업을 수행해야 하는가?
서비스 메시가 등장하기 이전에는, 당연히 위 방법들은 어플리케이션을 만드는 개발팀이 해야만 했다.
메트릭을 노출하는 엔드포인트를 만들고, 모든 요청에 span을 넣어서 트레이싱이 가능하게 한다던지..
요청이 실패했을 때 알아서 재시작을 하게 한다던지..
이를 위해 Eureka, Zuul 등의 다양한 언어 라이브러리들이 등장하였고 지금도 쓰이고 있기는 하다.
그러나 MSA 환경에서 효율적인 전략이라고 하기에는 역시나 많은 문제가 있다.

운영팀으로서는 이 해결책들을 개발팀한테 "해 줘"해야 하는 입장이긴 하나, 이러한 방식은 개발팀의 업무에 지장을 주기도 하는 동시에 전체 운영 환경의 유연성을 해친다는 것이다.

서비스 운영팀에서 해결하기 - 네트워크 레이어 분리

위 문제들은 운영 상 발생하는 문제이기도 한데, 비즈니스 로직에 집중을 해야 하는 개발팀이 주체적으로 대응하는 방식은 매우 아쉬운 해결책이다.
또한 재시도, 트레이싱 등의 해결책들은 어플리케이션 기능과도 관련도 없고 언어와 프레임워크에 한정해 고려해야 하는 요소들도 아니다.
이로부터 자연스럽게 이것들을 서비스 관리를 책임지는 운영팀에서 처리할 수 있는 방안이 강구되기 시작했고, 그렇게 등장한 것이 바로 서비스 메시이다.
image.png
위 문제와 해결 방법들은 사실 전부 네트워크와 관련되는 문제라는 공통 분모를 가지고 있다.
이로부터 어플리케이션 간에 이뤄져야 하는 네트워크 관련 기능과 이슈들은 아예 하나의 레이어로 분리하여 관리하는 것.
서비스 메시 레이어가 있으면 어플리케이션의 세팅이 어떤지 상관 없이 모든 네트워크 기능들을 운영 단계에서 해결할 수 있게 된다.
이것이 바로 서비스 메시의 등장 배경이자, 주된 기능이라고 할 수 있다!

서비스 메시 구조

image.png
image.png
image.png
클라우드넷 스터디의 자료가 굉장히 명쾌하게 이해된다고 생각해 가져왔다.
서비스 메시는 3번의 구조를 가지고 있는데, 왜 이런 구조를 가지고 있는지 단계적으로 이해하기 좋다.

데이터 플레인

배경에서 나온 내용에 이어서, 어떻게 어플리케이션과 별개로 네트워크 기능들을 처리한다는 말인가?
image.png
구체적으로는 이렇게 모든 서비스 앞단에 네트워크 기능을 처리하는 프록시를 두는 방식으로 이뤄진다.
이 프록시 서버가 서비스가 주고받을 트래픽을 먼저 받아서 스팬을 달던, 적절한 경로를 설정해주던 실패하면 재시도를 해주던, 암호화를 해주던!
트래픽의 모든 기능을 이해할 수 있는 L7 프록시로서 모든 기능을 처리하면 되는 것이다.

어플리케이션에 일체 설정을 하지 않고 어떻게 프록시가 트래픽을 처리할 수 있게 설정하는지 궁금할 수 있다.
이건 네트워크 트래픽이 흐르는 구조를 생각하면 쉽게 이해할 수 있다.
어떤 프로세스가 트래픽을 보낼 때는 네트워크 계층 구조를 거치는데, 어플리케이션은 이때 상위 계층의 구조만을 이해하고 트래픽을 처리한다.
그렇다면 해당 트래픽이 아래 계층을 타서 L1까지 이어져 다른 어플리케이션으로 가서 다시 L7의 트래픽으로 인식되기 전까지, 그 아래 계층에서 트래픽을 조작하면 간단하게 프록시가 트래픽을 받아서 처리하게 만들 수 있다.
가령 iptables를 이용하면 L3, L4 단계의 트래픽을 조작하는 것이 가능한데, 이걸 인프라 단계에서 설정해버리면 모든 서비스의 트래픽을 마음대로 조절하는 것이 가능하다.
image.png
그래서 서비스 메시에서는 서비스마다 트래픽이 프록시를 거치게 만들어 이러한 플로우를 달성한다.
당연히 각 서비스는 자신의 앞단에 프록시가 있는지 알 필요도 없고 알지도 못한다.

컨트롤 플레인

무수한 서비스가 있을 텐데 여기에 일일히 프록시를 주입하고 설정하는 것은 당연히 어려운 일이다.
image.png
그래서 서비스 메시에서는 보통 각 서비스에 부착되는 프록시 구조 일체의 영역을 데이터 플레인으로 두고, 이를 관리하는 컨트롤 플레인을 따로 구축한다.
운영 팀은 컨트롤 플레인에 각종 설정을 하고, 컨트롤 플레인은 설정에 기반하여 각 프록시를 세팅하고 관리하는 역할을 수행한다.
이스티오의 경우 컨트롤 플레인 istiod는 트래픽 라우팅 관리, 통신 암호화, 클러스터 환경 내 인증 인가 등의 기능을 수행한다.
이를 통해 서비스 메시 환경의 관리를 원활하게 수행할 수 있게 되는 것이다.

비단 데이터 플레인의 프록시를 조작하는 역할로서의 컨트롤 플레인을 상정하지 않더라도, 네트워크를 총괄하는 중앙 집중형 시스템을 구축한다는 것은 충분히 메리트있는 선택지이기는 하다.
이 부분에 대해서는 서비스 메시와 [[#다른 시스템과의 비교]]를 통해 조금 더 짚어보도록 하겠다.

서비스 메시의 기능

이제 서비스 메시라는 것은 하나의 추상화된 레이어를 일컫는 개념이자, 이를 활용하는 아키텍처라는 것을 명확히 할 수 있을 것이다.
그리고 서비스 메시는 인프라 레이어와 밀접한 연관을 가지는 어플리케이션의 네트워크 기능을 전적으로 담당하는 역할을 수행한다.
그럼 구체적으로 서비스 메시를 통해 어떤 것들을 할 수 있는지를 구체화시켜보자.

호고곡.. 어플리케이션에 영향을 주지 않고 이런 것들을 할 수 있다니 넘나 좋다!

서비스 메시 고려 요소

이렇게만 말하면 서비스를 운용할 때 반드시 서비스 메시를 사용해야 할 것처럼 들리기도 하지만, 당연히 서비스 메시를 도입하는 것에도 트레이드 오프는 존재한다.

서비스 메시가 적합한 경우는 인프라 환경과 어플리케이션이 명확하게 분리되어 운용될 수 있는 환경이다.

이럴 때, 인프라 환경과 어플리케이션의 관심 영역과 라이프사이클은 느슨한 결합도를 가질 수록 운영이 간편해지는데, 이때 중간다리로서 서비스 메시를 두는 것은 매우 효과적이다.
이런 상황에서 서비스 메시는 플랫폼과 코드를 이어주는 연결 조직 역할을 수행할 수 있다.

그렇다면 서비스 메시를 도입함으로써 가지게 되는 불편함은 무엇이 있을까?
(이스티오를 도입할 수 있는 장점은 이스티오를 도입하지 않아도 이룰 수 있다는 많은 실무자들의 많은 푸념을 많이 봤다..)

서비스 메시와 다른 시스템과의 비교

Enterprise Service Bus

image.png
ESB는 서비스 지향 아키텍처(Service Oriented Architecture)를 구축하는 방향성으로 나온 또다른 아키텍처이다.[1]
ESB는 하나의 서비스 버스(트래픽을 운송하는 수단)을 상정하는데, 서비스 메시와 마찬가지로 이것은 서비스 입장에서는 암묵적인 파트너(silent partener)로서 서비스는 이를 몰라도 되도록 구성된다.

그러나 서비스 메시와 다른 몇 가지 지점이 있다.

서비스 메시는 서비스가 자신 아래 어떤 메시가 구성돼있는지 몰라도 되는 한편, 서비스 메시도 자신이 관리할 서비스가 어떻게 구성돼있는지 자세히 알 필요가 없다.
각 서비스가 어떤 서비스와 통신을 해야하는지, 네트워크 구성도에 대한 정보만 알고 있다면 서비스 메시는 운영팀이 알아서 구성할 수 있다.

API Gateway

image.png
api 게이트웨이 역시 위의 구조와 상당히 비슷한데, 하나의 게이트웨이를 두고 외부 노출 엔드포인트와 클러스터 내부의 엔드포인트를 전부 관리하는 방식이다.
ESB와 같이 비즈니스 로직에 깊게 관여하진 않고, 하나의 중앙 경로 역할만 수행한다.
그냥 흔히 엔드포인트를 기반으로 라우팅할 백엔드를 두는 프록시를 생각하면 된다.
대체로 엔드포인트 경로를 기반으로 라우팅할 서비스가 결정되는데, 이 역시 중앙 집중형 시스템으로 인해 단일 장애 지점이 생기는 꼴이라 할 수 있다.

그렇지만 각 서비스가 통신을 하기 위해 하나의 홉을 더 거치게 되므로 비효율이 야기된다.
또 서비스 메시에서 할 수 있는 서킷 브레이커나 복원성에 대한 기능들까지 감안된 아키텍처도 아니다.

이스티오

이제 본격적으로 대표적인 서비스 메시 툴 중 하나인 이스티오에 대해서 알아보자.
image.png
쿠버네티스에서 활용할 수 있는 대표적인 서비스 메시 툴.
어플리케이션 간 트래픽을 연결 관리하면서, 보안이나 모니터링을 용이하게 해준다.
가령 자체적으로 mTLS를 적용하거나 로드밸런싱, 트래픽 미러링 등의 작업을 할 수 있다.

2017년에 처음 발표되고 CNCF에 기증되어 쿠버네티스, 프로메테우스와 비슷한 시기에 졸업 프로젝트가 됐다.
구글과 IBM이 파트너십을 체결하고 개발에 착수했으며, Envoy를 만든 Lyft팀과 결합하여 개발됐다.

이스티오의 언어적 의미는 그리스 언어로 "Sail", 즉 항해를 의미한다.
그리스어로 조타수를 의미하는 쿠버네티스와 언어적 연관성을 두는 작명이라 할 수 있겠다.

최근 다양한 CNI들이 서비스 메시적인 기능을 제공하기 시작했다.
그러나 이들이 자체 표준으로 서비스 메시를 제공하는 것은 아니며, 어떤 것을 쓸지는 선택이다.
다만 이스티오는 훨씬 성숙하고, 정제된 형태로 발전해왔으며 게이트웨이API도 실질적으로 이스티오를 전신으로 둔 채로 개발된 것이나 다름없다는 점을 생각하면 이스티오의 대안이 있다고 해서 이스티오가 가뿐히 무시될 만하다고 보기는 힘들다고 생각한다.

이스티오 구조

image.png
서비스 메시로서, 이스티오는 데이터 플레인 프록시로 Envoy를 활용하고 컨트롤 플레인에는 istiod를 두고 있다.
기본 구조 자체는 서비스 메시에서 나온 내용 그대로이니 각 영역에 어떤 것이 쓰이는지만 다루겠다.

데이터 플레인 - Envoy

엔보이는 각 파드에 사이드카 컨테이너로 같이 배포되어, 서비스 간 트래픽의 모든 영역을 담당한다.
엔보이는 동적 설정이 가능해서 유동적으로 컨트롤 플레인이 트래픽을 관리할 수 있도록 돕는다.
대표적으로 엔보이가 하게 되는 기능을 정리하자면...
동적 서비스 디스커버리 - 로드 밸런싱 - TLS 터미네이션 - HTTP2, gRPC 프록시 - 서킷 브레이킹 - 헬스체크 - 트래픽 스플릿 - 메트릭 - 에러 주입 등등..
그냥 다 해준다.
아무튼 모든 파드에 붙어 네트워크 기능을 제공해주는 방식이라고만 알면 되겠다.
참고로 이 방식을 벗어나 새롭게 나온 모드가 ambient mode인데 관련한 내용은 이후 주차에 보게 될 것이다.

컨트롤 플레인 - istiod

istiod 내부에는 다시 세 가지 컴포넌트로 나뉜다.

image.png
내부적으로는 이렇게 세 가지로 나뉘기는 하나 실상 클러스터에 배포되는 파드에는 이 프로세스들이 통합되어 있다.

istioctl

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: default
  hub: gcr.io/istio-testing
  tag: latest
  revision: 1-8-0
  meshConfig:
    accessLogFile: /dev/stdout
    enableTracing: true
  components:
    egressGateways:
    - name: istio-egressgateway
      enabled: true
  values:
    ...

이스티오는 자체적인 명령툴인 istioctl을 제공한다.
istioctl은 istio operator라는 양식을 통해 이스티오에 대한 전반적인 설정을 관리할 수 있도록 도와준다.

프로필

이스티오는 배포, 플랫폼 프로필의 개념을 이용하여 요구사항에 맞게, 환경에 맞게 설치 방식을 더 세분화시킨다.
프로필을 무조건 뭘로 해야지만 제대로 동작한다, 이런 개념은 아니다.
그냥 요구사항에 맞는 갖가지 내장 베이스라인을 제공하는 정도로 생각하면 되겠다.
image.png
배포 프로필의 종류는 이렇다.

image.png
플랫폼 프로필에는 위 종류들이 있다.

본격적으로 실습을 진행하며 istioctl을 사용하는 방법을 구체화해보자.

실습 진행

이번 실습에서는 아주 간단하게 이스티오를 구축하고, 공식 문서의 예제를 배포해본다.
세부 설정과 개념에 대해서는 이후 주차에서 다루게 될 것이고, 여기에서는 그냥 단순하게 느낌만 가져가면 된다.

kind 세팅

일단 클러스터 환경으로는 KIND를 사용했다.
평소 실습할 때는 Vagrant를 이용해 kubeadm을 직접 설정했는데, 솔직히 vagrant 개구리다.
클러스터를 세팅하는 실습을 할 때야 유용하지만, 클러스터 내부에서 각종 툴을 세팅하는 연습을 하거나 커스텀 컨트롤러를 개발할 때는 이만한 게 없다.
이후의 클러스터도 대체로 kind를 이용할 것이며 클러스터 세팅에 대한 설명은 이후 문서에선 다루지 않는다.

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: myk8s
nodes:
- role: control-plane
  image: kindest/node:v1.32.2
  extraPortMappings:
  - containerPort: 30000 # Sample Application (istio-ingrssgateway)
    hostPort: 30000
  - containerPort: 30001 # Prometheus
    hostPort: 30001
  - containerPort: 30002 # Grafana
    hostPort: 30002
  - containerPort: 30003 # Kiali
    hostPort: 30003
  - containerPort: 30004 # Tracing
    hostPort: 30004
  - containerPort: 30005 # kube-ops-view
    hostPort: 30005
  extraMounts:
  - hostPath: ../istio-in-action/book-source-code-master
    containerPath: /istiobook
networking:
  podSubnet: 10.10.0.0/16
  serviceSubnet: 10.200.1.0/24

5개의 포트를 미리 포워딩하여 로컬 환경에서 클러스터의 서비스에 접속할 수 있도록 세팅한다.
현 실습에서는 컨트롤 플레인 하나만 두고 진행하나, 이후에는 워커 노드를 추가할 수도 있다.
볼륨 마운팅을 한 것도 보이는데 이것은 책의 예제 코드를 클러스터 내부에서 활용하고자 할 때 활용하기 위한 것이다.
코드는 여기에서 받을 수 있다.[2]

kind create cluster --config kind.yaml

딸깍 구축!

istio 설치

curl -L https://istio.io/downloadIstio | sh -

먼저 istioctl을 설치해준다.

export ISTIOV=1.25.1
echo 'export ISTIOV=1.25.1' >> /root/.bashrc
curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV sh -
sudo cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl

버전을 명시해서 설치할 때는 이런 식으로 해주면 된다.
image.png
위와 같이 설치를 진행하면 istioctl과, 실습할 때 도움되는 각종 샘플 파일 등을 함께 받아볼 수 있다.
이번 실습에서는 samples에 있는 addons(관측 가능성 툴), bookinfo(실습 예제) 디렉토리를 활용한다.

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: demo
  components:
    ingressGateways:
    - name: istio-ingressgateway
      enabled: true
      k8s:
        service:
          type: NodePort
          ports:
          - port: 80
            targetPort: 8080
            nodePort: 30000
          externalTrafficPolicy: Local
    egressGateways:
    - name: istio-egressgateway
      enabled: false
  meshConfig:
    defaultProviders:
      metrics:
      - prometheus
      tracing: []

istio operator는 이런 식으로 작성했다.
인그레스 게이트웨이를 활성화하고 노드포트를 미리 지정해주었다.
또한 tracing 필드를 비웠는데, 이건 아래 관측 가능성 세팅에서 조금 더 본다.

istioctl install -f initstio.yaml -y

image.png
설치 자체는 매우 간단하게 이뤄진다.

kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system 

image.png
굉장히 많은 것들이 설치된 것을 확인할 수 있다.
워크로드만 따지자면, 데모 프로필로 설치된 컴포넌트는 컨트롤 플레인에 해당하는 istiod와 이스티오 인그레스 게이트웨이이다.
image.png
istiod의 포트가 상당히 많길래 봤는데, 다음과 같이 엔보이와 통신할 때 쓰일 포트와 디버그, 모니터링 등을 위한 포트가 설정돼있는 것을 확인할 수 있다.

관측 가능성 세팅

image.png
이스티오에서 제공하는 모니터링 툴들은 istioctl을 설치할 때 받은 samples/addons 디렉에 들어있다.
각 툴을 현재 자세히 다루진 않겠다.
간단하게 설명만 하자면,

apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
  name: mesh-default
  namespace: istio-system
spec:
  metrics:
    - overrides:
        - match:
            metric: ALL_METRICS
            mode: SERVER
          disabled: true
  tracing:
  - providers:
    - name: jaeger

그 다음 이렇게 Telemetry 리소스를 하나 새로 만든다(세팅 간편화를 위해 addons 디렉토리에 넣어두는 걸 추천한다).
최신 이스티오에서는 telemetry api를 제공하고 있으며 이를 통해 클러스터 전역, 네임스페이스 별, 혹은 특정 워크로드를 매칭하여 관측 가능성 세팅을 할 수 있다.[3]
istioctl에서는 tracing 필드를 비웠는데, 이걸 활용하기 위해서 비운 것이다!

추가적으로 키알리 대시보드에서 에러율 추적을 명확하게 하기 위해 서버 측 메트릭을 비활성화해준다.
자세한 내용은 관측 가능성을 다루는 주차에서 보게 될 것이다.

키알리, 예거 연동을 위한 설정

image.png
그냥 세팅을 진행하면 키알리에서 예거 관련 추적이 제대로 되지 않는다.[4]
image.png
키알리 configmap에 세팅 파일이 들어있는데, 여기에 tracing 필드가 비활성화돼있을 것이다.

    external_services:
      custom_dashboards:
        enabled: true
      istio:
        root_namespace: istio-system
      tracing:
        enabled: true
        internal_url: "http://tracing.istio-system:16685/jaeger"

그래서 해당 부분을 위와 같이 고쳐준다.

k apply -f addons

준비가 완료됐으면 디렉토리 단위로 딸깍!
image.png
image.png
localhost로 각 포트에 들어가보면 모니터링 툴들이 배포된 것을 확인할 수 있다.
image.png
키알리에 mesh 탭에 예거가 표시되는지도 확인해본다.

참고 - ingress gateway 관측 가능성 세팅

kubectl exec -it deploy/istio-ingressgateway -n istio-system -- curl -X POST http://localhost:15000/logging?http=debug

로깅 설정을 동적으로 수정해보자.
그냥 /logging으로 요청을 보내면 어떤 것들에 대해 로깅 설정을 할 수 있는지 정보가 나온다.
image.png
디버그 레벨로 로깅 설정을 하자 훨씬 자세하게 정보를 볼 수 있다.

샘플 어플리케이션 배포 후 확인


샘플 어플리케이션 bookInfo는 이렇게 구성돼있다.[5]
간단하게 파이썬으로 웹페이지가 만들어져 있는데, 이 페이지 데이터를 reviews 서버와 details 서버에 api 동기 요청을 날려 완성한다.
이때 reviews의 경우 버전에 3개가 있으며 v2와 v3에서는 ratings에 또 api를 날려 평점 정보를 받는다.

kubectl label namespace default istio-injection=enabled

먼저 데이터 플레인에 사이드카가 주입될 수 있도록 네임스페이스에 라벨을 달아준다.
image.png
이 설정은 승인 웹훅을 발동시키는데, 이 중에서 위의 리소스를 발동시킨다.
image.png
이름 때문에 당연히 istio-sidecar-injector가 작동하는 줄 알았으나, 무슨 연유에선지 해당 리소스는 그냥 사용이 되지 않도록 설정돼있다.
image.png
대신 istio-revision-tag-default 리소스를 보면 이렇게 네임스페이스의 라벨에 따라 웹훅이 발동되도록 설정이 돼있는 것을 확인할 수 있다.
내 생각에는 아마 rev 관련 변형 승인 웹훅까지 추가되면서 한 리소스로 모든 웹훅을 관리하기 위한 변화과정이 아닐까 한다.

image.png
아무튼 샘플로 주어진 예제를 실행한다.
예제가 무척 많기 때문에, 각각 어떤 예제인지 확인하면서 진행하는 것도 실습에 도움이 될 것 같다.
image.png
여러 개의 파드가 사이드카가 주입된 채 실행된다.

containers:
  - image: docker.io/istio/examples-bookinfo-productpage-v1:1.20.2
    name: productpage
    ports:
    - containerPort: 9080
      protocol: TCP
  - args:
    - proxy
    - sidecar
    - --domain
    - $(POD_NAMESPACE).svc.cluster.local
    - --proxyLogLevel=warning
    - --proxyComponentLogLevel=misc:error
    - --log_output_level=default:info
    image: docker.io/istio/proxyv2:1.25.1
    name: istio-proxy
    ports:
    - containerPort: 15090
      name: http-envoy-prom
      protocol: TCP
    resources:
      limits:
        cpu: "2"
        memory: 1Gi
      requests:
        cpu: 10m
        memory: 40Mi
  initContainers:
  - args:
    - istio-iptables
    - -p
    - "15001"
    - -z
    - "15006"
    - -u 
    - "1337"
    - -m
    - REDIRECT
    - -i
    - '*'
    - -x
    - ""
    - -b
    - '*'
    - -d
    - 15090,15021,15020
    - --log_output_level=default:info
    image: docker.io/istio/proxyv2:1.25.1
    name: istio-init

(마운팅이랑 환경 변수 개수가 너무 많아서 편집했다)
간단하게 파드를 살펴본다.
사이드카 모드이기 때문에 알아서 컨테이너가 추가됐는데, 첫번째는 기본 iptable 세팅을 담당하는 초기화 컨테이너, 그리고 사이드카로 동작할 istio-proxy 컨테이너가 들어갔다.
image.png
맛보기로 해보는 거니 간단하게만 보는 건데 역시 궁금해서 조금 검색해봤다.
초기화 컨테이너에서는 정말 모든 트래픽을 곧이곧대로 엔보이 프록시로 보내버리도록 설정돼있다.

istioctl proxy-status

image.png
엔보이가 설정에 맞게 제대로 배포됐는지 체크할 때 쓰는 명령어이다.
제대로 동기화된 것을 확인할 수 있다.
참고로 proxy-status의 약자는 ps이다.

istioctl pc all productpage-v1-d49bb79b4-vpmkh

pc는 proxy-config의 약자로 특정 파드의 엔보이에 설정된 정보들을 확인하는 명령어이다.
단순하게 all로 찍으면 매우 많은 정보들이 표시된다.
image.png
image.png
라우팅 규칙이나 리스너에 암호화 통신을 위한 인증서 정보도 확인할 수 있다.

kubectl port-forward deployment/productpage-v1 15000:15000

15000 포트로 엔보이의 관리자 페이지가 노출되고 있으므로, 해당 포트를 포워딩하면 관리자 페이지에 들어가볼 수 있다.
image.png
물론 이렇게 일일히 엔보이를 세팅하는 건 안티 패턴이고, 현재 설정이 어떻게 돼있는지를 알아볼 때도 그냥 istio의 자체 기능을 활용하는 것이 나을 것이다.
다만 조금 더 딮하게 파보고 싶다면 이런 영역도 있다~ 정도?

트래픽 노출 세팅

이스티오를 설치할 때 인그레스 게이트웨이를 설치하여 외부에서 클러스터로 접속이 가능한 게이트웨이를 뚫었다.
이걸 사용하지 않고 Gateway API를 쓰는 것도 가능한데, 다음 실습에서 보도록 하겠다.
그러나 일단 먼저 기본적인 이스티오의 리소스를 사용해본다.

apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 8080
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
  - "*"
  gateways:
  - bookinfo-gateway
  http:
  - match:
    - uri:
        exact: /productpage
    - uri:
        prefix: /static
    - uri:
        exact: /login
    - uri:
        exact: /logout
    - uri:
        prefix: /api/v1/products
    route:
    - destination:
        host: productpage
        port:
          number: 9080

각 리소스가 무엇인지 명확하게 분석하는 것은 이후 주차로 미루겠다.
다만 대충 봐도 쿠버의 기본 인그레스, 서비스를 사용하는 방식이랑 상당히 비슷한 것은 확인할 수 있을 것이다.
나중에 볼 게이트웨이api와는 더 비슷하게 느껴질 것이다.

k -n istio-system get svc istio-ingressgateway -oyaml | yh

image.png
간단하게만 말하자면 인그레스 게이트웨이 엔보이가 현재 배포돼있는 상태로 여기에서 외부 트래픽을 수신할 수 있다.
이를 게이트웨이 리소스로 추적하여 이스티오 서비스 레지스트리에 넣어두는 작업을 한다.
이후에는 가상 서비스 리소스를 이용해 인그레스마냥 엔드포인트 조건에 부합하는 모든 트래픽을 특정 서비스로 라우팅하는 규칙을 기입하여 적용한 것이다.
image.png
결과적으로 실제 트래픽은 이 친구가 받게 될 것이다.

아무튼 위 설정 파일을 배포해보면...
image.png
간단하게 만들어진 리소스들을 확인할 수 있다.
image.png
페이지가 정상적으로 열리는 것을 확인할 수 있다.
image.png
프록시의 로그에 접속 정보가 남는 것을 확인할 수 있다.
이제 구체적으로 어떻게 로컬 환경에서 클러스터의 서비스에 접근할 수 있었는지 시각적으로 확인해보자.

Kiali 확인

키알리는 서비스 메시 시스템을 시각화시켜주는 모니터링 툴이다.

while true; do curl -s http://127.0.0.1:30000/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; done

실시간 메트릭 흐름을 추적하기 위해 먼저 지속적으로 트래픽을 유발시킨다.
키알리의 경우 최근의 트래픽을 모니터링하는 도구이기 때문에 트래픽이 발생하지 않으면 제대로 시각화를 하기 어렵다.
image.png
트래픽 그래프 탭에 들어와서 시각화 표시에 각종 세팅을 넣어준다.
꼭 해야 한다 이런 건 없지만, 세팅할수록 이뻐진다..!
추가적으로 넣어준 시각화 세팅은 다음과 같다.

image.png
이렇게 하면 실시간으로 트래픽이 전송되는 것을 시각적으로 확인할 수 있게 된다!
(근데 간단한 샘플인데도 생각보다 렉이 조금.. 있다..)
versioned app graph를 사용했는데, 서비스만 보거나 워크로드만 보는 식으로 커스텀도 가능하다.
앞서 미리 샘플 어플리케이션을 분석하지 않았는데, 이렇게 키알리만으로 쉽게 파악이 가능하기 때문이다.

키알리를 통해 전체 구조를 다시 보자면 4개의 어플리케이션이 있다.
메인 web ui는 productpage에서 제공하며, 뒷단에 WAS로 detail과 review가 존재한다.
이때 review의 경우 세 개의 파드가 배포돼있는 상태(각각 디플로이먼트가 돼있음)로 2,3버전부터 rating으로부터 별점 정보까지 가져온다.
image.png
리뷰 쪽에 각 다른 버전들이 있기 때문에, 실제로도 새로고침을 계속 해주면 평점이 생겼다 없어졌다 한다.
image.png
참고로 검은 색깔은 버전 2, 빨간 색깔이 버전 3이다.

image.png
트래픽의 흐름으로 보자면, 먼저 로컬에서 반복문으로 돌리고 있는 요청은 인그레스 게이트웨이를 타고 productpage 서비스에 먼저 전해진다.
이쪽으로 전달되는 이유는 virtual service에 라우팅 규칙이 세팅돼있기 때문이다.
그럼 해당 서비스의 엔드포인트로 실제 트래픽이 전달되고, 여기에서 다시 detail과 review로 추가 요청이 날아가는 방식이다.
image.png
실제 트래픽을 받는 대상들만 명확히 하고자 service nodes는 시각화에서 제외시켰다.
어차피 서비스는 셀렉터에 맞게 엔드포인트를 업데이트하는 역할만 하기 때문에 트래픽의 흐름만 명확하게 보고 싶다면 서비스 객체를 안 보는 것도 좋은 선택지 같다.
image.png
트래픽 분산 비율을 볼 때 주의점이 조금 있다.
키알리는 각 워크로드의 엔보이가 노출하는 프로메테우스 메트릭을 기반으로 보기 좋게 시각화해주는 툴이다.
메트릭에 표시된 정보에 따라서 각종 정보를 계산해 보여줄 뿐이므로, 이 비율을 곧이곧대로 받아들이면 곤란하다.
현재 샘플 어플리케이션은 productpage에서 review와 detail에 각각 한번씩 api 요청을 날리는데 이것은 매 요청마다 각각 이뤄지는 것이지, 분산하여 트래픽을 보내는 것이 아니다(빨간색).
반면 review 서비스에서 3개의 엔드포인트 파드에 트래픽을 보내는 것은 실제로 iptables 규칙에 따라 트래픽이 분산되는 것이 맞다(파란색).
간단하게만 정리하자면,

이런 식으로 이해해야 명확하게 비율을 파악할 수 있다.

image.png
다음으로 옆의 탭들을 둘러본다.
워크로드 탭에 내가 배포한 디버그용 파드에 missing app이라고 표시되는 것이 보인다.
워크로드에 app: {앱}, version: {버전} 라벨을 달아두어야 키알리에서 명확하게 어플리케이션으로서 인식하고 시각화를 해주기 때문에 비즈니스 로직이 들어가는 워크로드의 경우 각 라벨을 설정해주는 게 좋다.
image.png
워크로드에 들어가보면 이렇게 트레이싱 정보도 확인할 수 있다.
image.png
참고로 워크로드에서는 이렇게 컨테이너의 로깅 정보도 확인할 수 있다.
image.png
인그레스 게이트웨이도 워크로드로서 추적이 되기 때문에 로그를 받아볼 수 있다.

image.png
서비스 탭에 들어가보면 각 서비스들이 보인다.
productpage의 경우 게이트웨이와 직접적으로 연결되며 virtual service의 대상으로 설정돼있기에 세부정보가 표시된다.
kubernetes 서비스의 경우 트래픽이 한번도 발생하지 않았기 때문에 헬스 상태가 표시되지 않는 것도 확인할 수 있다.

image.png
(초기 실습하면서 예거 연동을 하지 않은 모습)
마지막으로 mesh 탭에 들어가면 현재 이스티오 관련 설정된 전체 구조 정보를 확인할 수 있다.

Jaeger 확인

이제 트레이싱 영역을 조금 더 파보자.
image.png
예거가 제대로 세팅됐다면 위와 같이 서비스 단위로 트래픽을 추적할 수 있게 된다.
image.png
어떤 단위로 트레이스를 찾던, 스팬으로 묶인 트레이스들이 나오게 되니 자신이 명확하게 짚을 수 있는 서비스를 골라 찾아보면 된다.
image.png
하나의 트레이스를 골라서 분석해본다.
이 정보로부터 확언할 수는 없지만, productpage로의 요청으로 인해 발생하는 detail과 review에 대한 요청은 동기적으로 이뤄질 가능성이 높다.
만약 비동기적으로 요청을 보내는 방식이었다면 하위 스팬이 겹쳐서 나타나거나, 발생 간격이 매우 짧았을 가능성이 높다.
아무튼 api 요청 중에서는 review에 대한 요청이 상당히 긴 것을 확인할 수 있다.
image.png
각각의 스팬을 뜯어보면 OTel 기반으로 트레이싱을 하는 것으로 보인다.
image.png
실제로도 스팬을 자세히 보면 요청을 받았으면서도 자신도 요청을 보내게 되는 productpage의 경우 client와 server 두 가지 유형의 span을 가지고 있어서 트레이스의 깊이가 더 깊어지는 것을 볼 수 있다.
image.png
이밖에도 다양한 방식으로 트레이스를 분석할 수 있다.
image.png
참고로 위 그래프는 이런 식으로 보면 된다.
productpage가 요청을 처리한 전체 시간 중, 자기 자신이 실제로 할애한 처리시간을 절반 정도를 차지한다.

그라파나 확인

마지막으로 프로메테우스 그라파나까지 보려고 했으나, 솔직히 아직 어떤 메트릭이 중요한지 명확하게 판단을 못하겠어서 내용 정리를 하면서까지 실습하진 않는다.
image.png
음 이런 게 있구나..
컨트롤 플레인 메트릭에 전체 워크로드 트래픽 성공률 등의 지표가 대시보드에 있다.

결론

기본적으로 서비스 메시가 무엇인지, 그 중 하나인 이스티오의 개략적인 구조와 실습을 진행했다.
간단하게 설치하는 것은 매우 쉽긴 하다.
간단히 설치하고 어플리케이션 단의 세팅을 하지 않고 트래픽을 조정하고 모니터링을 할 수 있다는 것은 엄청난 장점이라고 생각한다.
(근데 참고로 트레이싱의 경우 스팬이 잘 이어지도록 헤더 포워딩 세팅이 코드 상에 들어있기는 하다.)

그러나 이번 실습하면서 느낀 게 딸깍 세팅할 때까지만 쉽다 ㅋㅋ
차후 실습을 진행하면서 점점 더 상세하게 커스텀하고 설정을 하는 방법을 알아보게 될 것으로 기대된다.

bookInfo 예제 코드는 이스티오를 익히는데 필요한 세팅이 매우 잘 돼있어서, 기회가 된다면 해당 코드를 직접 까보는 것을 추천한다.

이전 글, 다음 글

다른 글 보기

이름 index noteType created
1W - 서비스 메시와 이스티오 1 published 2025-04-10
1W - 간단한 장애 상황 구현 후 대응 실습 2 published 2025-04-10
1W - Gateway API를 활용한 설정 3 published 2025-04-10
1W - 네이티브 사이드카 컨테이너 이용 4 published 2025-04-10
2W - 엔보이 5 published 2025-04-19
2W - 인그레스 게이트웨이 실습 6 published 2025-04-17
3W - 버츄얼 서비스를 활용한 기본 트래픽 관리 7 published 2025-04-22
3W - 트래픽 가중치 - flagger와 argo rollout을 이용한 점진적 배포 8 published 2025-04-22
3W - 트래픽 미러링 패킷 캡쳐 9 published 2025-04-22
3W - 서비스 엔트리와 이그레스 게이트웨이 10 published 2025-04-22
3W - 데스티네이션 룰을 활용한 네트워크 복원력 11 published 2025-04-26
3W - 타임아웃, 재시도를 활용한 네트워크 복원력 12 published 2025-04-26
4W - 이스티오 메트릭 확인 13 published 2025-05-03
4W - 이스티오 메트릭 커스텀, 프로메테우스와 그라파나 14 published 2025-05-03
4W - 오픈텔레메트리 기반 트레이싱 예거 시각화, 키알리 시각화 15 published 2025-05-03
4W - 번외 - 트레이싱용 심플 메시 서버 개발 16 published 2025-05-03
5W - 이스티오 mTLS와 SPIFFE 17 published 2025-05-11
5W - 이스티오 JWT 인증 18 published 2025-05-11
5W - 이스티오 인가 정책 설정 19 published 2025-05-11
6W - 이스티오 설정 트러블슈팅 20 published 2025-05-18
6W - 이스티오 컨트롤 플레인 성능 최적화 21 published 2025-05-18
8W - 가상머신 통합하기 22 published 2025-06-01
8W - 엔보이와 iptables 뜯어먹기 23 published 2025-06-01
9W - 앰비언트 모드 구조, 원리 24 published 2025-06-07
9W - 앰비언트 헬름 설치, 각종 리소스 실습 25 published 2025-06-07
7W - 이스티오 메시 스케일링 26 published 2025-06-09
7W - 엔보이 필터를 통한 기능 확장 27 published 2025-06-09

관련 문서

이름 noteType created
서비스 메시 knowledge 2024-06-13
Gateway API knowledge 2025-01-06
Amazon VPC Lattice knowledge 2025-04-23
pilot-agent knowledge 2025-04-28
Kiali knowledge 2025-04-28
사이드카 모드 knowledge 2025-05-18
메시 배포 모델 knowledge 2025-05-21
앰비언트 모드 knowledge 2025-06-02
1W - 서비스 메시와 이스티오 published 2025-04-10
4W - 번외 - 트레이싱용 심플 메시 서버 개발 published 2025-05-03
6W - 이스티오 컨트롤 플레인 성능 최적화 published 2025-05-18
8W - 엔보이와 iptables 뜯어먹기 published 2025-06-01
E-이스티오 컨트롤 플레인 성능 최적화 topic/explain 2025-05-18
E-이스티오의 데이터 플레인 트래픽 세팅 원리 topic/explain 2025-05-27

참고


  1. https://web.archive.org/web/20150724002202/https://www2.computable.nl/downloads/ibm_ws-soa-whitepaper.pdf ↩︎

  2. https://github.com/istioinaction/book-source-code ↩︎

  3. https://istio.io/latest/docs/tasks/observability/distributed-tracing/jaeger/ ↩︎

  4. https://github.com/istio/istio/blob/master/samples/addons/kiali.yaml ↩︎

  5. https://istio.io/latest/docs/examples/bookinfo/ ↩︎