Kubernetes

Istio in Action 10장 데이터 플레인 성능 튜닝하기

mokpolar 2025. 10. 26. 15:46
반응형

안녕하세요?
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를 볼 수 있다.
해당 경고에 대해서는 키알리 검증 페이지를 확인해보면 된다.

Validations | Kiali

해결 방법은 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 
반응형