Repository navigation
Reduce memory utilization in Envoy egress gateway by deduplicating policy object - #2651
Conversation
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
|
Benchmark results of single core dataplane with 1000QPS of H/1 requests did not change from baseline. As expected. |
|
is this ready for review? |
|
I ran a small egress test with this change and see some big improvements on memory per tunnel. Setup: 100 actors × 1,000 endpoints = 100,000 HTTPS tunnels. Every actor has the same 1,000-host policy. One gateway replica (16 Envoy threads).
|
Yes it is. Test failed due to unrelated flake. I will try to re-start it. |
Lior Lieberman (LiorLieberman)
left a comment
There was a problem hiding this comment.
nice improvement in memory!! thanks
| }; | ||
| envoy_log_trace!("egress policy store: policy={:?}", policy); | ||
| let mut local_store = GlobalEgressPolicyStore::get_local_store(); | ||
| if let Some(existing_policy) = local_store.lookup(policy.hash) { |
There was a problem hiding this comment.
is there a chance of collision here? I read that its small, but how expensive is it for us to compare the full policy on a store hit and fail closed if it doesn't match?
There was a problem hiding this comment.
I'm not sure. Could be a lot of string comparisons for policies with a lot of SNIs. I have added a sanity check for now. We could see if it shows up in CPU profiles for load tests.
|
|
||
| ## What it decides | ||
| To minimize memory usage egress policies are hashed using [Rapidhash](https://docs.rs/rapidhash/latest/rapidhash/) | ||
| which produces collision resistant 64 bit hashes. Policies are then stored in the worker local |
There was a problem hiding this comment.
nit: this is not really collision resistant since its non cryto.
| @@ -63,6 +63,12 @@ const ( | |||
| // the egress-policy module: {"rules": [{"pattern": ..., "mode": ...}]}, | |||
| // most specific first. | |||
There was a problem hiding this comment.
suggesting this for line 61-68
// EgressPolicyMetadataNamespace holds the SNI rules returned on CONNECT, as
// JSON under EgressPolicyJSONKey: {"rules": [{"pattern": ..., "mode": ...}]},
// most specific first.
EgressPolicyMetadataNamespace = "dev.ate.policy.egress"
// EgressPolicyHashFilterStateKey holds the hash the inner listener uses to
// find those rules in the egress-policy module's per-thread store.
EgressPolicyHashFilterStateKey = "dev.ate.policy.egress.hash"There was a problem hiding this comment.
I have changed comments and fixed the doc.
Signed-off-by: Yan Avlasov <[email protected]>
Signed-off-by: Yan Avlasov <[email protected]>
This PR reduces memory usage by SNI based egress policies, surface by scalability tests with 1M actors and policies and 1K SNI rules per policy.
The cause of memory consumption was two fold:
This PR makes two high level changes:
With this change, if all actors have exactly the same policy, Envoy will only have 1 copy of the policy object per worker thread.