[KANS] 3기 7주 – Service Mesh : Istio- Mode(Sidecar, Ambient)

CloudNet@팀에서 진행하는 쿠버네티스 네트워크 스터디 3기 참가글입니다.

‘쿠버네티스’ 네트워크에 대해서 직접 실습을 통해 장애 시 해결 능력을 갖추고, 학습 내용을 전파 및 공유합니다!


1. Service Mesh

소프트웨어 아키텍처에서 서비스 메시(Service Mesh)는 프록시를 사용하여 서비스 또는 마이크로서비스 간의 서비스 간 통신을 용이하게 하는 전용 인프라 계층을 말한다.

In software architecture, a service mesh is a dedicated infrastructure layer for facilitating service-to-service communications between services or microservices using a proxy

Service Mesh, wikipeda

등장배경

  • 마이크로서비스 아키텍처 환경의 시스템 전체 모니터링의 어려움
  • 운영 시 시스템 장애나 문제 발생할 때 원인과 병목 구간 찾기 어려움
  • 내부망 진입점에 역할을 하는 GW(예. API Gateway) 경우 모든 동작 처리에 무거워지거나, 내부망 내부 통신 제어는 어려움


개념

  • 마이크로서비스 간에 매시 형태의 통신이나 그 경로를 제어
  • 예) 이스티오(Istio), 링커드(Linkerd), 콘술(Consul), Nginx, 등등


기본 동작

  • 파드 간 통신 경로에 프록시를 놓고 트래픽 모니터링이나 트래픽 컨트롤
  • > 기존 애플리케이션 코드에 수정 없이 구성 가능

1. 기존 통신 환경

  • 어플리케이션 간 직접 통신

2. Proxy를 통한 통신

  • 어플리케이션 수정 없이, 모든 애플리케이션 통신 사이에 Proxy 를 두고 통신
  • 파드 내에 사이드카 컨테이너로 주입되어서 동작
  • Proxy 컨테이너가 Application 트래픽을 가로채야됨 → iptables rule 구현

3. 중앙 관리를 위한 ControlPlane 구성

  • Proxy 는 결국 DataPlane > 이를 관리하는 ControlPlane을 두고 중앙 관리
  • Proxy 는 중앙에서 설정 관리가 잘되는 툴을 선택.
    • 즉, 원격에서 동적인 설정 관리가 유연해야함
    • → 풍부한 API 지원이 필요
    • Envoy
      • 구글 IBM 리프트(Lyft)’가 중심이 되어 개발하고 있는 오픈 소스 소프트웨어이며, C++ 로 구현된 고성능 Proxy
      • 네트워크의 투명성을 목표, 다양한 필터체인 지원(L3/L4, HTTP L7), 동적 configuration API 제공, api 기반 hot reload 제공
  • 중앙에서 어떤 동작/설정을 관리해야 될까
  • > 라우팅, 보안 통신을 위한 mTLS 관련, 동기화 상태 정보 등
    • 트래픽 모니터링
      • 요청의 ‘에러율, 레이턴시, 커넥션 개수, 요청 개수’ 등 메트릭 모니터링, 특정 서비스간 혹은 특정 요청 경로로 필터링 → 원인 파악 용이!
    • 트래픽 컨트롤
      • 트래픽 시프팅(Traffic shifting) : 예시) 99% 기존앱 + 1% 신규앱 , 특정 단말/사용자는 신규앱에 전달하여 단계적으로 적용하는 카니리 배포 가능
      • 서킷 브레이커(Circuit Breaker) : 목적지 마이크로서비스에 문제가 있을 시 접속을 차단하고 출발지 마이크로서비스에 요청 에러를 반환 (연쇄 장애, 시스템 전제 장애 예방)
      • 폴트 인젝션(Fault Injection) : 의도적으로 요청을 지연 혹은 실패를 구현
      • 속도 제한(Rate Limit) : 요청 개수를 제한


2. Istio

Istio는 기존의 분산 애플리케이션에 투명하게 계층을 추가하는 오픈 소스 서비스 메시입니다. Istio의 강력한 기능은 서비스 보안, 연결, 모니터링을 보다 효율적이고 일관되게 수행할 수 있는 방법을 제공합니다. Istio는 로드 밸런싱, 서비스 간 인증, 모니터링을 위한 경로를 제공하며, 서비스 코드의 변경이 거의 없거나 전혀 없이 이를 실현할 수 있습니다. Istio는 다음과 같은 기능을 제공합니다:

Istio is an open source service mesh that layers transparently onto existing distributed applications. Istio’s powerful features provide a uniform and more efficient way to secure, connect, and monitor services. Istio is the path to load balancing, service-to-service authentication, and monitoring – with few or no service code changes. It gives you:

What is Istio?, Istio Docs

Istio는 service mesh의 대표적인 구현체 중 하나이다.


Architecture

Architecture, Istio docs

istio의 시스템은 크게 컨트롤플레인 역할을 하는 istiod / 데이터플레인 역할을 하는 istio-proxy(envoy)로 나뉜다

istiod

  • service discovery, 구성 및 인증서 관리 담당
  • Pilot, Galley, Citadel 등의 구성 요소가 있었음, 현재는 통합되었지만 수행 역할은 동일
    • Pilot: 데이터 플레인과 통신하면서 라우팅 규칙을 동기화, ADS Aggregate discovery service:
    • Galley: Istio 와 K8S 연동, Endpoint 갱신 등
    • Citadel: 연결 암호화, 인증서 관리 등


istio-proxy(envoy)

  • Golang 으로 작성되었고 envoy 래핑한 Proxy, istiod와 통신하고 서비스 트래픽을 통제, 옵저버빌리티를 위한 메트릭 제공


동작방식

  • 이스티오는 각 파드 안에 사이드카엔보이 프록시가 들어가 있는 형태
  • 모든 마이크로서비스간 통신은 엔보이를 통과하여, 메트릭을 수집하거나 트래픽 컨트롤을 할 수 있음
  • 트래픽 컨트롤을 하기위해 엔보이 프록시에 전송 룰을 설정 → 컨트롤 플레인이스티오가 정의된 정보를 기반으로 엔보이 설정을 하게 함
  • 마이크로서비스 간의 통신을 mutual TLS 인증(mTLS)으로 서로 TLS 인증으로 암호화 할 수 있음
  • 각 애플리케이션은 파드 내의 엔보이 프록시에 접속하기 위해 localhost 에 TCP 접속을 함


3. Envoy

Envoy는 대규모 모던 서비스 지향 아키텍처를 위해 설계된 L7 프록시이자 통신 버스입니다. 이 프로젝트는 다음과 같은 믿음에서 출발했습니다:

네트워크는 애플리케이션에 명확해야 한다. 네트워크 및 애플리케이션 문제 발생 시, 문제의 원인을 쉽게 파악할 수 있어야 한다.

실제로 앞서 언급한 목표를 달성하는 것은 매우 어렵습니다. Envoy는 다음과 같은 고수준 기능을 제공함으로써 이를 시도합니다.

Envoy is an L7 proxy and communication bus designed for large modern service oriented architectures. The project was born out of the belief that:

The network should be transparent to applications. When network and application problems do occur it should be easy to determine the source of the problem.

In practice, achieving the previously stated goal is incredibly difficult. Envoy attempts to do so by providing the following high level features:

What is Envoy, Envoy docs


Envoy 는 istio의 sidecar proxy로 사용되는 L4/7의 프록시이다.

주요 용어)

  • Cluster
    • envoy 가 트래픽을 포워드할 수 있는 논리적인 서비스 (엔드포인트 세트)
    • 실제 요청이 처리되는 IP 또는 엔드포인트의 묶음을 의미.
  • Endpoint
    • IP 주소, 네트워크 노드로 클러스터로 그룹핑됨, 실제 접근이 가능한 엔드포인트를 의미.
    • 엔드포인트가 모여서 하나의 Cluster 가 된다.
  • Listener
    • 무엇을 받을지 그리고 어떻게 처리할지 IP/Port 를 바인딩하고, 요청 처리 측면에서 다운스트림을 조정하는 역할.
  • Route
    • Listener 로 들어온 요청을 어디로 라우팅할 것인지를 정의.
    • 라우팅 대상은 일반적으로 Cluster 라는 것에 대해 이뤄지게 된다.
  • Filter
    • Listener 로부터 서비스에 트래픽을 전달하기까지 요청 처리 파이프라인
  • UpStream
    • envoy 요청을 포워딩해서 연결하는 백엔드 네트워크 노드
    • 사이드카일때 application app, 아닐때 원격 백엔드
  • DownStream
    • envoy 요청을 보내는 존재
    • 사이드카일때 local application 또는 네트워크 노트 / 아닐때 원격 클라이언트


High level architecture

High level architecture, envoy docs
  • Listener subsystem
    • 다운스트림 요청 처리를 담당
    • 다운스트림 요청의 수명 주기 관리 및 클라이언트로의 응답 경로 처리
    • 다운스트림 HTTP/2 코덱은 이곳에서 작동
  • Cluster subsystem
    • 엔드포인트로의 업스트림 연결을 선택 및 구성
    • 클러스터 및 엔드포인트 상태, 로드 밸런싱, connection pooling에 대한 정보
    • 업스트림 HTTP/2 코덱은 이곳에서 작동
  • 두 subsystem은 HTTP 라우터 필터를 통해 연결
    • 다운스트림에서 업스트림으로 HTTP 요청 전달 역할.
Architecture cheatsheet-Dataplane, TetrateLabs


Envoy는 구성을 동적으로 관리하기 위한 강력한 API를 제공이 중요합니다

  • Service Mesh 솔루션이나, Gateway API 구현체들을 Enovy를 내부적으로 사용하고 있으며, Envoy가 제공하는 동적 구성을 위한 API (xDS Sync API)를 이용하여 다양한 네트워크 정책을 구성하게 됩니다.
  • Envoy의 xDS Sync API는 아래와 같은 레이어에서 동작하게 됩니다.
    • LDS – Listener Discovery Service
    • RDS – Route Discovery Service
    • CDS – Cluseter Discovery Service
    • EDS – Endpoint Discovery Service
Architecture cheatsheet-xDS, TetrateLabs


4. Istio 실습

실습환경 구성
EC2 on AWS

  • CloudFormation 스택 배포
# YAML 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/kans/kans-7w.yaml

# CloudFormation 스택 배포
# aws cloudformation deploy --template-file kans-7w.yaml --stack-name mylab --parameter-overrides KeyName=<My SSH Keyname> SgIngressSshCidr=<My Home Public IP Address>/32 --region ap-northeast-2
예시) aws cloudformation deploy --template-file kans-7w.yaml --stack-name mylab --parameter-overrides KeyName=kp-gasida SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2

## Tip. 인스턴스 타입 변경 : MyInstanceType=t3.xlarge (vCPU 4, Mem 16)
예시) aws cloudformation deploy --template-file kans-7w.yaml --stack-name mylab --parameter-overrides MyInstanceType=t3.xlarge KeyName=kp-gasida SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2

# CloudFormation 스택 배포 완료 후 작업용 EC2 IP 출력
aws cloudformation describe-stacks --stack-name mylab --query 'Stacks[*].Outputs[0].OutputValue' --output text --region ap-northeast-2

# [모니터링] CloudFormation 스택 상태 : 생성 완료 확인
while true; do 
  date
  AWS_PAGER="" aws cloudformation list-stacks \
    --stack-status-filter CREATE_IN_PROGRESS CREATE_COMPLETE CREATE_FAILED DELETE_IN_PROGRESS DELETE_FAILED \
    --query "StackSummaries[*].{StackName:StackName, StackStatus:StackStatus}" \
    --output table
  sleep 1
done

# 배포된 aws ec2 유동 공인 IP 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text
k3s-s	3.38.151.222	running
k3s-w1	15.165.75.117	running
k3s-w2	3.39.223.99	running
testpc	54.180.243.135	running

# EC2 SSH 접속 : 바로 접속하지 말고, 3~5분 정도 후에 접속 할 것
ssh -i ~/.ssh/kp-gasida.pem ubuntu@$(aws cloudformation describe-stacks --stack-name mylab --query 'Stacks[*].Outputs[0].OutputValue' --output text --region ap-northeast-2)
...
(⎈|default:N/A) root@k3s-s:~# <- kubeps 가 나오지 않을 경우 ssh logout 후 다시 ssh 접속 할 것!

  • k3s-s(cp)/ testpc 각각 접속확인
    • K3S v1.30.4
    • 노드 OS(Ubuntu 22.04.5)
    • CNI(Flannel)
    • IPTABLES proxy mode
    • Istio v1.23.2(Envoy v1.32.2)
# [자신의 PC] 배포된 aws ec2 유동 공인 IP 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text
# k3s-s   3.36.108.237    running
# k3s-w2  13.125.61.111   running
# k3s-w1  13.125.146.139  running
# testpc  3.39.224.38     running

# k3s-s 접속 후 확인 : ssh -i <> ubuntu@3.36.108.237
kc get node -owide
NAME     STATUS   ROLES                  AGE     VERSION        INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION   CONTAINER-RUNTIME
k3s-s    Ready    control-plane,master   8m57s   v1.30.5+k3s1   192.168.10.10    <none>        Ubuntu 22.04.5 LTS   6.8.0-1015-aws   containerd://1.7.21-k3s2
k3s-w1   Ready    <none>                 8m46s   v1.30.5+k3s1   192.168.10.101   <none>        Ubuntu 22.04.5 LTS   6.8.0-1015-aws   containerd://1.7.21-k3s2
k3s-w2   Ready    <none>                 8m45s   v1.30.5+k3s1   192.168.10.102   <none>        Ubuntu 22.04.5 LTS   6.8.0-1015-aws   containerd://1.7.21-k3s2

hostnamectl 
...
 Hardware Vendor: Amazon EC2
  Hardware Model: t3.xlarge

# testpc 각각 접속 후 확인 : ssh -i <> ubuntu@13.125.146.139
ip -br -c addr
lo               UNKNOWN        127.0.0.1/8 ::1/128 
ens5             UP             192.168.10.200/24 metric 100 fe80::3:e9ff:fefa:85d9/64 

hostnamectl 
...
 Hardware Vendor: Amazon EC2
  Hardware Model: t3.small

4.1. envoy 실습

envoy를 설치하고 기본 관리페이지 접근하여 설정값 확인

testpc EC2에 envoy 설치 – Installing Envoy

  • Install Envoy on Debian-based Linux
# 설치
# echo "deb [signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list
wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io jammy main" | sudo tee /etc/apt/sources.list.d/envoy.list
sudo apt-get update && sudo apt-get install envoy -y

# 확인
envoy --version

# 도움말
envoy --help

Envoy proxy 실습

  • envoy-demo.yaml
# (터미널1) 데모 config 적용하여 실행
curl -O https://www.envoyproxy.io/docs/envoy/latest/_downloads/92dcb9714fb6bc288d042029b34c0de4/envoy-demo.yaml
envoy -c envoy-demo.yaml


# (터미널2) 정보 확인
ss -tnlp
State    Recv-Q  Send-Q    Local Address:Port   Peer Address:Port    Process
LISTEN   0       4096      0.0.0.0:10000        0.0.0.0:*            users:(("envoy",pid=8007,fd=18),("envoy",pid=8007,fd=16))

# 접속 테스트
curl -s http://127.0.0.1:10000 | grep -o "<title>.*</title>"

# 외부 접속 정보 출력
echo -e "http://$(curl -s ipinfo.io/ip):10000"
http://54.180.243.135:10000

--------------------
# 자신의 PC 웹브라우저에서 외부 접속 정보 접속 확인!

# k3s-s 에서 접속 테스트
curl -s http://192.168.10.200:10000 | grep -o "<title>.*</title>" 
--------------------

# 연결 정보 확인
ss -tnp

# (터미널1) envoy 실행 취소(CTRL+C) 후 (관리자페이지) 설정 덮어쓰기 - 링크
cat <<EOT> envoy-override.yaml
admin:
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9902
EOT
envoy -c envoy-demo.yaml --config-yaml "$(cat envoy-override.yaml)"

# envoy 관리페이지 외부 접속 정보 출력
echo -e "http://$(curl -s ipinfo.io/ip):9902"
http://54.180.243.135:9902

--------------------
# 자신의 PC 웹브라우저에서 관리 페이지 외부 접속 정보 접속 확인!

결과

  • envoy 서버 시작 후, user envoy의 프로세스 및 포트 확인
  • envoy admin 접근 확인

4.2. Istio 설치

Installation Guides 에 따르면 Istioctl, Helm, Operator 등의 설치방법을 제공한다. 이들 중 operator 방식은 deprecated 되었으며 istioctl(cli) 또는 helm을 통한 설치가 권장된다.


구성 과정에서, 사전 구성된 profile에 따라 설치되는 구성요소가 일부 달라진다

Installation Configuration Profiles

deprecated된 istio operator 대신, sail operator 개발 중 – 블로그/깃헙

istio 구성

  • istioctl을 통한 설치
# istioctl 설치
export ISTIOV=1.23.2
echo "export ISTIOV=1.23.2" >> /etc/profile
curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV TARGET_ARCH=x86_64 sh -
tree istio-$ISTIOV -L 2 # sample yaml 포함
cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
istioctl version --remote=false

# (demo 프로파일) 컨트롤 플레인 배포 - 링크 Customizing
# The istioctl command supports the full IstioOperator API via command-line options for individual settings or for passing a yaml file containing an IstioOperator custom resource (CR).
istioctl profile list
istioctl profile dump default
istioctl profile dump --config-path components.ingressGateways
istioctl profile dump --config-path values.gateways.istio-ingressgateway
istioctl profile dump demo

istioctl profile dump demo > demo-profile.yaml
vi demo-profile.yaml # 복잡성을 줄이게 실습 시나리오 환경 맞춤
--------------------
    egressGateways:
    - enabled: false
--------------------    

istioctl install -f demo-profile.yaml -y
✔ Istio core installed ⛵️                                                                                                          
✔ Istiod installed 🧠                                                                                                              
✔ Ingress gateways installed 🛬                                                                                                    
✔ Installation complete                                                                                                            

# 설치 확인 : istiod, istio-ingressgateway
kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system
kubectl get crd | grep istio.io | sort

# istio-ingressgateway 의 envoy 버전 확인
kubectl exec -it deploy/istio-ingressgateway -n istio-system -c istio-proxy -- envoy --version
envoy  version: 6c72b2179f5a58988b920a55b0be8346de3f7b35/1.31.2-dev/Clean/RELEASE/BoringSSL

# istio-ingressgateway 서비스 NodePort로 변경
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec":{"type":"NodePort"}}'

# istio-ingressgateway 서비스 확인
kubectl get svc,ep -n istio-system istio-ingressgateway

## istio-ingressgateway 서비스 포트 정보 확인
kubectl get svc -n istio-system istio-ingressgateway -o jsonpath={.spec.ports[*]} | jq

## istio-ingressgateway 디플로이먼트 파드의 포트 정보 확인 
kubectl get deploy/istio-ingressgateway -n istio-system -o jsonpath={.spec.template.spec.containers[0].ports[*]} | jq
kubectl get deploy/istio-ingressgateway -n istio-system -o jsonpath={.spec.template.spec.containers[0].readinessProbe} | jq

# istiod(컨트롤플레인) 디플로이먼트 정보 확인
kubectl exec -it deployment.apps/istiod -n istio-system -- ss -tnlp
kubectl exec -it deployment.apps/istiod -n istio-system -- ss -tnp
kubectl exec -it deployment.apps/istiod -n istio-system -- ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
istio-p+       1       0  0 05:27 ?        00:00:07 /usr/local/bin/pilot-discovery discovery --monitoringAddr=:15014 --log_output_l

# istio-ingressgateway 디플로이먼트 정보 확인
kubectl exec -it deployment.apps/istio-ingressgateway -n istio-system -- ss -tnlp
kubectl exec -it deployment.apps/istio-ingressgateway -n istio-system -- ss -tnp
kubectl exec -it deployment.apps/istio-ingressgateway -n istio-system -- ps -ef
istio-p+       1       0  0 05:27 ?        00:00:01 /usr/local/bin/pilot-agent proxy router --domain istio-system.svc.cluster.local
istio-p+      15       1  0 05:27 ?        00:00:11 /usr/local/bin/envoy -c etc/istio/proxy/envoy-rev.json --drain-time-s 45 --drai

kubectl exec -it deployment.apps/istio-ingressgateway -n istio-system -- cat /etc/istio/proxy/envoy-rev.json
kubectl exec -it deployment.apps/istio-ingressgateway -n istio-system -- ss -xnlp
kubectl exec -it deployment.apps/istio-ingressgateway -n istio-system -- ss -xnp
  • Auto Injection with namespace label : 해당 네임스페이스에 생성되는 모든 파드들은 istio 사이드카가 자동으로 injection 됨
# mutating Webhook admisstion controller 사용
kubectl label namespace default istio-injection=enabled
kubectl get ns -L istio-injection
NAME              STATUS   AGE     ISTIO-INJECTION
default           Active   58m     enabled
...

istio 접속 테스트를 위한 변수 지정

  • 변수 지정
mypc)
## istio-ingressgateway 파드가 배치된 노드의 유동 공인 IP 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text
k3s-s	3.38.151.222	running
k3s-w1	15.165.75.117	running
k3s-w2	3.39.223.99	running
testpc	54.180.243.135	running


k3s-s)
# istio ingress gw NodePort(HTTP 접속용) 변수 지정 : 아래 ports[0] 은 어떤 용도의 포트일까요?
export IGWHTTP=$(kubectl get service -n istio-system istio-ingressgateway -o jsonpath='{.spec.ports[1].nodePort}')
echo $IGWHTTP
IGWHTTP=<각자 자신의 NodePort>

# /etc/hosts 파일 수정
MYDOMAIN=<각자 자신의 www 도메인> # 단, 사용하고 있지 않는 공인 도메인을 사용 할 것
MYDOMAIN=www.gasida.dev
echo "<istio-ingressgateway 파드가 있는 워커 노드> $MYDOMAIN" >> /etc/hosts

MYDOMAIN=<각자 자신의 www 도메인>
export MYDOMAIN=www.gasida.dev
echo -e "192.168.10.10 $MYDOMAIN" >> /etc/hosts
echo -e "export MYDOMAIN=$MYDOMAIN" >> /etc/profile

# istio ingress gw 접속 테스트 : 아직은 설정이 없어서 접속 실패가 된다
curl -v -s $MYDOMAIN:$IGWHTTP
  • testpc
# 아래 변수는 각자 자신의 값을 직접 입력 할 것
IGWHTTP=<각자 출력된 NodePort>
IGWHTTP=32759
export MYDOMAIN=www.gasida.dev
echo -e "192.168.10.10 $MYDOMAIN" >> /etc/hosts
echo -e "export MYDOMAIN=$MYDOMAIN" >> /etc/profile

# istio ingress gw 접속 테스트 : 아직은 설정이 없어서 접속 실패가 된다
curl -v -s $MYDOMAIN:$IGWHTTP
  • localPC
# 아래 변수는 각자 자신의 값을 직접 입력 할 것 : ISTIONODEIP는 3개의 노드 중 아무거나 입력
IGWHTTP=<각자 출력된 NodePort>
IGWHTTP=32759
ISTIONODEIP=<k3s-s 의 유동 공인 IP>
ISTIONODEIP=3.38.208.153

MYDOMAIN=www.gasida.dev
echo "$ISTIONODEIP $MYDOMAIN" | sudo tee -a /etc/hosts

# istio ingress gw 접속 테스트 : 아직은 설정이 없어서 접속 실패가 된다
curl -v -s $MYDOMAIN:$IGWHTTP

결과

  • istioctl 1.23.2, envoy 1.31.2
  • ingressgateway(envoy)pod에 envoy와 pilot-agent 프로세스 확인
  • 현재는 배포된 서비스가 없어 응답없음=접근 불가

4.3. Istio를 통한 외부 노출

Istio Gateway/VirtualService 설정 > Host 기반 트래픽 라우팅 설정

istio in action,oreily
  • 클라이언트 PC
  • → (Service:NodePort) Istio ingressgateway 파드
  • → (Gateway, VirtualService, Service 는 Bypass)
  • → Endpoint(파드 : 사이드카 – Application 컨테이너)

  • Gateway
    • 지정한 인그레스 게이트웨이로부터 트래픽이 인입
    • 프로토콜 및 포트, HOSTS, Proxy 등 설정 가능
  • VirtualService
    • 인입 처리할 hosts 설정, L7 PATH 별 라우팅, 목적지에 대한 정책 설정 가능 (envoy route config)

Istio 를 통한 Nginx 파드 접속 테스트

  • nginx deploy, svc 배포
# 로그 모니터링
kubectl get pod -n istio-system -l app=istiod
kubetail -n istio-system -l app=istiod -f

kubectl get pod -n istio-system -l app=istio-ingressgateway
kubetail -n istio-system -l app=istio-ingressgateway -f
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kans-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-websrv
spec:
  replicas: 1
  selector:
    matchLabels:
      app: deploy-websrv
  template:
    metadata:
      labels:
        app: deploy-websrv
    spec:
      serviceAccountName: kans-nginx
      terminationGracePeriodSeconds: 0
      containers:
      - name: deploy-websrv
        image: nginx:alpine
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc-clusterip
spec:
  ports:
    - name: svc-webport
      port: 80
      targetPort: 80
  selector:
    app: deploy-websrv
  type: ClusterIP
EOF
# 사이드카 컨테이너 배포 확인
kubectl get pod,svc,ep,sa -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
deploy-websrv-7d7cf8586c-rhhv8   2/2     Running   0          29s   172.16.2.6   k3s-w2   <none>           <none>
...

kc describe pod
  • Gateway, VirtualService CRD
cat <<EOF | kubectl create -f -
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: test-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: nginx-service
spec:
  hosts:
  - "$MYDOMAIN"
  gateways:
  - test-gateway
  http:
  - route:
    - destination:
        host: svc-clusterip
        port:
          number: 80
EOF
# Istio Gateway(=gw)/VirtualService(=vs) 설정 정보를 확인
kc explain gateways.networking.istio.io
kc explain virtualservices.networking.istio.io
kubectl api-resources  | grep istio

# virtual service 는 다른 네임스페이스의 서비스(ex. svc-nn.<ns>)도 참조할 수 있다
kubectl get gw,vs
NAME                                       AGE
gateway.networking.istio.io/test-gateway   21s

NAME                                               GATEWAYS           HOSTS                AGE
virtualservice.networking.istio.io/nginx-service   ["test-gateway"]   ["www.gasida.dev"]   4m9s

# Retrieves last sent and last acknowledged xDS sync from Istiod to each Envoy in the mesh
# istioctl proxy-status command was improved to include the time since last change, and more relevant status values.
istioctl proxy-status # 단축어 ps
istioctl ps
  • 외부(localPC,testpc) 접속 테스트
# istio ingress gw 를 통한 접속 테스트
curl -s $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>"
curl -v -s $MYDOMAIN:$IGWHTTP
curl -v -s <유동공인이IP>:$IGWHTTP
  • 출력 로그 확인
kubetail -n istio-system -l app=istio-ingressgateway -f
kubetail -l app=deploy-websrv
  • istioctl 정보 확인
#
istioctl proxy-status
NAME                                                   CLUSTER        CDS                LDS                EDS                RDS                ECDS        ISTIOD                      VERSION
deploy-websrv-7d7cf8586c-l22cs.default                 Kubernetes     SYNCED (22m)       SYNCED (22m)       SYNCED (22m)       SYNCED (22m)       IGNORED     istiod-7f8b586864-mv944     1.23.2
istio-ingressgateway-5f9f654d46-c4g7s.istio-system     Kubernetes     SYNCED (5m19s)     SYNCED (5m19s)     SYNCED (5m19s)     SYNCED (5m19s)     IGNORED     istiod-7f8b586864-mv944     1.23.2

# Envoy config dump : all, cluster, endpoint, listener 등
istioctl proxy-config --help 
istioctl proxy-config all deploy-websrv-7d7cf8586c-l22cs
istioctl proxy-config all deploy-websrv-7d7cf8586c-l22cs -o json | jq
istioctl proxy-config route deploy-websrv-7d7cf8586c-l22cs -o json | jq
  • pilot
    • istio-proxy 내 uds 로 envoy 와 grpc 통신
    • istiod 받아온 dynamic config 를 envoy 에 전달
# istio-proxy 사용자 정보 확인 : uid(1337):gid(1337) 확인 -> iptables rule 에서 사용됨
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- tail -n 3 /etc/passwd
# ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
# tcpdump:x:100:102::/nonexistent:/usr/sbin/nologin
# istio-proxy:x:1337:1337::/home/istio-proxy:/bin/sh

# envoy 설정 정보 확인 : dynamic_resources , static_resources - listeners  : 출력되는 IP가 누구인지 확인 해보자
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- cat /etc/istio/proxy/envoy-rev.json
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- ss -nlp
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- ss -np
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- netstat -np
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 172.16.1.10:15021       172.16.1.1:49548        TIME_WAIT   -                   
tcp        0      0 172.16.1.10:15006       172.16.2.4:37814        ESTABLISHED 12/envoy            
tcp        0      0 172.16.1.10:15021       172.16.1.1:43138        TIME_WAIT   -                   
tcp        0      0 127.0.0.1:39158         127.0.0.1:15020         ESTABLISHED 12/envoy            
tcp        0      0 172.16.1.10:15021       172.16.1.1:42948        TIME_WAIT   -                   
tcp        0      0 172.16.1.10:51370       10.10.200.82:15012      ESTABLISHED 1/pilot-agent       
tcp        0      0 172.16.1.10:15021       172.16.1.1:39522        TIME_WAIT   -                   
tcp        0      0 172.16.1.10:51360       10.10.200.82:15012      ESTABLISHED 1/pilot-agent       
tcp        0      0 127.0.0.1:39172         127.0.0.1:15020         ESTABLISHED 12/envoy            
tcp6       0      0 127.0.0.1:15020         127.0.0.1:39158         ESTABLISHED 1/pilot-agent       
tcp6       0      0 127.0.0.1:15020         127.0.0.1:39172         ESTABLISHED 1/pilot-agent       

Active UNIX domain sockets (w/o servers)
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
unix  3      [ ]         STREAM     CONNECTED     151002   1/pilot-agent        var/run/secrets/workload-spiffe-uds/socket
unix  3      [ ]         STREAM     CONNECTED     152729   -                    
unix  3      [ ]         STREAM     CONNECTED     152723   -                    
unix  3      [ ]         STREAM     CONNECTED     152727   -                    
unix  3      [ ]         STREAM     CONNECTED     150129   12/envoy             
unix  3      [ ]         STREAM     CONNECTED     152726   -                    
unix  3      [ ]         STREAM     CONNECTED     152724   -                    
unix  3      [ ]         STREAM     CONNECTED     152722   -                    
unix  3      [ ]         STREAM     CONNECTED     150979   12/envoy             
unix  3      [ ]         STREAM     CONNECTED     152728   -                    
unix  3      [ ]         STREAM     CONNECTED     152725   -                    
unix  3      [ ]         STREAM     CONNECTED     150120   1/pilot-agent        etc/istio/proxy/XDS

#
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
istio-p+       1       0  0 07:11 ?        00:00:00 /usr/local/bin/pilot-agent proxy sidecar --domain default.svc.cluster.local --p
istio-p+      12       1  0 07:11 ?        00:00:02 /usr/local/bin/envoy -c etc/istio/proxy/envoy-rev.json --drain-time-s 45 --drai
istio-p+      91       0  0 07:21 pts/0    00:00:00 ps -ef

# 출력되는 IP가 누구인지 확인 해보자
kubectl get pod,svc -A -owide
kubectl exec -it deploy/deploy-websrv -c istio-proxy -- netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:15004         0.0.0.0:*               LISTEN      1/pilot-agent       
tcp        0      0 127.0.0.1:15000         0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15090           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15090           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15021           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15021           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15006           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15006           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15001           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 0.0.0.0:15001           0.0.0.0:*               LISTEN      12/envoy            
tcp        0      0 172.16.1.10:15006       172.16.2.4:37814        ESTABLISHED 12/envoy            
tcp        0      0 172.16.1.10:15021       172.16.1.1:42632        TIME_WAIT   -                   
tcp        0      0 127.0.0.1:39158         127.0.0.1:15020         ESTABLISHED 12/envoy            
tcp        0      0 172.16.1.10:15021       172.16.1.1:55752        TIME_WAIT   -                   
tcp        0      0 172.16.1.10:51370       10.10.200.82:15012      ESTABLISHED 1/pilot-agent       
tcp        0      0 172.16.1.10:15021       172.16.1.1:50394        TIME_WAIT   -                   
tcp        0      0 172.16.1.10:51360       10.10.200.82:15012      ESTABLISHED 1/pilot-agent       
tcp        0      0 172.16.1.10:15021       172.16.1.1:49496        TIME_WAIT   -                   
tcp        0      0 127.0.0.1:39172         127.0.0.1:15020         ESTABLISHED 12/envoy            
tcp6       0      0 :::80                   :::*                    LISTEN      -                   
tcp6       0      0 :::15020                :::*                    LISTEN      1/pilot-agent       
tcp6       0      0 127.0.0.1:15020         127.0.0.1:39158         ESTABLISHED 1/pilot-agent       
tcp6       0      0 127.0.0.1:15020         127.0.0.1:39172         ESTABLISHED 1/pilot-agent  


# istiod 정보 같이 확인 : 출력되는 IP가 누구인지 확인 해보자
kubectl get pod,svc -A -owide
kubectl exec -it deploy/istiod -n istio-system -- ps -ef
kubectl exec -it deploy/istiod -n istio-system -- netstat -antp
kubectl exec -it deploy/istiod -n istio-system -- ss -nlp
kubectl exec -it deploy/istiod -n istio-system -- ss -np
https://www.anyflow.net/sw-engineer/istio-internals-by-port

결과

  • 배포확인
    • pod,svc,ep,sa > deploy-svc 구성요소
    • gw,vs > istio 구성요소
  • 접근 확인
    • vs에 호스트라우팅 설정
    • DNS기반 접근만 가능/IP 불가
  • /etc/istio/proxy/envoy-rev.json 확인
    • dynamic_resources > xDS(lds,cds 등) 설정
    • static_resources > xDS 소켓 통신
    • listeners > 음..?
  • envoy 세션정보
    • envoy) deploy-websrv 에서 ingressgateway로 연결
    • pilot-agent) deploy-websrv 에서 istiod로 연결
      • 172.16.0.6 > deploy-websrv pod IP
      • 172.16.0.5 > istio-ingressgateway pod IP
      • 10.10.200.128 > istiod svc IP

4.4. Bookinfo 실습 및 istio 기능

Bookinfo Application

Bookinfo 애플리케이션 소개

  • 4개의 마이크로서비스로 구성
    • Productpage
    • reviews
    • ratings
    • details
  • 작동방식
    • ProductPage 페이지에서 요청을 받으면
    • 도서 리뷰는 Reviews / 도서 상세 정보는 Details 서비스에 접속 및 조회,
    • ProductPage 는 Reviews 와 Details 결과를 사용자에게 응답
  • 버전별 차이
    • Reviews 서비스는 v1, v2, v3 세 개의 버전이 있고 v2, v3 버전의 경우 Ratings 서비스에 접속하여 도서에 대한 5단계 평가를 가져옴.
      • v1은 Rating 이 없음
      • v2는 검은색 별로 Ratings 가 표시
      • v3는 색깔이 있는 별로 Ratings 가 표시

Bookinfo 애플리케이션 배포

# 모니터링
watch -d 'kubectl get pod -owide;echo;kubectl get svc'

# Bookinfo 애플리케이션 배포
echo $ISTIOV
cat ~/istio-$ISTIOV/samples/bookinfo/platform/kube/bookinfo.yaml
kubectl apply -f ~/istio-$ISTIOV/samples/bookinfo/platform/kube/bookinfo.yaml

# 확인
kubectl get all,sa

# product 웹 접속 확인
kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"

# 로그
kubetail -l app=productpage -f

4.4.1 Istio 를 통한 인입 기본 설정

Istio의 Traffic Management 문서에서, 트래픽 관리를 위한 리소스는 아래의 5개가 있다.

  • Virtual Services (vs)
    • 트래픽 라우팅 규칙을 정의하여 서비스 간 통신 흐름을 제어
  • Destination Rules (dr)
    • 특정 서비스의 트래픽 정책(예: 로드 밸런싱, 연결 설정, 재시도등)을 정의
  • Gateways (gw)
    • 외부 트래픽을 메시로 들어오거나 나가게 할 때 경로 설정
  • Service Entries (se)
    • 외부 서비스(메시 외부)의 트래픽을 istio에서 인식하고 제어할 수 있도록 추가
  • Sidecars
    • 서비스 메시의 기능을 애플리케이션에 제공하기 위해 배포되는 프록시 컨테이너(envoy)

이번 단계에서는 이들 중, gateway(gw)와 virtualservice(vs)의 사용법을 확인

Istio Gateway/VirtualService 설정

  • bookinfo-gateway.yaml
# yaml 내부
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  # The selector matches the ingress gateway pod labels.
  # If you installed Istio using Helm following the standard documentation, this would be "istio=ingress"
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 8080
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
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
# Istio Gateway/VirtualService 설정
cat ~/istio-$ISTIOV/samples/bookinfo/networking/bookinfo-gateway.yaml
kubectl apply -f ~/istio-$ISTIOV/samples/bookinfo/networking/bookinfo-gateway.yaml

# 확인
kubectl get gw,vs
istioctl proxy-status
NAME                                                   CLUSTER        CDS                LDS                EDS                RDS                ECDS        ISTIOD                      VERSION
details-v1-65cfcf56f9-4drsk.default                    Kubernetes     SYNCED (7m4s)      SYNCED (7m4s)      SYNCED (6m57s)     SYNCED (7m4s)      IGNORED     istiod-7f8b586864-mv944     1.23.2
istio-ingressgateway-5f9f654d46-c4g7s.istio-system     Kubernetes     SYNCED (3m7s)      SYNCED (3m7s)      SYNCED (6m57s)     SYNCED (3m7s)      IGNORED     istiod-7f8b586864-mv944     1.23.2
productpage-v1-d5789fdfb-5cr6m.default                 Kubernetes     SYNCED (6m59s)     SYNCED (6m59s)     SYNCED (6m57s)     SYNCED (6m59s)     IGNORED     istiod-7f8b586864-mv944     1.23.2
ratings-v1-7c9bd4b87f-9q4nv.default                    Kubernetes     SYNCED (7m3s)      SYNCED (7m3s)      SYNCED (6m57s)     SYNCED (7m3s)      IGNORED     istiod-7f8b586864-mv944     1.23.2
reviews-v1-6584ddcf65-rqgp7.default                    Kubernetes     SYNCED (7m2s)      SYNCED (7m2s)      SYNCED (6m57s)     SYNCED (7m2s)      IGNORED     istiod-7f8b586864-mv944     1.23.2
reviews-v2-6f85cb9b7c-h6m7p.default                    Kubernetes     SYNCED (7m2s)      SYNCED (7m2s)      SYNCED (6m57s)     SYNCED (7m2s)      IGNORED     istiod-7f8b586864-mv944     1.23.2
reviews-v3-6f5b775685-rprpb.default                    Kubernetes     SYNCED (6m58s)     SYNCED (6m58s)     SYNCED (6m57s)     SYNCED (6m58s)     IGNORED     istiod-7f8b586864-mv944     1.23.2

# productpage 파드의 istio-proxy 로그 확인 Access log 가 출력 - Default access log format : 링크
kubetail -l app=productpage -c istio-proxy -f

Istio 를 통한 productpage 접속(반복) 테스트 & 웹 브라우저 접속 테스트

  • k3s-s NodePort 접속 확인
#
export IGWHTTP=$(kubectl get service -n istio-system istio-ingressgateway -o jsonpath='{.spec.ports[1].nodePort}')
echo $IGWHTTP
32759

# 접속 확인
kubectl get svc -n istio-system istio-ingressgateway
curl -s http://localhost:$IGWHTTP/productpage
curl -s http://192.168.10.101:$IGWHTTP/productpage
curl -s http://192.168.10.102:$IGWHTTP/productpage

# 정보 확인
echo $MYDOMAIN
cat /etc/hosts

#
curl -s http://$MYDOMAIN:$IGWHTTP/productpage
  • 자신의 PC에서 접속 확인
#
echo $MYDOMAIN $IGWHTTP
cat /etc/hosts

#
curl -v -s $MYDOMAIN:$IGWHTTP/productpage
echo -e "http://$MYDOMAIN:$IGWHTTP/productpage"

#
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text
  • testpc에서 접속 실행
# istio ingress gw 를 통한 접속 테스트
curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>"
while true; do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; done
for i in {1..100};  do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; done

결과

  • gw > vs > svc > pod(productpage) > svc(review,detail) > pod(review,detail)
  • review service에 각 review pod가 endpoint 등록 > 무작위 응답

4.4.2 모니터링

Kiali는 istio의 서비스 메시 구성 및 검증 기능을 갖춘 observability 콘솔입니다. 트래픽 흐름을 모니터링하여 메시의 구조와 상태를 이해하고 오류를 보고하는 데 도움을 줍니다. Kiali는 상세한 메트릭을 제공하며, 기본적인 Grafana 통합을 통해 고급 쿼리에 활용할 수 있습니다. 분산 추적 기능은 Jaeger와의 통합을 통해 지원됩니다.

Kiali is an observability console for Istio with service mesh configuration and validation capabilities. It helps you understand the structure and health of your service mesh by monitoring traffic flow to infer the topology and report errors. Kiali provides detailed metrics and a basic Grafana integration, which can be used for advanced queries. Distributed tracing is provided by integration with Jaeger.

Kiali, istio docs

Kiali는 istio와 같은 서비스 메시 환경에서 사용되는 트래픽 가시화 툴이다.

  • Kiali is an observability console for Istio with service mesh configuration and validation capabilities. Kiali provides detailed metrics and a basic Grafana integration, which can be used for advanced queries. Distributed tracing is provided by integration with Jaeger.
    • Jaeger 와 연동을 통해서 분산 트레이싱을 제공할 수 있다
  • Monitoring port of the IstioD pod : Kiali connects directly to the IstioDpod (not the Service) to check for its health. By default, the connection is done to port15014 which is the default monitoring port of the IstioD pod.
    • 파드의 헬스체크는 Kiali 가 직접 IstioD 파드에 TCP Port 15014 를 통해서 체크한다 (링크)
  • Prometheus, Jaeger and Grafana Prometheus and Jaeger are primary data sources for Kiali. This page describes how to configure Kiali to communicate with these dependencies. A minimalistic Grafana integration is also available.
    • 주 데이터 소스는 Prometheus and Jaeger 이며, 최소 수준의 Grafana 와 연동할 수 있다 – 링크


istio는 여러 다른 어플리케이션들과의 호환성을 제공하고 있기때문에 간편히 구성하고 사용할 수 있다.

Addon 설치 : Kiali (키알리) 대시보드 along with Prometheus, Grafana, and Jaeger

# Install Kiali and the other addons and wait for them to be deployed. : Kiali dashboard, along with Prometheus, Grafana, and Jaeger.
tree ~/istio-$ISTIOV/samples/addons/
kubectl apply -f ~/istio-$ISTIOV/samples/addons # 디렉터리에 있는 모든 yaml 자원을 생성
kubectl rollout status deployment/kiali -n istio-system

# 확인
kubectl get all,sa,cm -n istio-system
kubectl get svc,ep -n istio-system

# kiali 서비스 변경
kubectl patch svc -n istio-system kiali -p '{"spec":{"type":"NodePort"}}'

# kiali 웹 접속 주소 확인
KIALINodePort=$(kubectl get svc -n istio-system kiali -o jsonpath={.spec.ports[0].nodePort})
echo -e "KIALI UI URL = http://$(curl -s ipinfo.io/ip):$KIALINodePort"

# Grafana 서비스 변경
kubectl patch svc -n istio-system grafana -p '{"spec":{"type":"NodePort"}}'

# Grafana 웹 접속 주소 확인 : 7개의 대시보드
GRAFANANodePort=$(kubectl get svc -n istio-system grafana -o jsonpath={.spec.ports[0].nodePort})
echo -e "Grafana URL = http://$(curl -s ipinfo.io/ip):$GRAFANANodePort"

# Prometheus 서비스 변경
kubectl patch svc -n istio-system prometheus -p '{"spec":{"type":"NodePort"}}'

# Prometheus 웹 접속 주소 확인
PROMENodePort=$(kubectl get svc -n istio-system prometheus -o jsonpath={.spec.ports[0].nodePort})
echo -e "Prometheus URL = http://$(curl -s ipinfo.io/ip):$PROMENodePort"

Kiali (키알리) 대시보드 둘러보기

  • Visualizing Your Mesh
    • Namespace 를 default 로 선택 후
    • Graph (Traffic, Versioned app graph)의 Display 옵션 중
    • ‘Traffic Distribution’ 과 ‘Traffic Animation’ 활성화!
    • Security 체크 (Last 1m, Evety 10s)
  • testpc에서 반복 트래픽 요청 (1초, 0.5초, 0.3초, 0.1초)
testpc 에서 아래 실행
# 반복 접속 테스트
while true; do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; done
while true; do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 0.1; done
while true; do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 0.5; done
for i in {1..100};  do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; done
for i in {1..1000}; do curl -s $MYDOMAIN:$IGWHTTP/productpage | grep -o "<title>.*</title>" ; done

결과

  • 프로메테우스 동작 확인
    • istio_, envoy_ 로 시작하는 메트릭 수집 확인
  • 그라파나 동작 확인
    • istio 관련 기본 대시보드 및 데이터 수집 확인

  • 키알리 동작 확인
    • 트래픽 시각화, 앱 로그등 기능 확인

4.4.3 Traffic Management

동작 소개

  • 클라이언트 PC → Istio ingressgateway 파드 → (Gateway, VirtualService + DestinationRule) → Cluster(Endpoint – 파드)
  • Gateway
    • 지정한 인그레스 게이트웨이로부터 트래픽이 인입, 프로토콜 및 포트, HOSTS, Proxy 등 설정 가능
  • VirtualService
    • 인입 처리할 hosts 설정, L7 PATH 별 라우팅, 목적지에 대한 정책 설정 가능 (envoy route config)
# VirtualService 예시
# 헤더 매칭에 따라서, 각기 다른 destination 으로 라우팅
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v3
  • VirtualService 는 DestinationRule 에서 설정된 서브셋(subset)을 사용하여 트래픽 컨트롤을 할 수 있다
    • hosts 필드 : 목적지 주소 – IP address, a DNS name (FQDN), 혹은 k8s svc 이름 , wildcard (”*”) prefixes
    • Routing rules : HTTP 경우 – Match 필드(예, 헤더) , Destination(istio/envoy 에 등록된 대상, subnet 에 DestinationRule 활용)
    • HTTPRoute : redirect , rewrite , fault(장애 주입) , mirror(복제, 기본 100%) , corsPolicy(CORS 삽입) , headers(헤더 조작) 등
    • Routing rule precedence : Routing rules are evaluated in sequential order from top to bottom – 위에서 순차적 적용
  • DestinationRule
    • 실제 도착지(서비스와 1:1 연결)의 정교한 정책(부하분산, 연결 옵션, 서킷 브레이크, TLS 등)을 설정
# 3개의 subsets for the my-svc destination service 에 3개의 subsets 이 있고, 이중 v1/v3 은 RAMDOM 이고 v2 는 ROUND_ROBIN
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: my-destination-rule
spec:
  host: my-svc
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
    trafficPolicy:
      loadBalancer:
        simple: ROUND_ROBIN
  - name: v3
    labels:
      version: v3
  • Load balancing options : Round robin(기본값) , Random , Weighted , Least requests
    • Destination Rule : TrafficPolicy , Subset , ConnectionPoolSettings 등
    • 서브셋(subsets)을 정의할 수 있어 마이크로서비스 버전별로 라우팅할 때 사용한다

Request Routing

이 작업에서는 여러 버전의 마이크로서비스로 요청을 동적으로 라우팅하는 방법을 보여줍니다 – 링크

실습 전 기본 DestinationRule 적용 : 각각의 파드에 subset 지정

# 샘플 파일들 확인
cd ~/istio-$ISTIOV/samples/bookinfo/networking
tree

# 기본 DestinationRule 적용
kubectl apply -f destination-rule-all.yaml

# DestinationRule 확인 dr(=destinationrules) : KIALI Services 확인 시 GW, VS, DR 확인
kubectl get dr
NAME          HOST          AGE
details       details       16m
productpage   productpage   16m
ratings       ratings       16m
reviews       reviews       16m

virtual-service-all-v1.yaml
4개 서비스 모두 v1 의 서브셋(subset) 에 전송하는 정책 테스트

  • virtual-service-all-v1.yaml
# yaml 내부
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: productpage
spec:
  hosts:
  - productpage
  http:
  - route:
    - destination:
        host: productpage
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - route:
    - destination:
        host: ratings
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: details
spec:
  hosts:
  - details
  http:
  - route:
    - destination:
        host: details
        subset: v1
---
# istio vs(virtualservices) 확인
kubectl get vs
NAME       GATEWAYS               HOSTS   AGE
bookinfo   ["bookinfo-gateway"]   ["*"]   85m

# 모든 마이크로서비스에 대해 v1 의 서브셋(subset) 에 전송되게 virtualservices 적용
kubectl apply -f virtual-service-all-v1.yaml

# istio vs(virtualservices) 확인 >> KIALI 에서 reviews v2,v3 향하는 트래픽 경로가 사라진다!
kubectl get virtualservices
NAME          GATEWAYS               HOSTS             AGE
bookinfo      ["bookinfo-gateway"]   ["*"]             85m
details                              ["details"]       9s
productpage                          ["productpage"]   9s
ratings                              ["ratings"]       9s
reviews                              ["reviews"]       9s

virtual-service-reviews-test-v2.yaml
User Identity 기반 라우팅, end-user 커스텀 헤더에 jason 매칭 시 reviews v2 로 전달

  • virtual-service-reviews-test-v2.yaml : match 설정이 위에 배치되어 있다
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v1
  • Match 조건에는 완전 일치(exact) , 전방 일치(prefix) , 정규 표현(regex) – 3가지 패턴을 선택할 수 있다
# 모든 마이크로서비스에 대해 v1 의 서브셋(subset) 에 전송되게 virtualservices 적용
kubectl apply -f virtual-service-reviews-test-v2.yaml

# jason 로그인 시 로그 확인
kubetail -l app=productpage -f
[productpage-v1-6b746f74dc-7ptpj productpage] INFO:werkzeug:127.0.0.6 - - [13/Feb/2022 09:00:37] "POST /login HTTP/1.1" 302 -
[productpage-v1-6b746f74dc-7ptpj productpage] DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): details:9080
[productpage-v1-6b746f74dc-7ptpj productpage] send: b'GET /details/0 HTTP/1.1\r\nHost: details:9080\r\nuser-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nX-B3-TraceId: 5d48ade1f048c3fc7ebe4197c22c3275\r\nX-B3-SpanId: 675da1ab468945b5\r\nX-B3-ParentSpanId: 7ebe4197c22c3275\r\nX-B3-Sampled: 1\r\nend-user: jason\r\nx-request-id: 95907bc3-1a86-9f1d-8963-3723b9fb1e21\r\n\r\n'
[productpage-v1-6b746f74dc-7ptpj productpage] reply: 'HTTP/1.1 200 OK\r\n'
[productpage-v1-6b746f74dc-7ptpj productpage] header: content-type: application/json
[productpage-v1-6b746f74dc-7ptpj productpage] header: server: envoy
[productpage-v1-6b746f74dc-7ptpj productpage] header: date: Sun, 13 Feb 2022 09:00:37 GMT
[productpage-v1-6b746f74dc-7ptpj productpage] header: content-length: 178
[productpage-v1-6b746f74dc-7ptpj productpage] header: x-envoy-upstream-service-time: 1

[productpage-v1-6b746f74dc-7ptpj productpage] DEBUG:urllib3.connectionpool:http://details:9080 "GET /details/0 HTTP/1.1" 200 178
[productpage-v1-6b746f74dc-7ptpj productpage] DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): reviews:9080
[productpage-v1-6b746f74dc-7ptpj productpage] send: b'GET /reviews/0 HTTP/1.1\r\nHost: reviews:9080\r\nuser-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nX-B3-TraceId: 5d48ade1f048c3fc7ebe4197c22c3275\r\nX-B3-SpanId: 675da1ab468945b5\r\nX-B3-ParentSpanId: 7ebe4197c22c3275\r\nX-B3-Sampled: 1\r\nend-user: jason\r\nx-request-id: 95907bc3-1a86-9f1d-8963-3723b9fb1e21\r\n\r\n'
[productpage-v1-6b746f74dc-7ptpj productpage] reply: 'HTTP/1.1 200 OK\r\n'
[productpage-v1-6b746f74dc-7ptpj productpage] header: x-powered-by: Servlet/3.1
[productpage-v1-6b746f74dc-7ptpj productpage] header: content-type: application/json
[productpage-v1-6b746f74dc-7ptpj productpage] header: date: Sun, 13 Feb 2022 09:00:37 GMT
[productpage-v1-6b746f74dc-7ptpj productpage] header: content-language: en-US
[productpage-v1-6b746f74dc-7ptpj productpage] header: content-length: 379
[productpage-v1-6b746f74dc-7ptpj productpage] header: x-envoy-upstream-service-time: 32
[productpage-v1-6b746f74dc-7ptpj productpage] header: server: envoy
[productpage-v1-6b746f74dc-7ptpj productpage] DEBUG:urllib3.connectionpool:http://reviews:9080 "GET /reviews/0 HTTP/1.1" 200 379
[productpage-v1-6b746f74dc-7ptpj productpage] INFO:werkzeug:127.0.0.6 - - [13/Feb/2022 09:00:37] "GET /productpage HTTP/1.1" 200 -

결과

  • virtual-service-all-v1.yaml 적용
    • reviews-v1으로만 트래픽 전달 / v2,v3는 트래픽 수신없음
  • virtual-service-reviews-test-v2.yaml
    • 기존접근시 v1만 출력, jason 로그인시 jason 헤더정보 추가 및 v2 출력 확인

5. Istio 트래픽 흐름

  • Istio 통신
    • 호스트의 tcp/ip 와 iptables 과 파드 내에 iptables 와 envoy 를 경유
    • 달리기에 비유하자면, Istio 가 없을 경우를 운동장 한바퀴라면, istio 사용 시 대략 운동장 세바퀴라고 볼 수 있습니다.
    • Istio 사용 시 장점도 있지만, 없을 경우 대비 비용(지연 추가, 프로세싱 추가, 복잡한 구조 등)이 추가됩니다.
Service mesh w/traditional networking


  • 외부 클라이언트 PC에서 K8S 파드(웹서버)로 접속 과정

Istio 접속 테스트를 위한 변수 지정

  • k3s-s
k3s-s)
# istio ingress gw NodePort(HTTP 접속용) 변수 지정 : 아래 ports[0] 은 어떤 용도의 포트일까요?
export IGWHTTP=$(kubectl get service -n istio-system istio-ingressgateway -o jsonpath='{.spec.ports[1].nodePort}')
echo $IGWHTTP
IGWHTTP=<각자 자신의 NodePort>

## istio-ingressgateway 파드가 배치된 노드의 유동 공인 IP 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text
k3s-s	3.38.151.222	running
k3s-w1	15.165.75.117	running
k3s-w2	3.39.223.99	running
testpc	54.180.243.135	running

# /etc/hosts 파일 수정
MYDOMAIN=<각자 자신의 www 도메인> # 단, 사용하고 있지 않는 공인 도메인을 사용 할 것
MYDOMAIN=www.gasida.dev
echo "<istio-ingressgateway 파드가 있는 워커 노드> $MYDOMAIN" >> /etc/hosts

MYDOMAIN=<각자 자신의 www 도메인>
export MYDOMAIN=www.gasida.dev
echo -e "192.168.10.10 $MYDOMAIN" >> /etc/hosts
echo -e "export MYDOMAIN=$MYDOMAIN" >> /etc/profile

# istio ingress gw 접속 테스트 : 아직은 설정이 없어서 접속 실패가 된다
curl -v -s $MYDOMAIN:$IGWHTTP
  • testpc
# 아래 변수는 각자 자신의 값을 직접 입력 할 것
IGWHTTP=30492
export MYDOMAIN=www.gasida.dev
echo -e "192.168.10.10 $MYDOMAIN" >> /etc/hosts
echo -e "export MYDOMAIN=$MYDOMAIN" >> /etc/profile

# istio ingress gw 접속 테스트 : 아직은 설정이 없어서 접속 실패가 된다
curl -v -s $MYDOMAIN:$IGWHTTP
  • localPC
# 아래 변수는 각자 자신의 값을 직접 입력 할 것 : ISTIONODEIP는 3개의 노드 중 아무거나 입력
IGWHTTP=30492
ISTIONODEIP=3.39.223.99
MYDOMAIN=www.gasida.dev
echo "$ISTIONODEIP $MYDOMAIN" | sudo tee -a /etc/hosts

# istio ingress gw 접속 테스트 : 아직은 설정이 없어서 접속 실패가 된다
curl -v -s $MYDOMAIN:$IGWHTTP

실습을 위한 환경 설정 및 배포
nginx-app 로 향하는 통신의 경우 peer 간 mtls 끄기

  • 리소스 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx-app
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc-nginx
spec:
  ports:
    - name: svc-nginx
      port: 80
      targetPort: 80
  selector:
    app: nginx-app
  type: ClusterIP
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: test-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: nginx-service
spec:
  hosts:
  - "$MYDOMAIN"
  gateways:
  - test-gateway
  http:
  - route:
    - destination:
        host: svc-nginx
        port:
          number: 80
EOF
  • 접근확인
# 모니터링
watch -d "kubectl get svc -n istio-system -l app=istio-ingressgateway;echo;kubectl get pod -n istio-system -o wide -l app=istio-ingressgateway;echo;kubectl get pod -owide nginx-pod"
watch -d "kubectl get pod -n istio-system -o wide -l app=istio-ingressgateway;echo;kubectl get pod -owide nginx-pod"

testpc 에서 아래 실행
# istio ingress 를 통한 접속
curl -s -v $MYDOMAIN:$IGWHTTP
curl -s $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>"
while true; do curl -s $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; done
while true; do curl -s $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 0.1; done

# 서비스 중 app: nginx-app 로 향하는 통신의 경우 peer 간 mtls 끄기(istio-ingressgw 와 목적지 워커노드의 파드에 istio-proxy 간)
cat <<EOF | kubectl create -f -
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: "example-workload-policy"
spec:
  selector:
     matchLabels:
       app: nginx-app
  portLevelMtls:
    80:
      mode: DISABLE
EOF
  • ClientIP 확인을 위한 추가설정
# istio-ingressgateway 서비스 externalTrafficPolicy 설정 : 점검
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec":{"externalTrafficPolicy": "Local"}}'

# testpc 에 /etc/hosts 에 istio-ingressgateway 파드가 배포된 ec2의 private ip 로 도메인 변경
vi /etc/hosts

5.1. 클라이언트(요청) → 파드(인입)

  • 트래픽 흐름
    • 외부 클라이언트 PC에서 k8s 클러스터 내부의 웹 서버 파드로 인입 시 트래픽 흐름입니다
    • 기존 패킷 내용 중 변경 전(굵음)과 변경 후(빨간 색)으로 표현하였습니다


understand-inbound-handler


5.1.1 Client PC → Istio IngressGateway 파드 구간

  • 외부 클라이언트 PC(192.168.10.254) 에서 웹 서버 파드로 접속 시도
# 아래 처럼 정상적으로 웹 서버 접속 정보 출력 확인
curl -s -v $MYDOMAIN:$IGWHTTP
curl -s $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>"
while true; do curl -s $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; done
while true; do curl -s $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 0.1; done

curl -s --user-agent "IPHONE" $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>"
while true; do curl -s $MYDOMAIN:$IGWHTTP | grep -o "<title>.*</title>"; date "+%Y-%m-%d %H:%M:%S" ; echo "--------------" ; sleep 1; done

# 로그 확인
kubetail -l app=nginx-app -f


5.1.2. Istio IngressGateway 파드 → 노드 인입

  • Istio IngressGateway(envoy) 파드를 경유하여 웹 서버 파드가 있는 노드로 인입
    • Istio IngressGateway(envoy) 파드는 클라이언트 PC의 IP를 HTTP XFF(X-Forwarded-for) 헤더에 담아서 전달합니다
    • Istio IngressGateway(envoy) 파드 x-envoy-Y 헤더를 추가해서 전달합니다


5.1.3. [파드 내부] IPTables 적용 → Istio-proxy 컨테이너 인입

  • ‘PAUSE 컨테이너’가 파드 네트워크 네임스페이스를 생성하여 제공하며,
  • ‘Init 컨테이너’는 Istio-proxy가 트래픽을 가로챌 수 있게 파드 내에 iptables rules 설정을 완료합니다.
# 아래 처럼 'istio-init 컨테이너' 의 로그에 iptables rules 설정을 확인할 수 있습니다.
# 참고로, NAT Tables 만 설정되고, 그외(filter, mangle, raw 등)은 설정하지 않습니다.
(istio-k8s:default) root@k8s-m:~# kubectl logs nginx-pod -c istio-init
* nat
-N ISTIO_INBOUND
-N ISTIO_REDIRECT
-N ISTIO_IN_REDIRECT
-N ISTIO_OUTPUT
-A ISTIO_INBOUND -p tcp --dport 15008 -j RETURN
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
-A PREROUTING -p tcp -j ISTIO_INBOUND
-A ISTIO_INBOUND -p tcp --dport 22 -j RETURN
-A ISTIO_INBOUND -p tcp --dport 15090 -j RETURN
-A ISTIO_INBOUND -p tcp --dport 15021 -j RETURN
-A ISTIO_INBOUND -p tcp --dport 15020 -j RETURN
-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
-A OUTPUT -p tcp -j ISTIO_OUTPUT
-A ISTIO_OUTPUT -o lo -s 127.0.0.6/32 -j RETURN
-A ISTIO_OUTPUT -o lo ! -d 127.0.0.1/32 -m owner --uid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -o lo ! -d 127.0.0.1/32 -m owner --gid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
-A ISTIO_OUTPUT -j ISTIO_REDIRECT
COMMIT
  • 파드 내 IPTables Chains/Rules 적용 (NAT 테이블) → ‘Istio-proxy 컨테이너’로 인입됩니다.
    • PREROUTING → ISTIO_INBOUND → ISTIO_IN_REDIRECT (redir ports 15006)

5.1.4. [파드 내부] Istio-proxy 컨테이너 → IPTables 적용

  • ‘Istio-proxy 컨테이너’ 는 대리인(Proxy) 역할로, 출발지 IP를 127.0.0.6 으로 변경하여 ‘Nginx 컨테이너’와 연결을 한다

5.1.5. [파드 내부] IPTables 적용 → Nginx 컨테이너 인입

  • 파드 내에 IPTables 는 전역(?)으로 적용되므로, ‘Istio-proxy’ 의 인/아웃 시 트래픽 구별이 중요하다.
  • 최종적으로 nginx 컨테이너에 클라이언트의 요청 트래픽이 도착한다.

5.2. 파드(리턴 트래픽) → 클라이언트

  • 트래픽 흐름
    • nginx (웹 서버)컨테이너에서 리턴 트래픽(응답, 200 OK)를 클라이언트에 전달합니다.
    • IPTables CT(Connection Table)에 정보를 참고해서 역변환 등이 적용되어 전달됩니다.


  • 8번 과정의 패킷
    • 200 OK 응답이며, ‘Istio-proxy’ 에 의해서 x-envoy-upstream-Y 헤더가 추가되어 있습니다.

5.3. 파드(요청) → 외부 웹서버

  • 트래픽 흐름
    • 파드에서 업데이트 나 패치 다운로드 처럼 외부 웹서버 나 인터넷 연결 과정에서의 트래픽의 흐름입니다.


  • 파드 내 IPTables 적용 흐름
    • 아래 (9) ~ (15) 까지의 과정

5.3.1. [파드 내부] Client PC → Istio IngressGateway 파드 구간

  • ‘nginx 컨테이너’ 에서 외부 웹서버 요청을 합니다.

5.3.2. [파드 내부] IPTables → Istio-proxy 컨테이너 인입

  • 파드 내 IPTables Chains/Rules 적용 (NAT 테이블) → ‘Istio-proxy 컨테이너’로 인입됩니다.
    • OUTPUT → ISTIO_OUTPUT → ISTIO_REDIRECT (redir ports 15001)


5.3.3. [파드 내부] Istio-proxy 컨테이너 → 노드의 호스트 네임스페이스

  • ‘Istio-proxy 컨테이너’ 는 대리인(Proxy) 역할로, 출발지 포트를 변경(+2) 후 외부 웹서버에 연결을 한다
  • 파드를 빠져나가기 전, 다시 한번 더 IPTables 적용 된다 ⇒ 이때, 이전 트래픽과 매칭되는 Rule 이 다른 것은 UID 1337 때문


5.3.4. 노드 → 외부

  • 노드에 SNAT(masquerading) 설정이 되어 있을 경우, 출발지 IP 를 노드의 NIC IP로 변환하여 외부 웹서버에 요청을 전달합니다.


5.4. 외부 웹서버(리턴 트래픽) → 파드

  • 웹 서버에서 리턴 트래픽이 파드에 돌아오는 과정은 **1.**2 에서 알아본 흐름과 유사합니다.
  • 다만, 파드 내로 인입 시 목적지 포트(+2) 이므로, ‘Nginx 컨테이너’ 로 바로 가지 않고, ‘Istio-proxy 컨테이너’ 로 먼저 가게 됩니다.

Leave a Reply