Ssoon
[4주차] 관찰 가능성(서비스 동작 이해) : Istio의 표준 메트릭 사용자 지정 본문
📊 Istio의 표준 메트릭 커스터마이징하기
Istio는 서비스 간 통신을 모니터링하기 위해 기본적으로 제공되는 표준 메트릭을 통해 강력한 observability를 지원합니다.
📋 Istio 표준 메트릭 이해하기
- Istio는 서비스 간 통신에서 발생하는 다양한 메트릭을 자동으로 수집합니다. 대표적인 표준 메트릭은 다음과 같습니다:
Metric Name | Type | Description |
istio_requests_total | Counter | 각 요청마다 증가하는 카운터 |
istio_request_duration_milliseconds | Distribution | 요청 처리 시간의 분포 |
istio_request_bytes | Distribution | 요청 본문 크기의 분포 |
istio_response_bytes | Distribution | 응답 본문 크기의 분포 |
istio_request_messages_total (gRPC) | Counter | 클라이언트에서 받은 메시지 수를 나타내는 카운터 (gRPC) |
istio_response_messages_total (gRPC) | Counter | 서버에서 보낸 메시지 수를 나타내는 카운터 (gRPC) |
- 예를 들어, istio_requests_total은 서비스로 들어오거나 나가는 요청 수를 카운트하는 counter 메트릭입니다.
- Istio는 Envoy proxy의 플러그인을 활용해 메트릭을 생성, 표시, 커스터마이징합니다.
- 이를 이해하려면 메트릭의 세 가지 핵심 개념을 알아야 합니다: Metric, Dimension, Attribute.
Istio의 표준 메트릭은 서비스 통신을 모니터링하기 위한 기본 도구입니다.
🔍 메트릭, Dimension, Attribute란?
- Istio 메트릭을 커스터마이징하기 위해 다음 세 가지 개념을 이해하는 것이 중요합니다.
1️⃣ Metric
- Metric은 서비스 간 통신에서 발생하는 telemetry 데이터를 수집하는 단위입니다. 메트릭에는 세 가지 유형이 있습니다:
- Counter: 증가만 하는 값(예: istio_requests_total은 요청 수를 카운트).
- Gauge: 변동하는 값(예: 현재 활성 연결 수).
- Histogram/Distribution: 데이터 분포를 기록(예: 요청 소요 시간).
- 예를 들어, istio_requests_total은 서비스로 들어오는(inbound) 또는 나가는(outbound) 요청 수를 기록합니다. 서비스가 양방향 요청을 처리하면 두 개의 별도 메트릭 항목이 생성됩니다.
2️⃣ Dimension
- Dimension은 메트릭을 세분화하는 속성입니다. 예를 들어, istio_requests_total 메트릭은 다음과 같은 dimension을 가질 수 있습니다:
- response_code: HTTP 응답 코드(예: 200, 500).
- reporter: 메트릭을 보고하는 주체(예: destination, source).
- destination_service: 요청 대상 서비스(예: webapp.istioinaction.svc.cluster.local).
- connection_security_policy: 보안 정책(예: mutual_tls).
- Dimension이 다르면 동일한 메트릭이라도 별도의 항목으로 표시됩니다. 아래는 istio_requests_total 메트릭의 예입니다: response_code가 다르므로 두 개의 별도 메트릭 항목이 생성됩니다.
istio_requests_total{
response_code="200",
reporter="destination",
source_workload="istio-ingressgateway",
destination_workload="webapp",
request_protocol="http",
connection_security_policy="mutual_tls"
}
istio_requests_total{
response_code="500",
reporter="destination",
source_workload="istio-ingressgateway",
destination_workload="webapp",
request_protocol="http",
connection_security_policy="mutual_tls"
}
3️⃣ Attribute
- Attribute는 Envoy proxy가 런타임에 생성하는 데이터로, dimension의 값을 채우는 데 사용됩니다.
Envoy는 다양한 attribute를 기본 제공하며, Istio는 추가적인 attribute를 제공합니다.
Attribute | Description |
request.path | URL의 경로(path) 부분 |
request.url_path | 쿼리 문자열을 제외한 URL의 경로(path) 부분 |
request.host | URL의 호스트(host) 부분 |
request.scheme | URL의 스킴(scheme) 부분 (예: "http") |
request.method | 요청 메서드 (예: "GET") |
request.headers | 소문자로 변환된 이름을 키로 하는 모든 요청 헤더 |
request.referer | Referer 요청 헤더 |
request.useragent | User-Agent 요청 헤더 |
request.time | 첫 번째 바이트가 수신된 시간 |
request.id | x-request-id 헤더 값에 해당하는 요청 ID |
request.protocol | 요청 프로토콜 |
- Envoy의 기본 attribute 외에도 Istio의 peer-metadata filter를 통해 추가 attribute를 사용할 수 있습니다. 예를 들어:
- upstream_peer.cluster_id: 업스트림 서비스의 클러스터 ID.
- downstream_peer.istio_version: 다운스트림 Istio proxy의 버전.
Attribute | Description |
name | Pod의 이름 |
namespace | Pod가 실행 중인 네임스페이스 |
labels | 워크로드 라벨 |
owner | 워크로드 소유자 |
workload_name | 워크로드 이름 |
platform_metadata | 접두사가 붙은 키를 가진 플랫폼 메타데이터 |
istio_version | 프록시의 버전 식별자 |
mesh_id | 메시의 고유 식별자 |
cluster_id | 해당 워크로드가 속한 클러스터의 식별자 |
app_containers | 애플리케이션 컨테이너의 짧은 이름 목록 |
.
- Attribute는 upstream_peer 또는 downstream_peer 접두사를 사용해 참조합니다.
예를 들어, 호출자의 Istio 버전을 참조하려면 downstream_peer.istio_version을 사용합니다.
Metric은 데이터를 수집하고, dimension은 데이터를 분류하며, attribute는 dimension의 값을 제공합니다.
🛠️ 메트릭 커스터마이징하기
- Istio에서는 attribute를 활용해 메트릭의 dimension을 커스터마이징할 수 있습니다.
예를 들어, istio_requests_total 메트릭에 새로운 dimension을 추가하거나 기존 dimension의 값을 변경할 수 있습니다. - 커스터마이징은 Envoy proxy의 설정을 수정하거나 Istio의 Telemetry API를 사용해 수행합니다. 구체적인 방법은 다음과 같습니다:
- 속성 선택: 사용할 attribute(예: downstream_peer.istio_version)를 결정합니다.
- Dimension 정의: 메트릭에 추가할 dimension을 설정합니다.
- 설정 적용: Istio의 Telemetry 리소스나 Envoy 필터 설정을 업데이트합니다.
- 이 과정은 Istio의 설정 파일이나 Kubernetes 리소스를 통해 구성됩니다.
Attribute를 사용해 메트릭의 dimension을 커스터마이징하면 더 세밀한 모니터링이 가능합니다.
📌 핵심 요약
- 표준 메트릭: istio_requests_total 같은 메트릭은 서비스 통신의 기본 telemetry를 제공합니다.
- Metric, Dimension, Attribute:
- Metric: Counter, Gauge, Histogram 등으로 데이터를 수집.
- Dimension: 메트릭을 세분화하는 속성(예: response_code, destination_service).
- Attribute: Envoy와 Istio가 제공하는 런타임 데이터로 dimension 값을 채움.
- Attribute 종류: Envoy의 기본 attribute와 Istio의 peer-metadata filter를 통해 제공되는 attribute를 사용.
- 커스터마이징: Attribute를 활용해 메트릭의 dimension을 사용자 정의하여 원하는 데이터를 수집.
- 다음 단계: 설정 파일을 수정해 실제로 메트릭을 커스터마이징합니다.
📊 기존 Istio 메트릭 설정하기
Istio의 메트릭은 기본적으로 Envoy proxy의 stats 플러그인을 통해 구성되며, 이를 커스터마이징하여 원하는 데이터를 수집할 수 있습니다.
🔍 Istio의 기본 메트릭 설정 확인
- Istio를 설치하면 기본적으로 EnvoyFilter 리소스를 통해 메트릭 관련 설정이 적용됩니다.
이 설정은 Envoy proxy의 stats 플러그인을 사용해 메트릭을 생성합니다.
설치된 EnvoyFilter를 확인하려면 다음 명령어를 실행하세요:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl get envoyfilter -n istio-system
NAME AGE
stats-filter-1.13 3h4m
stats-filter-1.14 3h4m
stats-filter-1.15 3h4m
stats-filter-1.16 3h4m
stats-filter-1.17 3h4m
tcp-stats-filter-1.13 3h4m
tcp-stats-filter-1.14 3h4m
tcp-stats-filter-1.15 3h4m
tcp-stats-filter-1.16 3h4m
tcp-stats-filter-1.17 3h4m
- stats-filter-1.13을 살펴보면 아래와 같은 설정을 확인할 수 있습니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl get envoyfilter stats-filter-1.13 -n istio-system -o yaml
...
spec:
configPatches:
- applyTo: HTTP_FILTER #HTTP 필터 레벨에서 수정
match:
context: SIDECAR_OUTBOUND #사이드카 프록시가 바깥쪽으로 요청을 보낼 때 적용
listener:
filterChain:
filter:
name: envoy.filters.network.http_connection_manager
#HTTP 요청을 관리하는 기본 핸들러인 http_connection_manager 필터를 찾아서 수정
subFilter:
name: envoy.filters.http.router
#router 필터 앞에 끼워 넣습니다.
proxy:
proxyVersion: ^1\.13.* #proxyVersion이 1.13대 버전인 프록시(Envoy)만 대상
patch:
operation: INSERT_BEFORE #router 필터 바로 전에 새 필터를 삽입(INSERT_BEFORE)
value:
name: istio.stats #삽입할 필터 이름은 istio.stats
typed_config:
'@type': type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
#Envoy에 Wasm으로 작성된 프로그램을 집어넣는 방식
value:
config:
configuration:
'@type': type.googleapis.com/google.protobuf.StringValue
# Wasm 프로그램의 설정(configuration)
value: |
{
"debug": "false", #디버그 모드를 끄고
"stat_prefix": "istio" #모든 수집한 메트릭 이름 앞에 istio_ 를 붙입니다.
}
root_id: stats_outbound #Wasm 필터를 식별하는 고유 ID
vm_config:
code:
local:
inline_string: envoy.wasm.stats
#사용하려는 Wasm 코드가 envoy.wasm.stats 라는 이름으로 Envoy 안에 내장
runtime: envoy.wasm.runtime.null #null runtime을 사용
vm_id: stats_outbound
#실제 Wasm을 실행하는 건 아니고, Envoy에 이미 C++로 포팅된 버전을 "Wasm처럼" 실행
...
- 이 설정은 istio.stats라는 WebAssembly(Wasm) 플러그인을 정의합니다.
- 이 플러그인은 Envoy 코드베이스에 직접 컴파일되어 별도의 Wasm VM 없이 실행됩니다.
- Wasm VM에서 실행하려면 설치 시 --set values.telemetry.v2.prometheus.wasmEnabled=true 플래그를 추가해야 합니다.
Istio의 기본 메트릭은 EnvoyFilter를 통해 stats 플러그인으로 설정됩니다.
🛠️ 기존 메트릭에 새로운 Dimension 추가
istio_requests_total 메트릭에 새로운 dimension을 추가하여 더 세밀한 모니터링을 구현해보겠습니다. 예를 들어, 업그레이드 추적을 위해 업스트림 프록시의 버전(upstream_proxy_version)과 소스 메쉬 ID(source_mesh_id)를 추가하고, 불필요한 request_protocol dimension을 제거하겠습니다.
📝 IstioOperator로 Dimension 설정
- 아래는 새로운 dimension을 추가하는 IstioOperator 설정입니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ cat ch7/metrics/istio-operator-new-dimensions.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
profile: demo #demo 프로파일을 기반으로 설치
values:
telemetry:
v2: #telemetry v2 을 설정
prometheus:
configOverride: #기본 Prometheus 메트릭 수집 방식을 오버라이드(수정)
inboundSidecar: #파드(사이드카)로 들어오는 트래픽에 대해 설정.
metrics:
- name: requests_total #기본 requests_total 메트릭을 수정.
dimensions:
upstream_proxy_version: upstream_peer.istio_version #요청을 보낸 쪽(upstream)의 Istio 버전을 메트릭 라벨로 추가
source_mesh_id: node.metadata['MESH_ID'] #요청을 보낸 쪽 사이드카의 MESH_ID 메타데이터를 메트릭 라벨로 추가
tags_to_remove:
- request_protocol #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: #Istio 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
- 이 설정은 다음과 같은 작업을 수행합니다:
- requests_total 메트릭에 upstream_proxy_version과 source_mesh_id dimension을 추가.
- request_protocol dimension을 제거.
- inboundSidecar, outboundSidecar, gateway에 동일한 설정을 적용.
🚀 설정 적용
- 다음 명령어로 IstioOperator 설정을 적용합니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ docker exec -it myk8s-control-plane bash
root@myk8s-control-plane:/#
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ docker exec -it myk8s-control-plane bash
root@myk8s-control-plane:/#
root@myk8s-control-plane:/# 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
root@myk8s-control-plane:/# istioctl install -f istio-operator-new-dimensions.yaml -y
✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
- Pruning removed resources Removed HorizontalPodAutoscaler:istio-system:istiod.
Removed HorizontalPodAutoscaler:istio-system:istio-ingressgateway.
✔ Installation complete Making this installation the default for injection and validation.
Thank you for installing Istio 1.17. Please take a few minutes to tell us about your install/upgrade experience! https://forms.gle/hMHGiwZHPU7UQRWe9
- 적용 후, istioctl은 내부적으로 stats-filter-1.13 EnvoyFilter를 업데이트합니다.
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl get envoyfilter stats-filter-1.13 -n istio-system -o yaml
...
patch:
operation: INSERT_BEFORE
...
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
vm_config:
code:
local:
inline_string: envoy.wasm.stats
runtime: envoy.wasm.runtime.null
vm_id: stats_outbound
- applyTo: HTTP_FILTER
...
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_inbound
vm_config:
code:
local:
inline_string: envoy.wasm.stats
runtime: envoy.wasm.runtime.null
vm_id: stats_inbound
- applyTo: HTTP_FILTER
...
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"]}]}
...
Figure: Behind the Scenes
IstioOperator를 통해 새로운 dimension을 추가하면 stats-filter-1.13 EnvoyFilter가 자동으로 업데이트됩니다.
IstioOperator를 사용해 새로운 dimension을 추가하고 불필요한 dimension을 제거합니다.
🔧 Pod에 Annotation 추가
- 새로운 dimension이 메트릭에 반영되려면 Istio proxy가 이를 인식하도록 Pod에 annotation을 추가해야 합니다. 이 annotation은 deployment의 spec.template.metadata에 추가됩니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ cat ch7/metrics/webapp-deployment-extrastats.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: webapp
name: webapp
spec:
replicas: 1
selector:
matchLabels:
app: webapp
template:
metadata:
annotations:
proxy.istio.io/config: |-
#사이드카 proxy의 설정을 커스터마이즈 하겠다; EnvoyFilter나 텔레메트리 설정을 별도로 건드리지 않고 Pod별로 적용
extraStatTags: #Envoy가 수집하는 메트릭(stat) 에 추가 태그(dimension) 를 붙이라는 의미
- "upstream_proxy_version" #upstream_proxy_versio 라는 라벨을 추가
- "source_mesh_id" #source_mesh_id 라는 라벨을 추가
labels:
app: webapp
spec:
containers:
- env:
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: istioinaction/webapp:latest
imagePullPolicy: IfNotPresent
name: webapp
ports:
- containerPort: 8080
name: http
protocol: TCP
securityContext:
privileged: false
- 이 설정을 적용합니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl apply -n istioinaction -f ch7/metrics/webapp-deployment-extrastats.yaml
deployment.apps/webapp configured
Pod annotation을 추가해 새로운 dimension을 Istio proxy에 반영합니다.
🌊 메트릭 생성 및 확인
- 설정을 적용한 후, 서비스에 요청을 보내 메트릭을 생성합니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ for in in {1..10}; do curl -s http://webapp.istioinaction.io:30000/api/catalog ; sleep 0.5; done
- webapp 서비스의 Istio proxy에서 메트릭을 확인합니다.
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl -n istioinaction exec -it deploy/webapp -c istio-proxy \
-- curl localhost:15000/stats/prometheus | grep istio_requests_total
# TYPE istio_requests_total counter
istio_requests_total{reporter="destination",source_workload="istio-ingressgateway",source_canonical_service="istio-ingressgateway",source_canonical_revision="latest",source_workload_namespace="istio-system",source_principal="spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account",source_app="istio-ingressgateway",source_version="unknown",source_cluster="Kubernetes",destination_workload="webapp",destination_workload_namespace="istioinaction",destination_principal="spiffe://cluster.local/ns/istioinaction/sa/webapp",destination_app="webapp",destination_version="",destination_service="webapp.istioinaction.svc.cluster.local",destination_canonical_service="webapp",destination_canonical_revision="latest",destination_service_name="webapp",destination_service_namespace="istioinaction",destination_cluster="Kubernetes",response_code="200",grpc_response_status="",response_flags="-",connection_security_policy="mutual_tls",source_mesh_id="cluster.local",upstream_proxy_version="unknown"} 83
istio_requests_total{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",response_code="200",grpc_response_status="",response_flags="-",connection_security_policy="unknown",source_mesh_id="cluster.local",upstream_proxy_version="1.17.8"} 83
- 출력에서 upstream_proxy_version과 source_mesh_id가 추가되고, request_protocol이 제거된 것을 확인할 수 있습니다.
새로운 dimension이 포함된 메트릭을 생성하고 확인합니다.
🆕 새로운 Telemetry API 사용
- Istio 1.12부터 도입된 Telemetry API를 사용하면 메트릭 설정을 더 유연하게 제어할 수 있습니다. IstioOperator는 글로벌 설정을 변경하지만, Telemetry API는 특정 namespace 또는 workload에만 적용할 수 있습니다.
Figure: Telemetry API
Telemetry API는 Istio 1.13 기준 alpha 단계로, 변경될 수 있습니다. 자세한 내용은 Istio 문서를 참조하세요.
- Telemetry API를 사용한 설정 예시는 다음과 같습니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ cat 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
Telemetry API를 사용하면 특정 namespace나 workload에 메트릭 설정을 세밀하게 적용할 수 있습니다.
📌 핵심 요약
- 기본 설정: Istio는 EnvoyFilter(stats-filter-1.13)를 통해 메트릭을 stats 플러그인으로 구성.
- Dimension 추가: IstioOperator를 사용해 upstream_proxy_version, source_mesh_id 같은 새로운 dimension을 추가하고 request_protocol을 제거.
- Pod Annotation: extraStatTags annotation을 Pod에 추가해 새로운 dimension을 반영.
- 메트릭 확인: 서비스 요청 후 proxy에서 메트릭을 확인해 새로운 dimension이 적용되었는지 검증.
- Telemetry API: 특정 namespace나 workload에 메트릭 설정을 적용하는 유연한 방법 제공.
📈 새로운 Istio 메트릭 생성하기
Istio에서는 기존 메트릭의 dimension을 커스터마이징하는 것뿐만 아니라, 새로운 메트릭을 직접 정의할 수도 있습니다. 예를 들어, HTTP GET 요청 수를 카운트하는 istio_get_calls 메트릭을 생성하는 과정을 단계별로 다룹니다.
🛠️ 새로운 메트릭 정의하기
- Istio의 stats 플러그인을 활용하면 새로운 메트릭을 정의할 수 있습니다.
여기서는 HTTP GET 요청 수를 카운트하는 istio_get_calls 메트릭을 생성합니다.
이 메트릭은 IstioOperator 설정을 통해 구성됩니다.
📝 IstioOperator로 메트릭 정의
- 아래는 새로운 메트릭을 정의하는 IstioOperator 설정입니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ cat ch7/metrics/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
type: COUNTER #숫자를 하나씩 증가시키는 타입
value: "(request.method.startsWith('GET') ? 1 : 0)"
#request.method가 GET으로 시작하면 1, 아니면 0으로 기록; GET 요청만 세겠다
outboundSidecar: #나가는 요청(보내는 쪽)
definitions:
- name: get_calls
type: COUNTER
value: "(request.method.startsWith('GET') ? 1 : 0)"
gateway: #Istio Ingress/Egress Gateway 트래픽
definitions:
- name: get_calls
type: COUNTER
value: "(request.method.startsWith('GET') ? 1 : 0)"
- 이 설정의 주요 내용을 살펴보면:
- name: 메트릭 이름은 get_calls로 정의하며, Istio가 자동으로 istio_ 접두사를 추가해 istio_get_calls로 생성됩니다.
- type: 메트릭 유형은 COUNTER로 설정하며, GAUGE와 HISTOGRAM도 가능합니다.
- value: Common Expression Language(CEL, 공식 문서)를 사용해 메트릭 값을 정의합니다. 여기서는 request.method가 'GET'으로 시작하면 1을, 아니면 0을 반환합니다.
🚀 설정 적용
- 다음 명령어로 IstioOperator 설정을 적용합니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ docker exec -it myk8s-control-plane bash
root@myk8s-control-plane:/# 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
type: COUNTER
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
root@myk8s-control-plane:/# istioctl install -f istio-operator-new-metric.yaml -y
✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
✔ Installation complete Making this installation the default for injection and validation.
Thank you for installing Istio 1.17. Please take a few minutes to tell us about your install/upgrade experience! https://forms.gle/hMHGiwZHPU7UQRWe9
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl get istiooperator -n istio-system installed-state -o yaml | grep -A2 get_calls$
- name: get_calls
type: COUNTER
value: '(request.method.startsWith(''GET'') ? 1 : 0)'
--
- name: get_calls
type: COUNTER
value: '(request.method.startsWith(''GET'') ? 1 : 0)'
--
- name: get_calls
type: COUNTER
value: '(request.method.startsWith(''GET'') ? 1 : 0)'
- 이 명령은 inboundSidecar, outboundSidecar, gateway에 새로운 istio_get_calls 메트릭을 추가합니다.
IstioOperator를 사용해 새로운 메트릭 istio_get_calls를 정의하고 적용합니다.
🔧 Pod에 Annotation 추가
- 새로운 메트릭이 Istio proxy에서 노출되려면 Pod에 sidecar.istio.io/statsInclusionPrefixes annotation을 추가해야 합니다. 이 annotation은 deployment의 spec.template.metadata에 설정됩니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ cat ch7/metrics/webapp-deployment-new-metric.yaml
...
template:
metadata:
annotations:
proxy.istio.io/config: |-
proxyStatsMatcher:
inclusionPrefixes:
- "istio_get_calls"
labels:
app: webapp
...
- 이 설정을 적용합니다:
- 이 annotation은 Istio proxy가 istio_get_calls 메트릭을 Prometheus로 노출하도록 지시합니다.
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl -n istioinaction apply -f ch7/metrics/webapp-deployment-new-metric.yaml
deployment.apps/webapp configured
Pod annotation을 추가해 새로운 메트릭을 Istio proxy에 노출합니다.
🌊 메트릭 생성 및 확인
- 설정을 적용한 후, 서비스에 HTTP GET 요청을 보내 메트릭을 생성합니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ for in in {1..10}; do curl -s http://webapp.istioinaction.io:30000/api/catalog ; sleep 0.5; done
- webapp 서비스의 Istio proxy에서 메트릭을 확인합니다.
- istio_get_calls 메트릭이 생성되었으며, 현재까지 GET 메서드 요청이 160번 있었다는 의미입니다.
현재는 dimension이 설정되지 않았으므로 메트릭만 표시됩니다.
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl -n istioinaction exec -it deploy/webapp -c istio-proxy -- curl localhost:15000/stats/prometheus | grep istio_get_calls
# TYPE istio_get_calls counter
istio_get_calls{} 160
서비스 요청을 보내 새로운 메트릭을 생성하고 proxy에서 확인합니다.
🔍 더 세밀한 메트릭 생성 가능성
- 시스템 내 모든 GET 요청 수를 카운트하는 간단한 메트릭을 생성했습니다.
하지만 Istio의 stats 플러그인은 더 세밀한 메트릭을 생성할 수 있는 강력한 기능을 제공합니다.
예를 들어, catalog 서비스의 /items 엔드포인트로 들어오는 GET 요청만 카운트하려면 다음과 같이 CEL 표현식을 수정할 수 있습니다:
value: "(request.method.startsWith('GET') && request.path.startsWith('/items') ? 1 : 0)"
- 이처럼 새로운 dimension과 attribute를 추가해 원하는 조건에 맞는 메트릭을 정의할 수 있습니다.
Istio stats 플러그인은 CEL을 사용해 세밀한 메트릭을 생성할 수 있습니다.
📌 핵심 요약
- 새로운 메트릭 정의: IstioOperator를 사용해 istio_get_calls 메트릭을 정의하며, CEL로 GET 요청 수를 카운트.
- Pod Annotation: statsInclusionPrefixes annotation을 추가해 새로운 메트릭을 proxy에 노출.
- 메트릭 확인: 서비스 요청 후 proxy에서 istio_get_calls 메트릭을 확인.
- 확장 가능성: CEL과 attribute를 활용해 특정 엔드포인트나 조건에 맞는 세밀한 메트릭 생성 가능.
- 다음 단계: dimension과 attribute를 추가해 메트릭을 더 커스터마이징.
📊 새로운 Attribute로 Istio 호출 그룹화하기
Istio에서는 기존 attribute를 조합해 새로운 attribute를 만들어 메트릭을 더 세밀하게 관리할 수 있습니다.
🛠️ 새로운 Attribute 생성하기
- Istio의 attribute-gen 플러그인을 사용하면 기존 attribute를 조합해 새로운 attribute를 생성할 수 있습니다.
- request.url_path와 request.method를 조합해 /items 엔드포인트에 대한 GET, POST, DELETE 요청을 구분하는 istio_operationId attribute를 만듭니다.
📝 Attribute-gen 플러그인 설정
- 아래는 attribute-gen 플러그인을 설정하는 EnvoyFilter의 주요 부분입니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ cat ch7/metrics/attribute-gen.yaml
...
patch:
operation: INSERT_BEFORE
value:
name: istio.attributegen
#필터 이름은 istio.attributegen
typed_config:
'@type': type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
#Envoy의 Wasm 플러그인을 이용해서 동작
value:
config:
configuration:
'@type': type.googleapis.com/google.protobuf.StringValue
value: |
{
"attributes": [
{
"output_attribute": "istio_operationId", #생성할 Attribute 이름은 istio_operationId
"match": [ #요청 URL과 메서드에 따라 istio_operationId 값을 다르게 설정
{
"value": "getitems", #생성되는 Attribute 값
"condition": "request.url_path == '/items' && request.method == 'GET'"
},
{
"value": "createitem", #생성되는 Attribute 값
"condition": "request.url_path == '/items' && request.method == 'POST'"
},
{
"value": "deleteitem", #생성되는 Attribute 값
"condition": "request.url_path == '/items' && request.method == 'DELETE'"
}
]
}
]
}
...
- output_attribute: 새로운 attribute 이름(istio_operationId)을 정의.
- match: 조건에 따라 istio_operationId의 값을 설정.
- /items에 대한 GET 요청은 getitems.
- /items에 대한 POST 요청은 createitem.
- /items에 대한 DELETE 요청은 deleteitem.
🚀 EnvoyFilter 적용
- attribute-gen.yaml 을 적용하기 전에 proxyVersion: ^1\.16.* 을 설치된 istio 버전에 맞게 1.16 혹은 1.17 로 수정.
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ docker exec -it myk8s-control-plane istioctl version
client version: 1.17.8
control plane version: 1.17.8
data plane version: 1.17.8 (4 proxies)
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ vi ch7/metrics/attribute-gen.yaml
...
proxy:
proxyVersion: ^1\.17.*
- 다음 명령어로 EnvoyFilter를 적용해 webapp 서비스의 outbound 호출에 attribute-gen 플러그인을 추가합니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl apply -f ch7/metrics/attribute-gen.yaml -n istioinaction
envoyfilter.networking.istio.io/attribute-gen-example created
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl get envoyfilter -n istioinaction
NAME AGE
attribute-gen-example 19s
attribute-gen 플러그인을 사용해 새로운 istio_operationId attribute를 생성합니다.
📈 새로운 Dimension으로 메트릭 확장
- 새로운 istio_operationId attribute를 활용해 istio_requests_total 메트릭에 upstream_operation dimension을 추가합니다. 이를 통해 /items API 호출을 더 세밀하게 추적할 수 있습니다.
📝 Stats 플러그인 설정
- 아래는 upstream_operation dimension을 추가하는 IstioOperator 설정입니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ cat ch7/metrics/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 #기본 제공 메트릭인 requests_total 을 수정
dimensions:
upstream_operation: istio_operationId
#requests_total 메트릭에 새로운 Dimension (라벨) upstream_operation을 추가
#이 upstream_operation 값은 요청에 붙은 istio_operationId Attribute 값을 사용
🚀 설정 적용
- 다음 명령어로 새로운 dimension 설정을 적용합니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ docker exec -it myk8s-control-plane bash
root@myk8s-control-plane:/# 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
root@myk8s-control-plane:/# istioctl install -f istio-operator-new-attribute.yaml -y
✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
✔ Installation complete Making this installation the default for injection and validation.
Thank you for installing Istio 1.17. Please take a few minutes to tell us about your install/upgrade experience! https://forms.gle/hMHGiwZHPU7UQRWe9
새로운 upstream_operation dimension을 istio_requests_total 메트릭에 추가합니다.
🔧 Pod에 Annotation 추가
- 새로운 dimension이 메트릭에 반영되려면 Pod에 extraStatTags annotation을 추가해야 합니다.
이 annotation은 deployment의 spec.template.metadata에 설정됩니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ cat ch7/metrics/webapp-deployment-extrastats-new-attr.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: webapp
name: webapp
spec:
replicas: 1
selector:
matchLabels:
app: webapp
template:
metadata:
annotations:
proxy.istio.io/config: |-
extraStatTags:
- "upstream_operation"
labels:
app: webapp
spec:
containers:
- env:
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: istioinaction/webapp:latest
imagePullPolicy: IfNotPresent
name: webapp
ports:
- containerPort: 8080
name: http
protocol: TCP
securityContext:
privileged: false
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl -n istioinaction apply -f ch7/metrics/webapp-deployment-extrastats-new-attr.yaml
deployment.apps/webapp configured
- 이 설정은 Istio proxy가 upstream_operation dimension을 포함한 메트릭을 생성하도록 지시합니다.
Pod annotation을 추가해 새로운 dimension을 Istio proxy에 반영합니다.
🌊 메트릭 생성 및 확인
- 설정을 적용한 후, 서비스에 요청을 보내 메트릭을 생성합니다:
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ for in in {1..10}; do curl -s http://webapp.istioinaction.io:30000/api/catalog ; sleep 0.5; done
- webapp 서비스의 Istio proxy에서 메트릭을 확인합니다.
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-QMAIJOE:~/aews-labs/istio-in-action/book-source-code-master$ kubectl -n istioinaction exec -it deploy/webapp -c istio-proxy -- curl localhost:15000/stats/prometheus | grep istio_requests_total
# TYPE istio_requests_total counter
istio_requests_total{reporter="destination",source_workload="istio-ingressgateway",source_canonical_service="istio-ingressgateway",source_canonical_revision="latest",source_workload_namespace="istio-system",source_principal="spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account",source_app="istio-ingressgateway",source_version="unknown",source_cluster="Kubernetes",destination_workload="webapp",destination_workload_namespace="istioinaction",destination_principal="spiffe://cluster.local/ns/istioinaction/sa/webapp",destination_app="webapp",destination_version="",destination_service="webapp.istioinaction.svc.cluster.local",destination_canonical_service="webapp",destination_canonical_revision="latest",destination_service_name="webapp",destination_service_namespace="istioinaction",destination_cluster="Kubernetes",request_protocol="http",response_code="200",grpc_response_status="",response_flags="-",connection_security_policy="mutual_tls"} 10
istio_requests_total{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",upstream_operation="getitems"} 10
- 출력에서 upstream_operation="getitems"가 추가된 것을 확인할 수 있습니다. 이는 /items 엔드포인트로의 GET 요청이 추적되고 있음을 보여줍니다.
새로운 dimension이 포함된 메트릭을 생성하고 proxy에서 확인합니다.
📚 Istio 메트릭의 중요성
- 마이크로서비스 아키텍처에서는 서비스 간 네트워크 통신이 많아질수록 문제가 발생할 가능성이 높아집니다. Istio는 개발자가 애플리케이션 코드에 별도의 로직을 추가하지 않아도 golden-signal metrics(latency, throughput, errors, saturation)를 수집할 수 있게 해줍니다.
- Istio는 성공률, 실패율, 재시도 횟수, 레이턴시 같은 네트워크 메트릭을 자동으로 수집하며, 애플리케이션 또는 비즈니스 레벨 메트릭과 함께 사용할 수 있습니다.
Istio는 golden-signal metrics를 자동으로 수집해 마이크로서비스 모니터링을 간소화합니다.
📌 핵심 요약
- 새로운 Attribute: attribute-gen 플러그인을 사용해 istio_operationId attribute를 생성해 /items API 호출을 구분.
- 새로운 Dimension: istio_requests_total 메트릭에 upstream_operation dimension을 추가해 호출을 세밀하게 추적.
- Pod Annotation: extraStatTags annotation을 추가해 새로운 dimension을 proxy에 반영.
- 메트릭 확인: 서비스 요청 후 proxy에서 upstream_operation dimension이 포함된 메트릭 확인.
- Istio의 가치: golden-signal metrics를 자동 수집해 마이크로서비스 모니터링을 간소화하며, Grafana나 Kiali로 시각화 가능.
'Istio Hands-on Study [1기]' 카테고리의 다른 글
[4주차] 관찰 가능성(네트워크 동작 시각화하기) : Kiali로 시각화하기 (0) | 2025.04.22 |
---|---|
[4주차] 관찰 가능성(네트워크 동작 시각화하기) : 분산 추적 (0) | 2025.04.22 |
[4주차] 관찰 가능성(서비스 동작 이해) : Prometheus로 Istio 메트릭 스크래핑 (0) | 2025.04.22 |
[4주차] 관찰 가능성(서비스 동작 이해) : Istio 메트릭 살펴보기 (0) | 2025.04.22 |
[4주차] 관찰 가능성(서비스 동작 이해) : Observability란 무엇인가? (0) | 2025.04.22 |