Ssoon
[7주차] 요청 경로에서 Istio 확장 : Lua로 Istio의 Data Plane 확장 본문
Istio Hands-on Study [1기]
[7주차] 요청 경로에서 Istio 확장 : Lua로 Istio의 Data Plane 확장
구구달스 2025. 4. 23. 16:52🚀 Lua로 Istio 데이터 플레인 확장하기
🛠️ Lua 필터란?
Lua와 Envoy의 통합
- Lua는 가볍고 임베디드 시스템에 적합한 스크립팅 언어로, Envoy에서는 LuaJIT 가상 머신을 통해 실행됩니다.
Envoy의 Lua 필터를 사용하면 요청(envoy_on_request) 또는 응답(envoy_on_response) 경로에서 헤더 조작, 본문 검사 같은 커스텀 로직을 구현할 수 있습니다.
요청 본문을 검사하면 프록시가 본문을 메모리에 완전히 버퍼링할 수 있어 성능에 영향을 줄 수 있습니다.
- Lua 스크립트는 EnvoyFilter 리소스를 통해 Envoy의 HttpConnectionManager(HCM) 필터 체인에 삽입됩니다. 이를 통해 기존 필터로는 구현할 수 없는 유연한 확장이 가능합니다.
Lua 필터는 Lua 스크립트를 통해 Envoy의 요청/응답 경로를 커스터마이징하며,
성능 주의가 필요합니다.
🔧 A/B 테스트를 위한 Lua 필터 설정
예제 시나리오
- A/B 테스트를 위해 요청마다 동적으로 테스트 그룹을 결정하고, 이를 헤더로 추가하는 시나리오를 구현해 보겠습니다. 요청이 들어오면 외부 A/B 테스트 서비스(bucket-tester)를 호출해 그룹을 결정하고, 결과를 x-test-cohort 헤더로 추가합니다.
환경 설정
- 테스트를 위한 서비스를 배포합니다:
$ kubectl apply -f ch14/httpbin.yaml -n istioinaction
serviceaccount/httpbin created
service/httpbin created
deployment.apps/httpbin created
$ kubectl apply -f ch14/bucket-tester-service.yaml -n istioinaction
service/bucket-tester created
deployment.apps/bucket-tester created
- httpbin: 요청 헤더를 에코하는 서비스
- bucket-tester: 요청 헤더를 평가해 A/B 테스트 그룹을 반환
A/B 테스트 예제를 위해 httpbin과 bucket-tester 서비스를 배포합니다.
🛠️ Lua 스크립트 구현
Lua 스크립트 작성
- Lua 필터는 envoy_on_request 함수를 구현해 요청을 처리합니다.
외부 서비스 호출에는 Envoy의 httpCall 함수를 사용하며, 이는 Envoy의 비동기 스레드 아키텍처를 준수합니다.
아래는 bucket-tester 서비스를 호출해 테스트 그룹을 추가하는 Lua 스크립트입니다:
function envoy_on_request(request_handle) #Envoy 필터가 요청을 받을 때 실행되는 함수를 정의
local headers, test_bucket = request_handle:httpCall(
#Envoy 프록시가 다른 서비스에 HTTP 요청을 보내는 기능을 사용
#request_handle:httpCall 메서드는 지정된 서비스에 HTTP 요청을 보내고, 응답 헤더와 본문을 반환
"bucket_tester", #요청을 보낼 업스트림 서비스의 이름
{
[":method"] = "GET", #HTTP 메서드를 GET으로 설정
[":path"] = "/", #요청 경로를 루트 경로("/")로 설정
[":scheme"] = "http",
[":authority"] = "bucket-tester.istioinaction.svc.cluster.local",
#Host 헤더를 설정합니다. 이는 요청을 보낼 서비스의 주소
["accept"] = "*/*" #Accept 헤더를 설정하여 모든 미디어 타입을 허용
},
"", #요청 본문(body)을 빈 문자열로 설정
5000 #요청 타임아웃을 5000밀리초(5초)로 설정
)
request_handle:headers():add("x-test-cohort", test_bucket)
#httpCall 메서드로부터 받은 응답 본문(test_bucket)을 원래 요청의 헤더에 추가
end
- httpCall: bucket-tester 서비스에 GET 요청을 보내고 응답을 test_bucket에 저장
- headers():add: 응답 값을 x-test-cohort 헤더로 추가
일반 Lua 라이브러리로 RPC 호출을 하면 Envoy의 스레드 모델과 충돌할 수 있으므로,
httpCall 같은 Envoy 내장 함수를 사용해야 합니다.
Lua 스크립트는 httpCall로 외부 서비스를 호출하고,
결과를 헤더로 추가해 요청을 커스터마이징합니다.
🔍 EnvoyFilter로 Lua 필터 적용
EnvoyFilter 설정
- Lua 스크립트를 Envoy의 HCM 필터 체인에 삽입하려면 EnvoyFilter 리소스를 사용합니다.
아래는 httpbin 워크로드에 Lua 필터를 적용하는 설정입니다:
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: webapp-lua-extension
namespace: istioinaction
spec:
workloadSelector:
labels:
app: httpbin
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
portNumber: 80
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
subFilter:
name: "envoy.filters.http.router"
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.lua
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
inlineCode: |
function envoy_on_request(request_handle)
local headers, test_bucket = request_handle:httpCall(
"bucket_tester",
{
[":method"] = "GET",
[":path"] = "/",
[":scheme"] = "http",
[":authority"] = "bucket-tester.istioinaction.svc.cluster.local",
["accept"] = "*/*"
},
"",
5000
)
request_handle:headers():add("x-test-cohort", test_bucket)
end
- workloadSelector: app: httpbin 워크로드에 적용
- applyTo: HTTP 필터를 80번 포트의 HCM에 삽입
- operation: envoy.filters.http.router 앞에 Lua 필터 삽입
- 설정을 적용합니다:
$ kubectl apply -f ch14/lua-filter.yaml
envoyfilter.networking.istio.io/httpbin-lua-extension created
EnvoyFilter를 사용해 Lua 스크립트를 HCM 필터 체인에 삽입하며,
특정 워크로드에 적용합니다.
🛠️ 테스트 및 검증
Lua 필터 동작 확인
- httpbin 서비스에 요청을 보내 Lua 필터가 x-test-cohort 헤더를 추가하는지 확인합니다: 실패! => 확인필요invalid header value for: x-test-cohort 오류 메시지는 Envoy 프록시가 x-test-cohort라는 이름의 헤더에 할당된 값을 유효한 헤더 값 형식으로 인식하지 못했다는 것을 의미합니다.
$ kubectl exec -it deploy/sleep -n istioinaction -c sleep -- curl http://httpbin.istioinaction:8000/ -v
* Host httpbin.istioinaction:8000 was resolved.
* IPv6: (none)
* IPv4: 10.200.3.30
* Trying 10.200.3.30:8000...
* Connected to httpbin.istioinaction (10.200.3.30) port 8000
> GET / HTTP/1.1
> Host: httpbin.istioinaction:8000
> User-Agent: curl/8.5.0
> Accept: */*
>
< HTTP/1.1 503 Service Unavailable
< content-length: 39
< content-type: text/plain
< istioinaction: it works!
< date: Tue, 20 May 2025 02:10:10 GMT
< server: envoy
< x-envoy-upstream-service-time: 97
<
* Connection #0 to host httpbin.istioinaction left intact
invalid header value for: x-test-cohort
- 정상 응답 예시:
{
"headers": {
"Accept": "*/*",
"Content-Length": "0",
"Host": "httpbin.istioinaction:8000",
"User-Agent": "curl/7.69.1",
"X-B3-Sampled": "1",
"X-B3-Spanid": "1d066f4b17ee147b",
"X-B3-Traceid": "1ec27110e4141e131d066f4b17ee147b",
"X-Test-Cohort": "dark-launch-7"
}
}
- x-test-cohort 헤더가 포함되어 있다면 Lua 필터가 정상적으로 동작하는 것입니다.
Lua 필터는 요청에 x-test-cohort 헤더를 추가하며,
curl로 테스트해 동작을 확인할 수 있습니다.
📌 핵심 요약
- Lua 필터의 역할: Lua 스크립트를 사용해 Envoy의 요청/응답 경로에 커스텀 로직을 추가하며, 헤더 조작이나 외부 서비스 호출이 가능합니다.
- A/B 테스트 예제: httpCall로 bucket-tester 서비스를 호출해 A/B 테스트 그룹을 결정하고, 결과를 x-test-cohort 헤더로 추가합니다.
- EnvoyFilter 설정: Lua 스크립트를 HCM 필터 체인에 삽입해 httpbin 워크로드에 적용합니다.
- 주의사항: 요청 본문 처리는 성능에 영향을 줄 수 있으며, Envoy의 내장 함수(httpCall)를 사용해야 스레드 안전성을 보장합니다.
'Istio Hands-on Study [1기]' 카테고리의 다른 글
[8주차] 가상 머신 워크로드를 Mesh 에 통합 : Istio의 VM 지원 (0) | 2025.05.26 |
---|---|
[7주차] 요청 경로에서 Istio 확장 : WebAssembly로 Istio의 Data Plane 확장 (0) | 2025.04.23 |
[7주차] 요청 경로에서 Istio 확장 : 외부 콜아웃으로 요청 속도 제한 (0) | 2025.04.23 |
[7주차] 요청 경로에서 Istio 확장 : EnvoyFilter 리소스로 Envoy 필터 구성 (0) | 2025.04.23 |
[7주차] 요청 경로에서 Istio 확장 : Envoy의 확장 기능 (0) | 2025.04.23 |
Comments