안녕하세요?
Istio in Action 책을 공부하면서 내용을 조금씩 정리해보려고 합니다.
10장은 데이터 플레인 트러블슈팅하기 입니다.
실습 환경 준비
- MacOS, OrbStack으로 Container 구동
- Kind, k8s 1.33.1
- istioctl 1.27.0
curl -L https://istio.io/downloadIstio | sh -
istioctl install --set profile=demo -y
|\
| \
| \
| \
/|| \
/ || \
/ || \
/ || \
/ || \
/ || \
/______||__________\
____________________
\__ _____/
\_____/
WARNING: Istio is being upgraded from 1.13.0 to 1.27.0.
Running this command will overwrite it; use revisions to upgrade alongside the existing version.
Before upgrading, you may wish to use 'istioctl x precheck' to check for upgrade warnings.
✔ Istio core installed ⛵️
✔ Istiod installed 🧠
✔ Egress gateways installed 🛫
✔ Ingress gateways installed 🛬
✔ Installation complete
- 서비스 프록시에서 요청 처리에 참여하는 구성 요소들
- istiod : 데이터 플레인이 원하는 상태 desired state로 동기화되도록 보장
- 인그레스 게이트웨이 : 트래픽을 클러스터로 허용
- 서비스 프록시 : 접근 제어 기능을 제공하고, 다운스트림에서 로컬 애플리케이션으로 흐르는 트래픽을 처리
- 애플리케이션 그 자체 : 요청을 처리하고, 또 다른 업스트림 서비스로 체인을 이어나가는 다른 서비스에 요청을 허용하는 것

10.1 가장 흔한 실수
- 이스티오의 서비스 프록시 설정 : VirtualService, DestinationRule 로 노출
- 이 설정들이 Envoy 설정으로 변환되어 데이터 플레인에 적용됨
트러블 슈팅을 하기 위해 예제 배포
k apply -f services/catalog/kubernetes/catalog.yaml
k apply -f ch10/catalog-deployment-v2.yaml
k apply -f ch10/catalog-gateway.yaml
k apply -f ch10/catalog-virtualservice-subsets-v1-v2.yaml

10.2 데이터 플레인 문제 식별하기
10.2.1 데이터 플레인이 최신 상태인지 확인하는 방법
- 데이터 플레인 솔정은 궁극적 일관성
- 컨트롤 플레인과 동기화 전까지는 데이터 플레인에 즉시 반영되지 않음.
- 컨트롤 프렐인은 특정 서비스의 개별 엔드포인트 IP 주소를 데이터 플레인으로 보냄
- 이런 엔드포인트 중 하나가 비정상이 되면 쿠버네티스는 이를 인지하고 파드를 비정상을오 표시하는데 시간이 걸리고, 컨트롤 플레인도 문제를 인지하고 엔드포인트를 데이터 플레인에서 제거
대규모 클러스터에서는 데이터 플레인을 동기화 하는데 필요한 시간도 늘어난다.

워크로드가 비정상이 된 후 데이터 플레인 구성 요소의 설정이 업데이트될 때까지 일련의 이벤트
istioctl proxy-status
NAME CLUSTER ISTIOD VERSION SUBSCRIBED TYPES
catalog-5899bbc954-xnq22.istioinaction Kubernetes istiod-85798b5866-8ptm6 1.27.0 4 (CDS,LDS,EDS,RDS)
catalog-primary-658c756d7f-kv52g.istioinaction Kubernetes istiod-85798b5866-8ptm6 1.27.0 4 (CDS,LDS,EDS,RDS)
catalog-v2-7cc6f578cd-5jzdl.istioinaction Kubernetes istiod-85798b5866-8ptm6 1.27.0 4 (CDS,LDS,EDS,RDS)
catalog-v2-7cc6f578cd-rjrms.istioinaction Kubernetes istiod-85798b5866-8ptm6 1.27.0 4 (CDS,LDS,EDS,RDS)
istio-egressgateway-559bd55945-nspdv.istio-system Kubernetes istiod-85798b5866-8ptm6 1.27.0 3 (CDS,LDS,EDS)
istio-ingressgateway-74df47f5f9-nv65v.istio-system Kubernetes istiod-85798b5866-8ptm6 1.27.0 4 (CDS,LDS,EDS,RDS)
커맨드로 데이터 플레인이 최신 설정과 동기화되었는지 확인할 수 있다.
모든 워크로드와 모든 xDS API 별로 동기화 상태가 나열
- SYNCED : istiod가 보낸 마지막 설정을 엔보이가 확인
- NOT SENT : istiod가 아무것도 엔보이로 보내지 않았다. 보통은 istiod가 보낼 것이 없기 때문.
- STALE : istiod가 엔보이에 업데이트를 보냈지만 확인받지 못했다. istio가 과부하됐거나, 엔보이와 istiod 사이에 커넥션 부족 또는 끊김. 혹은 이스티오의 버그.
10.2.2 키알리로 잘못된 설정 발견하기
kiali 설치
kubectl apply -f samples/addons/prometheus.yaml
kubectl apply -f samples/addons/kiali.yaml
serviceaccount/prometheus created
configmap/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
service/prometheus created
deployment.apps/prometheus created
serviceaccount/kiali created
configmap/kiali created
clusterrole.rbac.authorization.k8s.io/kiali created
clusterrolebinding.rbac.authorization.k8s.io/kiali created
service/kiali created
deployment.apps/kiali created
istioctl dashboard kiali

이런 에러를 볼 수 있다.

이렇게 확인할 수 있다.

내장 편집기에서 문제가 강조된다.
경고 아이콘위로 마우스를 올리면 KIA1107 Subset not found를 볼 수 있다.
해당 경고에 대해서는 키알리 검증 페이지를 확인해보면 된다.

해결 방법은 DestinationRule 리소스를 만드는 것이다.
10.2.3 istioctl로 잘못된 설정 발견하기
- istioctl로 이스티오 설정 분석하기
istioctl analyze -n istioinaction 2025-10-26T05:23:38.971889Z error kube translation function for core/v1alpha1/MeshConfig not found controller=analysis-controller 2025-10-26T05:23:38.972204Z error kube translation function for core/v1alpha1/MeshNetworks not found controller=analysis-controller Error [IST0101] (VirtualService istioinaction/catalog-v1-v2) Referenced host+subset in destinationrule not found: "catalog.istioinaction.svc.cluster.local+version-v1" Error [IST0101] (VirtualService istioinaction/catalog-v1-v2) Referenced host+subset in destinationrule not found: "catalog.istioinaction.svc.cluster.local+version-v2" Error: Analyzers found issues when analyzing namespace: istioinaction. See https://istio.io/v1.27/docs/reference/config/analysis for more information about causes and resolutions.
똑같이 부분집합을 찾지 못했음을 보여준다.
IST0101이라는 오류코드도 제공하는데 문서에서 확인할 수 있다.
Istio / Configuration Analysis Messages

- 워크로드별로 설정 오류 찾기
describe
- 워크로드가 서비스 메시지의 일부인지 알려준다.
- 어떤 VirtualService와 DestinationRule이 적용되는지 알려준다.
- 상호 인증 트래픽을 요구하는지 알려준다.
istioctl x describe pod catalog-5899bbc954-xnq22
Pod: catalog-5899bbc954-xnq22
Pod Revision: default
Pod Ports: 3000 (catalog)
--------------------
Service: catalog-canary
Port: http 80/HTTP targets pod port 3000
DestinationRule: catalog-canary for "catalog-canary"
No Traffic Policy
--------------------
Effective PeerAuthentication:
Workload mTLS mode: PERMISSIVE
10.3 엔보이 설정에서 수동으로 잘못된 설정 발견하기
- 워크로드에 적용된 엔보이 설정은 엔보이 관리 인터페이스나 istioctl로 가져올 수 있다.
- 10.3.1 엔보이 관리 인터페이스
- 엔보이 관리 인터페이스는 프록시의 특정 부분 수정 기능과 엔보이 설정을 노출함
- 모든 서비스 프록시에서 15000 포트로 접근 가능
istioctl dashboard envoy deploy/catalog -n is
tioinaction
http://localhost:15000

이렇게 브라우저 창이 열리면서 관리 대시보드가 노출한 옵션이 나열된다.
config_dump를 사용해서 프록시에서 현재 적재한 엔보이 설정을 출력할 수 있지만 데이터양이 많으니 주의해야 한다.
curl -s localhost:15000/config_dump | wc -l
14633
10.3.2 istioctl로 프록시 설정 쿼리하기
- istioctl proxy-config 명령어를 사용하면 엔보이 xDS API를 기반으로 워크로드의 프록시 설정을 가져오고 필터링할 수 있다.
- cluster : 클러스터 설정을 가져온다.
- endpoint : 엔드포인트 설정을 가져온다.
- listener : 리스너 설정을 가져온다.
- route : 루트 설정을 가져온다.
- secret : 시크릿 설정을 가져온다.
요청을 라우팅하기 위한 엔보이 API의 상호작용
- 엔보이 리스너는 네트워크 설정 (다운 스트림 트래픽을 프록시로 허용하는 IP 주소 및 포트 등)을 정의한다.
- 허용된 커넥션에 HTTP 필터 체인이 만들어진다. 체인에서 가장 중요한 필터는 라우터 필터로, 고급 라우팅 작업을 수행한다.
- 엔보이 루트는 가상 호스트를 클러스터에 일치시키는 규칙 집합
- 루트는 순서대로 처리된다.
- 일치하는 첫 번째 항목이 트래픽을 워크로드 클러스터로 라우팅하는 데 사용된다.
- 루트는 정적으로 설정할 수도 있지만, 이스티오에서는 RDS를 사용해 동적으로 설정한다.
- 엔보이 클러스터에서, 각 클러스터에는 유사한 워크로드에 대한 엔드포인트 그룹이 있다.
- 부분집합은 클러스터 내에서 워크로드를 더 분할하는 데 사용되며 정밀한 트래픽 관리가 가능
- 엔보이 엔드포인트는 요청을 처리하는 워크로드의 IP 주소

엔보이 리스너 설정 쿼리하기
- 인그레스 게이트웨이 localhost 80 포트로 도착하는 트래픽이 클러스터로 허용되는지 확인 필요
- 트래픽을 허용하는것은 엔보이 리스너의 역할
- 이스티오에서는 Gateway 리소스로 설정
istioctl proxy-config listeners deploy/istio-ingressgateway -n istio-system
ADDRESSES PORT MATCH DESTINATION
0.0.0.0 8080 ALL Route: http.8080 # 8080 포트에 대한 요청은 루트 http.8080에 따라 라우팅 하도록 설정
0.0.0.0 15021 ALL Inline Route: /healthz/ready*
0.0.0.0 15090 ALL Inline Route: /stats/prometheus*
- 리스너는 8080 포트에 설정되어 있다.
- 그 리스너에서 트래픽은 http.8080 이라는 루트에 따라 라우팅된다.
- 왜 80포트가 아니라 8080포트에서 리스닝하는가.
- 80에서 8080으로 흐르는 트래픽은 쿠버네티스 서비스 istio-ingressgateway 가 전달한다.
- 인그레스 게이트웨이는 8080 포트에서 리스닝하는데, 8080포트가 제한된 포트가 아니기 때문.
k -n istio-system get svc istio-ingressgateway -oyaml | grep "ports:" -A 10
ports:
- name: status-port
nodePort: 31652
port: 15021
protocol: TCP
targetPort: 15021
- name: http2
nodePort: 31733
port: 80 # 80포트의 트래픽은 파드의 8080 포트를 대상으로 함.
protocol: TCP
targetPort: 8080
- 트래픽이 8080 포트에 도달하며, 그 트래픽을 인그레스 게이트웨이로 허용하는 리스너가 존재함.
- 리스너의 라우팅은 루트 http.8080 이 수행.
엔보이 루트 설정 쿼리하기
- 엔보이 루트 설정 : 트래픽을 라우팅할 클러스터를 결정하는 규칙 집합을 정의
- 이스티오는 엔보이 루트를 VirtualService로 설정.
- 클러스터는 디스커버리로 자동 설정되거나, DestinationRule 리소스로 정의
istioctl pc routes deploy/istio-ingressgateway -n istio-system --name http.8080
NAME VHOST NAME DOMAINS MATCH VIRTUAL SERVICE
http.8080 catalog.istioinaction.io:80 catalog.istioinaction.io /* catalog-v1-v2.istioinaction
- 호스트 catalog.istioinaction.io의 트래픽 중 URL이 경로 접두사 /* 와 일치 하는 것들이 istioinaction 네임스페이스의 catalog 서비스에 있는 catalog VirtualService로 라우팅됨을 보여줌
- catalog.istioinaction VirtualService의 뒷단 클러스터에 대한 세부 정보는 루트 설정을 JSON 포맷으로 출력할 때 표시
istioctl pc routes deploy/istio-ingressgateway -n istio-system --name http.8080 -o json
[
{
"name": "http.8080",
"virtualHosts": [
{
"name": "catalog.istioinaction.io:80",
"domains": [
"catalog.istioinaction.io"
],
"routes": [
{
"match": {
"prefix": "/" # 일치해야 하는 라우팅 규칙
},
"route": {
"weightedClusters": {
"clusters": [ # 규칙이 일치할 때 트래픽 라우팅 클러스터
{
"name": "outbound|80|version-v1|catalog.istioinaction.svc.cluster.local",
"weight": 20
},
{
"name": "outbound|80|version-v2|catalog.istioinaction.svc.cluster.local",
"weight": 80
}
]
},
"timeout": "0s",
"retryPolicy": {
"retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
"numRetries": 2,
"retryHostPredicate": [
{
"name": "envoy.retry_host_predicates.previous_hosts",
"typedConfig": {
"@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
}
}
],
"hostSelectionRetryMaxAttempts": "5"
},
"maxGrpcTimeout": "0s"
},
"metadata": {
"filterMetadata": {
"istio": {
"config": "/apis/networking.istio.io/v1/namespaces/istioinaction/virtual-service/catalog-v1-v2"
}
}
},
"decorator": {
"operation": "catalog-v1-v2:80/*"
}
}
],
"includeRequestAttemptCount": true
}
],
"validateClusters": false,
"maxDirectResponseBodySizeBytes": 1048576,
"ignorePortInHostMatching": true
}
]
엔보이 클러스터 설정 쿼리하기
- 엔보이 클러스터 설정은 요청을 라우팅할 수 있는 백엔드 서비스를 정의
- 클러스터는 부하를 여러 인스턴스나 엔드포인트에 분산
- 이 엔드포인트 (대개 IP 주소) 는 최종 사용자 트래픽을 처리하는 개별 워크로드 인스턴스를 나타냄.
- istioctl proxy-config clusters의 플래그 direction, fqdn, port, subset을 사용하면 특정 클러스터만 출력 가능
outbound | 80 | version-v1 | catalog.istioinaction.svc.cluster.local
방향 포트 부분집합 FQDN
istioctl proxy-config clusters deploy/istio-ingressgateway.istio-system --fqdn catalog.istioinaction.svc.cluster.local --port 80 --subset version-v1
SERVICE FQDN PORT SUBSET DIRECTION TYPE DESTINATION RULE
- 부분집합에 대한 클러스터가 없어서 요청이 실패.
- VirtualService가 조재하지 않는 클러스터로 라우팅하기 때문.
istioctl analyze ch10/catalog-destinationrule-v1-v2.yaml -n istioinaction
✔ No validation issues found when analyzing ch10/catalog-destinationrule-v1-v2.yaml.
k apply -f ch10/catalog-destinationrule-v1-v2.yaml
destinationrule.networking.istio.io/catalog created
결과 : 새로 정의한 부분집합이 보임.
istioctl pc clusters deploy/istio-ingressgateway -n istio-system --fqdn catalog.istioinaction.svc.cluster.local --port 80
SERVICE FQDN PORT SUBSET DIRECTION TYPE DESTINATION RULE
catalog.istioinaction.svc.cluster.local 80 - outbound EDS catalog.istioinaction
catalog.istioinaction.svc.cluster.local 80 version-v1 outbound EDS catalog.istioinaction
catalog.istioinaction.svc.cluster.local 80 version-v2 outbound EDS catalog.istioinaction
클러스터는 어떻게 설정되는가?
- 아래를 보면 edsClusterConfig가 엔드포인트를 쿼리하는데 ADS Aggregated Discovery Service를 사용하도록 설정
- 서비스 이름 outbound|80|version-v1|catalog.istioinaction.svc.cluster.local 은 ADS 에서 쿼리할때 엔드포인트용 필터로 사용.
istioctl pc clusters deploy/istio-ingressgateway -n istio-system --fqdn catalog.istioinaction.svc.cluster.local --port 80 --subset version-v1 -o json .... "name": "outbound|80|version-v1|catalog.istioinaction.svc.cluster.local", "altStatName": "outbound|80|version-v1|catalog.istioinaction.svc.cluster.local;", "type": "EDS", "edsClusterConfig": { "edsConfig": { "ads": {}, "initialFetchTimeout": "0s", "resourceApiVersion": "V3" }, "serviceName": "outbound|80|version-v1|catalog.istioinaction.svc.cluster.local" }, "connectTimeout": "10s", "lbPolicy": "LEAST_REQUEST", "circuitBreakers": { "thresholds": [ { "maxConnections": 4294967295, "maxPendingRequests": 4294967295, "maxRequests": 4294967295, "maxRetries": 4294967295, "trackRemaining": true } ] }, "commonLbConfig": {}, "metadata": { "filterMetadata": { "istio": { "config": "/apis/networking.istio.io/v1/namespaces/istioinaction/destination-rule/catalog", "services": [ { "host": "catalog.istioinaction.svc.cluster.local", "name": "catalog", "namespace": "istioinaction" } ], "subset": "version-v1" } } }, "filters": [ { "name": "istio.metadata_exchange", "typedConfig": { "@type": "type.googleapis.com/udpa.type.v1.TypedStruct", "typeUrl": "type.googleapis.com/envoy.tcp.metadataexchange.config.MetadataExchange", "value": { "enable_discovery": true, "protocol": "istio-peer-exchange" } } } ] } ]
엔보이 클러스터 엔드포인트 쿼리하기
- 출력을 보면 이 클러스터 뒤에 있는 유일한 워크로드 엔드포인트를 나열.
istioctl pc endpoints deploy/istio-ingressgateway -n istio-system --cluster "outbound|80|version-v1|catalog.istioinaction.svc.cluster.local"
ENDPOINT STATUS OUTLIER CHECK CLUSTER
10.244.0.17:3000 HEALTHY OK outbound|80|version-v1|catalog.istioinaction.svc.cluster.local
- 이 IP 주소로 파드를 쿼리해 실제 워크로드가 있는지 확인 가능
k get pod -n istioinaction --field-selec tor status.podIP=10.244.0.17 NAME READY STATUS RESTARTS AGE catalog-primary-658c756d7f-kv52g 2/2 Running 0 99m
10.3.3 애플리케이션 문제 트러블 슈팅하기
간헐적으로 제한 시간을 초과하는 느린 워크로드 준비
CATALOG_POD=$(k get pods -l version=v2 -n istioinaction -o jsonpath={.items..metadata.name} | cut -d ' ' -f1)
echo $CATALOG_POD
catalog-v2-7cc6f578cd-5jzdl
요청 처리 제한 시간이 0.5초가 되도록 VirtualService를 설정
k patch vs catalog-v1-v2 -n istioinactio
n --type json -p '[{"op": "add", "path": "/spec/http/0/timeout", "value": "0.5s"}]'
virtualservice.networking.istio.io/catalog-v1-v2 patched

엔보이 액세스 로그 이해하기
- 엔보이 액세스로그는 엔보이 프록시가 처리한 모든 요청을 기록
- TEXT 형식이 기본
메시 범위에서 액세스 로그 활성화하기
서비스 프록시 액세스 로그는 설정할 수 있다.
기본적으로 이스티오의 설치 프로필만 액세스 로그를 표준 출력으로 출력한다.
다른 프로필을 사용하거나 설치 설정에서 벗어난 경우
이스티오 설치 중에 다음과 같이 meshConfig.accessLogFile="/dev/stdout" 속성을 설정해야 한다.
istioctl install --set meshConfig.accessLogFile="/dev/stdout"
이렇게 하면 메시 전체에서 액세스 로그가 활성화된다. 특정 워크로드 하나에만 액세스 로그를 활성화하려면 텔레메트리 API를 사용할 수 있다.
엔보이 액세스 로그 형식 바꾸기
- 액세스 로그를 JSON 형식으로 출력하도록 업데이트 가능
istioctl install --set profile=demo --set meshConfig.accessLogEncoding="JSON"- 물론 이렇게하면 메시 전체에 적용돼 모든 워크로드 프록시의 로그양이 엄청나게 증가
- 로그 인프라에 부담을 주므로 대규모 클러스터에서는 사용 X
가독성을 높여서 확인 가능
k -n istio-system logs deploy/istio-ingressgateway | grep 504 | tail -n 1 | jq
- response_flags 값이 UT
- 업스트림 요청 제한 시간 초과 upstream request timeout 을 의미
- upstream_host 값
- 요청을 처리하는 워크로드의 실제 IP 주소를 나타냄
엔보이 응답 플래그
엔보이는 응답 플래그를 사용해 커넥션 실패에 대한 정보를 안내
UT : 제한 시간 설정에 비춰봤을 때 업스트림이 너무 느렸다. UT가 있다는 의미는 제한 시간 초과 결정을 내린 주체가 애플리케이션이 아니라 프록시임을 의미한다.
UH : 정상적인 업스트림이 없음 (클러스터에)
NR : 설정된 루트 없음
UC : 업스트림 커넥션 종료
DC : 다운스트림 커넥션 종료
- upstream_host 는 간헐적으로 느린 앱을 구분하는데 도움이됨.
- ip주소를 찾아서 디버깅하면 된다.
인그레스 게이트웨이의 로깅 수준 높이기
istioctl proxy-config log deploy/istio-ingressgateway -n istio-system
istio-ingressgateway-74df47f5f9-nv65v.istio-system:
active loggers:
admin: warning
alternate_protocols_cache: warning
aws: warning
assert: warning
backtrace: warning
basic_auth: warning
cache_filter: warning
client: warning
config: warning
connection: warning # 커넥션 범위에서는 네트워크 계측과 관련된 정보를 기록
conn_handler: warning
compression: warning
credential_injector: warning
...
happy_eyeballs: warning
hc: warning
health_checker: warning
http: warning # HTTP 범위에서는 HTTP 헤더, 경로 등 앱 계층 관련 정보
http2: warning
hystrix: warning
...
router: warning # 라우팅범위에서는 요청이 어느 클러스터로 라우팅되는지 세부사항
runtime: warning
stats: warning
...
- 다른 로깅 수준에는
- none, error, warning, info, debug
10.3.4 ksniff로 네트워크 트래픽 검사
- ksniff : tcpdump를 사용해 파드의 네트워크 트래픽을 포착하고 이를 와이어 샤크로 리다이렉트
kubectl krew install sniff
k sniff -n istioinaction $SLOW_POD -i lo 'Kubernetes' 카테고리의 다른 글
| Istio in Action 9장 - 마이크로서비스 통신 보호하기 (0) | 2025.10.12 |
|---|---|
| Istio in Action 7장 - 관찰 가능성: 서비스의 동작 이해하기 (0) | 2025.09.17 |
| Istio in Action 6장 - 복원력: 애플리케이션 네트워킹 문제 해결하기 (0) | 2025.09.07 |
| Istio in Action 5장 - 트래픽 제어 : 세밀한 트래픽 라우팅 (1) | 2025.08.28 |
| Istio in Action 4장 - Istio Gateway : 클러스터로 트래픽 들이기 (0) | 2025.08.20 |