Skip to content

Commit 01444dd

Browse files
committed
feat(enricher): make ring buffer capacity configurable
Signed-off-by: Matthew McKeen <matthew.mckeen@fastly.com>
1 parent 577d917 commit 01444dd

11 files changed

Lines changed: 74 additions & 14 deletions

File tree

cmd/standard/daemon.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,11 @@ func (d *Daemon) Start() error {
245245
if daemonConfig.EnablePodLevel {
246246
pubSub := pubsub.New()
247247
controllerCache := controllercache.New(pubSub)
248-
enrich := enricher.New(ctx, controllerCache)
248+
ringCap, capErr := enricher.RingCapacityOrDefault(daemonConfig.EnricherRingCapacity)
249+
if capErr != nil {
250+
mainLogger.Fatal("invalid enricher ring capacity", zap.Error(capErr))
251+
}
252+
enrich := enricher.New(ctx, controllerCache, ringCap)
249253
//nolint:govet // shadowing this err is fine
250254
fm, err := filtermanager.Init(5, daemonConfig.FilterMapMaxEntries) //nolint:gomnd // defaults
251255
if err != nil {

deploy/standard/manifests/controller/helm/retina/templates/configmap.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ data:
3030
packetParserRingBuffer: {{ .Values.packetParserRingBuffer }}
3131
packetParserRingBufferSize: {{ .Values.packetParserRingBufferSize }}
3232
filterMapMaxEntries: {{ .Values.filterMapMaxEntries }}
33+
enricherRingCapacity: {{ .Values.enricherRingCapacity }}
3334
{{- end}}
3435
---
3536
{{- if .Values.os.windows}}

deploy/standard/manifests/controller/helm/retina/values.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ packetParserRingBufferSize: 8388608
7272
# This map tracks IP addresses of pods of interest for network observability.
7373
# Default: 255. Increase for large clusters with many tracked pods.
7474
filterMapMaxEntries: 255
75+
# Capacity of the enricher flow ring buffer. Must be one less than a power of two
76+
# (e.g. 1023, 4095, 65535). Default: 1023. Increase to absorb bursts and reduce enricher_ring drops.
77+
enricherRingCapacity: 1023
7578

7679
imagePullSecrets: []
7780
nameOverride: "retina"

docs/02-Installation/03-Config.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Apply to both Agent and Operator.
5656
* `dataSamplingRate`: Defines the data sampling rate for `packetparser`. See [Sampling](../03-Metrics/plugins/Linux/packetparser.md#sampling) for more details.
5757
* `packetParserRingBuffer`: Selects the kernel-to-userspace transport for `packetparser`. Accepted values: `enabled` (ring buffer) or `disabled` (perf event array). `auto` is reserved for future use.
5858
* `packetParserRingBufferSize`: Ring buffer size in bytes when `packetParserRingBuffer=enabled`. Must be a power of two between the kernel page size and 1GiB (inclusive); invalid values cause startup to fail.
59+
* `enricherRingCapacity`: Capacity of the enricher flow ring buffer (default `1023`). Must be one less than a power of two (e.g. `1023`, `4095`, `65535`); invalid values cause startup to fail. Increase to absorb bursts and reduce `enricher_ring` lost events. Takes effect on agent restart.
5960

6061
## Operator Configuration
6162

pkg/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ type Config struct {
135135
PacketParserRingBufferSize uint32 `yaml:"packetParserRingBufferSize"`
136136
FilterMapMaxEntries uint32 `yaml:"filterMapMaxEntries"`
137137
EnableTCX TCXMode `yaml:"enableTCX"`
138+
EnricherRingCapacity uint32 `yaml:"enricherRingCapacity"`
138139
}
139140

140141
func GetConfig(cfgFilename string) (*Config, error) {

pkg/enricher/enricher.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package enricher
55

66
import (
77
"context"
8+
"fmt"
89
"reflect"
910
"sync"
1011

@@ -41,28 +42,41 @@ type Enricher struct {
4142
outputRing *container.Ring
4243
}
4344

44-
func New(ctx context.Context, c cache.CacheInterface) *Enricher {
45+
func New(ctx context.Context, c cache.CacheInterface, ringCapacity container.Capacity) *Enricher {
4546
once.Do(func() {
46-
e = newEnricher(ctx, c)
47+
e = newEnricher(ctx, c, ringCapacity)
4748
})
4849

4950
return e
5051
}
5152

52-
func newEnricher(ctx context.Context, c cache.CacheInterface) *Enricher {
53-
ir := container.NewRing(container.Capacity1023)
53+
func newEnricher(ctx context.Context, c cache.CacheInterface, ringCapacity container.Capacity) *Enricher {
54+
ir := container.NewRing(ringCapacity)
5455
enricher := &Enricher{
5556
ctx: ctx,
5657
l: log.Logger().Named("enricher"),
5758
cache: c,
5859
inputRing: ir,
5960
Reader: container.NewRingReader(ir, ir.OldestWrite()),
60-
outputRing: container.NewRing(container.Capacity1023),
61+
outputRing: container.NewRing(ringCapacity),
6162
}
6263
initialized = true
6364
return enricher
6465
}
6566

67+
// RingCapacityOrDefault converts a configured ring capacity to a container.Capacity,
68+
// using the default when n is 0. n must be one less than a power of two.
69+
func RingCapacityOrDefault(n uint32) (container.Capacity, error) {
70+
if n == 0 {
71+
return container.Capacity1023, nil
72+
}
73+
c, err := container.NewCapacity(int(n))
74+
if err != nil {
75+
return nil, fmt.Errorf("invalid ring capacity %d: %w", n, err)
76+
}
77+
return c, nil
78+
}
79+
6680
func Instance() *Enricher {
6781
return e
6882
}

pkg/enricher/enricher_test.go

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/cilium/cilium/api/v1/flow"
1414
v1 "github.com/cilium/cilium/pkg/hubble/api/v1"
15+
"github.com/cilium/cilium/pkg/hubble/container"
1516
retinav1alpha1 "github.com/microsoft/retina/crd/api/v1alpha1"
1617
"github.com/microsoft/retina/pkg/common"
1718
"github.com/microsoft/retina/pkg/controllers/cache"
@@ -102,7 +103,7 @@ func TestEnricher(t *testing.T) {
102103
err = c.UpdateRetinaEndpoint(destPod)
103104
require.NoError(t, err)
104105

105-
e := newEnricher(context.Background(), c)
106+
e := newEnricher(context.Background(), c, container.Capacity1023)
106107

107108
var wg sync.WaitGroup
108109
defer wg.Wait()
@@ -159,7 +160,7 @@ func TestEnricherSecondaryIPs(t *testing.T) {
159160
require.NoError(t, err)
160161

161162
// create new enricher (not using singleton here)
162-
e := newEnricher(ctx, c)
163+
e := newEnricher(ctx, c, container.Capacity1023)
163164
var wg sync.WaitGroup
164165

165166
wg.Add(1)
@@ -279,7 +280,7 @@ func TestEnricherZoneResolution(t *testing.T) {
279280
ctx, cancel := context.WithCancel(context.Background())
280281
defer cancel()
281282

282-
e := newEnricher(ctx, c)
283+
e := newEnricher(ctx, c, container.Capacity1023)
283284

284285
// Get the export reader before running and writing, so we don't miss events.
285286
oreader := e.ExportReader()
@@ -330,7 +331,7 @@ func TestEnricherZoneResolution_NoNode(t *testing.T) {
330331
ctx, cancel := context.WithCancel(context.Background())
331332
defer cancel()
332333

333-
e := newEnricher(ctx, c)
334+
e := newEnricher(ctx, c, container.Capacity1023)
334335

335336
oreader := e.ExportReader()
336337
e.Run()
@@ -357,3 +358,30 @@ func TestEnricherZoneResolution_NoNode(t *testing.T) {
357358
assert.Equal(t, "unknown", utils.SourceZone(enrichedFlow))
358359
assert.Equal(t, "unknown", utils.DestinationZone(enrichedFlow))
359360
}
361+
362+
func TestRingCapacityOrDefault(t *testing.T) {
363+
tests := []struct {
364+
name string
365+
n uint32
366+
want container.Capacity
367+
wantErr bool
368+
}{
369+
{"zero uses default", 0, container.Capacity1023, false},
370+
{"valid 1023", 1023, container.Capacity1023, false},
371+
{"valid 4095", 4095, container.Capacity4095, false},
372+
{"valid max 65535", 65535, container.Capacity65535, false},
373+
{"invalid not power-of-two-minus-one", 4096, nil, true},
374+
{"invalid arbitrary", 5000, nil, true},
375+
}
376+
for _, tt := range tests {
377+
t.Run(tt.name, func(t *testing.T) {
378+
got, err := RingCapacityOrDefault(tt.n)
379+
if tt.wantErr {
380+
require.Error(t, err)
381+
return
382+
}
383+
require.NoError(t, err)
384+
assert.Equal(t, tt.want, got)
385+
})
386+
}
387+
}

pkg/managers/controllermanager/controllermanager.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package controllermanager
44

55
import (
66
"context"
7+
"fmt"
78
"log/slog"
89
"time"
910

@@ -85,7 +86,11 @@ func (m *Controller) Init(ctx context.Context) error {
8586
m.cache = cache.New(m.pubsub)
8687

8788
// create enricher instance
88-
m.enricher = enricher.New(ctx, m.cache)
89+
ringCap, err := enricher.RingCapacityOrDefault(m.conf.EnricherRingCapacity)
90+
if err != nil {
91+
return fmt.Errorf("failed to resolve enricher ring capacity: %w", err)
92+
}
93+
m.enricher = enricher.New(ctx, m.cache, ringCap)
8994
}
9095

9196
return nil

pkg/plugin/ciliumeventobserver/ciliumeventobserver_linux_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"time"
1111

1212
v1 "github.com/cilium/cilium/pkg/hubble/api/v1"
13+
"github.com/cilium/cilium/pkg/hubble/container"
1314
"github.com/cilium/cilium/pkg/hubble/testutils"
1415
"github.com/cilium/cilium/pkg/monitor"
1516
monitorAPI "github.com/cilium/cilium/pkg/monitor/api"
@@ -31,7 +32,7 @@ func TestStartError(t *testing.T) {
3132
_, _ = log.SetupZapLogger(log.GetDefaultLogOpts())
3233

3334
c := cache.New(pubsub.New())
34-
e := enricher.New(ctxTimeout, c)
35+
e := enricher.New(ctxTimeout, c, container.Capacity1023)
3536
e.Run()
3637
defer e.Reader.Close()
3738

test/enricher/main_linux.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/cilium/cilium/api/v1/flow"
1111
v1 "github.com/cilium/cilium/pkg/hubble/api/v1"
12+
"github.com/cilium/cilium/pkg/hubble/container"
1213
"github.com/microsoft/retina/pkg/controllers/cache"
1314
"github.com/microsoft/retina/pkg/enricher"
1415
"github.com/microsoft/retina/pkg/log"
@@ -26,7 +27,7 @@ func main() {
2627
ctx := context.Background()
2728
c := cache.New(pubsub.New())
2829

29-
e := enricher.New(ctx, c)
30+
e := enricher.New(ctx, c, container.Capacity1023)
3031

3132
e.Run()
3233

0 commit comments

Comments
 (0)