I have an app running in my cluster with Istio and due to some issue with app we cannot enables Istio sidecar therefore it is not possible for us to apply any kind of timeout settings in the VirtualService or traffic management settings using the DestinationRule.
We have been doing some tests and noticed that when we make our app pods unavailable (by scaling it to zero) the Istio Gateway start responding with “no healthy upstream” and returns a 503 status code. However it doesn’t close the connection when the upstream is nit available, it keeps it alive and the clients accessing our app keep reusing the connection and keep receiving 503. In this scenario the expected behavior for us is for the Istio Gateway to terminate the connection so when the clients open a new connection they end up in a different failover environment.
To make the Istio Gateway close the connection I tried using the following EnvoyFilter, where when the app pods are unavailable Istio Gateway should send Connection: close
in the header response but it didn’t work. However, we could send other custom header.
kind: EnvoyFilter
metadata:
name: close-connection-on-unhealthy-or-no-response
namespace: app-ns
spec:
configPatches:
- applyTo: HTTP_FILTER
match:
context: GATEWAY
listener:
portNumber: 80
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.lua
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
inline_code: |
function envoy_on_response(response_handle)
local headers = response_handle:headers()
-- Check if there are any response headers
if not headers or headers:get(":status") == nil then
-- If no response headers or no status code, close connection
response_handle:headers():add("Connection", "close")
return
end
-- Check for specific health-related headers or status codes
local upstream_health_flags = headers:get("x-envoy-upstream-health-flags")
local attempt_count = headers:get("x-envoy-attempt-count")
-- Close connection if upstream is unhealthy or multiple attempts were made
if upstream_health_flags or (attempt_count and tonumber(attempt_count) > 1) then
response_handle:headers():add("Connection", "close")
elseif headers:get(":status") == "503" then
-- Also close connection on 503 status code
response_handle:headers():add("Connection", "close")
end
end
Not sure why it cannot send the Connection: close
header response!
Is there any other way to initiate a connection termination using EnvoyFilter or by any other means in this sitaution?
1