DevOps/Study

Istio Hands-on Study [1기] [4주차 1/2] Observability 서비스의 동작 이해하기

juyeon22 2025. 5. 3. 18:18
CloudNet@ 가시다님이 진행하는 Istio In Action 책 기반 Hands-on Study  

Chap.7 관찰가능성: 서비스의 동작 이해하기

목차

  • 1.관찰 가능성이란?
  • 2.Istio Metric
  • 3.Prometheus로 Istio Metric 가져오기
  • 4.Istio 표준 Metric 커스터마이징하기

1. 관찰 가능성이란?

개요

현대 애플리케이션은 일반적으로 마이크로서비스 아키텍처(MSA)로 구성되어 있습니다. 이러한 구조는 기존의 단일 Monolith 아키텍처에 비해 복잡도가 크게 증가하며, 서비스 간 의존성이 높아져 고려해야 할 요소들이 기하급수적으로 늘어납니다

이처럼 시스템이 점점 복잡해짐에 따라 관리해야 할 애플리케이션의 수가 급격히 증가하고, 관리 포인트를 놓치거나 특정 애플리케이션에 트래픽이 집중되는 문제가 발생할 수 있습니다

이러한 문제를 안정적으로 해결하고 평균 복구 시간(Mean Time To Recovery, MTTR)을 단축하기 위해 관찰 가능성(Observability) 이라는 개념이 자주 등징하기 시작했습니다.

관찰 가능성의 개념과 정의

관찰 가능성 이란 시스템의 외부에서 관찰 가능한 신호(지표, 로그, 추적 등)를 통해 시스템 내부 상태를 이해하고 추론할 수 있는 능력 이라고 합니다.

관찰 가능성 을 통해 시스템에 문제가 발생했을 때, 다양한 Metric 정보를 유기적으로 활용하여 문제의 원인을 신속하게 파악하고 해결할 수 있어야 합니다

Istio는 관찰 가능성 중 애플리케이션 계층의 네트워크 계측 을 보조하며, 서비스 간 트래픽 흐름과 상태를 보다 쉽게 파악 할 수 있도록 도와주는 역할을 수행합니다.

관찰 가능성과 모니터링 비교

모니터링 은 시스템 장애 유발 가능성이 있는 지표(Metric, log, trace 등)를 수집하고, 이를 기준과 비교하여 상태를 진단하는 활동입니다(Ex 디스크 사용량, 메모리 사용량)

모니터링 개념은 관찰 가능성의 부분집합 이며, 관찰 가능성은 기존 모니터링만으로는 해결할 수 없는, 예측하지 못한 장애 상황까지 진단할 수 있는 개념 입니다.

예를 들어 장애로까지 이어지지 않더라도 사용자 경험에 영향을 줄 수 있는 지연이나 성능 저하가 발생했을 때, 관찰 가능성을 충분히 확보한 시스템이라면 문제 발생 지점을 정확하게 파악할 수 있습니다

Istio와 관찰 가능성의 연관성

Istio는 서비스 메시 내에서 각 애플리케이션 앞단에 Istio-proxy(Envoy)를 사이드카로 배치하여, 서비스 간 네트워크 트래픽을 투명하게 계측하고 관찰할 수 있도록 지원합니다

이를 통해 요청 처리 수, 처리 시간, 실패 요청 건수 등 다양한 네트워크 Metric을 자동으로 수집할 수 있으며, 필요에 따라 추가 Metric도 정의할 수 있습니다

Istio에서는 이런 관찰 가능성 을 돕기 위해 Prometheus, Kiali, Grafana, Jaeger 같은 도구들을 지원합니다.

2.Istio Metric

DataPlane의 Metric

Istio의 Data Plane에서는 연결(Connection), 요청(Request), 런타임(Runtime) 등 다양한 Metric을 수집하여 서비스 간 네트워크 상태를 파악할 수 있게 합니다

실습을 통해 Istio-Proxy의 Metric 을 통해 시각화하여 관찰 가능할 수 있는 시스템을 구성 해 보겠습니다.

# 실습 환경 준비
kind create cluster --name myk8s --image kindest/node:v1.23.17 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000 # Sample Application (istio-ingrssgateway) HTTP
    hostPort: 30000
  - containerPort: 30001 # Prometheus
    hostPort: 30001
  - containerPort: 30002 # Grafana
    hostPort: 30002
  - containerPort: 30003 # Kiali
    hostPort: 30003
  - containerPort: 30004 # Tracing
    hostPort: 30004
  - containerPort: 30005 # Sample Application (istio-ingrssgateway) HTTPS
    hostPort: 30005
  - containerPort: 30006 # TCP Route
    hostPort: 30006
  - containerPort: 30007 # kube-ops-view
    hostPort: 30007
  kubeadmConfigPatches:
  - |
    kind: ClusterConfiguration
    controllerManager:
      extraArgs:
        bind-address: 0.0.0.0
  extraMounts: # 해당 부분 생략 가능
  - hostPath: /home/duswn916/istio-in-action/book-source-code-master # 각자 자신의 pwd 경로로 설정
    containerPath: /istiobook
networking:
  podSubnet: 10.10.0.0/16
  serviceSubnet: 10.200.1.0/24
EOF

# myk8s-control-plane 진입 후 설치 진행
docker exec -it myk8s-control-plane bash
apt update && apt install tree psmisc lsof wget bridge-utils net-tools dnsutils tcpdump ngrep iputils-ping git vim -y

# istioctl 설치
export ISTIOV=1.17.8
echo 'export ISTIOV=1.17.8' >> /root/.bashrc

curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV sh -
cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
istioctl version --remote=false

# default 프로파일 컨트롤 플레인 배포
istioctl install --set profile=demo -y

# 빠져나오기
exit


# 실습을 위한 네임스페이스 설정
kubectl create ns istioinaction
kubectl label namespace istioinaction istio-injection=enabled

# istio-ingressgateway 서비스 : NodePort 변경 및 nodeport 지정 변경 , externalTrafficPolicy 설정 (ClientIP 수집)
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 8080, "nodePort": 30000}]}}'
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 443, "targetPort": 8443, "nodePort": 30005}]}}'
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec":{"externalTrafficPolicy": "Local"}}'


# 내부 접속 테스트용 netshoot 파드 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: netshoot
spec:
  containers:
  - name: netshoot
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
EOF
# host파일에 등록
echo "127.0.0.1       webapp.istioinaction.io" | sudo tee -a /etc/hosts

# catalog 앱 기동
kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction

# webapp 앱 기동
kubectl apply -f services/webapp/kubernetes/webapp.yaml -n istioinaction

# gateway, virtualservice 설정
kubectl apply -f services/webapp/istio/webapp-catalog-gw-vs.yaml -n istioinaction

# 호출테스트
curl -s http://webapp.istioinaction.io:30000
curl -s http://webapp.istioinaction.io:30000/api/catalog | jq
curl -s http://webapp.istioinaction.io:30000/api/catalog | jq

# 쿼리를 실행해 파드의 통계 확인 : 정보가 많음. 프록시가 보관하는 정보는 휠씬 더 많지만, 대부분은 기본적으로 제거됨.
kubectl exec -it deploy/catalog -c istio-proxy -n istioinaction -- curl localhost:15000/stats
kubectl exec -it deploy/webapp  -c istio-proxy -n istioinaction -- curl localhost:15000/stats
# Result
cluster_manager.cds.version_text: "2025-05-02T11:53:00Z/12"
listener_manager.lds.version_text: "2025-05-02T11:53:00Z/12"
cluster.xds-grpc.assignment_stale: 0
cluster.xds-grpc.assignment_timeout_received: 0
cluster.xds-grpc.bind_errors: 0
....
listener_manager.lds.update_duration: P0(nan,1) P25(nan,1.05) P50(nan,1.1) P75(nan,2.1) P90(nan,32.6) P95(nan,32.8) P99(nan,32.96) P99.5(nan,32.98) P99.9(nan,32.996) P100(nan,33)
server.initialization_time_ms: P0(nan,190) P25(nan,192.5) P50(nan,195) P75(nan,197.5) P90(nan,199) P95(nan,199.5) P99(nan,199.9) P99.5(nan,199.95) P99.9(nan,199.99) P100(nan,200)

인바운드 및 아웃바운드 호출에 측정되는 주요한 표준 Istio Metric

  • istio_request_total
    • Ingress Gateway에서 webapp 서비스로 들어오는 요청의 갯수에 대한 INTEGER TYPE Metric 입니다.
  • istio_request_bytes
    • 요청 전문에서 Body부분의 크기를 Byte로 표현한 DISTRIBUTION TYPE Metric 입니다.
  • istio_response_bytes
    • 응답 전문에서 Body부분의 크기를 Byte로 표현한 DISTRIBUTION TYPE Metric 입니다.
  • istio_request_duration_milliseconds
    • 요청 전문의 처리 시간을 표현한 DISTRIBUTION TYPE Metric 입니다.

더보기

표준 Istio Metric 말고도 더 상세한 정보를 표시 할 수 있도록 설정을 변경하는 방법은 다음과 같습니다.

# 방법 1 비추천, 메시 전체에서 수집하는 Metric이 증가하여 시스템을 과부화 상태로 만들 수 있어, 권장하지 않음
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: control-plane
spec:
  profile: demo
  meshConfig:
    defaultConfig: # Defines the default proxy configuration for all services
      proxyStatsMatcher: # Customizes the reported metrics
        inclusionPrefixes: # Metrics matching the prefix will be reported alongside the default ones.
        - "cluster.outbound|80||catalog.istioinaction"
# 방법 2 추천 워크로드 단위로 설정 (어노테이션으로 포함할 Metric 지정)
cat ch7/webapp-deployment-stats-inclusion.yaml

kubectl apply -f  ch7/webapp-deployment-stats-inclusion.yaml -n istioinaction
...
  template:
    metadata:
      annotations:
        proxy.istio.io/config: |-
          proxyStatsMatcher:
            inclusionPrefixes:
            - "cluster.outbound|80||catalog.istioinaction"
      labels:
        app: webapp
# 호출테스트
curl -s http://webapp.istioinaction.io:30000/api/catalog | jq
kubectl exec -it deploy/webapp -c istio-proxy -n istioinaction -- curl localhost:15000/stats | grep catalog
# Upstream 클러스터로 향하는 Connection이나 요청에서 서킷 브레이커가 적용되는지 확인 가능
...
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_cx_active: 2
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_cx_total: 2
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_cx_tx_bytes_buffered: 0
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_rq_0rtt: 0
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_rq_200: 3
...
# East-West Traffic에 대한 Metric 확인 방법
kubectl exec -it deploy/webapp -c istio-proxy -n istioinaction -- curl localhost:15000/stats | grep catalog | grep internal
# Result
...
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.internal.upstream_rq_200: 3
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.internal.upstream_rq_2xx: 3
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.internal.upstream_rq_completed: 3
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_internal_redirect_failed_total: 0
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_internal_redirect_succeeded_total: 0
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.internal.upstream_rq_time: P0(nan,5) P25(nan,5.075) P50(nan,6.05) P75(nan,61.25) P90(nan,61.7) P95(nan,61.85) P99(nan,61.97) P99.5(nan,61.985) P99.9(nan,61.997) P100(nan,62)
...
# cluster_name.internal.*. Metric들을 보면 트래픽이 TLS로 UpStream Cluster로 이동 여부와 Coneection과 관련된 세부정보를 얻을 수 있습니다. 
kubectl exec -it deploy/webapp -c istio-proxy -n istioinaction -- curl localhost:15000/stats | grep catalog | grep ssl
# Result

...
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.ssl.no_certificate: 0
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.ssl.ocsp_staple_failed: 0
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.ssl.ocsp_staple_omitted: 0
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.ssl.ocsp_staple_requests: 0
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.ssl.ocsp_staple_responses: 0
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.ssl.session_reused: 1
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.ssl.sigalgs.rsa_pss_rsae_sha256: 2
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.ssl.versions.TLSv1.3: 2
...
# svc.cluster.local.upstream_cx* ,svc.cluster.local.upstream_rq* Metric들은 각각 Envoy의 Connection 상태 및 Request에 관한 Metric들을 나타냅니다. 

kubectl exec -it deploy/webapp -c istio-proxy -n istioinaction -- curl localhost:15000/stats | grep catalog | egrep 'local.upstream_cx|local.upstream_rq'
# Result
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_cx_total: 2
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_cx_tx_bytes_buffered: 0
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_cx_tx_bytes_total: 3852
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_rq_0rtt: 0
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_rq_200: 3
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_rq_2xx: 3
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_rq_active: 0
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_rq_cancelled: 0
cluster.outbound|80||catalog.istioinaction.svc.cluster.local.upstream_rq_completed: 3

이렇가 각각의 Istio-proxy 내부에 접근 하여 수집되고 있는 Metric 정보를 볼 수 있지만, 확인이 불편하기 때문에 Prometheus나 Datadog같은 Metric 수집 시스템에 저장을 하여 Metric을 확인 합니다.

Control Plane의 Metric

Istiod에서 많은 Metric들을 확인 할 수 있지만, 특정 Metric 만 알아보도록 하겠습니다.

# CSR : Certificate Signing Request 인증서 발급 요청
# Citadel : Istio 보안 컴포넌트
# 15014포트는 Metric 수집을 위해 노출된 포트입니다.
kubectl exec -it -n istio-system deploy/istiod -n istio-system -- curl localhost:15014/metrics | grep citadel
# Result
citadel_server_csr_count 5 # Control Plane으로 들어온 CSR 요청 갯수
citadel_server_root_cert_expiry_timestamp 2.061546606e+09 # 워크로드 인증서 만료 시점
citadel_server_success_cert_issuance_count 5 # 발급된 인증서 갯수
kubectl exec -it -n istio-system deploy/istiod -n istio-system -- curl localhost:15014/metrics | grep convergence
# Result
# le초 이내로 Istio-Proxy에 설정을 주입한 건수가 42개
pilot_proxy_convergence_time_bucket{le="0.1"} 42
pilot_proxy_convergence_time_bucket{le="0.5"} 42
pilot_proxy_convergence_time_bucket{le="1"} 42
pilot_proxy_convergence_time_bucket{le="3"} 42
pilot_proxy_convergence_time_bucket{le="5"} 42
pilot_proxy_convergence_time_bucket{le="10"} 42
pilot_proxy_convergence_time_bucket{le="20"} 42
pilot_proxy_convergence_time_bucket{le="30"} 42
pilot_proxy_convergence_time_bucket{le="+Inf"} 42
pilot_proxy_convergence_time_sum 0.086078397
pilot_proxy_convergence_time_count 42
kubectl exec -it -n istio-system deploy/istiod -n istio-system -- curl localhost:15014/metrics | grep pilot | egrep 'service|^pilot_xds'

# Result
pilot_services 7 # 현재 Control Plane에 등록된 Service 갯수
pilot_virt_services 1 # 사용자가 생성한 VirtualService 갯수
pilot_vservice_dup_domain 0 # 동일한 도메인을 사용하는 VirtualService의 갯수
pilot_xds{version="1.17.8"} 4 # 현재 Istio에 배포된 Istio-proxy의 갯수

3.Prometheus로 Istio Metric 가져오기

Prometheus란?

사운드 클라우드에서 시작된 Metric 수집 엔진 이며, 모니터링 및 얼럿 도구들의 집합 입니다.

Prometheus 는 다른 수집기와 다르게 저장소로 Metric을 Push로 보내는 방식이 아닌 pull 방식 으로 Metric을 가져옵니다.

Prometheus 는 HTTP 클라이언트나 브라우저를 통해 Metric EndPoint를 살펴 볼 수 있습니다.

Figure 3.1 Prometheus가 Metric을 수집하는 방식
# Prometheus가 수집하는 Metric Port 15090
kubectl exec -it deploy/webapp -c istio-proxy -n istioinaction -- curl localhost:15090/stats/prometheus
# Result
# Proemtheus가 이해할 수 있는 형식으로 Metric이 출력되는 것을 확인 할 수 있습니다.  
...
istio_response_bytes_count{reporter="source",source_workload="webapp",source_canonical_service="webapp",source_canonical_revision="latest",source_workload_namespace="istioinaction",source_principal="spiffe://cluster.local/ns/istioinaction/sa/webapp",source_app="webapp",source_version="",source_cluster="Kubernetes",destination_workload="catalog",destination_workload_namespace="istioinaction",destination_principal="spiffe://cluster.local/ns/istioinaction/sa/catalog",destination_app="catalog",destination_version="v1",destination_service="catalog.istioinaction.svc.cluster.local",destination_canonical_service="catalog",destination_canonical_revision="v1",destination_service_name="catalog",destination_service_namespace="istioinaction",destination_cluster="Kubernetes",request_protocol="http",response_code="200",grpc_response_status="",response_flags="-",connection_security_policy="unknown"} 3

Prometheus와 Grafna 설정하기


# 실습 준비 kube-prometheus-stack 설치

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

cat << EOF > prom-values-2.yaml
prometheusOperator:
  tls:
    enabled: false
  admissionWebhooks:
    patch:
      enabled: false

prometheus:
  service:
    type: NodePort
    nodePort: 30001

grafana:
  service:
    type: NodePort
    nodePort: 30002
EOF

kubectl create ns prometheus
helm install prom prometheus-community/kube-prometheus-stack --version 13.13.1 \
-n prometheus -f ch7/prom-values.yaml -f prom-values-2.yaml

# Prometheus 접속
wslview http://127.0.0.1:30001


# Grafana 접속
wslview http://127.0.0.1:30002

Prometheus의 Istio Control Plane과 Data Plane 정보 수집 설정

앞에서 설치한 Prometheus는 Istio의 Control Plane과 Data Plane의 정보를 가져가는 방법을 모르기 때문에 설정을 진행해보도록 하겠습니다.

이때 Prometheus의 Operator에 있는 CR ServiceMonitor, PodMonitor 를 이용하여 설정 진행 하겠습니다.

alt textalt text

 

alt text

Figure 3.2 Prometheus Operator 원리
cat ch7/service-monitor-cp.yaml
kubectl apply -f ch7/service-monitor-cp.yaml -n prometheus

# 호출 테스트
kubectl exec -it netshoot -- curl -s istiod.istio-system:15014/metrics
kubectl exec -it netshoot -- curl -s istiod.istio-system:15014/metrics | grep pilot_xds
kubectl exec -it netshoot -- curl -s istiod.istio-system:15014/metrics | grep citadel
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: istio-component-monitor
  namespace: prometheus
  labels:
    monitoring: istio-components
    release: prom
spec:
  jobLabel: istio
  targetLabels: [app]
  selector:
    matchExpressions:
    - {key: istio, operator: In, values: [pilot]}
  namespaceSelector:
    any: true
  endpoints:
  - port: http-monitoring # 15014
    interval: 15s

Figure 3.3 웹 접속 후 Control Plane Metric 수집 확인
cat ch7/pod-monitor-dp.yaml
kubectl apply -f ch7/pod-monitor-dp.yaml -n prometheus

# 접속 테스트
WEBAPP=$(kubectl get pod -n istioinaction -l app=webapp -o jsonpath='{.items[0].status.podIP}')
kubectl exec -it netshoot -- curl -s $WEBAPP:15020/stats/prometheus
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: envoy-stats-monitor
  namespace: prometheus
  labels:
    monitoring: istio-proxies
    release: prom
spec:
  selector:
    matchExpressions:
    - {key: istio-prometheus-ignore, operator: DoesNotExist}
  namespaceSelector:
    any: true
  jobLabel: envoy-stats
  podMetricsEndpoints:
  - path: /stats/prometheus
    interval: 15s
    relabelings:
    - action: keep
      sourceLabels: [__meta_kubernetes_pod_container_name]
      regex: "istio-proxy"
    - action: keep
      sourceLabels: [__meta_kubernetes_pod_annotationpresent_prometheus_io_scrape]
    - sourceLabels: [
    __address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
      action: replace
      regex: ([^:]+)(?::\d+)?;(\d+)
      replacement: $1:$2
      targetLabel: __address__
    - action: labeldrop
      regex: "__meta_kubernetes_pod_label_(.+)"
    - sourceLabels: [__meta_kubernetes_namespace]
      action: replace
      targetLabel: namespace
    - sourceLabels: [__meta_kubernetes_pod_name]
      action: replace
      targetLabel: pod_name

Figure 3.4 웹 접속 후 DataPlane Plane Metric 수집 확인

4.Istio 표준 Metric 커스터마이징하기

Istio는 Envoy Proxy SideCar에 플러그인을 을 이용하여 Metric 표시, 커스터마이징, 생성되는 방법들을 설정 할 수 있습니다.

커스터마이징을 하기 전에 우선 Metric, Dimension, Attribute 에 대한 개념을 우선 알아야 합니다.

Metric

  • 서비스 호출 간 Telemetry의 Counter, Gauge, Histogram, Distribution 과 같은 측정 값을 말합니다.
    • Counter: 항상 증가만 하는 누적 지표입니다.
    • Gauge: : 특정 시점의 값을 나타내는 지표입니다
    • Histogram, Distribution: 특정 값들의 분포 상태를 나타냅니다.

Dimension

  • Metric을 분류하기 위한 라벨 및 태그 를 의미합니다.
    • Ex) 요청 메서드(Request Method)별 요청 수를 알고 싶을 때 사용

Attribute

  • Envoy Proxy에서 수집된 원본 데이터 를 의미합니다.
    • Ex) request.code Dimension은 request.code Attribute를 기반으로 생성

Envoy에서 사용할 수 있는 속성

기존 Metric 수정하기

Istio Metric은 Istio 설치 시 설치되는 EnvoyFilter CRD 를 사용하여 stats Proxy 플러그인에서 설정합니다.

하단 예시의 Envoy Filter는 istio.stats 라는 필터를 직접 구성하는 예제이며, 해당 필터는 통계 기능 을 구현 하는 WASM 플러그인입니다.

kubectl get envoyfilter stats-filter-1.13 -n istio-system -o yaml
...
spec:
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_OUTBOUND
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: envoy.filters.http.router
      proxy:
        proxyVersion: ^1\.13.*
    patch:
      operation: INSERT_BEFORE
      value:
        name: istio.stats # 필터 이름
        typed_config:
          '@type': type.googleapis.com/udpa.type.v1.TypedStruct
          type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
          value:
            config: # 필터 설정
              configuration:
                '@type': type.googleapis.com/google.protobuf.StringValue
                value: |
                  {
                    "debug": "false",
                    "stat_prefix": "istio"
                  }
...

기존 Metric에 디멘션 추가하기

cat ch7/metrics/istio-operator-new-dimensions.yaml
# 기존 설정 확인
kubectl get istiooperator installed-state -n istio-system -o yaml | grep -E "prometheus:|telemetry:" -A2

# request_protocol 디멘션 확인
kubectl -n istioinaction exec -it deploy/webapp -c istio-proxy \
-- curl localhost:15000/stats/prometheus | grep istio_requests_total | grep request_protocol 
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: demo
  values:
    telemetry:
      v2:
        prometheus:
          configOverride:
            inboundSidecar:
              metrics:
              - name: requests_total
                dimensions: # 추가한 새 디멘션
                  upstream_proxy_version: upstream_peer.istio_version
                  source_mesh_id: node.metadata['MESH_ID']
                tags_to_remove: # 제거한 태그 목록
                - request_protocol
...
# Result
    telemetry:
      enabled: true
      v2:
--
        prometheus:
          enabled: true
          wasmEnabled: false

# Result 2
...
request_protocol="http" # 확인
# 설정 적용
docker exec -it myk8s-control-plane bash
# 파일 작성
cat << EOF > istio-operator-new-dimensions.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: demo
  values:
    telemetry:
      v2:
        prometheus:
          configOverride:
            inboundSidecar:
              metrics:
              - name: requests_total
                dimensions:
                  upstream_proxy_version: upstream_peer.istio_version
                  source_mesh_id: node.metadata['MESH_ID']
                tags_to_remove:
                - request_protocol
            outboundSidecar:
              metrics:
              - name: requests_total
                dimensions:
                  upstream_proxy_version: upstream_peer.istio_version
                  source_mesh_id: node.metadata['MESH_ID']
                tags_to_remove:
                - request_protocol
            gateway:
              metrics:
              - name: requests_total
                dimensions:
                  upstream_proxy_version: upstream_peer.istio_version
                  source_mesh_id: node.metadata['MESH_ID']
                tags_to_remove:
                - request_protocol
EOF
 # 리소스별로 적용결과를 출력
istioctl install -f istio-operator-new-dimensions.yaml -y

# 터미널 나오기
exit

# 변경사항 확인
kubectl get istiooperator -n istio-system installed-state -o yaml | grep -E "prometheus:" -A9
...
        prometheus:
          configOverride:
            gateway:
              metrics:
              - dimensions:
                  source_mesh_id: node.metadata['MESH_ID']
                  upstream_proxy_version: upstream_peer.istio_version
                name: requests_total
                tags_to_remove:
                - request_protocol
...
kubectl get envoyfilter stats-filter-1.13 -n istio-system -o yaml
...
        name: istio.stats
        typed_config:
          '@type': type.googleapis.com/udpa.type.v1.TypedStruct
          type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
          value:
            config:
              configuration:
                '@type': type.googleapis.com/google.protobuf.StringValue
                value: |
                  {"metrics":[{"dimensions":{"source_mesh_id":"node.metadata['MESH_ID']","upstream_proxy_version":"upstream_peer.istio_version"},"name":"requests_total","tags_to_remove":["request_protocol"]}]}
              root_id: stats_outbound
...
kubectl -n istioinaction exec -it deploy/webapp -c istio-proxy -- curl localhost:15000/stats/prometheus | grep istio_requests_total | grep request_protocol
# 수행 결과 출력 되지 않음

Telemetry 리소스로도 Dimension을 추가 및 삭제를 할 수 있습니다.

cat ch7/metrics/v2/add-dimensions-telemetry.yaml
kubectl apply -n istioinaction -f ch7/metrics/v2/add-dimensions-telemetry.yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
  name: add-dimension-tags
  namespace: istioinaction
spec:
  metrics:
  - providers:
      - name: prometheus
    overrides:
      - match:
          metric: REQUEST_COUNT
          mode: CLIENT_AND_SERVER
        disabled: false
        tagOverrides:
          upstream_proxy_version:
            operation: UPSERT
            value: upstream_peer.istio_version
          source_mesh_id:
            operation: UPSERT
            value: node.metadata['MESH_ID']
          request_protocol:
            operation: REMOVE

새로운 Metric 만들기

기존 Metric을 수정하는 것이 아닌, 신규 Metric을 생성 하는 경우 stats 플러그인에 새 Metric을 정의하여 생성 하면됩니다.

docker exec -it myk8s-control-plane bash
cat << EOF > istio-operator-new-metric.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: demo
  values:
    telemetry:
      v2:
        prometheus:
          configOverride:
            inboundSidecar:
              definitions:
              - name: get_calls # istio_ 접두사는 자동으로 붙음
                type: COUNTER # GAUGE, HISTOGRAM도 선택 가능
                value: "(request.method.startsWith('GET') ? 1 : 0)"
            outboundSidecar:
              definitions:
              - name: get_calls
                type: COUNTER
                value: "(request.method.startsWith('GET') ? 1 : 0)"
            gateway:
              definitions:
              - name: get_calls
                type: COUNTER
                value: "(request.method.startsWith('GET') ? 1 : 0)"
EOF

# 리소스별로 적용결과를 출력
istioctl verify-install -f istio-operator-new-metric.yaml istioctl install -f istio-operator-new-metric.yaml -y

# 출력 결과 확인
kubectl get envoyfilter -n istio-system stats-filter-1.13 -o yaml | grep get_calls

Figure 3.5 신규 Metric 수집 확인

새 속성으로 호출 그룹화 하기

기존 속성을기반으로 더 세분화 하거나, 응용하여 새로운 속성을 만들 수 있습니다.

이번 예제를 통해서는 request.path_url와 request.method 속성을 조합하여, Istio_operationId 속성을 만들 예정입니다.
해당 속성을 통해 GET 호출 갯수를 파악 할 수 있습니다.

 

그룹화를 하기 위해서는 Attribute-gen 이라는 Proxy 플러그인 을 사용하며 이 플러그인은 stats플러그인 보다 먼저 적용 됩니다.

# proxyVersion을 1.17로 변경
vi ch7/metrics/attribute-gen.yaml
      proxy:
        proxyVersion: ^1\.13.* # ^1\.17.*로 변경
cat ch7/metrics/attribute-gen.yaml
kubectl apply -f ch7/metrics/attribute-gen.yaml -n istioinaction

# istio_operationId 속성에 대하여 /item으로 오는 GET, POST, DELETE 요청들에 대한 호출 수집
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: attribute-gen-example
  namespace: istioinaction
spec:
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_OUTBOUND
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: istio.stats
...
 typed_config:
          '@type': type.googleapis.com/udpa.type.v1.TypedStruct
          type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
          value:
            config:
              configuration:
                '@type': type.googleapis.com/google.protobuf.StringValue
                value: |
                  {
                    "attributes": [
                      {
                        "output_attribute": "istio_operationId", # 속성 이름
                        "match": [
                         {
                           "value": "getitems", # 속성 값
                           "condition": "request.url_path == '/items' && request.method == 'GET'"
                         },
                         {
                           "value": "createitem",
                           "condition": "request.url_path == '/items' && request.method == 'POST'"
                         },     
                         {
                           "value": "deleteitem",
                           "condition": "request.url_path == '/items' && request.method == 'DELETE'"
                         }                                             
                       ]
                      }
                    ]
                  }
              vm_config:
                code:
                  local:
                    inline_string: envoy.wasm.attributegen
# stats 플러그인 설정 업데이트
docker exec -it myk8s-control-plane bash

cat << EOF > istio-operator-new-attribute.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: demo
  values:
    telemetry:
      v2:
        prometheus:
          configOverride:
            outboundSidecar:
              metrics:
              - name: requests_total
                dimensions:
                  upstream_operation: istio_operationId # 새 디멘션에 추가
EOF
# 리소스별로 적용결과를 출력
istioctl verify-install -f istio-operator-new-attribute.yaml 

# stats 플러그인 업데이트 적용
istioctl install -f istio-operator-new-attribute.yaml -y

# OutboundSidecar에만 적용되는 것 확인
kubectl get istiooperator -n istio-system installed-state -o yaml | grep -B2 -A1 istio_operationId$

# 호출테스트
for in in {1..100}; do curl -s http://webapp.istioinaction.io:30000/api/catalog ; sleep 0.5; done
# OutboundSidecar Result
              metrics:
              - dimensions:
                  upstream_operation: istio_operationId
                name: requests_total

Figure 3.6 신규 그룹화 Metric 수집 확인