Skip to content

Commit b4c06c9

Browse files
authored
Set GOMEMLIMIT on FLP (#2447)
* Set GOMEMLIMIT on FLP (Same as done on the agent) * Fix tests; do not set limit=0 * Make sure pods are restarted on changed args/envs
1 parent 56f1e43 commit b4c06c9

File tree

6 files changed

+29
-16
lines changed

6 files changed

+29
-16
lines changed

internal/controller/ebpf/agent_controller.go

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ const (
5656
envKafkaSASLIDPath = "KAFKA_SASL_CLIENT_ID_PATH"
5757
envKafkaSASLSecretPath = "KAFKA_SASL_CLIENT_SECRET_PATH"
5858
envLogLevel = "LOG_LEVEL"
59-
envGoMemLimit = "GOMEMLIMIT"
6059
envEnablePktDrop = "ENABLE_PKT_DROPS"
6160
envEnableDNSTracking = "ENABLE_DNS_TRACKING"
6261
envEnableFlowRTT = "ENABLE_RTT"
@@ -730,16 +729,8 @@ func getEnvConfig(coll *flowslatest.FlowCollector, cinfo *cluster.Info) []corev1
730729
})
731730
}
732731

733-
// set GOMEMLIMIT which allows specifying a soft memory cap to force GC when resource limit is reached
734-
// to prevent OOM
735-
if coll.Spec.Agent.EBPF.Resources.Limits.Memory() != nil {
736-
if memLimit, ok := coll.Spec.Agent.EBPF.Resources.Limits.Memory().AsInt64(); ok {
737-
// we will set the GOMEMLIMIT to current memlimit - 10% as a headroom to account for
738-
// memory sources the Go runtime is unaware of
739-
memLimit -= int64(float64(memLimit) * 0.1)
740-
config = append(config, corev1.EnvVar{Name: envGoMemLimit, Value: fmt.Sprint(memLimit)})
741-
}
742-
}
732+
// set GOMEMLIMIT which allows specifying a soft memory cap to force GC when resource limit is reached to prevent OOM
733+
config = helper.EnvFromReqsLimits(config, &coll.Spec.Agent.EBPF.Resources)
743734

744735
if coll.Spec.Agent.EBPF.IsPktDropEnabled() {
745736
config = append(config, corev1.EnvVar{

internal/controller/ebpf/agent_controller_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/stretchr/testify/assert"
1313
appsv1 "k8s.io/api/apps/v1"
1414
corev1 "k8s.io/api/core/v1"
15+
"k8s.io/apimachinery/pkg/api/resource"
1516
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1617
"k8s.io/utils/ptr"
1718
)
@@ -98,7 +99,6 @@ func TestGetEnvConfig_Default(t *testing.T) {
9899

99100
env := getEnvConfig(&fc, &cluster.Info{})
100101
assert.Equal(t, []corev1.EnvVar{
101-
{Name: "GOMEMLIMIT", Value: "0"},
102102
{Name: "METRICS_ENABLE", Value: "true"},
103103
{Name: "METRICS_SERVER_PORT", Value: "9400"},
104104
{Name: "METRICS_PREFIX", Value: "netobserv_agent_"},
@@ -129,6 +129,9 @@ func TestGetEnvConfig_WithOverrides(t *testing.T) {
129129
"TC_ATTACH_MODE": "any",
130130
},
131131
},
132+
Resources: corev1.ResourceRequirements{
133+
Limits: corev1.ResourceList{corev1.ResourceMemory: resource.MustParse("800Mi")},
134+
},
132135
Metrics: flowslatest.EBPFMetrics{
133136
Enable: ptr.To(false),
134137
},
@@ -148,7 +151,7 @@ func TestGetEnvConfig_WithOverrides(t *testing.T) {
148151

149152
env := getEnvConfig(&fc, &cluster.Info{})
150153
assert.Equal(t, []corev1.EnvVar{
151-
{Name: "GOMEMLIMIT", Value: "0"},
154+
{Name: "GOMEMLIMIT", Value: "754974720"},
152155
{Name: "FLOW_FILTER_RULES", Value: `[{"ip_cidr":"0.0.0.0/0","action":"Accept"}]`},
153156
{Name: "AGENT_IP", Value: "",
154157
ValueFrom: &corev1.EnvVarSource{
@@ -177,7 +180,6 @@ func TestGetEnvConfig_OCP4_14(t *testing.T) {
177180
info.Mock("4.14.5", "")
178181
env := getEnvConfig(&fc, &info)
179182
assert.Equal(t, []corev1.EnvVar{
180-
{Name: "GOMEMLIMIT", Value: "0"},
181183
{Name: "METRICS_ENABLE", Value: "true"},
182184
{Name: "METRICS_SERVER_PORT", Value: "9400"},
183185
{Name: "METRICS_PREFIX", Value: "netobserv_agent_"},

internal/controller/flp/flp_common_objects.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ func podTemplate(
161161
}
162162
envs = append(envs, constants.EnvNoHTTP2)
163163

164+
envs = helper.EnvFromReqsLimits(envs, &desired.Processor.Resources)
165+
164166
container := corev1.Container{
165167
Name: constants.FLPName,
166168
Image: imageName,

internal/controller/flp/flp_controller_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,9 @@ func ControllerSpecs() {
255255
Protocol: "TCP",
256256
}))
257257
g.Expect(cnt.Env).To(Equal([]v1.EnvVar{
258-
{Name: "GOGC", Value: "400"}, {Name: "GOMAXPROCS", Value: "33"}, {Name: "GODEBUG", Value: "http2server=0"},
258+
{Name: "GOGC", Value: "400"},
259+
{Name: "GOMAXPROCS", Value: "33"},
260+
{Name: "GODEBUG", Value: "http2server=0"},
259261
}))
260262

261263
By("Allocating the proper toleration to allow its placement in the master nodes")

internal/pkg/helper/comparators.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,9 @@ func volumesChanged(old, n *corev1.PodTemplateSpec, report *ChangeReport) bool {
130130
func containerChanged(old, n *corev1.Container, report *ChangeReport) bool {
131131
return report.Check("Image changed", n.Image != old.Image) ||
132132
report.Check("Pull policy changed", n.ImagePullPolicy != old.ImagePullPolicy) ||
133-
report.Check("Args changed", !deepDerivative(n.Args, old.Args)) ||
133+
report.Check("Args changed", !deepEqual(n.Args, old.Args)) ||
134134
report.Check("Resources req/limit changed", !deepDerivative(n.Resources, old.Resources)) ||
135+
report.Check("Env changed", !deepEqual(n.Env, old.Env)) ||
135136
report.Check("Liveness probe changed", probeChanged(n.LivenessProbe, old.LivenessProbe)) ||
136137
report.Check("Startup probe changed", probeChanged(n.StartupProbe, old.StartupProbe))
137138
}

internal/pkg/helper/env.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package helper
22

33
import (
4+
"fmt"
5+
46
corev1 "k8s.io/api/core/v1"
57
)
68

@@ -24,3 +26,16 @@ func BuildEnvFromDefaults(config, defaults map[string]string) []corev1.EnvVar {
2426
}
2527
return result
2628
}
29+
30+
func EnvFromReqsLimits(envs []corev1.EnvVar, reqs *corev1.ResourceRequirements) []corev1.EnvVar {
31+
// set GOMEMLIMIT which allows specifying a soft memory cap to force GC when resource limit is reached to prevent OOM
32+
if reqs.Limits.Memory() != nil {
33+
if memLimit, ok := reqs.Limits.Memory().AsInt64(); ok && memLimit > 0 {
34+
// we will set the GOMEMLIMIT to current memlimit - 10% as a headroom to account for
35+
// memory sources the Go runtime is unaware of
36+
memLimit -= int64(float64(memLimit) * 0.1)
37+
envs = append(envs, corev1.EnvVar{Name: "GOMEMLIMIT", Value: fmt.Sprint(memLimit)})
38+
}
39+
}
40+
return envs
41+
}

0 commit comments

Comments
 (0)