Service Mesh ์์๋ณด๊ธฐ
- [Service Mesh] 1. Service Mesh๋?
- [Service Mehs] 2. Envoy Proxy
- [Service Mesh] 3. Istio?
- [Service Mesh] 4. Istio Traffic Management (1) - Virtual Service & Destination Rule
- [Service Mesh] 5. Istio Traffic Managerment (2) - Gateway & Service Entry
- [Service Mesh] 6. Service Monitoring in Istio
- [Service Mesh] 7. Logging
์ด๋ฒ์๊ฐ์๋ ์๋น์ค ๋ฉ์ ๋ด๋ถ ์ดํ๋ฆฌ์ผ์ด์ ์์ ๋ฐ์ํ๋ ๋ก๊ทธ๋ฅผ Istio์์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ๋์ง์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. Kubernetes Cluster์ ๋ฐฐํฌ๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ํ๋ฅผ ์ถ์ ํ๊ณ ํ์ธํ๊ธฐ ์ํด์๋ ๋ก๊ทธ ๋ฐ์ดํฐ๋ฅผ ์์งํ๊ณ ์ด๋ฅผ ๋ถ์ํ๋ ๊ณผ์ ์ด ํ์ํฉ๋๋ค. ์ด ๋ ๋ฐ์ํ๋ ๋ก๊ทธ์ ์ข ๋ฅ๋ก๋ ์์คํ ๋ก๊ทธ๋ ์ดํ๋ฆฌ์ผ์ด์ ์์ ๋ฐ์ํ๋ ๋ก๊ทธ, ์ดํ๋ฆฌ์ผ์ด์ ์ ์์ธ์คํ๋ ๋ก๊ทธ์ ๊ฐ์ด ๋ค์ํ๊ฒ ์กด์ฌํฉ๋๋ค.
์ด ์ค ์์ธ์ค ๋ก๊ทธ๋ ์๋น์ค ๋ฉ์ ์ํคํ ์ณ์ ๋ฐฐํฌ๋๋ ์ดํ๋ฆฌ์ผ์ด์ ์ด ๋ชจ๋ ํต์ ์ด Envoy Sidecar๋ฅผ ํตํด ์ด๋ฃจ์ด์ง๊ณ , ์ด๋ Istio์์ ๊ด๋ฆฌ๋๊ธฐ ๋๋ฌธ์ ์์ฒญ ๋ฐ ์์ธ์ค ๊ณผ์ ์ ์ถ์ ํ ์ ์์ต๋๋ค. Service Metric ์์ง๊ณผ ๋์ผํ๊ฒ Mixer๊ฐ ์กด์ฌํ๋ Istio 1.8 ๋ฒ์ ์ด์ ์ ๊ฒฝ์ฐ์๋ Adapter๋ฅผ ํตํด Logging Backend๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์กํ ์ ์์ต๋๋ค. ์ด์ ๋ฌ๋ฆฌ Mixer๊ฐ Deprecated ๋ Istio 1.8 ๋ฒ์ ์ดํ์๋ WASM์ ํตํด Envoy ๋ด๋ถ์์ ์ด๋ฐ ๊ณผ์ ๋ค์ด ์ด๋ฃจ์ด์ง๊ฒ ๋ฉ๋๋ค. ์ด๋ฒ ๊ธ์์๋ ๋๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ํด์ ๊ฐ๋จํ๊ฒ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
EFK Stack
์ด ๊ธ์ ์ฐธ๊ณ ํ๋ฉด ๋ก๊ทธ๋ฅผ ์์ง ๋ฐ ์ ์กํ๊ธฐ ์ํ Fluentd, ์ ์ฅ์ ์ํ Elasticsearch, ์กฐํ๋ฅผ ์ํ Kibana๋ฅผ ๋ฐฐํฌํ ์ ์๋ manifest๊ฐ ์กด์ฌํฉ๋๋ค. ์ด๋ฅผ ํตํด EFK Stack์ Kubernetes Cluster์ ๋ฐฐํฌํ ์ ์์ต๋๋ค. ์ค์ ๊ณผ ๊ด๋ จ๋ ๋ถ๋ถ์ ๋ฐ๋ก ๋ค๋ฃจ์ง ์๊ฒ ์ต๋๋ค.
Logging (with Mixer)
Metric์ ์์งํ๋ ๊ฒ๊ณผ ๊ฐ์ด Istio 1.8 ์ด์ ๋ฒ์ ์์๋ Mixer๋ฅผ ํ์ฉํ์ฌ Access Logging์ ์ฒ๋ฆฌํ์์ต๋๋ค. ์ดํ๋ฆฌ์ผ์ด์ ์ ์์ธ์ค ๋ก๊ทธ๋ฅผ ์์งํด์ผํ๋ ์ํฉ์ ๊ฐ์ ํ์ ๋ ํด๋นํ๋ ๋ก๊ทธ ๋ฐ์ดํฐ๋ฅผ ์์งํ์ฌ ๋ก๊น ๋ฐฑ์๋๋ก ์ ์กํ๊ธฐ ์ํ Adapter๊ฐ ํ์ํฉ๋๋ค.
Adapter๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํ Handler, Instance, Rule ์ญํ ์ ๋ํ ์ค๋ช ์ ์ด์ ๊ธ์์ ํ์ธํ์ค ์ ์์ต๋๋ค.
# Configuration for logentry instances
apiVersion: config.istio.io/v1alpha2
kind: instance
metadata:
name: newlog
namespace: istio-system
spec:
compiledTemplate: logentry
params:
severity: '"info"'
timestamp: request.time
variables:
source: source.labels["app"] | source.workload.name | "unknown"
user: source.user | "unknown"
destination: destination.labels["app"] | destination.workload.name | "unknown"
responseCode: response.code | 0
responseSize: response.size | 0
latency: response.duration | "0ms"
monitored_resource_type: '"UNSPECIFIED"'
---
# Configuration for a Fluentd handler
apiVersion: config.istio.io/v1alpha2
kind: handler
metadata:
name: handler
namespace: istio-system
spec:
compiledAdapter: fluentd
params:
address: "fluentd-es.logging:24224"
---
# Rule to send logentry instances to the Fluentd handler
apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
name: newlogtofluentd
namespace: istio-system
spec:
match: "true" # match for all requests
actions:
- handler: handler
instances:
- newlog
---
- timestamp ํ๋์ ๋์ ๋๋ request.time์ envoy์์ ์ ๊ณต๋ฉ๋๋ค.
- Instance์ Variable์ ์ ์ธ๋๋ ๋ฐ์ดํฐ์ ์ข ๋ฅ๋ ์ด ๊ธ์์ ํ์ธํ ์ ์์ต๋๋ค.
- Handler์ compiledAdapter๋ Fluentd Adapter๋ฅผ ์๋ฏธํ๊ณ , address์์ ๊ตฌ๋ ์ค์ธ fluentd Daemon์ ๋ฐ์ดํฐ๋ฅผ ์ ์กํฉ๋๋ค.
์์ Adapter๋ฅผ ํตํด ์ดํ๋ฆฌ์ผ์ด์ ์ ๊ทผ ๋ก๊ทธ๋ฅผ Fluentd Daemon์ ์ ์กํ ์ ์์ต๋๋ค.
Logging (with WASM)
์ด๋ฒ์๋ Mixer๊ฐ Deprecated ๋ ์ดํ WASM์ ํตํด ์ด๋ป๊ฒ ์์ ๊ธฐ๋ฅ์ ์ํํ ์ ์๋์ง ์์๋ณด๊ฒ ์ต๋๋ค. ๋จผ์ WASM Plugin์ ๊ฐ๋ฐํ๊ธฐ ์ด์ ์ Fluentd Adapter๊ฐ ํ๋ ์ญํ ์ ํ ๋ฒ ์ง์ด๋ณด๊ฒ ์ต๋๋ค. Fleuntd Adapter๋ ์์ ํ Envoy Attribute๋ฅผ ํตํด ๋ก๊ทธ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๊ณ , ์ด๋ฅผ fluentd Daemon์ ๋ณด๋ด๋ ์ญํ ์ ๋ด๋นํฉ๋๋ค. ๋ฐ๋ผ์ WASM Plugin์์ ์ํํ ์์ ์ Log Data๋ฅผ ์์ฑํ์ฌ ์ด๋ฅผ Fluentd Daemon์ ์ ์กํ๋ ์์ ์ด์ด์ผ ํฉ๋๋ค. ์์ ๊ฐ ์์๋ metric๊ณผ๋ ๋ค๋ฅด๊ฒ logging์ ๋ํ ์์๋ ์๊ธฐ ๋๋ฌธ์ proxy-wasm-go-sdk์ ๋ฉ์๋๋ค์ ์ฐพ์๋ณด๋ฉฐ ์งํํด๋ณด๊ฒ ์ต๋๋ค.
์งํํ๋ฉฐ ๊ฐ์ฅ ์ด๋ ค์ ๋ ์ ์ Custom Log Metric์ ์ด๋ป๊ฒ ์์ฑํ๋์ง์ ๋ํ ๋ถ๋ถ์ ๋๋ค. logentry variable ํ๋์์ ์ ์ํ๋ source.labels, response.code์ ๊ฐ์ ๋ฐ์ดํฐ๋ค์ ์ด๋ป๊ฒ ์ป์ ์ ์๋์ง์ ๋ํด์ ๋ฌธ์๋ฅผ ํ์ธํด๋ณด๋ฉด ์์์ ์ฌ์ฉ๋ ๋ฐ์ดํฐ๋ค์ ๋ฏธ๋ฆฌ ํค์๋๋ก ์ ์ํด๋๊ณ ์ด๋ฅผ Attribute Vocabulary๋ผ๊ณ ํ๋ฉฐ Envoy๋ Mixer์ Adapter์์ ์์ฑ๋๋ค๊ณ ๋ช ์๋์ด ์์ต๋๋ค. ๋ํ, Istio Deployment๋ ์ด๋ฐ Attribute Vocabulary๋ฅผ ์์ฑํ๋ agent๊ฐ ์กด์ฌํ๋ค๊ณ ๋์์์ต๋๋ค. ํ์ง๋ง Telemetry V2๋ K8S Metadata์ ์ ๊ทผํ๊ธฐ ์ํ Mixer๊ฐ ์ฌ๋ผ์ก๊ธฐ ๋๋ฌธ์ metadata์ ๋ํ ์ฒ๋ฆฌ๋ฅผ Envoy Proxy ์์ฒด์ ์ผ๋ก ์ํํด์ผ ํฉ๋๋ค.
์ด๋ฅผ ์ํด ๋จผ์ ์์์ผ ํ๋ ์ ์ ์ด๋ค Envoy Attribute๊ฐ ์กด์ฌํ๊ณ , ์ด๋ฅผ WASM Plugin์์ ์ด๋ป๊ฒ ์ฌ์ฉํ ์ ์๋์ง์ ๋ํ ๋ถ๋ถ์ ๋๋ค. ์ ๋ ์ด๊ฑฐ๋ฅผ ์ฐพ๋๋ฐ ์ ๋ฅผ ๋จน์ด Stackoverflow์ ์ง๋ฌธ๊น์ง ํ๋๋ฐ ๋คํํ ๊ธ๋ฐฉ ๋์์ ๋ฐ์ ์ ์์์ต๋๋ค.

์์ ๋ด์ฉ์ ๋ณด๋ฉด Envoy์์ ์ฌ์ฉํ ์ ์๋ ๋ฐ์ดํฐ์ ๋ชฉ๋ก์ Attributes ๋ฌธ์์์ ํ์ธํ ์ ์๊ณ , ์ด ๊ธ์ ๋ง์ง๋ง ๋ถ๋ถ์ Path Expressions ๋ถ๋ถ์ ๋ณด๋ฉด WASM ABI์์ ์ด๋ป๊ฒ ๊ฐ์ ์ป์ ์ ์๋์ง ๋ํ๋ ์์ต๋๋ค. ๋ํ, proxy-wasm-go-sdk์ PR์ ๋ณด๋ฉด 2020๋ 9์์ get_property ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
WASM Plugin
๋จผ์ get_property ํจ์๋ฅผ ํ์ธํด๋ณด๊ฒ ์ต๋๋ค.
func GetProperty(path []string) ([]byte, error) {
var ret *byte
var retSize int
raw := SerializePropertyPath(path)
err := types.StatusToError(rawhostcall.ProxyGetProperty(&raw[0], len(raw), &ret, &retSize))
if err != nil {
return nil, err
}
return RawBytePtrToByteSlice(ret, retSize), nil
}
Parameter๋ก ๋ฐ๋ path์ Envoy Attributes์ ๊ฒฝ๋ก๋ ์ ๋ ฅํ๋ ๋ฐฉ์์ผ๋ก ๊ฐ์ ์ป์ด์ฌ ์ ์์ต๋๋ค.
์ด๋ฅผ ํตํด์ ๊ฐ๋จํ๊ฒ Http ์์ฒญ์ผ๋ก๋ถํฐ ๊ฐ์ ๋ฐ์์ค๊ฑฐ๋ connections์ ๊ดํ ์ ๋ณด ๋ฑ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
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)
}
type httpLogRootContext struct {
proxywasm.DefaultRootContext
contextID uint32
}
func newRootContext(contextID uint32) proxywasm.RootContext {
return &httpLogRootContext{contextID: contextID}
}
// override
func (ctx *httpLogRootContext) OnVMStart(vmConfigurationSize int) bool {
path := []string{"cluster_name"}
result, err := proxywasm.GetProperty(path)
if err != nil {
proxywasm.LogCritical("failed to get property in envoy.")
} else {
proxywasm.LogInfo("Node Info : " + string(result))
}
return true
}
type logHttpContext struct {
proxywasm.DefaultHttpContext
}
func newHttpContext(uint32, uint32) proxywasm.HttpContext {
return &logHttpContext{}
}
// override
func (ctx *logHttpContext) OnHttpRequestHeaders(numHeaders int, endOfStream bool) types.Action {
pathMethod := []string{"request", "method"}
methodResult, _ := proxywasm.GetProperty(pathMethod)
proxywasm.LogInfo("Request Method : " + string(methodResult))
connectionPath := []string{"source", "address"}
connectionResult, _ := proxywasm.GetProperty(connectionPath)
proxywasm.LogInfo("Source Address :" + string(connectionResult))
return types.ActionContinue
}
๊ฐ๋จํ๊ฒ ์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด OnVMStart ํจ์๋ ์ด๊ธฐ ์คํ ์ ์ํ๋๊ณ , OnHttpRequestHeaders ํจ์๋ HTTP ์์ฒญ์ด ๋ค์ด์์ ๋ ์ํ์ด ๋ฉ๋๋ค. ์ด ๋ ์ฌ์ฉํ Context๋ฅผ main ํจ์์์ ์ ์ํ๋ ๋ฐฉ์์ผ๋ก ์ํ๋ฉ๋๋ค.
์ ์ฝ๋์ ์คํ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
//Start
starting main dispatch loop
wasm log my_root_id: failed to get property in envoy.
// HTTP Request In
wasm log: Request Method : GET
wasm log: Source Address :127.0.0.1:58181
์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด OnVMStart์์ ํธ์ถ๋ cluster_name์ ๋ํด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค์ง ๋ชปํ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ์ด์ ๊ด๋ จํด์ ์์ง sdk์ ๊ตฌ์กฐ๋ฅผ ์๋ฒฝํ๊ฒ ํ์ ํ์ง๋ ๋ชปํ์ง๋ง ์ ๊ฐ ์ ๋ฆฌํ ๋ฐ๋
- ์ฌ๋ฌ๊ฐ์ง Envoy Attribute๋ฅผ ํ ์คํธ ํ ๊ฒฐ๊ณผ ๊ฐ Attribute๋ ๊ฐ์ ธ์ฌ ์ ์๋ ์์ ์ด ์กด์ฌํ๊ณ ์ด ์์ ์ Context์ On--- Method๋ก ๊ตฌ๋ถ๋ฉ๋๋ค.
- On---Method์์๋ HttpHeader ๋ฐ Up/DownStream / Connection๊ณผ ๊ฐ์ ๋ค์ํ ์ด๋ฒคํธ ๋ฐ์๊ณผ ๋์๋๋ฉฐ ์ด ๋ ์ํํ ํ๋์ ์ง์ ํ ์ ์์ต๋๋ค.
์์ ๊ณผ์ ์ ํตํด Envoy Attribute์์ ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ป์ด์ฌ ์ ์์ต๋๋ค. ์ด ๋ฐ์ดํฐ๋ฅผ Fleuntd Daemon์ ๋ณด๋์ผ๋ก์จ Mixer Adapter๊ฐ ์ํํ๋ ๊ธฐ๋ฅ์ Envoy Proxy ์์ฒด๊ฐ ์ํํ ์ ์์ต๋๋ค.
์์ฑํ ๋ก๊ทธ ๋ฐ์ดํฐ๋ฅผ Fluentd Daemon์ ์ ์กํ๋ ์์ ์ ๋ํด์๋ ์งํํ์ด์ผ ํ์ง๋ง TCP Socket์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ๋ WASM ABI๋ฅผ ์ฐพ์ง ๋ชปํด์ ์ด ๋ถ๋ถ์ ์ข ๋ ์ฐพ์๋ณธ ํ ๋ค์ ๊ธ๋ก ์์ฑํ๋๋ก ํ๊ฒ ์ต๋๋ค...
๋ง์น๋ฉฐ
์ด๋ฒ ์๊ฐ์๋ Mixer๋ฅผ ์ฌ์ฉํ์ฌ Access Log๋ฅผ ์์งํ๋ ๋ฐฉ๋ฒ๊ณผ WASM๋ฅผ ์ฌ์ฉํ์ฌ Custom Log๋ฅผ ์์งํ๋ ๊ณผ์ ์ ์ผ๋ถ..(Envoy Attribute ์์ ๋ฐ์ดํฐ ์์ง)๋ฅผ ์งํํ์ต๋๋ค. ๋ฌผ๋ก ์ ๋ WASM์ ๋ํด ์ ์์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ์ ๊ฐ ์์ฑํ ๋ฐฉ๋ฒ๋ค์ด ์ค์ ๋ก ์ฌ์ฉ๋๊ธฐ๋ ํ๋ค๊ณ ๊ทธ์ ๋์ํ๋ ๋ฐฉ์์ ์ดํดํ๊ธฐ ์ํ ์ ๋๋ก๋ง ์๊ฐํ์๋ฉด ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ง๊ธ๊น์ง์ ๊ธ์ ํตํด Service Mesh ์ํคํ ์ณ ๋ฐ Istio์ ๋ํด ์์๋ณด๋ ์๊ฐ์ ๊ฐ์ ธ๋ณด์์ต๋๋ค. ๊ณต๋ถ๋ฅผ ํ๋ฉด์ ๋๊ผ๋ ๋ถ๋ถ์ ์์ง ๋ฌธ์ํ๊ฐ ๋ ๋ ๋ถ๋ถ๋ค๋ ์๊ณ , ๋ฒ์ ์ ๋ฐ๋ผ ๋ง์ ๋ถ๋ถ๋ค์ด ๋ณํ๋ ์ํฉ์ธ์ง๋ผ ์ํ๋ ์ ๋ณด๋ฅผ ์ฐพ๊ธฐ ์กฐ๊ธ ์ด๋ ต๋ค๋ ์๊ฐ์ด ๋ค์์ต๋๋ค. ๋ํ, ๋ถ๋ช ์ธํ๋ผ ๋ ๋ฒจ์์ ์ฒ๋ฆฌํ๋ ๊ฒ์ ๋ํด ์ฅ์ ์ด ์กด์ฌํ์ง๋ง, ์ด๋ฅผ ์ ์ฉํจ์ผ๋ก์จ ๊ธฐ์กด์ Server - Client์ ์ฌ์ด์ ๋ ํ๋์ ๊ณ์ธต์ด ์ถ๊ฐ๋๊ธฐ ๋๋ฌธ์ ๊ด๋ฆฌํด์ผํ ํฌ์ธํธ๊ฐ ์ฆ๊ฐํ๊ฒ ๋๋ค๋ ์ ์ ๋๋ค. ๋ชจ๋ ๊ธฐ์ ์ ์ฅ์ ๋ง ์กด์ฌํ์ง ์๊ธฐ์ Istio ๋ฐ envoy์ ์์ ์ฑ์ ๋ํ ๊ฒ์ฆ๋ ๋ถ๋ช ํ์ํ๋ค๋ ์๊ฐ์ด ๋ค์์ต๋๋ค.
์ง๊ธ๊น์ง ๊ธ์ ์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์์ ์ด ํ์ํ๊ฑฐ๋ ๋ ๋์ ์๊ฒฌ์ด ์๋ค๋ฉด ์ธ์ ๋ ์ง ํผ๋๋ฐฑ ๋ถํ๋๋ฆฝ๋๋ค :)
์ฐธ๊ณ ์๋ฃ
'๐ Service Mesh' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Service Mesh] 6. Service Monitoring in Istio (0) | 2021.01.19 |
---|---|
[Service Mesh] 5. Istio Traffic Management (2) - Gateway & Service Entry (0) | 2021.01.16 |
[Service Mesh] 4. Istio Traffic Management (1) - Virtual Service & Destination Rule (0) | 2021.01.14 |
[Service Mesh] 3. Istio? (0) | 2020.12.22 |
[Service Mesh] 2. Envoy Proxy (0) | 2020.12.21 |
๋๊ธ