티스토리 뷰

10장. 데이터 플레인 트러블 슈팅하기

10장에서 다루는 내용
  • 잘못 설정한 워크로드 트러블슈팅하기 Troubleshooting a misconfigured workload
  • istioctl과 키알리로 잘못된 설정 감지 및 방지하기 Detecting and preventing misconfigurations using istioctl and Kiali
  • istioctl을 사용해 서비스 프록시 설정 조사하기 Using istioctl to investigate the service proxy configuration
  • 엔보이 로그 이해하기 Making sense of Envoy logs
  • 텔레메트리를 사용해 앱에 대한 통찰력 얻기 Using telemetry to gain insights into apps

데이터 플레인 문제 해결

  • 잘 알다시피 네트워크를 통해 통신할 때는 많은 것이 잘못될 수 있다.
  • 이스티오가 존재하는 주요 이유는 무언가 잘못됐을 때 네트워크 통신을 조명하고 타임아웃, 재시도, 서킷 브레이커 같은 복원 기능을 배치함으로써 애플리케이션이 네트워크 문제에 자동으로 대응할 수 있도록 하기 위함이다.
  • 서비스 프록시는 네트워크에서 일어나는 일을 매우 자세히 보여주지만, 프록시 자신이 예기치 못하게 작동하면 어떻게 될까?
  • 그림 10.1은 요청 처리에 참여하는 구성 요소들을 보여준다.
    • istiod, 데이터 플레인원하는 상태 desired state 로 동기화되도록 보장한다.
    • 인그레스 게이트웨이. 트래픽을 클러스터로 허용한다.
    • 서비스 프록시, 접근 제어 기능을 제공하고, 다운스트림에서 로컬 애플리케이션으로 흐르는 트래픽을 처리한다.
    • 애플리케이션 그 자체, 요청을 처리하고, 또 다른 업스트림 서비스로 체인을 이어나가는 다른 서비스에 요청하는 것 등을 한다.

요청을 라우팅하는 데 참여하는 구성 요소들

 

  • 따라서 예기치 못한 문제는 이 체인의 어떤 구성 요소와도 관련 있을 수 있다.
  • 모든 구성 요소를 디버깅하는 것은 시간이 많이 필요한데, 앱이 클러스터나 시스템 전체에 영향을 줄 때는 그럴 시간이 없다.
  • 이번 장에서는 오류 시나리오를 해결하기 위해 프록시와 관련 설정을 살펴보는 도구를 활용해본다.

 

10.1 가장 흔한 실수: 잘못 설정한 데이터 플레인

☞ https://netpple.github.io/docs/istio-in-action/Istio-ch10-troubleshooting

 

The most common mistake: A misconfigured data plane : 환경 설정하기 (실습~)

  • 이스티오는 서비스 프록시 설정을 사람이 읽을 수 있는 형식인 VirtualService, DestinationRule 등과 같은 CRD로 누출한다.
  • 이 리소스들은 엔보이 설정으로 변환돼 데이터 플레인적용된다.
  • 새 리소스를 적용한 후 데이터 플레인의 동작이 예상과 다를 때 가장 일반적인 원인은 우리가 설정을 잘못한 것이다.
  • 데이터 플레인을 잘못 설정했을 때 트러블슈팅하는 방법을 보여주기 위해 다음 예제를 준비한다.
  • 이스티오 인그레스 게이트웨이로 트래픽을 허용하는 Gateway 리소스와 그림 10.2처럼 요청 중 20% 부분집합 version-v1으로, 나머지 80%를 version-v2로 라우팅하는 VirtualService리소스를 사용할 것이다.

 

 

  • ‘여기까지는 괜찮다’고 생각할 수 있지만, 그렇지 않다.
  • DestinationRule 리소스가 없으면 인그레스 게이트웨이는 부분집합 version-v1과 version-v2에 대한 클러스터 정의가 없으므로, 모든 요청은 실패할 것이다.
  • 이는 트러블슈팅을 해보기에 좋은 문제다!
  • 먼저 이스티오는 배포했지만 (2장 참조) 다른 애플리케이션 구성 요소는 배포해두지 않았다고 해보자.
  • 앞 장들부터 계속해오고 있다면, 다음과 같이 남아 있는 Deployment, Service, Gateway, VirtualService 를 정리 후 샘플 애플리케이션 배포하자.
더보기
# 샘플 애플리케이션 배포
kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction # catalog v1 배포
kubectl apply -f ch10/catalog-deployment-v2.yaml -n istioinaction # catalog v2 배포
kubectl apply -f ch10/catalog-gateway.yaml -n istioinaction # catalog-gateway 배포
kubectl apply -f ch10/catalog-virtualservice-subsets-v1-v2.yaml -n istioinaction

# Gateway 
cat ch10/catalog-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: catalog-gateway
  namespace: istioinaction
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - "catalog.istioinaction.io"
    port:
      number: 80
      name: http
      protocol: HTTP

# VirtualService
cat ch10/catalog-virtualservice-subsets-v1-v2.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog-v1-v2
  namespace: istioinaction
spec:
  hosts:
  - "catalog.istioinaction.io"
  gateways:
  - "catalog-gateway"
  http:
  - route:
    - destination:
        host: catalog.istioinaction.svc.cluster.local
        subset: version-v1
        port:
          number: 80
      weight: 20
    - destination:
        host: catalog.istioinaction.svc.cluster.local
        subset: version-v2
        port:
          number: 80
      weight: 80

# 확인
kubectl get deploy,svc -n istioinaction
kubectl get gw,vs -n istioinaction

 

  • 통신 확인 : 부분집합 설정 누락으로 503 ‘Service Unavailable’ 출력 - Envoy
더보기
# 로그 확인 : NC - NoClusterFound : Upstream cluster not found.
kubectl logs -n istio-system -l app=istio-ingressgateway -f
[2025-05-09T01:54:51.145Z] "GET /items HTTP/1.1" 503 NC cluster_not_found - "-" 0 0 0 - "172.18.0.1" "curl/8.7.1" "90a7d941-cbc4-91ae-9da1-bc95695d5c50" "catalog.istioinaction.io:30000" "-" - - 10.10.0.7:8080 172.18.0.1:64130 - -

# 반복 호출 시도
for i in {1..100}; do curl http://catalog.istioinaction.io:30000/items -w "\nStatus Code %{http_code}\n"; sleep .5;  done
Status Code 503

 

 

※ Envoy response flag

더보기

%RESPONSE_FLAGS%

HTTP and TCP

 UH: No healthy upstream hosts in upstream cluster in addition to 503 response code.

 UF: Upstream connection failure in addition to 503 response code.

 UO: Upstream overflow (circuit breaking) in addition to 503 response code.

 NR: No route configured for a given request in addition to 404 response code, or no matching filter chain for a downstream connection.

 URX: The request was rejected because the upstream retry limit (HTTP) or maximum connect attempts (TCP) was reached.

 NC: Upstream cluster not found.

 DT: When a request or connection exceeded max_connection_duration or max_downstream_connection_duration.

 

HTTP only

 DC: Downstream connection termination.

 LH: Local service failed health check request in addition to 503 response code.

 UT: Upstream request timeout in addition to 504 response code.

 LR: Connection local reset in addition to 503 response code.

 UR: Upstream remote reset in addition to 503 response code.

 UC: Upstream connection termination in addition to 503 response code.

 DI: The request processing was delayed for a period specified via fault injection.

 FI: The request was aborted with a response code specified via fault injection.

 RL: The request was ratelimited locally by the HTTP rate limit filter in addition to 429 response code.

 UAEX: The request was denied by the external authorization service.

 RLSE: The request was rejected because there was an error in rate limit service.

 IH: The request was rejected because it set an invalid value for a strictly-checked header in addition to 400 response code.

 SI: Stream idle timeout in addition to 408 response code.

 DPE: The downstream request had an HTTP protocol error.

 UPE: The upstream response had an HTTP protocol error.

 UMSDR: The upstream request reached max stream duration.

 OM: Overload Manager terminated the request.

 DF: The request was terminated due to DNS resolution failure.

 

10.2 데이터 플레인 문제 식별하기

일상적인 운영에서는 보통 데이터 플레인 문제를 처리할 것이다. 바로 데이터 플레인 디버깅에 뛰어드는 습관이 생길 수도 있지만, 컨트롤 플레인 문제를 추정 원인에서 빠르게 배제하는 것이 중요하다. 컨트롤 플레인의 주요 기능이 데이터 플레인을 최신 설정으로 동기화하는 것임을 감안하면, 첫 단계는 컨트롤 플레인과 데이터 플레인이 동기화된 상태인지 확인하는 것이다.

 

 

10.2.1 데이터 플레인이 최신 상태인지 확인하는 방법

  • 데이터 플레인 설정은 설계상 궁극적으로 일관성을 가진다. The data-plane configuration is eventually consistent by design.
  • 즉, 환경(서비스, 엔드포인트, 상태)이나 설정의 변화는 컨트롤 플레인과 적절히 동기화하기 전까지는 데이터 플레인에 즉시 반영되지 않는다.
  • 예를 들어 앞 장들에서 봤듯이 컨트롤 플레인은 특정 서비스의 개별 엔드포인트 IP 주소를 데이터 플레인으로 보낸다. (서비스 내의 각 파드 IP 주소와 대강 동일)
  • 이런 엔드포인트 중 어느 하나가 비정상이 되면, 쿠버네티스가 이를 인지하고 파드를 비정상으로 표시하는 데 시간이 걸린다.
  • 어느 시점에 컨트롤 플레인도 문제를 인지하고 엔드포인트를 데이터 플레인에서 제거한다.
  • 따라서 컨트롤 플레인은 최신 설정으로 돌아오며, 프록시 설정도 다시 일관된 상태가 된다.
  • 그림 10.3은 데이터 플레인을 업데이트하기 위해 발생하는 이벤트를 시각화한다.

워크로드가 비정상이 된 후 데이터 플레인 구성 요소의 설정이 업데이트될 때까지 일련의 이벤트

 

  1. kubelet은 주기적으로 노드 내에서 실행 중인 파드의 상태를 확인한다.
  2. 쿠버네티스 API서버는 상태 확인을 실패한 파드를 통보받는다.
  3. API 서버가 모든 이해 당사자들에게 알린다.
  4. istiod가 데이터 플레인을 업데이트해 설정에서 엔드포인트를 제거한다.
  5. 건강하지 않은 인스턴스로 더 이상 트래픽을 전송되지 않는다.
워크로드와 이벤트 개수가 늘어나는 대규모 클러스터에서는 데이터 플레인을 동기화하는 데 필요한 시간도 비례해 늘어난다. 대규모 클러스터에서 성능을 개선하는 방법은 11장에서 살펴볼 것이다.

 

 

  • istioctl proxy-status 로 데이터 플레인이 최신 설정과 동기화했는지 확인하자.
더보기
docker exec -it myk8s-control-plane istioctl proxy-status
NAME                                                   CLUSTER        CDS        LDS        EDS        RDS          ECDS         ISTIOD                    VERSION
catalog-6cf4b97d-l44zk.istioinaction                   Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-8d74787f-ltkhs     1.17.8
catalog-v2-56c97f6db-d74kv.istioinaction               Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-8d74787f-ltkhs     1.17.8
catalog-v2-56c97f6db-m6pvj.istioinaction               Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-8d74787f-ltkhs     1.17.8
istio-egressgateway-85df6b84b7-2f4th.istio-system      Kubernetes     SYNCED     SYNCED     SYNCED     NOT SENT     NOT SENT     istiod-8d74787f-ltkhs     1.17.8
istio-ingressgateway-6bb8fb6549-hcdnc.istio-system     Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED       NOT SENT     istiod-8d74787f-ltkhs     1.17.8
  • SYNCED : istiod가 보낸 마지막 설정을 엔보이가 확인했다.
  • NOT SENT : istiod가 아무것도 엔보이로 보내지 않았다. 보통은 istiod가 보낼 것이 없기 때문이다.
  • STALE : istiod가 엔보이에 업데이트를 보냈지만 확인받지 못했다. 이는 다음 중 하나를 나타낸다.
    • istiod가 과부하됐거나, 엔보이와 istiod 사이의 커넥션 부족 또는 끊김이거나, 이스티오의 버그다.

 

  • 그런데 우리의 출력에는 설정을 받지 못한 stale 상태의 워크로드가 없다.
  • 따라서 컨트롤 플레인에 문제가 있을 가능성은 낮으므로 데이터 플레인 구성 요소를 조사해야 한다.
  • 데이터 플레인 구성 요소에서 가장 일반적인 문제잘못된 워크로드 설정이다.
  • 키알리를 사용하면 설정을 빠르게 검증할 수 있다.

 

10.2.2 키알리로 잘못된 설정 발견하기

  • 대시보드에 Overview 에 istioinaction 네임스페이스에 경고 표시 확인 → 클릭 시 Istio Config 로 이동 ⇒ 클릭 시 내장 편집기에서 경고 메시지 확인 - Docs

 

 

 

 

 

  • 경고 아이콘 위로 마우스를 올리면 경고 메시지 ‘KIA1107 Subnet not found’를 보여준다. 자세한 건 키알리 공식 문서 참고 - Docs
    • 예를 들어 다음은 KIA1107 경고의 해결책 부분이다.
      • 존재하지 않은 부분집합을 가리키는 루트를 수정하자. 아마 부분집합 이름의 오타를 수정하거나 DestinationRule 에서 빠트린 부분집합을 정의하자.

https://kiali.io/docs/features/validations/

  • 키알리 검증은 도움이 되므로, 워크로드가 예상대로 동작하지 않을 때 취하는 첫 초지 중 하나여야 한다.
  • 다음 조치는 또 다른 검증 모음을 제공하는 istioctl을 사용하는 것이다.

 

 

 

10.2.3 istioctl로 잘못된 설정 발견하기

  • 잘못 설정된 워크로드를 자동으로 트러블슈팅하는 데 가장 유용한 istioctl 명령어 두 가지는 istioctl analyze 와 istioctl describe 이다.

※ istioctl 로 이스티오 설정 분석하기 ANALYZING ISTIO CONFIGURATIONS WITH ISTIOCTL

  • istioctl analyze 명령어는 이스티오 설정을 분석하는 강력한 진단 도구다.
  • 이미 문제가 발생한 클러스터에 실행하거나, 리소스를 잘못 구성하는 것을 방지하고자 클러스터에 적용하기 전에 설정이 유효한지 검사할 수 있다.
  • analyze 명령어는 여러 분석기를 실행하는데, 각 분석기는 특정 문제를 감지하는 데 특화돼 있다.
  • analyze 명령어는 쉽게 확장할 수 있어 이스티오와 함께 발전할 수 있다.
  • 감지된 문제를 살펴보자 - IstioDocs , 0101
더보기

 

#
docker exec -it myk8s-control-plane istioctl analyze -h
docker exec -it myk8s-control-plane istioctl analyze --list-analyzers
...
docker exec -it myk8s-control-plane istioctl analyze -n istioinaction
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.17/docs/reference/config/analysis for more information about causes and resolutions.

# 이전 명령어 종료 코드 확인
echo $? # (참고) 0 성공
79

 

  • 출력은 부분집합을 찾지 못했음을 보여준다. 오류 메시지 외에 istio 오류 코드 IST0101 도 제공 - IstioDocs , 0101
 

ReferencedResourceNotFound

Connect, secure, control, and observe services.

istio.io

 

 

워크로드별로 설정 오류 찾기 DETECTING WORKLOAD-SPECIFIC MISCONFIGURATIONS

  • describe는 워크로드별 설정을 기술하는데 사용한다.
  • describe는 워크로드 하나에 직간접적으로 영향을 미치는 이스티오 설정을 분석해 요약 내용을 출력한다.
  • 이 요약은 다음과 같은 워크로드 관련 질문에 답변을 제공한다.
    • 이 워크로드는 서비스 메시의 일부인가?
    • 어떤 VirtualService 와 DestinationRule 이 적용되는가?
    • 상호 인증 트래픽을 요구하는가?

 

더보기
#
kubectl get pod -n istioinaction -l app=catalog -o jsonpath='{.items[0].metadata.name}'
CATALOG_POD1=$(kubectl get pod -n istioinaction -l app=catalog -o jsonpath='{.items[0].metadata.name}')

# 단축키 : experimental(x), describe(des)
docker exec -it myk8s-control-plane istioctl experimental describe -h
docker exec -it myk8s-control-plane istioctl x des pod -n istioinaction $CATALOG_POD1
Pod: catalog-6cf4b97d-l44zk
   Pod Revision: default
   Pod Ports: 3000 (catalog), 15090 (istio-proxy)
--------------------
Service: catalog
   Port: http 80/HTTP targets pod port 3000
--------------------
Effective PeerAuthentication:
   Workload mTLS mode: PERMISSIVE


Exposed on Ingress Gateway http://172.18.0.2
VirtualService: catalog-v1-v2
   WARNING: No destinations match pod subsets (checked 1 HTTP routes)
      Warning: Route to subset version-v1 but NO DESTINATION RULE defining subsets!
      Warning: Route to subset version-v2 but NO DESTINATION RULE defining subsets!


# 문제 해결 후 확인
cat ch10/catalog-destinationrule-v1-v2.yaml       
kubectl apply -f ch10/catalog-destinationrule-v1-v2.yaml
docker exec -it myk8s-control-plane istioctl x des pod -n istioinaction $CATALOG_POD1
Pod: catalog-6cf4b97d-l44zk
   Pod Revision: default
   Pod Ports: 3000 (catalog), 15090 (istio-proxy)
--------------------
Service: catalog
   Port: http 80/HTTP targets pod port 3000
DestinationRule: catalog for "catalog.istioinaction.svc.cluster.local"
   Matching subsets: version-v1 # 일치하는 부분집합
      (Non-matching subsets version-v2) # 일치하지 않은 부분집합
   No Traffic Policy
--------------------
Effective PeerAuthentication:
   Workload mTLS mode: PERMISSIVE

Exposed on Ingress Gateway http://172.18.0.2
VirtualService: catalog-v1-v2 # 이 파드로 트래픽을 라우팅하는 VirtualService
   Weight 20%

# 다음 점검 방법을 위해 오류 상황으로 원복
kubectl delete -f ch10/catalog-destinationrule-v1-v2.yaml
  • 하위 명령어 analyze 와 describe 모두 설정에서 흔한 오류를 식별하느 데 도움이 되며, 보통은 해결책을 제시하기에 충분한다.
  • 이 명령어로 드러나지 않은 문제나 해결 지침을 충분히 제공하지 않은 문제는 더 깊이 파고들 필요가 있다. 그것은 다음 절에서 할 일이다.

 

도전과제 -1

istioctl analyze와 istioctl describe를 CI/CD 파이프라인에서 istio 설정 검증 활용 해보기

 

  명령어 활용 예시

더보기
# 로컬 YAML 파일 검증
istioctl analyze --use-kube=false samples/bookinfo/networking/bookinfo-gateway.yaml

# 라이브 클러스터와 YAML 파일 조합 검증
istioctl analyze samples/bookinfo/networking/bookinfo-gateway.yaml samples/bookinfo/networking/destination-rule-all.yaml

# 특정 경고 억제
istioctl analyze --namespace default --suppress "IST0102=Namespace default"

# 모든 네임스페이스 분석
istioctl analyze --all-namespaces

# 디렉토리 내 모든 YAML 파일 분석
istioctl analyze --recursive my-istio-config/

 

  GitHub Actions 예시

더보기
name: Istio YAML 분석

on:
  push:
    paths:
      - 'istio-configs/**.yaml'
  pull_request:

jobs:
  istio-analyze:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v3

    - name: Install istioctl
      run: |
        curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.22.0 sh -
        export PATH="$PATH:./istio-1.22.0/bin"
        echo "PATH=$PATH:./istio-1.22.0/bin" >> $GITHUB_ENV

    - name: Run istioctl analyze
      run: |
        # --use-kube=false를 지정하면 클러스터 없이도 로컬 파일만으로 분석 가능
        istioctl analyze ./istio-configs --use-kube=false --output json > analyze-report.json || true
        cat analyze-report.json

    - name: Fail if issues found
      run: |
        if grep -q '"Level":"Error"' analyze-report.json; then
          echo "Istio analyze found errors"
          exit 1
        fi

 

name: Istio YAML Validation

on:
  pull_request:
    branches:
      - main

jobs:
  validate-istio:
    runs-on: ubuntu-latest
    steps:
      # 리포지토리 체크아웃
      - name: Checkout code
        uses: actions/checkout@v3

      # Istio 설치
      - name: Install istioctl
        run: |
          curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.25.2 sh -
          mv istio-1.25.2/bin/istioctl /usr/local/bin/
          istioctl version

      # YAML 파일 검증
      - name: Run istioctl analyze
        run: |
          istioctl analyze --use-kube=false ./istio-config/*.yaml
        continue-on-error: false

      # 클러스터 접근 설정 (필요한 경우)
      - name: Setup kubeconfig
        run: |
          echo "${{ secrets.KUBECONFIG }}" > kubeconfig
          export KUBECONFIG=kubeconfig

      # 라이브 클러스터 분석
      - name: Run istioctl analyze with cluster
        run: |
          istioctl analyze ./istio-config/bookinfo-gateway.yaml

      # 파드 구성 확인 (배포 후)
      - name: Run istioctl describe
        run: |
          POD_NAME=$(kubectl get pods -l app=ratings -o jsonpath='{.items[0].metadata.name}')
          istioctl describe pod $POD_NAME

 

  istioctl describe 사용 : 디버깅용으로 로그 출력에 사용

더보기
...
- name: Describe Istio service
  run: |
    istioctl x describe svc reviews.default.svc.cluster.local || true

 

  GitLab CI 예시

더보기
# .gitlab-ci.yml

stages:
  - lint
  - build
  - deploy

variables:
  ISTIO_VERSION: "1.20.0" # 사용하는 Istio 버전에 맞게 조정

istioctl_analyze:
  stage: lint
  image: 
    name: gcr.io/google.com/cloudsdk/cloud-sdk:latest # kubectl, istioctl이 포함된 이미지 사용 (또는 커스텀 이미지)
    entrypoint: [""] # Entrypoint를 재정의하여 쉘 스크립트 실행
  before_script:
    # istioctl 다운로드 및 설치 (만약 이미지에 포함되어 있지 않다면)
    - apt-get update && apt-get install -y curl
    - curl -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIO_VERSION sh -
    - export PATH=$PWD/istio-$ISTIO_VERSION/bin:$PATH
  script:
    - echo "Analyzing Istio YAML files..."
    # 모든 Istio 관련 YAML 파일이 있는 디렉토리를 지정
    # 여기서는 project/istio-config/ 아래에 모든 Istio 설정 파일이 있다고 가정
    - istioctl analyze project/istio-config/
    # 또는 특정 파일만 지정
    # - istioctl analyze project/istio-config/gateway.yaml project/istio-config/virtualservice.yaml
    - if [ $? -ne 0 ]; then
        echo "Istio configuration analysis failed. Please check the reported errors."
        exit 1
      fi
    - echo "Istio configuration analysis passed."
  only:
    - merge_requests # PR/MR 시에만 실행
    - main           # main 브랜치 커밋 시에도 실행

 

☞ Jenkins 파이프라인

더보기

 

pipeline {
    agent any

    environment {
        ISTIO_VERSION = '1.22.0'
        ISTIOCTL_PATH = "${env.WORKSPACE}/istio-${ISTIO_VERSION}/bin"
    }

    stages {
        stage('Checkout') {
            steps {
                git 'https://your-repo-url.com/your-istio-config-repo.git'
            }
        }

        stage('Install istioctl') {
            steps {
                sh '''
                    curl -L https://istio.io/downloadIstio | ISTIO_VERSION=${ISTIO_VERSION} sh -
                    export PATH=$PATH:${ISTIOCTL_PATH}
                '''
            }
        }

        stage('Run istioctl analyze') {
            steps {
                sh '''
                    export PATH=$PATH:${ISTIOCTL_PATH}
                    istioctl analyze ./istio-configs --use-kube=false --output json > analyze-report.json || true
                    cat analyze-report.json
                    if grep -q '"Level":"Error"' analyze-report.json; then
                        echo "Istio analyze found errors"
                        exit 1
                    fi
                '''
            }
        }
    }
}

 

 


10.3 엔보이 설정에서 수동으로 잘못된 설정 발견하기

10.3.1 엔보이 관리(admin) 인터페이스

  • 엔보이 관리 인터페이스는 프록시의 특정 부분(로그 수준 증가 등)을 수정하는 기능과 엔보이 설정을 노출한다.
  • 이 인터페이스는 모든 서비스 프록시에서 포트 15000으로 접근 할 수 있다.
더보기
#
kubectl port-forward deploy/catalog -n istioinaction 15000:15000
open http://localhost:15000

# 현재 적재한 엔보이 설정 출력 : 데이터양이 많다!
curl -s localhost:15000/config_dump | wc -l
  13952

  • 출력은 너무 커서 기본적으로 사람이 읽을 수 없다.
  • 이런 이유로 istioctl은 출력을 작은 뭉치로 필터링하는 도구를 제공해 가독성을 높이고 이해를 돕는다.
  • 엔보이 관리 인터페이스 https://www.envoyproxy.io/docs/envoy/latest/operations/admin

 

10.3.2 istioctl 로 프록시 설정 쿼리하기

마이크로서비스 기반 애플리케이션에서 서비스 프록시가 생성하는 로그와 메트릭은 성능 병목을 일으키는 서비스 디스커버리, 빈번하게 실패하는 엔드포인트 식별, 성능 저하 감지 등과 같은 많은 문제를 트러블슈팅하는 데 도움이 된다. 6장에서는 이런 애플리케이션 복원력 문제를 해결하는 방법을 살펴봤다. 이번 절에서는 엔보이 액세스 로그와 메트릭을 사용해 이 문제들 중 일부를 트러블슈팅해본다. 그러나 먼저, 트러블슈팅할 문제가 생기도록 서비스를 업데이트하자.

 

 

간헐적으로 제한 시간을 초과하는 느린 워크로드 준비하기

 

설정 전 정상 통신 환경 상태 확인

# 신규 터미널
for in in {1..9999}; do curl http://catalog.istioinaction.io:30000/items -w "\nStatus Code %{http_code}\n"; sleep 1; done

 

 

 

- kiali : catalog - 100% 성공

 

- kiali : catalog 에 v1 링크 클릭 후 오른쪽 탭 메뉴 하단에 HTTP Request Response Time(ms)에 p99 확인 → 4.96ms

 

- kiali : catalog 에 v2 링크 클릭 후 오른쪽 탭 메뉴 하단에 HTTP Request Response Time(ms)에 p99 확인 → 4.8ms

 

- Grafana - Istio Mesh 대시보드

 

 

catalog 워크로드가 간헐적으로 응답을 느리게 반환하도록 설정

더보기
# catalog v2 파드 중 첫 번째 파드 이름 변수 지정
CATALOG_POD=$(kubectl get pods -l version=v2 -n istioinaction -o jsonpath={.items..metadata.name} | cut -d ' ' -f1)
echo $CATALOG_POD
catalog-v2-56c97f6db-d74kv

# 해당 파드에 latency (지연) 발생하도록 설정
kubectl -n istioinaction exec -c catalog $CATALOG_POD \
-- curl -s -X POST -H "Content-Type: application/json" \
-d '{"active": true, "type": "latency", "volatile": true}' \
localhost:3000/blowup ;
blowups=[object Object]


# 신규 터미널
for in in {1..9999}; do curl http://catalog.istioinaction.io:30000/items -w "\nStatus Code %{http_code}\n"; sleep 1; done

- Grafana - Istio Mesh 대시보드 : v2 에 P90, P99 레이턴스 확인 , v1 과 비교해보자.

 

- kiali : catalog v2

 

 

Istio 에 요청 처리 제한 시간 0.5초가 되도록 VirtualService 설정

2가지 변경 사항 : catalog v2 중 파드 1대는 간헐적으로 느린 응답을 하고, istio-proxy 가 요청 0.5초 이상 시 시간 초과 발생

더보기
#
kubectl get vs -n istioinaction
NAME            GATEWAYS              HOSTS                          AGE
catalog-v1-v2   ["catalog-gateway"]   ["catalog.istioinaction.io"]   6h44m

# 타임아웃(0.5s) 적용
kubectl patch vs catalog-v1-v2 -n istioinaction --type json \
-p '[{"op": "add", "path": "/spec/http/0/timeout", "value": "0.5s"}]'

# 적용확인 
kubectl get vs catalog-v1-v2 -n istioinaction -o jsonpath='{.spec.http[?(@.timeout=="0.5s")]}' | jq
...
  "timeout": "0.5s"
}

# 신규 터미널
for in in {1..9999}; do curl http://catalog.istioinaction.io:30000/items -w "\nStatus Code %{http_code}\n"; sleep 1; done
upstream request timeout
Status Code 504
upstream request timeout
Status Code 504
..

#
kubectl logs -n istio-system -l app=istio-ingressgateway -f
[2025-05-09T08:45:41.636Z] "GET /items HTTP/1.1" 504 UT response_timeout - "-" 0 24 501 - "172.18.0.1" "curl/8.7.1" "cb846eff-07ac-902e-9890-7af478c84166" "catalog.istioinaction.io:30000" "10.10.0.13:3000" outbound|80|version-v2|catalog.istioinaction.svc.cluster.local 10.10.0.7:58078 10.10.0.7:8080 172.18.0.1:61108 - -
[2025-05-09T08:45:43.175Z] "GET /items HTTP/1.1" 200 - via_upstream - "-" 0 502 375 374 "172.18.0.1" "curl/8.7.1" "3f2de0c1-5af2-9a33-a6ac-bca08c1ee271" "catalog.istioinaction.io:30000" "10.10.0.13:3000" outbound|80|version-v2|catalog.istioinaction.svc.cluster.local 10.10.0.7:58084 10.10.0.7:8080 172.18.0.1:61118 - -
...

kubectl logs -n istio-system -l app=istio-ingressgateway -f | grep 504
...

#
kubectl logs -n istioinaction -l version=v2 -c istio-proxy -f
[2025-05-09T08:42:38.152Z] "GET /items HTTP/1.1" 0 DC downstream_remote_disconnect - "-" 0 0 500 - "172.18.0.1" "curl/8.7.1" "69fef43c-2fea-9e51-b33d-a0375b382d86" "catalog.istioinaction.io:30000" "10.10.0.13:3000" inbound|3000|| 127.0.0.6:36535 10.10.0.13:3000 172.18.0.1:0 outbound_.80_.version-v2_.catalog.istioinaction.svc.cluster.local default
...

- kiali : catalog v2

 

- Grafana - Istio Mesh 대시보드 : 500 응답 증가, v2 에 Success Rate % 확인

 

 

엔보이 액세스 로그 이해하기 + 엔보이 액세스 로그 형식 바꾸기

  • 기본적으로 이스티오는 프록시가 로그를 TEXT 형식으로 기록하도록 설정하는데, 간결하지만 읽기는 어렵다.
  • JSON 형식을 사용하게 설정 : 이 형식의 이점은 값이 키와 연결돼 의미를 알 수 있다.
더보기
# 형식 설정 전 로그 확인
kubectl logs -n istio-system -l app=istio-ingressgateway -f | grep 504
...

# MeshConfig 설정 수정
KUBE_EDITOR="nano" kubectl edit -n istio-system cm istio
...
  mesh: |-
    accessLogFile: /dev/stdout # 기존 설정되어 있음
    accessLogEncoding: JSON # 추가
...

# 형식 설정 후 로그 확인
kubectl logs -n istio-system -l app=istio-ingressgateway -f | jq
...
{
  "upstream_host": "10.10.0.13:3000", # 요청을 받는 업스트림 호스트
  "bytes_received": 0,
  "upstream_service_time": null,
  "response_code_details": "response_timeout",
  "upstream_cluster": "outbound|80|version-v2|catalog.istioinaction.svc.cluster.local",
  "duration": 501, # 500ms 인 제한 시간 초과
  "response_code": 504,
  "path": "/items",
  "protocol": "HTTP/1.1",
  "upstream_transport_failure_reason": null,
  "connection_termination_details": null,
  "method": "GET",
  "requested_server_name": null,
  "start_time": "2025-05-09T08:56:38.988Z",
  "downstream_remote_address": "172.18.0.1:59052",
  "upstream_local_address": "10.10.0.7:57154",
  "downstream_local_address": "10.10.0.7:8080",
  "bytes_sent": 24,
  "authority": "catalog.istioinaction.io:30000",
  "x_forwarded_for": "172.18.0.1",
  "request_id": "062ad02a-ff36-9dcc-8a7d-68eabb01bbb5",
  "route_name": null,
  "response_flags": "UT", # 엔보이 응답 플래그, UT(Upstream request Timeout)로 중단됨, '업스트림 요청 제한 시간 초과'
  "user_agent": "curl/8.7.1"
}
...

# slow 동작되는 파드 IP로 느린 동작 파드 확인!
CATALOG_POD=$(kubectl get pods -l version=v2 -n istioinaction -o jsonpath={.items..metadata.name} | cut -d ' ' -f1)
kubectl get pod -n istioinaction $CATALOG_POD -owide
NAME                         READY   STATUS    RESTARTS   AGE     IP           NODE                  NOMINATED NODE   READINESS GATES
catalog-v2-56c97f6db-d74kv   2/2     Running   0          7h11m   10.10.0.13   myk8s-control-plane   <none>           <none>

- 필요 시 엔보이 프록시의 로깅 수준을 높여 더 자세한 로그를 얻을 수 있다.

 

 

엔보이 게이트웨이의 로깅 수준 높이기

 

- 현재 로깅 수준 확인

더보기
#
docker exec -it myk8s-control-plane istioctl proxy-config log deploy/istio-ingressgateway -n istio-system
istio-ingressgateway-6bb8fb6549-hcdnc.istio-system:
active loggers:
  admin: warning
  alternate_protocols_cache: warning
  aws: warning
  assert: warning
  backtrace: warning
  cache_filter: warning
  client: warning
  config: warning
  connection: warning # 커넥션 범위에서는 네트워크 계층과 관련된 정보를 기록.
  ...
  http: warning # HTTP 범위에서는 HTTP 헤더, 경로 등 애플리케이션과 관련된 졍보를 기록.
  ...
  router: warning # 라우팅 범위에서는 요청이 어느 클러스터로 라우팅되는지 같은 세부 사항을 기록.
...

 

- 사용할 수 있는 로깅 수준에는 none, error, warning, info, debug 가 있다.

- 각 범위에 로깅 수준을 서로 다르게 지정할 수 있는 덕분에 엔보이가 만들어내는 로그에 질식하지 않고 관심 영역의 로깅 수준만 정확하게 높일 수 있다.

  • connection : Logs related to layer 4 (transport); TCP connection details
  • http : Logs related to layer 7 (application); HTTP details
  • router: Logs related to the routing of HTTP requests
  • pool : Logs related to how a connection pool acquires or drops a connection’s upstream host

- connection , http , router , pool 로거의 수준을 debug 로 높여보자

더보기
#
docker exec -it myk8s-control-plane istioctl proxy-config log deploy/istio-ingressgateway -n istio-system \
--level http:debug,router:debug,connection:debug,pool:debug

# 로그 확인
kubectl logs -n istio-system -l app=istio-ingressgateway -f
k logs -n istio-system -l app=istio-ingressgateway -f > istio-igw-log.txt # 편집기로 열어서 보기
...

 

- 편집기로 열어서 보기

더보기
# 504 검색
2025-05-09T09:17:17.762027Z	debug	envoy http external/envoy/source/common/http/filter_manager.cc:967	[C18119][S12425904214070917868] Sending local reply with details response_timeout	thread=38
2025-05-09T09:17:17.762072Z	debug	envoy http external/envoy/source/common/http/conn_manager_impl.cc:1687	[C18119][S12425904214070917868] encoding headers via codec (end_stream=false):
':status', '504'
'content-length', '24'
'content-type', 'text/plain'
'date', 'Fri, 09 May 2025 09:17:17 GMT'
'server', 'istio-envoy'
	thread=38

# 커넥션 ID(C18119)로 다시 검색

## [C18119] new stream  # 시작
2025-05-09T09:17:17.262341Z	debug	envoy http external/envoy/source/common/http/conn_manager_impl.cc:329	[C18119] new stream	thread=38
2025-05-09T09:17:17.262425Z	debug	envoy http external/envoy/source/common/http/conn_manager_impl.cc:1049	[C18119][S12425904214070917868] request headers complete (end_stream=true):
':authority', 'catalog.istioinaction.io:30000'
':path', '/items'
':method', 'GET'
'user-agent', 'curl/8.7.1'
'accept', '*/*'
	thread=38

## /items 요청이 cluster로 매칭됨
2025-05-09T09:17:17.262445Z	debug	envoy http external/envoy/source/common/http/conn_manager_impl.cc:1032	[C18119][S12425904214070917868] request end stream	thread=38
2025-05-09T09:17:17.262468Z	debug	envoy connection external/envoy/source/common/network/connection_impl.h:92	[C18119] current connecting state: false	thread=38
025-05-09T09:17:17.262603Z	debug	envoy router external/envoy/source/common/router/router.cc:470	[C18119][S12425904214070917868] cluster 'outbound|80|version-v2|catalog.istioinaction.svc.cluster.local' match for URL '/items'	thread=38
2025-05-09T09:17:17.262683Z	debug	envoy router external/envoy/source/common/router/router.cc:678	[C18119][S12425904214070917868] router decoding headers:
':authority', 'catalog.istioinaction.io:30000'
':path', '/items'
':method', 'GET'
':scheme', 'http'
'user-agent', 'curl/8.7.1'
'accept', '*/*'
'x-forwarded-for', '172.18.0.1'
'x-forwarded-proto', 'http'
'x-envoy-internal', 'true'
'x-request-id', 'a6bc39e7-9215-950f-96ea-4cb5f6b12deb'
'x-envoy-decorator-operation', 'catalog-v1-v2:80/*'
'x-envoy-peer-metadata', 'ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCgpDTFVTVEVSX0lEEgwaCkt1YmVybmV0ZXMKGwoMSU5TVEFOQ0VfSVBTEgsaCTEwLjEwLjAuNwoZCg1JU1RJT19WRVJTSU9OEggaBjEuMTcuOAqcAwoGTEFCRUxTEpEDKo4DCh0KA2FwcBIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQoTCgVjaGFydBIKGghnYXRld2F5cwoUCghoZXJpdGFnZRIIGgZUaWxsZXIKNgopaW5zdGFsbC5vcGVyYXRvci5pc3Rpby5pby9vd25pbmctcmVzb3VyY2USCRoHdW5rbm93bgoZCgVpc3RpbxIQGg5pbmdyZXNzZ2F0ZXdheQoZCgxpc3Rpby5pby9yZXYSCRoHZGVmYXVsdAowChtvcGVyYXRvci5pc3Rpby5pby9jb21wb25lbnQSERoPSW5ncmVzc0dhdGV3YXlzChIKB3JlbGVhc2USBxoFaXN0aW8KOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIgoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBxoFZmFsc2UKGgoHTUVTSF9JRBIPGg1jbHVzdGVyLmxvY2FsCi8KBE5BTUUSJxolaXN0aW8taW5ncmVzc2dhdGV3YXktNmJiOGZiNjU0OS1oY2RuYwobCglOQU1FU1BBQ0USDhoMaXN0aW8tc3lzdGVtCl0KBU9XTkVSElQaUmt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1zeXN0ZW0vZGVwbG95bWVudHMvaXN0aW8taW5ncmVzc2dhdGV3YXkKFwoRUExBVEZPUk1fTUVUQURBVEESAioACicKDVdPUktMT0FEX05BTUUSFhoUaXN0aW8taW5ncmVzc2dhdGV3YXk='
'x-envoy-peer-metadata-id', 'router~10.10.0.7~istio-ingressgateway-6bb8fb6549-hcdnc.istio-system~istio-system.svc.cluster.local'
'x-envoy-expected-rq-timeout-ms', '500'
'x-envoy-attempt-count', '1'
	thread=38

## upstream timeout 으로 client 에서 끊음 (disconnect)
2025-05-09T09:17:17.262701Z	debug	envoy pool external/envoy/source/common/conn_pool/conn_pool_base.cc:265	[C17947] using existing fully connected connection	thread=38
2025-05-09T09:17:17.262710Z	debug	envoy pool external/envoy/source/common/conn_pool/conn_pool_base.cc:182	[C17947] creating stream	thread=38
2025-05-09T09:17:17.262736Z	debug	envoy router external/envoy/source/common/router/upstream_request.cc:581	[C18119][S12425904214070917868] pool ready	thread=38
2025-05-09T09:17:17.761697Z	debug	envoy router external/envoy/source/common/router/router.cc:947	[C18119][S12425904214070917868] upstream timeout	thread=38 # 업스트림 서버가 설정된 타임아웃 내에 응답하지 않아 요청이 실패
2025-05-09T09:17:17.761762Z	debug	envoy router external/envoy/source/common/router/upstream_request.cc:500	[C18119][S12425904214070917868] resetting pool request	thread=38
2025-05-09T09:17:17.761776Z	debug	envoy connection external/envoy/source/common/network/connection_impl.cc:139	[C17947] closing data_to_write=0 type=1	thread=38
2025-05-09T09:17:17.761779Z	debug	envoy connection external/envoy/source/common/network/connection_impl.cc:250	[C17947] closing socket: 1	thread=38
2025-05-09T09:17:17.761920Z	debug	envoy connection external/envoy/source/extensions/transport_sockets/tls/ssl_socket.cc:320	[C17947] SSL shutdown: rc=0	thread=38
2025-05-09T09:17:17.761982Z	debug	envoy pool external/envoy/source/common/conn_pool/conn_pool_base.cc:484	[C17947] client disconnected, failure reason: 	thread=38
2025-05-09T09:17:17.761997Z	debug	envoy pool external/envoy/source/common/conn_pool/conn_pool_base.cc:454	invoking idle callbacks - is_draining_for_deletion_=false	thread=38

## 504 응답
2025-05-09T09:17:17.762027Z	debug	envoy http external/envoy/source/common/http/filter_manager.cc:967	[C18119][S12425904214070917868] Sending local reply with details response_timeout	thread=38
2025-05-09T09:17:17.762072Z	debug	envoy http external/envoy/source/common/http/conn_manager_impl.cc:1687	[C18119][S12425904214070917868] encoding headers via codec (end_stream=false):
':status', '504'
'content-length', '24'
'content-type', 'text/plain'
'date', 'Fri, 09 May 2025 09:17:17 GMT'
'server', 'istio-envoy'
	thread=38
2025-05-09T09:17:17.762253Z	debug	envoy pool external/envoy/source/common/conn_pool/conn_pool_base.cc:215	[C17947] destroying stream: 0 remaining	thread=38
2025-05-09T09:17:17.763718Z	debug	envoy connection external/envoy/source/common/network/connection_impl.cc:656	[C18119] remote close	thread=38
2025-05-09T09:17:17.763731Z	debug	envoy connection external/envoy/source/common/network/connection_impl.cc:250	[C18119] closing socket: 0	thread=38

 

  • 두 가지 중요한 발견이 있다.
  • 첫 째, 응답이 느린 업스트림의 IP 주소가 액세스 로그에서 가져온 IP 주소와 일치한다는 점이다. 이는 오동작하는 인스턴스가 딱 하나라는 심증을 더욱 굳힌다. that the IP address of the upstream that responds slowly matches the IP address retrieved from the access logs, which further solidifies that only one instance is misbehaving instance
  • 둘 째, 로그 [C17947] client disconnected 에 표시된 대로 클라이언트(프록시)는 업스트림 커넥션을 종료했다. that the client (proxy) terminated the connection to the upstream, as indicated by the log [C17947] client disconnected.
  • 이는 업스트림 인스턴스가 제한 시간 설정을 초과해 클라이언트(프록시)가 요청을 종료한다는 우리의 예상과 일치한다. This matches our expectation that the client (proxy) is terminating the requests because the upstream instance is exceeding the timeout configuration.
  • 엔보이 로거는 프록시 동작을 깊이 꿰뚫는 통찰력을 얻게 해준다.
  • 다음 절에서는 서버측에서 네트워크 트래픽을 조사한다.

 

10.3.4 tcpdump로 네트워크 트래픽 검사

목표 : 특정 파드에서 tcpdump 후 wireshark 로 분석해보기

 

 

더보기
# kind(k8s) mac M 에서 실행 실패...
kubectl sniff -n istioinaction $CATALOG_POD -i lo
sudo kubectl sniff -n istioinaction $CATALOG_POD -i lo
ERRO[0000] failed to start remote sniffing, stopping wireshark  error="executing sniffer failed, exit code: '1'"

 

- wireshark 실행오류 발생

실행 후 permission denied 오류 발생

 

 

 

필자는 WSL리눅스 환경에서 테스트를 하고 있으므로 WSL 기준으로 설치오류를 해결했다.

 

※ sniff 실행 오류 해결 방법(WSL 기준)

1. Wireshark에서 dumpcap 권한 오류 

1) dumpcap 실행 권한 확인
dumpcap는 패킷 캡처를 위한 프로그램이며, 일반적으로 root 권한이 필요합니다.
ls -l /usr/bin/dumpcap​

# 예상 출력
-rwsr-x--- 1 root wireshark 376480 Aug  5  2023 /usr/bin/dumpcap

 

  • s 비트가 설정되어 있는지 확인하세요. 이는 setuid 비트를 의미하며, dumpcap를 실행할 때 root 권한을 잠시 얻게 됩니다.

2) 만약 s비트가 없는 경우
- 필자는 s비트가 없어서 다음과 같이 적용했음.
# 권한추가
sudo chmod u+s /usr/bin/dumpcap

# wireshark 그룹추가
sudo usermod -aG wireshark $(whoami)

# 변경 사항을 반영
newgrp wireshark​


3) $catalog pod 변수 설정하

export CATALOG_POD=$(kubectl get pod -n istioinaction -l app=catalog | grep Running | awk '{print $1}')​


3) 확인 방법
echo $CATALOG_POD​


4) sniff 명령 실행

kubectl sniff -n istioinaction $CATALOG_POD -i lo​

# 또는 Wireshark가 자동으로 열리지 않는 경우, 로컬 tcpdump 경로 지정:
kubectl sniff -n istioinaction $CATALOG_POD -i lo --local-tcpdump-path=/usr/bin/tcpdump

# tcpdump가 로컬에 없는 경우 설치 필요한 경우
sudo apt install tcpdump



5) 실행화면 출력결과

 

 

 

1. 특정 파드에서 tcpdump 후 wireshark 로 불러오기

Flow 예시

더보기
# slow 파드 정보 확인
CATALOG_POD=$(kubectl get pods -l version=v2 -n istioinaction -o jsonpath={.items..metadata.name} | cut -d ' ' -f1)
kubectl get pod -n istioinaction $CATALOG_POD -owide

# catalog 서비스 정보 확인
kubectl get svc,ep -n istioinaction
NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/catalog   ClusterIP   10.200.1.178   <none>        80/TCP    10h

NAME                ENDPOINTS                                         AGE
endpoints/catalog   10.10.0.12:3000,10.10.0.13:3000,10.10.0.14:3000   10h

# istio-proxy 에서 기본 정보 확인
kubectl exec -it -n istioinaction $CATALOG_POD -c istio-proxy -- sudo whoami
kubectl exec -it -n istioinaction $CATALOG_POD -c istio-proxy -- tcpdump -h
kubectl exec -it -n istioinaction $CATALOG_POD -c istio-proxy -- ip -c addr
kubectl exec -it -n istioinaction $CATALOG_POD -c istio-proxy -- ip add show dev eth0
kubectl exec -it -n istioinaction $CATALOG_POD -c istio-proxy -- ip add show dev lo

# istio-proxy 에 eth0 에서 패킷 덤프
kubectl exec -it -n istioinaction $CATALOG_POD -c istio-proxy -- sudo tcpdump -i eth0 tcp port 3000 -nnq
kubectl exec -it -n istioinaction $CATALOG_POD -c istio-proxy -- sudo tcpdump -i eth0 tcp port 3000 -nn
kubectl exec -it -n istioinaction $CATALOG_POD -c istio-proxy -- sudo tcpdump -i eth0 tcp port 3000

# istio-proxy 에 lo 에서 패킷 덤프
kubectl exec -it -n istioinaction $CATALOG_POD -c istio-proxy -- sudo tcpdump -i lo -nnq

# istio-proxy 에 tcp port 3000 에서 패킷 덤프
kubectl exec -it -n istioinaction $CATALOG_POD -c istio-proxy -- sudo tcpdump -i any tcp port 3000 -nnq
kubectl exec -it -n istioinaction $CATALOG_POD -c istio-proxy -- sudo tcpdump -i any tcp port 3000 -nn

#
kubectl describe pod -n istioinaction $CATALOG_POD
...
    Mounts:
      /etc/istio/pod from istio-podinfo (rw)
      /etc/istio/proxy from istio-envoy (rw)
      /var/lib/istio/data from istio-data (rw)
      /var/run/secrets/credential-uds from credential-socket (rw)
      /var/run/secrets/istio from istiod-ca-cert (rw)
      /var/run/secrets/tokens from istio-token (rw)
      /var/run/secrets/workload-spiffe-credentials from workload-certs (rw)
      /var/run/secrets/workload-spiffe-uds from workload-socket (rw)
...

# istio-proxy 에 tcp port 3000 에서 패킷 덤프에 출력 결과를 파일로 저장 
kubectl exec -it -n istioinaction $CATALOG_POD -c istio-proxy -- sudo tcpdump -i any tcp port 3000 -w /var/lib/istio/data/dump.pcap
kubectl exec -it -n istioinaction $CATALOG_POD -c istio-proxy -- ls -l /var/lib/istio/data/

# 출력 결과 파일을 로컬로 다운로드
kubectl cp -n istioinaction -c istio-proxy $CATALOG_POD:var/lib/istio/data/dump.pcap ./dump.pcap

# 로컬로 다운 받은 파일을 wireshark 로 불러오기
wireshark dump.pcap

 

2. Wireshark 에서 TLS 암호 통신 확인 : istio-ingressgateway → [ (캡처 지점) istio-proxycatalog application ]

Flow 예시

- Client Hello (SNI 확인) : EDS 의 클러스터 이름으로 접속

  • SNI에 값 형태를 추정?해보면, https 통신 시 EDS 기준 요청에 대한 통제를 SNI에서 값을 기준하기 위해서, 좀 더 상세한 출력으로 보임

 

- 암호화된 내용 확인 : Encrypted Application Data 에 값 확인

 

 

3. Wireshark 에서 평문 통신 확인 : istio-ingressgateway → [ istio-proxy (캡처 지점) catalog application ]

Flow 예시

- istio-proxy 가 HTTPS를 복호화해서 평문으로 애플리케이션으로 요청 : x-envoy, x-b3 등 헤더 추가 확인

 

- GET /items 패킷에서 우클릭 후 Follow → TCP Stream 클릭해서 해당 스트림(TCP) 필터링

 

  • Statistics → Flow Graph 확인 : 정상적으로 GET 요청과 200 응답 확인

 

  • 필터 (tcp.stream == 1 and http) 사용 ← 숫자 1은 각자 스트림 필터링 값 입력

4. catalog v2 가 늦게 응답을 해서 istio-proxy 가 timeout 으로 먼저 종료 확인

Flow 예시

- 필터 ((tcp.stream == 1 and http) or tcp.flags == 0x0011 or tcp.flags == 0x0004) : TCP RST, FIN/ACK 플래그 필터링 추가

 

  • No. 38번에서 요청 후 0.5초 이상 응답이 없으니 (42번)44번에 istio-ingressgateway istio-proxy 가 TCP RST 로 연결 종료
  • ⇒ 즉, 현재 구성 상 istio-ingressgw → catalog 이므로, istio-ingressgw 가 TCP Timeout 후 종료 처리함
  • 이후 45번은 catalog v2 istio-proxy 가 FIN/ACK를 applcation 에게 전달 이후 연결 종료
☞ TCP control flags
TCP 제어 플래그는 커넥션의 특정 상태를 나타낸다. 여기서 볼 수 있는 플래그는 다음과 같다.
- Synchronization (SYN)은 커넥션을 새로 수립하는 데 사용한다.
- Acknowledgment (ACK)는 패킷 수신이 성공했음을 확인하는 데 사용한다.
- Finish (FIN)는 커넥션 종료를 요청하는 데 사용한다.

 

- kiali 확인

 

- jaeger ui

 

  • 네트워크 트래픽을 검사하면 앞 서 관찰한 두 가지를 모두 확인할 수 있다.
  • 클라이언트가 커넥션 종료를 시작했고, 서비는 요청 응답이 느렸다.
  • 다음 절에서는 이 문제가 드문 문제인지, 즉시 주의를 기울여야 하는 빈번한 문제인지 파악하기 위해 서버를 성공률을 조사한다.

 

 

10.4 엔보이 텔레메트리로 자신의 애플리케이션 이해하기

10.4.1 그라파나에서 실패한 요청 비율 찾기

- Grafana - Istio Service 대시보드 ⇒ Service(catalog.istioinaction..) , Reporter(source) 선택

  • 클라이언트 성공률은 요청 중 70% 정도(아래 스샷은 79%)로 30% 정도 실패. ⇒ Client 응답에 5xx가 30% 정도 있음
  • 상태 코드 504 (’Gateway timeout’)로 표기되어 클라이언트 측 실패율에 반영.

  • 서버 성공률은 100%, 즉 서버 문제는 아님 ⇒ Server 응답에는 5xx 없음.
  • 엔보이 프록시가 다운스트림 종료 요청에 대한 응답 코드를 0으로 표시하며, 이는 5xx 응답이 아니라서 실패율에 포함되지 않는다.

  • [인그레스 게이트웨이 : 응답 플래그 UT, 상태 코드 504] ⇒ (요청 타임아웃) ⇒ [catalog v2 : 응답 플래그 DC, 상태 코드 0]

클라이언트와 서버가 설정한 응답 플래그와 응답 코드의 차이점

  • 정리하면, 올바른 값은 클라이언트가 보고하는 성공률이라는 것을 알 수 있다.
  • 실패율이 20~30%이면 즉시 주의를 기울여야 한다!
  • 그러나 현재 그라파나 대시보드catalog 서비스에 속한 모든 워크로드(v1,v2)의 성공률을 보여준다.
  • 문제가 있는 단일 인스턴스를 식별하려면 좀 더 상세한 출력이 필요하다.

10.4.2 프로메테우스를 사용해 영향받는 파드 쿼리하기

그라파나 대시보드의 정보가 부족하면 프로메테우스에 직접 쿼리할 수 있다.

예를 들어 파드 별 실패율을 쿼리해보자. 다음 기준을 충족하는 메트릭을 쿼리해보자.

  • destination 이 보고한 요청
  • destination 서비스가 catalog 인 요청
  • 응답 플래그가 DC(다운스트림 커넥션 종료)인 요청 ⇒ 서버 입장에서는 응답을 하려는데, 클라이언트가 먼저 끊어 버린 것!
더보기
sort_desc( # 가장 높은 값부터 내림차순 정렬
  sum( # irate 값들을 집계
    irate( #  요청 수 초당 증가율
      istio_requests_total {
        reporter="destination",   # 서버(destination) 측에서 보고한 메트릭만 필터링
        destination_service=~"catalog.istioinaction.svc.cluster.local",   # catalog 가 서버(destination)측인 메트릭만 필터링
        response_flags="DC"       # DC (다운스트림 커넥션 종료)로 끝난 메트릭만 필터링
      }[5m]
    )
  )by(response_code, pod, version) # 응답 코드(response_code), 대상 pod, 버전(version) 별로 분리 => sum.. 합산
)
# 쿼리1
istio_requests_total
istio_requests_total{reporter="destination", destination_service=~"catalog.istioinaction.svc.cluster.local"}
istio_requests_total{reporter="destination", destination_service=~"catalog.istioinaction.svc.cluster.local",response_flags="DC"}

# 쿼리2
istio_requests_total{reporter="destination", destination_service=~"catalog.istioinaction.svc.cluster.local",response_flags="DC"}[5m]
irate(istio_requests_total{reporter="destination", destination_service=~"catalog.istioinaction.svc.cluster.local",response_flags="DC"}[5m])
sum(irate(istio_requests_total{reporter="destination", destination_service=~"catalog.istioinaction.svc.cluster.local",response_flags="DC"}[5m]))

# 쿼리3
sum(irate(istio_requests_total{reporter="destination", destination_service=~"catalog.istioinaction.svc.cluster.local",response_flags="DC"}[5m])) by(response_code, pod, version)
sort_desc(sum(irate(istio_requests_total{reporter="destination", destination_service=~"catalog.istioinaction.svc.cluster.local",response_flags="DC"}[5m]))by(response_code, pod, version))

⇒ 해당 그래프는 오직 워크로드 하나만 실패를 보고 하고 있음을 보여준다.

 

  • 퀴리를 조금 수정해서 확인 : 여러 개 파드 중 catalog v2 만 응답 코드 0 기록 확인
더보기
sort_desc(sum(irate(istio_requests_total{reporter="destination", destination_service=~"catalog.istioinaction.svc.cluster.local"}[5m]))by(response_code, pod, version))

 

  • 이스티오 표준 메트릭에 필요한 정보가 없으며, 7장의 7.4절에서 소개한 방법처럼 커스텀 메트릭을 추가할 수 있다.
  • 또한 프로메테우스 클라이언트 라이브러리를 사용해 애플리케이션에 모니터링을 원하는 대로 설정할 수도 있다.
  • 이것으로 데이터 플레인을 트러블슈팅하는 데 흔히 사용하는 도구 탐색을 마치겠다.
  • 다양한 데이터 플레인 문제가 이전에는 블랙박스철머 보였을 수 있다.
  • 하지만 지금부터 이런 문제를 마주했을 때 자신감을 갖고 명확한 출발점을 찾을 수 있어야 한다.
  • 이스터이 작동 방식을 깊이 이해하고 적절한 도구가 있다면, 데이터 플레인 문제 디버깅이 휠씬 쉬워진다. (단, 결코 쉬운 일은 아니다)
  • 다음 장에서는 컨트롤 플레인에서 일어나는 문제를 해결하는 방법을 알아본다.
  • 서비스 메시 내 워크로드 개수가 늘어나면 컨트롤 플레인이 따라서 확장될 수 있도록 함으로써, 컨트롤 플레인 성능을 개선하는 방법을 알아본다.

 

Summary

- istioctl 명령어를 사용해 서비스 메시와 서비스 프록시에 대한 통찰력을 얻는다.
    - proxy-status 는 데이터 플레인 동기화 상태의 개요를 보여준다.
    - analyze는 서비스 메시 설정을 분석한다.
    - describe는 요약을 가져오고 서비스 프록시 설정을 검증한다.
    - proxy-config는 서비스 프록시 설정을 쿼리하고 수정한다.
- istioctl analyze 명령을 사용해 클러스터에 적용하기 전에 설정을 검증할 수 있다.
- 키알리와 그 검증 기능을 사용해 일반적인 설정 실수를 잡아낼 수 있다.
- 장애 상황을 살펴보려면 프로메테우스와 수집한 메트릭을 사용하자.
- ksniff(tcpdump)를 사용해 영향을 받는 파드의 네트워크 트래픽을 캡처할 수 있다.
- istioctl proxy-config log 명령어를 사용해 엔보이 프록시의 로깅 수준을 높일 수 있다.

 

 

부록 D 이스티오 구성 요소 트러블 슈팅하기

Internal Architecture by Port : Istiod(컨트롤플레인) + Istio Proxy(데이터플레인) 도식화 - Blog

https://www.anyflow.net/sw-engineer/istio-internals-by-port

 

D.1 이스티오 에이전트(DataPlane 위치에서 확인)가 노출하는 정보

- 실습 환경 초기화

더보기
# 기존 리소스 삭제
kubectl delete -n istioinaction deploy,svc,gw,vs,dr,envoyfilter --all

# 샘플 애플리케이션 배포
kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction
kubectl apply -f services/webapp/kubernetes/webapp.yaml -n istioinaction
kubectl apply -f services/webapp/istio/webapp-catalog-gw-vs.yaml -n istioinaction

# 확인
kubectl get gw,vs -n istioinaction
curl -s http://webapp.istioinaction.io:30000/api/catalog | jq

# 신규 터미널 : 반복 접속
while true; do curl -s http://webapp.istioinaction.io:30000/api/catalog ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done
  • 이스티오 사이드카는 많은 기능을 제공한다.
    • 헬스체크 Health checking
      • 프록시로서의 엔보이는 트래픽을 처리할 수 있는 즉시 준비 상태다.
      • 그러나 서비스 메시의 관점에서 보면 이 정도로는 충분하지 않다.
      • 프록시가 트래픽을 처리하기 전에 설정을 받았는지, ID를 할당받았는지 등의 더 많은 확인이 필요하다.
    • 메트릭 수집 및 노출 Metrics collection and exposure
      • 서비스 내에서 메트릭을 생성하는 세 가지 구성 요소는 애플리케이션, 에이전트, 엔보이 프록시다.
      • 에이전트는 다른 구성 요소의 메트릭을 집계해 노출한다.
    • DNS resolution 해석, 인바운드 및 아웃바운드 트래픽 라우팅 등

 

- 서비스 노출 포트 확인

더보기
kubectl -n istioinaction exec -it deploy/webapp -c istio-proxy -- netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 127.0.0.1:15000         0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:15004         0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:15021           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:15021           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:15001           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:15001           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:15006           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:15006           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:15090           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:15090           0.0.0.0:*               LISTEN     
tcp6       0      0 :::15020                :::*                    LISTEN     
tcp6       0      0 :::8080                 :::*                    LISTEN   

# 포트별 프로세스 확인 : 파일럿에이전트, 엔보이
kubectl -n istioinaction exec -it deploy/webapp -c istio-proxy --  ss -tnlp
State                Recv-Q               Send-Q                             Local Address:Port                                Peer Address:Port               Process                                            
LISTEN               0                    4096                                   127.0.0.1:15000                                    0.0.0.0:*                   users:(("envoy",pid=21,fd=18))                    
LISTEN               0                    4096                                   127.0.0.1:15004                                    0.0.0.0:*                   users:(("pilot-agent",pid=1,fd=11))               
LISTEN               0                    4096                                     0.0.0.0:15021                                    0.0.0.0:*                   users:(("envoy",pid=21,fd=25))                    
LISTEN               0                    4096                                     0.0.0.0:15021                                    0.0.0.0:*                   users:(("envoy",pid=21,fd=24))                    
LISTEN               0                    4096                                     0.0.0.0:15001                                    0.0.0.0:*                   users:(("envoy",pid=21,fd=36))                    
LISTEN               0                    4096                                     0.0.0.0:15001                                    0.0.0.0:*                   users:(("envoy",pid=21,fd=35))                    
LISTEN               0                    4096                                     0.0.0.0:15006                                    0.0.0.0:*                   users:(("envoy",pid=21,fd=38))                    
LISTEN               0                    4096                                     0.0.0.0:15006                                    0.0.0.0:*                   users:(("envoy",pid=21,fd=37))                    
LISTEN               0                    4096                                     0.0.0.0:15090                                    0.0.0.0:*                   users:(("envoy",pid=21,fd=23))                    
LISTEN               0                    4096                                     0.0.0.0:15090                                    0.0.0.0:*                   users:(("envoy",pid=21,fd=22))                    
LISTEN               0                    4096                                           *:15020                                          *:*                   users:(("pilot-agent",pid=1,fd=7))                
LISTEN               0                    4096                                           *:8080                                           *:*               

# istio-proxy 컨테이너에 Readiness Probe 정보 확인 : 15021 헬스체크 포트
kubectl describe pod -n istioinaction -l app=webapp | grep Readiness:
    Readiness:  http-get http://:15021/healthz/ready delay=1s timeout=3s period=2s #success=1 #failure=30

 

- 에이전트 및 엔보이 프록시의 포트와 각 포트의 기능

 

  • 서비스용 포트 Ports facing other services
    • 15020 : (파일럿 에이전트 프로세스) 여러 기능 제공!
      • 메트릭을 집계하고 노출하며, 이때 메트릭에는 엔보이 프록시의 15090 포트에 쿼리한 메트릭, 애플리케이션 메트릭(설정한 경우), 자체 메트릭이 있다.
      • 엔보이 및 DNS 프록시를 헬스 체크. 이 엔드포인트에서 애플리케이션도 헬스 체크하도록 프록시를 설정할 수 있지만, 보통은 가상머신과 같이 쿠버네티스가 아닌 워크로드에만 사용한다.
      • 이스티오 개발 팀에 유용한 파일럿 에이전트 디버깅용 엔드포인트로, 메모리 정보, CPU 프로파일링 등과 같은 정보를 노출한다.
    • 15021 : (엔보이 프로세스) 사이드카 주입된 파드는 이 포트에서 트래픽을 받을 준비가 됐는지 확인하도록 설정된다. Pods with the sidecar injected are configured to check their readiness to receive traffic on this port.
      • 앞서 설명한 것처럼 엔보이 프록시헬스 체크를 15020 포트의 파일럿 에이전트로 라우팅하며, 실제 헬스 체크는 여기서 일어난다. the Envoy proxy routes the health checks to the Pilot agent on port 15020, where the actual healthchecking occurs.
    • 15053 : (파일럿 에이전트 프로세스) 쿠버네티스 DNS 해석이 충분하지 않은 에지 케이스를 해결하기 위해 istiod가 구성한 로컬 DNS 프록시 Local DNS proxy configured by istiod to resolve edge cases where Kubernetes DNS resolution doesn’t suffice.
    • 15001 : (엔보이 프로세스) 애플리케이션에서 나가는 트래픽은 Iptable 규칙에 의해 일단 이 포트로 리다이렉트되며, 이후 프록시가 트래픽을 서비스로 라우팅한다.
    • 15006 : (엔보이 프로세스) 애플리케이션으로 들어오는 트래픽은 Iptable 규칙에 의해 일단 이 포트로 리다이렉트되며, 여기서 로컬 애플리케이션 라우팅된다.
  • 에이전트 디버깅 및 내부 상태 조사에 유용한 포트 useful for debugging and introspecting the agent
    • 15000 : (엔보이 프로세스) 엔보이 프록시 관리 인터페이스
    • 15090 : (엔보이 프로세스) 엔보이 프록시 메트릭을 노출 (xDS 통계, 커넥션 통계, HTTP 통계, 이상값 outlier 통계, 헬스 체크 통계, 서킷 브레이커 통계 등)
    • 15004 : (파일럿 에이전트 프로세스) 에이전트를 통해 이스티오 파일럿 디버그 엔드포인트를 노출. 파일럿과의 연결 문제를 디버깅에 유용.
    • 15020 : (파일럿 에이전트 프로세스) 파일럿 에이전트 디버기용 엔드포인트들을 노출.

D.1.1 이스티오 에이전트를 조사하고 트러블슈팅하기 위한 엔드포인트들 Endpoints to introspect and troubleshoot the Istio agent

  • 15020 포트의 엔드포인트들
    • /healthz/ready : 엔보이 및 DNS 프록시에서 일련의 검사를 수행한다.
      • 이느 워크로드가 클라이언트 요청을 처리할 준비가 됐는지 확인하기 위한 것이다.
    • /stats/prometheus : 엔보이 프록시와 애플리케이션의 메트릭을 자체 메트릭과 병합하고 긁어갈 수 있도록 노출한다.
    • /quitquitquit : 파일럿 에이전트의 프로세스를 종료시킨다.
    • /app-health/ : 이스티오 프록시 사이드카의 환경 변수 ISTIO_KUBE_APP_PROBERS로 정의한 애플리케이션 프로브를 실행한다.
      • 애플리케이션이 쿠버네티스 프로브를 정의하면 istiod mutating 웹훅이 정보를 추출해 이 환경 변수로 프로브를 설정한다 - Docs
      • 그러므로 에이전트는 이 경로로의 퀴리를 애플리케이션으로 리다이렉트한다.
더보기
#
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: liveness-http
  namespace: istioinaction
spec:
  selector:
    matchLabels:
      app: liveness-http
      version: v1
  template:
    metadata:
      labels:
        app: liveness-http
        version: v1
    spec:
      containers:
      - name: liveness-http
        image: docker.io/istio/health:example
        ports:
        - containerPort: 8001
        livenessProbe:
          httpGet:
            path: /foo
            port: 8001
          initialDelaySeconds: 5
          periodSeconds: 5
EOF

#
kubectl get pod -n istioinaction -l app=liveness-http
kubectl describe pod -n istioinaction -l app=liveness-http
...
Containers:
  liveness-http:
    Container ID:   containerd://edaf01bff5d553e03290b3d44f60bb26958319e615a27a9b38309aad9b2df477
    Image:          docker.io/istio/health:example
    Image ID:       docker.io/istio/health@sha256:d8a2ff91d87f800b4661bec5aaadf73d33de296d618081fa36a0d1cbfb45d3d5
    Port:           8001/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Sat, 10 May 2025 16:58:35 +0900
    Ready:          True
    Restart Count:  0
    Liveness:       http-get http://:15020/app-health/liveness-http/livez delay=5s timeout=1s period=5s #success=1 #failure=3
    ...
  istio-proxy:
    Container ID:  containerd://d4b0955372bdb7b3e1490eb3f290c6c6f5a9f2691eabea4cebafaafa8be85fc9
    Image:         docker.io/istio/proxyv2:1.17.8
    Image ID:      docker.io/istio/proxyv2@sha256:d33fd90e25c59f4f7378d1b9dd0eebbb756e03520ab09cf303a43b51b5cb01b8
    Port:          15090/TCP
    ...
    Readiness:  http-get http://:15021/healthz/ready delay=1s timeout=3s period=2s #success=1 #failure=30
    Environment:
      ...                          
      ISTIO_META_POD_PORTS:          [
                                         {"containerPort":8001,"protocol":"TCP"}
                                     ]
      ISTIO_META_APP_CONTAINERS:     liveness-http
      ISTIO_META_CLUSTER_ID:         Kubernetes
      ISTIO_META_NODE_NAME:           (v1:spec.nodeName)
      ISTIO_META_INTERCEPTION_MODE:  REDIRECT
      ISTIO_META_WORKLOAD_NAME:      liveness-http
      ISTIO_META_OWNER:              kubernetes://apis/apps/v1/namespaces/istioinaction/deployments/liveness-http
      ISTIO_META_MESH_ID:            cluster.local
      TRUST_DOMAIN:                  cluster.local
      ISTIO_KUBE_APP_PROBERS:        {"/app-health/liveness-http/livez":{"httpGet":{"path":"/foo","port":8001,"scheme":"HTTP"},"timeoutSeconds":1}}


kubectl get pod -n istioinaction -l app=liveness-http -o json | jq '.items[0].spec.containers[0].livenessProbe.httpGet'
{
  "path": "/app-health/liveness-http/livez",
  "port": 15020,
  "scheme": "HTTP"
}

# 헬스체크 확인
kubectl exec -n istioinaction deploy/liveness-http -c istio-proxy -- curl -s localhost:15020/app-health/liveness-http/livez -v

# 실습 확인 후 삭제
kubectl delete deploy liveness-http -n istioinaction
  • /debug/ndsz : istiod가 NDS Name Discovery Service API로 DNS 프록시에 설정한 호스트네임들을 나열한다. Lists the hostnames for which DNS proxy is configured by istiod using the Name Discovery Service (NDS) API.
  • /debug/pprof/* : 성능 문제, 메모리 누수 등을 디버깅하는 데 도움이 되는 Go 언어 프로파일링 엔드포인트. - Docs
    • 기본 경로 localhost:15020/debug/pprof 에 쿼리해 디버그 엔드포인트의 전체 목록을 확인할 수 있다.
    • 출력은 HTML이며 브라우저에서 보는 것이 가장 좋다 (로컬호스트 포트 포워딩).
    • 프로파일링 엔드포인트는 이스티오 개발자와 관련 있으며 이스티오 사용자는 신경 쓸 필요가 없다.

 

- 접근 확인

더보기
#
kubectl exec -n istioinaction deploy/webapp -c istio-proxy -- curl -s localhost:15020/healthz/ready -v

# webapp 워크로드의 병합된 통계 확인 : istio_agent로 시작하는 메트릭(에이전트에서 온 것) + envoy로 시작하는 메트릭(프록시에서 온 것)
kubectl exec -n istioinaction deploy/webapp -c istio-proxy -- curl -s localhost:15020/stats/prometheus
## 응답에서는 istio_agent로 시작하는 메트릭(에이전트에서 온 것)과 envoy로 시작하는 메트릭(프록시에서 온 것)을 볼 수 있는데,
## 이는 이 둘이 병합됐음을 보여준다.

#
kubectl exec -n istioinaction deploy/webapp -c istio-proxy -- curl -s localhost:15020/quitquitquit

#
kubectl exec -n istioinaction deploy/webapp -c istio-proxy -- curl -s localhost:15020/debug/ndsz

#
kubectl port-forward deploy/webapp -n istioinaction 15020:15020
open http://localhost:15020/debug/pprof # 혹은 웹 브라우저에서 열기

 

 

D.1.2 이스티오 에이전트를 통해 이스티오 파일럿 디버그 엔드포인트들 쿼리하기

  • 에이전트는 기본적으로 15004 포트에서 몇 가지 istiod 디버그 엔드포인트들을 노출한다.
  • 이 엔드포인트들에 한 요청은 xDS 이벤트 형태로 안전하게 istiod로 전달되는데, 이는 에이전트에서 컨트롤 플레인으로의 연결 상태를 확인 할 수 있는 좋은 방법이다.
  • 예를 들어 노출된 엔드포인트들 중 하나로 워크로드의 동기화 상태를 쿼리할 수 있다.
  • 이를 보려면, 프록시 중 하나의 셸 커넥션을 가져와서 파일럿 에이전트의 15004 포트에 /debug/sync 엔드포인트로 요청해보자.
더보기
#
kubectl exec -n istioinaction deploy/webapp -c istio-proxy -- curl -s localhost:15004/debug/syncz -v
kubectl exec -n istioinaction deploy/webapp -c istio-proxy -- curl -s localhost:15004/debug/syncz | jq
...
      "@type": "type.googleapis.com/envoy.service.status.v3.ClientConfig",
      "node": {
        "id": "catalog-6cf4b97d-fbftr.istioinaction", # 워크로드 ID
        "metadata": {
          "CLUSTER_ID": "Kubernetes"
        }
      },
      "genericXdsConfigs": [
        {
          "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
          "configStatus": "SYNCED" # xDS API는 최신 상태로 동기화됬다
        },
        {
          "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
          "configStatus": "SYNCED" # xDS API는 최신 상태로 동기화됬다
        },
        {
          "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment",
          "configStatus": "SYNCED" # xDS API는 최신 상태로 동기화됬다
        },
        {
          "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
          "configStatus": "SYNCED" # xDS API는 최신 상태로 동기화됬다
        },
...

# 하위 명령 출력 내용과 동일
docker exec -it myk8s-control-plane istioctl x internal-debug -h
docker exec -it myk8s-control-plane istioctl x internal-debug syncz
  • 노출된 정보는 이스티오 파일럿 디버그 엔드포인트들이 노출하는 정보의 부분집합이다.
  • 또한 istioctl에 새로 추가된 istioctl x internal-debug 명령어가 동일한 엔드포인트를 노출한다.
  • 이들이 노출하는 이런 포트와 서비스에 대한 지식은 트러블슈팅을 더 쉽게 만든다.
  • 따라서 최신 엔보이 설정을 쿼리할 수도 있고, DNS 해석을 직접 시험해볼 수도 있으며, 구성 요소의 동작을 알아보고자 메트릭을 퀴리할 수도 있다.
  • 다음으로 이스티오 파일럿이 노출하는 것들을 살펴보자.

 

D.2 이스티오 파일럿(ControlPlane 영역에서 확인)이 노출하는 정보

 

  • 파일럿은 서비스 메시를 검사하고 디버깅하기 위한 정보들도 노출한다.
  • 이 정보는 서비스 메시 운영자는 물론이고 외부 서비스들에도 유용하다.
  • 이스티오 파일럿이 열어둔 포트를 확인
더보기
#
kubectl -n istio-system exec -it deploy/istiod -- netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 127.0.0.1:9876          0.0.0.0:*               LISTEN     
tcp6       0      0 :::15017                :::*                    LISTEN     
tcp6       0      0 :::15014                :::*                    LISTEN     
tcp6       0      0 :::15012                :::*                    LISTEN     
tcp6       0      0 :::15010                :::*                    LISTEN     
tcp6       0      0 :::8080                 :::*                    LISTEN 

# pilot-discovery 프로세스 확인
kubectl -n istio-system exec -it deploy/istiod -- ss -tnlp
State          Recv-Q         Send-Q                 Local Address:Port                  Peer Address:Port         Process                                          
LISTEN         0              4096                       127.0.0.1:9876                       0.0.0.0:*             users:(("pilot-discovery",pid=1,fd=8))          
LISTEN         0              4096                               *:15017                            *:*             users:(("pilot-discovery",pid=1,fd=12))         
LISTEN         0              4096                               *:15014                            *:*             users:(("pilot-discovery",pid=1,fd=9))          
LISTEN         0              4096                               *:15012                            *:*             users:(("pilot-discovery",pid=1,fd=10))         
LISTEN         0              4096                               *:15010                            *:*             users:(("pilot-discovery",pid=1,fd=11))         
LISTEN         0              4096                               *:8080                             *:*             users:(("pilot-discovery",pid=1,fd=3)) 

#
kubectl describe pod -n istio-system -l app=istiod
...
Containers:
  discovery:
    Container ID:  containerd://f13d7ad8a32cc0cecf47392ef426ea4687ce12d1abf64b5a6d2a60c2f8934e04
    Image:         docker.io/istio/pilot:1.17.8
    Image ID:      docker.io/istio/pilot@sha256:cb9e7b1b1c7b8dcea37d5173b87c40f38a5ae7b44799adfdcf8574c57a52ad2c
    Ports:         8080/TCP, 15010/TCP, 15017/TCP
    Host Ports:    0/TCP, 0/TCP, 0/TCP
    Args:
      discovery
      --monitoringAddr=:15014
      --log_output_level=default:info
      --domain
      cluster.local
      --keepaliveMaxServerConnectionAge
      30m
    ...
    Readiness:  http-get http://:8080/ready delay=1s timeout=5s period=3s #success=1 #failure=3
    Environment:
      REVISION:                                     default
      JWT_POLICY:                                   third-party-jwt
      PILOT_CERT_PROVIDER:                          istiod
      POD_NAME:                                     istiod-8d74787f-ltkhs (v1:metadata.name)
      POD_NAMESPACE:                                istio-system (v1:metadata.namespace)
      SERVICE_ACCOUNT:                               (v1:spec.serviceAccountName)
      KUBECONFIG:                                   /var/run/secrets/remote/config
      PILOT_TRACE_SAMPLING:                         100
      PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_OUTBOUND:  true
      PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_INBOUND:   true
      ISTIOD_ADDR:                                  istiod.istio-system.svc:15012
      PILOT_ENABLE_ANALYSIS:                        false
      CLUSTER_ID:                                   Kubernetes
...

노출된 이스티오 파일럿 포트와 그 기능

 

  • 서비스용 포트
    • 15010 : xDS API 및 인증서 발급을 평문으로 노출한다. 트래픽을 스니핑할 수 있으므로 이 포트는 사용하지 않는 것이 좋다.
    • 15012 : 15010 포트와 노출하는 정보는 같지만 보안을 적용한다. 이 포트는 TLS를 사용해 ID를 발급하여, 후속 요청은 상호 인증된다.
    • 15014 : 11장에서 다룬 것과 같은 컨트롤 플레인 메트릭을 노출한다.
    • 15017 : 쿠버네티스 API 서버가 호출하는 웹훅 서버를 노출한다.
      • 쿠버네티스 API 서버는 새로 만들어진 파드에 사이드카를 주입하고, Gateway나 VirtualServie 같은 이스티오 리소스를 검증하기 위해 호출한다.
  • 디버깅 및 검사 포트
    • 8080 : 이스티오 파일럿 디버그 엔드포인트를 노출한다.
    • 9876 : istiod 프로세스에 대한 검사 정보를 노출한다.

 

D.2.1 이스티오 파일럿 디버그 엔드포인트

  • 이스티오 파일럿 디버그 엔드포인트는 파일럿이 알고 있는 전체 서비스 메시의 설정과 상태를 노출한다.
  • 엔드포인트는 다음과 같은 질문들에 답한다.
    • 프록시는 동기화됐는가? Are the proxies synchronized?
    • 프록시에 대한 마지막 푸시는 언제 수행됐는가? When was the last push to a proxy performed?
    • xDS API의 상태는 어떤가? What’s the state of the xDS APIs?
  • 디버그 엔드포인트로 접근해보자
더보기
#
kubectl -n istio-system port-forward deploy/istiod 8080
open http://localhost:8080/debug

# 파일럿이 알고 있는 서비스 메시 상태
## 클러스터, 루트, 리스너 설정
curl -s http://localhost:8080/debug/adsz | jq

## 이 파일럿이 관리하는 모든 프록시에 대한 푸시를 트리거한다.
curl -s http://localhost:8080/debug/adsz?push=true
Pushed to 4 servers

## /debug/edsz=proxyID=<pod>.<namespace> : 프록시가 알고 있는 엔드포인트들
curl -s http://localhost:8080/debug/edsz=proxyID=webapp.istioninaction

## /debug/authorizationz : 네임스페이스에 적용되는 인가 정책 목록
curl -s http://localhost:8080/debug/authorizationz | jq


# 파일럿이 알고 있는 데이터 플레인 설정을 나타내는 엔드포인트
## 이 파일럿 인스턴스에 연결된 모든 엔보이의 버전 상태 : 현재 비활성화되어 있음
curl -s http://localhost:8080/debug/config_distribution
Pilot Version tracking is disabled. It may be enabled by setting the PILOT_ENABLE_CONFIG_DISTRIBUTION_TRACKING environment variable to true

## 이스티오 파일럿의 현재 알려진 상태에 따라 엔보이 설정을 생성한다.
curl -s http://localhost:8080/debug/config_dump?=proxyID=webapp.istioninaction

## 이 파일럿이 관리하는 프록시들을 표시한다.
curl -s http://localhost:8080/debug/syncz | jq
...
  {
    "cluster_id": "Kubernetes",
    "proxy": "webapp-7685bcb84-lwsvj.istioinaction",
    "istio_version": "1.17.8",
    "cluster_sent": "ff5e6b2c-e857-4e12-b17e-46ad968567f4",
    "cluster_acked": "ff5e6b2c-e857-4e12-b17e-46ad968567f4",
    "listener_sent": "7280c908-010d-4788-807f-7138e74fe72e",
    "listener_acked": "7280c908-010d-4788-807f-7138e74fe72e",
    "route_sent": "2a1916c3-9c05-4ce5-8cfa-d777105b9205",
    "route_acked": "2a1916c3-9c05-4ce5-8cfa-d777105b9205",
    "endpoint_sent": "dffacd32-2674-4e39-8e76-17016ff32514",
    "endpoint_acked": "dffacd32-2674-4e39-8e76-17016ff32514"
  },
...

 

  • 파일럿이 알고 있는 서비스 메시 상태를 나타내는 엔드포인트
    • /debug/adsz : 클러스터, 루트, 리스너 설정
    • /debug/adsz?push=true : 이 파일럿이 관리하는 모든 프록시에 대한 푸시를 트리거한다.
    • /debug/edsz=*proxyID*=*<pod>.<namespace>* : 프록시가 알고 있는 엔드포인트들
    • /debug/authorizationz : 네임스페이스에 적용되는 인가 정책 목록

 

  • 파일럿이 알고 있는 데이터 플레인 설정을 나타내는 엔드포인트
    • /debug/config_distribution : 이 파일럿 인스턴스에 연결된 모든 엔보이의 버전 상태
    • /debug/config_dump?proxyID=<pod>.<namespace> : 이스티오 파일럿의 현재 알려진 상태에 따라 엔보이 설정을 생성한다.
    • /debug/syncz : 이 파일럿이 관리하는 프록시들을 표시한다.
      • 또한 프록시로 보낸 최신 논스 nonce 와 응답받은 최신 논스도 보여준다. 이 둘이 동일하면 프록시의 설정이 최신인 것이다.
  • 서비스 메시 운영자는 보통 키알리, istioctl 등 다른 도구를 통해 엔드포인트를 간접적으로 사용할 것이다.
  • 예를 들어 istioctl proxy-status 명령어는 프록시가 동기화됐는지 확인하기 위해 /debug/syncz 엔드포인트를 사용한다.
  • 그러나 이런 도구가 제공하는 정보로 충분하지 않을 때는 직접 디버그 엔드포인트를 사용해 더 깊이 파고들 수 있다.

 

D.2.2 ControlZ 인터페이스

  • 이스티오 파일럿에는 파일럿 프로세스의 현재 상태와 몇 가지 사소한 설정 가능성을 확인 할 수 있는 관리자 인터페이스가 함께 제공된다.
  • 이 인터페이스는 아래 표 D.1 에서 다룬 것 처럼 파일럿 인스턴스와 관련된 정보를 빠르게 조회할 수 있다.

 

페이지
설명
로깅 범위 Logging Scopes
이 프로세스에 대한 로깅은 범위별로 구성돼 있어 범위별로 로깅 단계를 별도로 설정할 수 있다.
메모리 사용량 Memory Usage
이 정보는 Go 런타임에서 수집되며 이 프로세스의 메모리 소비량을 나타낸다.
환경 변수 Environment Variables
이 프로세스에 정의된 환경 변수 집합이다.
프로세스 정보 Process Information
이 프로세스에 대한 정보다.
명령줄 인수 Command-Line Arguments
이 프로세스를 시작할 때 사용한 명령줄 인수 집합이다.
버전 정보 Version Info
바이너리(예: 이스티오 파일럿 1.7.3)와 Go 런타임(go 1.14.7)에 대한 정보다.
메트릭 Metrics
파일럿에서 노출하는 메트릭을 가져오는 방법 중 하나다.
시그널 Signals
실행 중인 프로세스에 SUGUSR1 시그널을 보낼수 있다.

 

 

- 접속 확인

더보기
#
kubectl -n istio-system port-forward deploy/istiod 9876
open http://localhost:9876

  • 이스티오 파일럿을 디버깅 해야 할 때 로깅 범위 변경 사용 가능.

 

 

 

 

 

 

 

 

본 포스팅은 CloudNet@에서 진행하는 Istio 스터디 내용 정리입니다.내용은 Istio In Action 참고서와 Istio 및 기타 공식 문서를 참고하여 작성하였습니다.
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/06   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함