๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ”Ž Service Mesh

[Service Mesh] 6. Service Monitoring in Istio

by Seongpyo Hong 2021. 1. 19.

Service Mesh ์•Œ์•„๋ณด๊ธฐ

  1. [Service Mesh] 1. Service Mesh๋ž€?
  2. [Service Mehs] 2. Envoy Proxy
  3. [Service Mesh] 3. Istio?
  4. [Service Mesh] 4. Istio Traffic Management (1) - Virtual Service & Destination Rule
  5. [Service Mesh] 5. Istio Traffic Managerment (2) - Gateway & Service Entry
  6. [Service Mesh] 6. Service Monitoring in Istio
  7. [Service Mesh] 7. Logging

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์„œ๋น„์Šค ๋ฉ”์‹œ ์•„ํ‚คํ…์ณ์—์„œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฉ”ํŠธ๋ฆญ์„ ์–ด๋–ป๊ฒŒ ์ˆ˜์ง‘ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ด๋ฅผ ์ธก์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”ํŠธ๋ฆญ์„ ์ˆ˜์ง‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ๊ณ ๊ฐ€์šฉ์„ฑ์„ ๋ชฉํ‘œ๋กœ ํ•œ๋‹ค๋ฉด ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•œ ํ›„ ๋ณต๊ตฌํ•˜๋Š” ๊ฒƒ๋„ ์ค‘์š”ํ•˜์ง€๋งŒ ์žฅ์• ์— ๋Œ€ํ•ด ๋ฏธ๋ฆฌ ์š”์ฒญ ์ˆ˜, ์‘๋‹ต ์‹œ๊ฐ„, ์‘๋‹ต ์ƒํƒœ์™€ ๊ฐ™์€ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฉ”ํŠธ๋ฆญ๊ณผ CPU ๋ฐ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ ๊ณผ ๊ฐ™์€ ์‹œ์Šคํ…œ ๋ฉ”ํŠธ๋ฆญ์˜ ์ž„๊ณ„๊ฐ’์„ ์ •ํ•ด๋†“๊ณ  ์žฅ์•  ์ƒํ™ฉ์„ ์˜ˆ๋ฐฉํ•˜๋Š” ๊ณผ์ •๋„ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ณผ์ •์„ ๋ชจ๋‹ˆํ„ฐ๋ง์ด๋ผ๊ณ  ํ•˜๋ฉฐ ์ „์ฒด ๋ชจ๋‹ˆํ„ฐ๋ง ๊ณผ์ •์€ ๋ณดํ†ต ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ง‘ => ๋ฉ”ํŠธ๋ฆญ ๋ถ„์„ => ์•Œ๋žŒ  ํ”„๋กœ์„ธ์Šค๋กœ ๋‚˜๋ˆ„์–ด์ง‘๋‹ˆ๋‹ค.

Istio๋ฅผ ๋„์ž…ํ•จ์— ์žˆ์–ด ๋งŽ์€ ์žฅ์ ๋“ค์ด ์กด์žฌํ•˜์ง€๋งŒ ๊ทธ ์ค‘ ์ง‘์ค‘ํ•ด๋ณผ ์ ์€ ํ–ฅ์ƒ๋œ ๊ด€์ธก์„ฑ๊ณผ ๊ด€๋ จ๋œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. Istio ์„œ๋น„์Šค ๋ฉ”์‹œ ์•„ํ‚คํ…์ณ๋Š” ๋ชจ๋“  ์„œ๋น„์Šค๊ฐ„ ํ†ต์‹ ์ด Envoy Proxy๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์ง€๊ณ  ์ด๋ฅผ ํ†ตํ•ด Istio Control Plane์€ ๋กœ๊ทธ ๋ฐ ๋ฉ”ํŠธ๋ฆญ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ์ง€๊ธˆ๋ถ€ํ„ฐ Istio์—์„œ ์ด๋Ÿฌํ•œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์–ด๋–ป๊ฒŒ ์ˆ˜ํ–‰ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


Istio Mixer (Deprecated)

1.8๋ฒ„์ „ ์ด์ „์˜ Istio ์—์„œ๋Š” ์„œ๋น„์Šค ๋ฉ”์‹œ์— ๊ด€๋ จ๋œ ๋ฉ”ํŠธ๋ฆญ์„ ๋ชจ์•„ ์—”๋“œํฌ์ธํŠธ๋กœ ๋…ธ์ถœํ•˜๋Š” Prometheus Adapter๊ฐ€ Mixer์— ๋‚ด์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. Mixer๋Š” ๊ฐ Envoy Proxy์™€ ์—ฐ๊ฒฐ์„ ๋งบ๊ณ  ์žˆ์œผ๋ฉฐ ์ด๋ฅผ ํ†ตํ•ด Service Metric์„ ์ˆ˜์ง‘ํ•˜์—ฌ endpoint๋กœ ๋…ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.  ์ถ”๊ฐ€๋กœ Envoy Proxy Level์—์„œ์˜ ๋ฉ”ํŠธ๋ฆญ๋„ ์ˆ˜์ง‘ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋Š” Proxy Container์—์„œ ์ง์ ‘ endpoint๋ฅผ ๋…ธ์ถœํ•˜์—ฌ Prometheus๊ฐ€ ์ด๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

Mixer๊ฐ€ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋˜๋Š”์ง€ ๊ด€๋ จ๋œ ๋‚ด์šฉ์€ alice_k106๋‹˜์˜ ๋ธ”๋กœ๊ทธ์— ์ •๋ฆฌ๋˜์–ด ์žˆ์–ด ์ด๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ •๋ฆฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.  

์ถœ์ฒ˜ : https://istio.io/v1.7/docs/reference/config/policy-and-telemetry/mixer-overview/

์ด์ „ ๊ธ€์—์„œ ์„ค๋ช…ํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ Adapter๋Š” Mixer์— ์ „์†ก๋œ Envoy Attribute๋ฅผ ๊ฐ€๊ณตํ•˜์—ฌ ์ ์ ˆํ•œ ์ธํ”„๋ผ ๋ฐฑ์—”๋“œ์— ์ „์†กํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ Envoy Attribute๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ง€๋Š” Configuration Model์„ ํ†ตํ•ด ์ •์˜๋ฉ๋‹ˆ๋‹ค. Configuration Model์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ 3๊ฐ€์ง€ ์š”์†Œ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

  • Instance
    Mixer๊ฐ€ ์ˆ˜์‹ ํ•œ Attribute๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ธ์ง€์— ๋Œ€ํ•œ ์ •์˜๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐ์ดํ„ฐ ํ…œํ”Œ๋ฆฟ์„ Handler์—๊ฒŒ ๋„˜๊ฒจ์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • Handler
    Instance์˜ ๋ฐ์ดํ„ฐ๋ฅผ Adapter ์ž…๋ ฅ์— ์–ด๋–ป๊ฒŒ ๋งคํ•‘ํ•  ๊ฒƒ์ธ์ง€๋ฅผ ์ •์˜ํ•˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด CloudWatch Adapter์— ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด Json Payload๋ฅผ ์ •์˜ํ•˜๋Š” ๋ถ€๋ถ„์ด ๋ฉ๋‹ˆ๋‹ค.
  • Rule
    Instance์™€ Handler๋ฅผ ๋งคํ•‘ํ•ด Adapter์— ์‹ค์ œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋ฉฐ, ๋งคํ•‘ํ•˜๊ธฐ ์›ํ•˜๋Š” ์กฐ๊ฑด(ex. TCP์ธ ๊ฒฝ์šฐ)์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Custom Metric (with Mixer)

๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณต๋˜๋Š” ๋ฉ”ํŠธ๋ฆญ ์ด์™ธ์—๋„ ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ Configuration Model์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ •์˜ ๋ฉ”ํŠธ๋ฆญ ๋˜ํ•œ ๋…ธ์ถœ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Istio๋กœ ์‹œ์ž‘ํ•˜๋Š” ์„œ๋น„์Šค ๋ฉ”์‹œ ์ฑ…์— ๋‚˜์™€์žˆ๋Š” ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฌ์šฉ์ž ์ •์˜ ๋ฉ”ํŠธ๋ฆญ์„ ๋…ธ์ถœ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ € Envoy Attribute๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ• ์ง€ ์ •์˜ํ•œ Instance๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

apiVersion: config.istio.io/v1alpha2
kind: instance
metadata:
  name: requestdouble
  namespace: istio-system
spec:
  compiledTemplate: metric
  params:
    value: "2"
    dimensions:
      source: source.workload.name | "unknown"
      destination: destination.workload.name | "unknown"

compiledTemplate์€ Envoy Attribute๋ฅผ ์ฒ˜๋ฆฌํ•ด์„œ ๋งŒ๋“ค์–ด ๋‚ผ ๋ฐ์ดํ„ฐ ํ…œํ”Œ๋ฆฟ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. params ํ•„๋“œ์˜ dimensions ํ•„๋“œ์—๋Š” ๋ฐ์ดํ„ฐ์— ๋‹ด๊ธธ ์‹ค์ œ ์ •๋ณด๋ฅผ ์ •์˜ํ•˜๊ณ , value ํ•„๋“œ์— ์‹ค์ œ ๋ฉ”ํŠธ๋ฆญ ๊ฐ’์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์œผ๋กœ Instance์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ๋งคํ•‘ํ• ์ง€ ์ •์˜ํ•œ Handler๋ฅผ ์ •์˜ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

apiVersion: config.istio.io/v1alpha2
kind: handler
metadata:
  name: doublehandler
  namespace: istio-system
spec:
  compiledAdapter: prometheus
  params:
    metrics:
    - name: doublerequest-count
      instance_name: requestdouble.instance.istio-system
      kind: COUNTER
      label_names:
      - source
      - destination

๋จผ์ € ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ Prometheus Adapter์— ๋ณด๋‚ผ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— compiledAdapter: prometheus๋กœ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  metrics ํ•„๋“œ์—์„œ๋Š” prometheus์— ์ €์žฅ๋  ๋ฉ”ํŠธ๋ฆญ ์ •๋ณด์— ๋Œ€ํ•ด ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. name์€ prometheus์˜ ๋ฉ”ํŠธ๋ฆญ ์ด๋ฆ„์„, instance_name์€ ๋งคํ•‘๋  instance์˜ ์ด๋ฆ„์„, kind๋Š” prometheus์˜ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„, label_name์€ prometheus ๋ฉ”ํŠธ๋ฆญ์˜ label ์ด๋ฆ„์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ Instance์™€ Handler๋ฅผ ๋งคํ•‘ํ•˜๊ธฐ ์œ„ํ•œ Rule์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
  name: requestdouble-prometheus
  namespace: istio-system
spec:
  actions:
  - handler: doublehandler
    instances: [ requestdouble ]
  match: match(destination.service.name, "webservice")

match ์กฐ๊ฑด์„ ๋งŒ์กฑํ•  ๋•Œ actions์— ์ •์˜๋œ handler์™€  instance๋ฅผ ๋งคํ•‘ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์œ„์˜ ๋ฉ”๋‹ˆํŽ˜์ŠคํŠธ๋ฅผ ์ •์˜ํ•˜๋ฉด ์ด๋ฆ„์ด webservice์ธ ์„œ๋น„์Šค์— ๋Œ€ํ•ด instance์™€ handler์˜ ์„ค์ •์ด ์ ์šฉ๋˜๊ณ , Prometheus Adapter์— ๋ฉ”ํŠธ๋ฆญ์ด ์ „๋‹ฌ๋˜์–ด ์ตœ์ข…์ ์œผ๋กœ endpoint๋กœ ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค. 


Web Assembly (After Istio 1.8)

์กฐ๊ธˆ ๋งŽ์ด ๋Œ์•„์˜จ ๊ฒƒ ๊ฐ™๊ธฐ๋„ ํ•˜์ง€๋งŒ ์ด๋ฒˆ๊ธ€์—์„œ ๋‹ค๋ฃจ๊ณ ์ž ํ•˜๋Š” ๋ถ€๋ถ„์€ Mixer๊ฐ€ Deprecated๋œ 1.8 ๋ฒ„์ „์ดํ›„ WebAssembly(WASM)๋ฅผ ํ†ตํ•ด ์–ด๋–ป๊ฒŒ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. Mixer๋ฅผ ํ†ตํ•œ ๋ฐฉ๋ฒ•๋„ ๋†’์€ ํ™•์žฅ์„ฑ์„ ๊ฐ–์ถ”๊ณ  ์žˆ์ง€๋งŒ ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ service level ๋ฉ”ํŠธ๋ฆญ์„ ์ˆ˜์ง‘ํ•˜๊ธฐ ์œ„ํ•ด Mixer๋Š” ๊ฐ Envoy Proxy์™€ ์—ฐ๊ฒฐ์„ ๋งบ๊ณ  ์žˆ์–ด์•ผ ํ•˜๊ณ  ์ด๋กœ ์ธํ•ด ๋งŽ์€ ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ๊ณผ ๊ฐ™์€ ์„ฑ๋Šฅ์ƒ ์ด์Šˆ๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์„ฑ๋Šฅ ๊ฐœ์„ ์„ ์œ„ํ•ด Istio์—์„œ๋Š” Envoy Proxy ์ชฝ์— WebAssembly Extension์„ ๋ถ™ํžˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ฑ„ํƒํ•˜์˜€์Šต๋‹ˆ๋‹ค. (Istio ๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด ๊ฐœ์„ ๋œ ๋ฐฉ๋ฒ•์ด ์ง€์—ฐ์‹œ๊ฐ„์„ 50~90% ๊ฐ์†Œ์‹œ์ผฐ์œผ๋ฉฐ, CPU ์‚ฌ์šฉ๋Ÿ‰๋„ 50% ์ •๋„ ๊ฐ์†Œํ•œ ์„ฑ๋Šฅ ๊ฐœ์„ ์„ ๋ณด์—ฌ์ค€๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.)

์ด์ „ ๋ฒ„์ „์˜ Envoy๋Š” ํ™•์žฅ์— ์žˆ์–ด ๋†’์€ ๋Ÿฌ๋‹์ปค๋ธŒ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. Extension์„ C++๋กœ ์ž‘์„ฑํ•ด์•ผ ํ–ˆ์œผ๋ฉฐ, Extension์„ ์ถ”๊ฐ€ํ•œ Envoy๋ฅผ ๋‹ค์‹œ ๋นŒ๋“œํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์กด์žฌํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ํ™•์žฅ์„ฑ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Istio ์ปค๋ฎค๋‹ˆํ‹ฐ๋Š” Envoy๋ฅผ ์œ„ํ•œ WASM ๋Ÿฐํƒ€์ž„์„ ๊ตฌํ˜„ํ•˜์˜€๊ณ , ๊ฐœ๋ฐœ์ž๋Š” custom ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  WASM ์ต์Šคํ…์…˜์œผ๋กœ ์ปดํŒŒ์ผ ํ›„ Envoy๊ฐ€ ์ด๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ์„ค์ •ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์œ ์—ฐํ•˜๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Overview (์ถœ์ฒ˜ : https://github.com/proxy-wasm/spec/blob/master/docs/WebAssembly-in-Envoy.md)


 Service Level Metric

WASM์„ ํ†ตํ•ด ๊ธฐ์กด์— Mixer์—์„œ ์ฒ˜๋ฆฌํ–ˆ๋˜ Service Level์˜ ๋ฉ”ํŠธ๋ฆญ์€ metadata-exchange, stats 2๊ฐ€์ง€ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํ†ตํ•ด Envoy Proxy์—์„œ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. 

Metadata Exchange Plugin

Service Level ๋ฉ”ํŠธ๋ฆญ์„ ์ˆ˜์ง‘ํ•˜๊ธฐ ์œ„ํ•ด Client / Server์˜ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์—๋Š” ํ•œ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. Service Mesh์—์„œ Envoy Sidecae Proxy๋Š” ์ž๊ธฐ ์ž์‹  ์ด์™ธ์˜ ๋‹ค๋ฅธ Proxy์˜ ์ •๋ณด๋ฅผ ์•Œ์ง€ ๋ชปํ•˜๋ฉฐ, ์ด๋Ÿฐ ์ •๋ณด๋“ค์€ Control Plane์„ ํ†ตํ•ด ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Control Plane์˜ ์ปดํฌ๋„ŒํŠธ์ธ Mixer๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์•˜์ง€๋งŒ Envoy Proxy์—์„œ ์ž์ฒด์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ, ์ด๋Ÿฌํ•œ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์–ป๊ธฐ ์œ„ํ•œ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. 

์ด๋ฅผ ์œ„ํ•ด ๋„์ž…ํ•œ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • HTTP ๊ธฐ๋ฐ˜ ํŠธ๋ž˜ํ”ฝ์˜ ๊ฒฝ์šฐ HTTP header์— ์ด์™€ ๊ด€๋ จ๋œ ํ•„๋“œ(envoy.wasm.metadata_exchange.upstream/downstream)๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ณด๋ƒ„์œผ๋กœ ํ•ด๊ฒฐํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • TCP ๊ธฐ๋ฐ˜ ํŠธ๋ž˜ํ”ฝ์ธ ๊ฒฝ์šฐ ALPN ๊ธฐ๋ฐ˜ ํ„ฐ๋„๋ง ๋ฐ ์ ‘๋‘์‚ฌ ๊ธฐ๋ฐ˜ ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์„œ๋น„์Šค ๋ฉ”์‹œ ๋‚ด๋ถ€์—์„œ client/server์— ์˜ํ•œ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๋ถ€์—ฌํ•จ์œผ๋กœ์จ ์œ„์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ด ๊ธ€์— ๋”ฐ๋ฅด๋ฉด Istio ๋‚ด๋ถ€์˜ Proxy ๊ฐ„์—๋Š” ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ๋‹ค๋ฅธ Client์™€ Istio ๋‚ด๋ถ€ Proxy์˜ ์‚ฌ์ด์˜ ๊ด€๊ณ„์—์„œ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ํ•œ๊ณ„์ ์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

Stats Plugin

Stats Plugin์€ inbound / outbound ํŠธ๋ž˜ํ”ฝ์„ Envoy ๋‚ด๋ถ€์— ๊ธฐ๋กํ•˜๊ณ  Prometheus๊ฐ€ ์ˆ˜์ง‘ ๊ฐ€๋Šฅํ•˜๋„๋ก ๋…ธ์ถœ์‹œํ‚ค๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ๋…ธ์ถœ๋˜๋Š” ๋ฉ”ํŠธ๋ฆญ์˜ ์ข…๋ฅ˜์™€ Label์€ Istio ๋ฌธ์„œ์—์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


Custom Metric (with WASM)

์ด๋ฒˆ์—๋Š” WASM์„ ํ†ตํ•ด Custom Metric์„ Expose ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. WASM Plugin์„ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์–ธ์–ด๋“ค์„ ์ง€์›ํ•˜๊ณ  ์žˆ๋Š”๋ฐ Golang์„ ์‚ฌ์šฉํ•ด์„œ ์ง„ํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ๊ณผ์ •์€ proxy-wasm-go-sdk์„ ์ฐธ๊ณ ํ•˜์—ฌ ์ง„ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

example/metrics ํด๋”์˜ ๋‚ด์šฉ์„ ์‚ดํŽด๋ณด๋ฉด custom metric์„ ์ˆ˜์ง‘ํ•˜๊ธฐ ์œ„ํ•œ ๋กœ์ง์„ ์ž‘์„ฑํ•œ main.go ํŒŒ์ผ๊ณผ ์ด๋ฅผ ์ถ”๊ฐ€ํ•œ envoy์˜ ์„ค์ •ํŒŒ์ผ์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. main.go๋ถ€ํ„ฐ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

package main

import (
	"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
	"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
)

func main() {
	proxywasm.SetNewRootContext(newRootContext)
	proxywasm.SetNewHttpContext(newHttpContext)
}

var counter proxywasm.MetricCounter

const metricsName = "sphong_custom.request_counter"

type metricRootContext struct {
	// you must embed the default context so that you need not to reimplement all the methods by yourself
	proxywasm.DefaultRootContext
}

func newRootContext(uint32) proxywasm.RootContext {
	return &metricRootContext{}
}

// override
func (ctx *metricRootContext) OnVMStart(vmConfigurationSize int) bool {
	counter = proxywasm.DefineCounterMetric(metricsName)
	return true
}

type metricHttpContext struct {
	// you must embed the default context so that you need not to reimplement all the methods by yourself
	proxywasm.DefaultHttpContext
}

func newHttpContext(uint32, uint32) proxywasm.HttpContext {
	return &metricHttpContext{}
}

// override
func (ctx *metricHttpContext) OnHttpRequestHeaders(numHeaders int, endOfStream bool) types.Action {
	prev := counter.Get()
	proxywasm.LogInfof("previous value of %s: %d", metricsName, prev)
	counter.Increment(1)
	return types.ActionContinue
}

 

๋จผ์ € Metric์„ ์œ„ํ•œ Root Context์™€ Http Context๋ฅผ ์ƒ์„ฑํ•˜๋Š”๋ฐ ๋ชจ๋“  ๋ฉ”์†Œ๋“œ๋ฅผ ์žฌ๊ตฌํ˜„ํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด์„œ๋Š” default context๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Metric ๊ฐ’์„ ์ €์žฅํ•  counter ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๊ณ  OnVMStart ๋ฉ”์„œ๋“œ์—์„œ "sphong_custom.request_counter"๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ OnHttpRequestHeaders ๋ฉ”์„œ๋“œ์—์„œ counter์˜ ๊ฐ’์„ ์ฆ๊ฐ€์‹œ์ผœ์ฃผ๋Š” ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.


Build

ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ๋นŒ๋“œํ•ด์•ผ ํ•˜๋Š”๋ฐ ๊ณต์‹์ ์ธ go ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— TinyGo๋ฅผ ํ†ตํ•ด ๋นŒ๋“œํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ €๋Š” tinygo docker image๋ฅผ ํ†ตํ•ด ๋นŒ๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

> docker run -it -w /tmp/proxy-wasm-go -v $(shell pwd):/tmp/proxy-wasm-go tinygo/tinygo:0.16.0 /bin/bash -c \
'find /tmp/proxy-wasm-go/examples/ -type f -name "main.go" | xargs -Ip tinygo build -o p.wasm -scheduler=none -target=wasi p'

Run

๋‹ค์Œ์œผ๋กœ local์— ์„ค์น˜๋œ envoy์— ์ถ”๊ฐ€ํ•œ WASM์„ ๋ถ™ํ˜€ ์ˆ˜ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

> envoy -c ./examples/${name}/envoy.yaml --concurrency 2 --log-format '%v'

์—ฌ๊ธฐ์„œ ๋ณด๊ณ  ์žˆ๋Š” envoy config ํŒŒ์ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

static_resources:
  listeners:
    - name: main
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 18000
      filter_chains:
        - filters:
            - name: envoy.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                stat_prefix: ingress_http
                codec_type: auto
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: local_service
                      domains:
                        - "*"
                      routes:
                        - match:
                            prefix: "/"
                          route:
                            cluster: web_service
                http_filters:
                  - name: envoy.filters.http.wasm
                    typed_config:
                      "@type": type.googleapis.com/udpa.type.v1.TypedStruct
                      type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
                      value:
                        config:
                          name: "my_plugin"
                          root_id: "my_root_id"
                          vm_config:
                            vm_id: "my_vm_id"
                            runtime: "envoy.wasm.runtime.v8"
                            code:
                              local:
                                filename: "./examples/metrics/main.go.wasm"
                            allow_precompiled: true
                  - name: envoy.filters.http.router
                    typed_config: {}

    - name: staticreply
      address:
        socket_address:
          address: 127.0.0.1
          port_value: 8099
      filter_chains:
        - filters:
            - name: envoy.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                stat_prefix: ingress_http
                codec_type: auto
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: local_service
                      domains:
                        - "*"
                      routes:
                        - match:
                            prefix: "/"
                          direct_response:
                            status: 200
                            body:
                              inline_string: "example body\n"
                http_filters:
                  - name: envoy.filters.http.router
                    typed_config: {}

  clusters:
    - name: web_service
      connect_timeout: 0.25s
      type: STATIC
      lb_policy: ROUND_ROBIN
      load_assignment:
        cluster_name: mock_service
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: 127.0.0.1
                      port_value: 8099

admin:
  access_log_path: "/dev/null"
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 8001

์„ค์ • ์ค‘ Custom Metric์„ Plugin๊ณผ ๊ด€๋ จ๋œ ๋ถ€๋ถ„๋งŒ ์‚ดํŽด๋ณด๋ฉด 18000์œผ๋กœ http ์š”์ฒญ์ด ๋“ค์–ด์˜ค๊ฒŒ ๋˜๋ฉด ์œ„์—์„œ ๋นŒ๋“œํ•œ main.go.wasm์„ ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ๋“ฑ๋กํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ์ด๋ฆ„๊ณผ vm์˜ ๋Ÿฐํƒ€์ž„๊ณผ ๊ฐ™์€ ์„ค์ •๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.


Custom Metric Test

Envoy๋ฅผ ์ˆ˜ํ–‰ํ•œ ํ›„ http://localhost:18000์— ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด Custom Metric์ธ "sphong_custom.request_counter"๊ฐ€ 1์”ฉ ์ฆ๊ฐ€ํ•จ์„ ๋ณด์—ฌ์ฃผ๋Š” ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๊ณ , localhost:8001/stats๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด ํ•ด๋‹น Custom Metric์˜ ๊ฐ’์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์š”์ฒญ์„ ๋ณด๋ƒˆ์„ ๋•Œ ๋กœ๊ทธ
http://localhost:8001/stats


์ด๋ฒˆ ๊ธ€์—์„œ๋Š” Istio์—์„œ ์–ด๋–ป๊ฒŒ ๋ชจ๋‹ˆํ„ฐ๋ง์„ ์ง€์›ํ•˜๋Š”์ง€, Custom Metric์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด Mixer๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฒ„์ „๊ณผ WASM์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฒ„์ „์„ ๋‚˜๋ˆ„์–ด ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค. WASM์„ ์‚ฌ์šฉํ•˜๋Š” ๋ถ€๋ถ„์€ ์•„์ง ๋ชจ๋ฅด๋Š” ๋ถ€๋ถ„์ด ๋งŽ์•„ ๊ธฐ๋ณธ์ ์ธ ํ™œ์šฉ๋ฐฉ๋ฒ•๋งŒ ๋‹ค๋ค„๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์œ„์—์„œ ๋‹ค๋ฃฌ ๋ฐฉ๋ฒ•๋“ค์€ Mesh ๋ฐ Service์— ๊ด€๋ จ๋œ Metric์„ ์–ป์„ ์ˆ˜ ์žˆ์ง€๋งŒ Node๋‚˜ K8S Cluster, Application Metric์„ ์ˆ˜์ง‘ ๋ฐ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ†ต์ƒ์ ์ธ Exporter๋ฅผ ํ†ตํ•ด Prometheus๊ฐ€ Scarapingํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 

๋‹ค์Œ ๊ธ€์—์„œ๋Š” Istio Service Mesh์—์„œ Logging Architecture๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ ์ž๋ฃŒ

๊ธ€์—์„œ ์‚ฌ์šฉ๋œ ๋ชจ๋“  ์ฝ”๋“œ๋Š” Github์— ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

๋Œ“๊ธ€