Skip to content

Commit 93c3d87

Browse files
committed
feat(deps): upgrade Cilium to v1.19.0
Upgrade the Cilium dependency from v1.18.0-pre.1 to v1.19.0 and adapt the codebase to breaking API changes. Key changes: - Rewrite Hubble flow enrichment and DNS parsing to work with Cilium v1.19 APIs (structpb-based extensions replace RetinaMetadata) - Add DI stubs for new Cilium cell/hive requirements - Resolve duplicate workqueue metrics providers - Add new eBPF-based DNS and TCP retransmission plugins - Bump Go base images to 1.25.7 and go directive to 1.25.0 - Remove cross-compilation from Dockerfiles for native arm64 builds via QEMU (Microsoft Go 1.25 requires CGO_ENABLED=1 for crypto) - Fix prometheus metric parsing with prometheus/common v0.67.5 - Upgrade golangci-lint from v1 to v2.9.0; set CGO_ENABLED=0 for lint to prevent typecheck errors from _cprog C source directories - Fix DNS metrics by moving recordsChannel creation outside EnablePodLevel conditional Refs: #1788 Signed-off-by: Quang Nguyen <nguyenquang@microsoft.com>
1 parent 180822f commit 93c3d87

File tree

104 files changed

+3756
-2229
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+3756
-2229
lines changed

.github/workflows/golangci-lint.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,17 @@ jobs:
2727
env:
2828
GOOS: ${{ matrix.goos }}
2929
GOARCH: ${{ matrix.goarch }}
30+
CGO_ENABLED: "0"
3031
steps:
3132
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
3233
with:
3334
fetch-depth: 0
3435
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
3536
with:
3637
go-version-file: go.mod
38+
- name: Check BPF object stubs
39+
if: env.IS_NOT_MERGE_GROUP
40+
run: make lint-bpf-objects
3741
- name: golangci-lint
3842
uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0
3943
with:

.gitignore

Lines changed: 26 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,43 @@
1-
# If you prefer the allow list template instead of the deny list, see community template:
2-
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3-
#
4-
# Binaries for programs and plugins
1+
# Binaries
52
*.exe
63
*.exe~
74
*.dll
85
*.so
96
*.dylib
10-
11-
# Avoid checking in keys
12-
*.pem
13-
14-
# Test binary, built with `go test -c`
157
*.test
16-
17-
# Output of the go coverage tool, specifically when used with LiteIDE
18-
*.out
19-
20-
# logs
21-
*.log
22-
23-
# Dependency directories (remove the comment below to include it)
24-
# vendor/
25-
26-
# Go workspace file
27-
go.work
28-
29-
# Object files
308
*.o
9+
bin/
10+
dist/
3111

32-
# docusaurus
33-
site/yarn.lock
34-
site/.docusaurus/
35-
site/node_modules/
12+
# Go
13+
go.work
3614

37-
output
38-
#vscode
39-
.vscode/
15+
# Keys and certificates
16+
*.pem
17+
.certs/
4018

41-
dist/
42-
bin/
19+
# Logs and output
20+
*.log
21+
*.out
22+
.output/
4323

44-
image-metadata-*.json
45-
*packetmonitorsupport*/
46-
*.pem
24+
# Test artifacts
4725
*results*.json
4826
netperf-*.json
4927
netperf-*.csv
28+
image-metadata-*.json
29+
*packetmonitorsupport*/
30+
test-summary
5031

51-
.certs/
32+
# Build artifacts
33+
.artifacts/
5234

53-
artifacts/
35+
# Documentation site
36+
site/yarn.lock
37+
site/.docusaurus/
38+
site/node_modules/
5439

55-
test-summary
40+
# IDE and editor
41+
.vscode/
42+
.clangd
43+
.clang-format

Makefile

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ help: ## Display this help
9696
##@ Tools
9797

9898
GOFUMPT = go tool mvdan.cc/gofumpt
99-
GOLANGCI_LINT = go tool github.com/golangci/golangci-lint/cmd/golangci-lint
99+
GOLANGCI_LINT = go tool github.com/golangci/golangci-lint/v2/cmd/golangci-lint
100100
GORELEASER = go tool github.com/goreleaser/goreleaser
101101
CONTROLLER_GEN = go tool sigs.k8s.io/controller-tools/cmd/controller-gen
102102
GINKGO = go tool github.com/onsi/ginkgo
@@ -141,10 +141,24 @@ fmt: ## run gofumpt on $FMT_PKG (default "retina").
141141
$(GOFUMPT) -w $(FMT_PKG)
142142

143143
lint: ## Fast lint vs default branch showing only new issues.
144-
$(GOLANGCI_LINT) run --new-from-rev main --timeout 10m -v $(LINT_PKG)/...
144+
CGO_ENABLED=0 $(GOLANGCI_LINT) run --new-from-rev main --timeout 10m -v $(LINT_PKG)/...
145145

146146
lint-existing: ## Lint the current branch in entirety.
147-
$(GOLANGCI_LINT) run -v $(LINT_PKG)/...
147+
CGO_ENABLED=0 $(GOLANGCI_LINT) run -v $(LINT_PKG)/...
148+
149+
lint-bpf-objects: ## Check that committed .o files are empty stubs (build generates real ones).
150+
@echo "Checking for non-empty .o files..."
151+
@non_empty=$$(git ls-files '*.o' | xargs -I{} sh -c 'test -s "{}" && echo "{}"'); \
152+
if [ -n "$$non_empty" ]; then \
153+
echo "ERROR: The following .o files must be empty stubs:"; \
154+
echo "$$non_empty"; \
155+
echo "Run 'make empty-bpf-objects' to fix."; \
156+
exit 1; \
157+
fi
158+
@echo "All .o files are empty stubs. OK."
159+
160+
empty-bpf-objects: ## Empty all tracked .o files (they are stubs for the linter).
161+
git ls-files '*.o' | xargs -I{} truncate -s 0 {}
148162

149163
clean: ## clean build artifacts
150164
$(RMDIR) $(OUTPUT_DIR)

cli/Dockerfile

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.24.11-azurelinux3.0 --format "{{.Name}}@{{.Digest}}"
2-
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/oss/go/microsoft/golang@sha256:531bd02db17b0c2ec919f10fc203a6a8c825e8ca01f40c3a1e32e1cf7119c6d8 AS builder
1+
# skopeo inspect docker://mcr.microsoft.com/oss/go/microsoft/golang:1.25.7-azurelinux3.0 --format "{{.Name}}@{{.Digest}}"
2+
FROM mcr.microsoft.com/oss/go/microsoft/golang@sha256:408661cbcfcbf24c06fc4f85c23566b42af722fdef5a5044782859e682916be7 AS builder
33

44
ARG VERSION
55
ARG APP_INSIGHTS_ID
@@ -16,21 +16,21 @@ ARG GOARCH=amd64
1616
ENV GOARCH=${GOARCH}
1717

1818
RUN --mount=type=cache,target="/root/.cache/go-build" \
19-
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
19+
GOOS=$GOOS GOARCH=$GOARCH go build \
2020
-ldflags "-X github.com/microsoft/retina/internal/buildinfo.Version="$VERSION" \
2121
-X "github.com/microsoft/retina/internal/buildinfo.ApplicationInsightsID"="$APP_INSIGHTS_ID" \
2222
-X "github.com/microsoft/retina/internal/buildinfo.RetinaAgentImageName"="$AGENT_IMAGE_NAME"" \
2323
-a -o kubectl-retina cli/main.go
2424

2525
# Target 1: Distroless (secure, minimal)
2626
# skopeo inspect docker://mcr.microsoft.com/azurelinux/distroless/minimal:3.0 --format "{{.Name}}@{{.Digest}}"
27-
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c AS distroless-target
27+
FROM mcr.microsoft.com/azurelinux/distroless/minimal@sha256:0801b80a0927309572b9adc99bd1813bc680473175f6e8175cd4124d95dbd50c AS distroless-target
2828
WORKDIR /
2929
COPY --from=builder /workspace/kubectl-retina .
3030

3131
# Target 2: Shell-enabled (operational, init container support)
3232
# skopeo inspect docker://mcr.microsoft.com/cbl-mariner/base/core:2.0 --format "{{.Name}}@{{.Digest}}"
33-
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/cbl-mariner/base/core@sha256:4d97d662d71c1fda938ed9df36d8f490d9107cff37e89c0efa932d073285ad85 AS shell-target
33+
FROM mcr.microsoft.com/cbl-mariner/base/core@sha256:4d97d662d71c1fda938ed9df36d8f490d9107cff37e89c0efa932d073285ad85 AS shell-target
3434
WORKDIR /
3535
COPY --from=builder /workspace/kubectl-retina /bin/kubectl-retina
3636
RUN chmod +x /bin/kubectl-retina

cmd/hubble/cells_linux.go

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,21 @@
55
package hubble
66

77
import (
8+
"github.com/cilium/cilium/pkg/datapath/link"
89
"github.com/cilium/cilium/pkg/defaults"
910
"github.com/cilium/cilium/pkg/gops"
1011
hubblecell "github.com/cilium/cilium/pkg/hubble/cell"
11-
exportercell "github.com/cilium/cilium/pkg/hubble/exporter/cell"
12+
ciliumparser "github.com/cilium/cilium/pkg/hubble/parser"
1213
k8sClient "github.com/cilium/cilium/pkg/k8s/client"
14+
"github.com/cilium/cilium/pkg/kpr"
15+
"github.com/cilium/cilium/pkg/kvstore"
1316
"github.com/cilium/cilium/pkg/logging"
1417
"github.com/cilium/cilium/pkg/logging/logfields"
1518
"github.com/cilium/cilium/pkg/node/manager"
1619
"github.com/cilium/cilium/pkg/option"
1720
"github.com/cilium/cilium/pkg/pprof"
18-
"github.com/cilium/cilium/pkg/recorder"
1921
"github.com/cilium/hive/cell"
22+
"github.com/cilium/statedb"
2023
"k8s.io/client-go/rest"
2124

2225
"github.com/microsoft/retina/internal/buildinfo"
@@ -31,6 +34,20 @@ import (
3134
"github.com/microsoft/retina/pkg/shared/telemetry"
3235
)
3336

37+
// disabledKVStoreClient wraps a kvstore.Client but returns IsEnabled() = false.
38+
// This is needed because K8sCiliumEndpointsWatcher only initializes if kvstore is disabled.
39+
// When kvstore is enabled, Cilium expects CiliumEndpoint data to come from kvstore,
40+
// but Retina watches CiliumEndpoint CRDs directly and needs the watcher to populate IPCache.
41+
type disabledKVStoreClient struct {
42+
kvstore.Client
43+
}
44+
45+
// IsEnabled returns false to indicate kvstore is not being used for CiliumEndpoint sync.
46+
// This allows the K8sCiliumEndpointsWatcher to initialize and populate IPCache with K8sMetadata.
47+
func (d *disabledKVStoreClient) IsEnabled() bool {
48+
return false
49+
}
50+
3451
var (
3552
Agent = cell.Module(
3653
"agent",
@@ -39,7 +56,7 @@ var (
3956
ControlPlane,
4057
)
4158
daemonSubsys = "daemon"
42-
logger = logging.DefaultLogger.WithField(logfields.LogSubsys, daemonSubsys)
59+
logger = logging.DefaultSlogLogger.With(logfields.LogSubsys, daemonSubsys)
4360

4461
Infrastructure = cell.Module(
4562
"infrastructure",
@@ -61,6 +78,19 @@ var (
6178
// Kubernetes client
6279
k8sClient.Cell,
6380

81+
// Kube proxy replacement config (needed by loadbalancer cells)
82+
kpr.Cell,
83+
84+
// Provide a disabled kvstore client for Retina.
85+
// This is important: the K8sCiliumEndpointsWatcher only initializes
86+
// if kvstore.IsEnabled() returns false (because with a real kvstore,
87+
// CiliumEndpoint data would come from kvstore instead of watching CRDs).
88+
// Since Retina doesn't use etcd/consul and relies on watching CiliumEndpoint CRDs,
89+
// we need IsEnabled() to return false so the watcher populates IPCache with K8sMetadata.
90+
cell.Provide(func(db *statedb.DB) kvstore.Client {
91+
return &disabledKVStoreClient{Client: kvstore.NewInMemoryClient(db, "default")}
92+
}),
93+
6494
cell.Provide(func(cfg config.Config, k8sCfg *rest.Config) telemetry.Config {
6595
return telemetry.Config{
6696
Component: "retina-agent",
@@ -92,11 +122,11 @@ var (
92122

93123
retinak8s.Cell,
94124

95-
recorder.Cell,
96-
97125
// Provides resources for hubble
98126
resources.Cell,
99-
cell.Provide(parser.New),
127+
128+
// Provides link cache needed by hubble parser
129+
link.Cell,
100130

101131
// Provides the node reconciler as node manager
102132
rnode.Cell,
@@ -106,9 +136,13 @@ var (
106136
},
107137
),
108138

109-
exportercell.Cell,
110-
// Provides the hubble agent
111-
hubblecell.Core,
139+
// Provides the full hubble agent (includes parser, exporter, metrics, and TLS)
140+
hubblecell.Cell,
141+
142+
// Override Cilium's parser with Retina's parser that understands v1.Event from plugins
143+
cell.DecorateAll(func(_ ciliumparser.Decoder, params parser.Params) ciliumparser.Decoder {
144+
return parser.New(params)
145+
}),
112146

113147
telemetry.Heartbeat,
114148
)

cmd/hubble/daemon_linux.go

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ package hubble
77
import (
88
"context"
99
"fmt"
10+
"log/slog"
1011

1112
"github.com/pkg/errors"
12-
"github.com/sirupsen/logrus"
1313

1414
"github.com/microsoft/retina/pkg/config"
15+
"github.com/microsoft/retina/pkg/log"
1516
"github.com/microsoft/retina/pkg/managers/pluginmanager"
1617
"github.com/microsoft/retina/pkg/managers/servermanager"
1718

@@ -20,7 +21,6 @@ import (
2021
v1 "github.com/cilium/cilium/pkg/hubble/api/v1"
2122
hubblecell "github.com/cilium/cilium/pkg/hubble/cell"
2223
"github.com/cilium/cilium/pkg/ipcache"
23-
"github.com/cilium/cilium/pkg/k8s"
2424
k8sClient "github.com/cilium/cilium/pkg/k8s/client"
2525
"github.com/cilium/cilium/pkg/k8s/watchers"
2626
monitoragent "github.com/cilium/cilium/pkg/monitor/agent"
@@ -34,7 +34,6 @@ import (
3434
ctrl "sigs.k8s.io/controller-runtime"
3535
"sigs.k8s.io/controller-runtime/pkg/client"
3636
logf "sigs.k8s.io/controller-runtime/pkg/log"
37-
zapf "sigs.k8s.io/controller-runtime/pkg/log/zap"
3837
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
3938
)
4039

@@ -44,7 +43,9 @@ var (
4443
"daemon",
4544
"Retina-Agent Daemon",
4645
// Create the controller manager, provides the hive with the controller manager and its client
47-
cell.Provide(func(k8sCfg *rest.Config, logger logrus.FieldLogger, rcfg config.RetinaHubbleConfig) (ctrl.Manager, client.Client, error) {
46+
cell.Provide(func(
47+
k8sCfg *rest.Config, logger *slog.Logger, rcfg config.RetinaHubbleConfig,
48+
) (ctrl.Manager, client.Client, error) {
4849
if err := corev1.AddToScheme(scheme); err != nil { //nolint:govet // intentional shadow
4950
logger.Error("failed to add corev1 to scheme")
5051
return nil, nil, errors.Wrap(err, "failed to add corev1 to scheme")
@@ -60,7 +61,7 @@ var (
6061
LeaderElectionID: "ecaf1259.retina.io",
6162
}
6263

63-
logf.SetLogger(zapf.New())
64+
logf.SetLogger(log.LogrLogger())
6465
ctrlManager, err := ctrl.NewManager(k8sCfg, mgrOption)
6566
if err != nil {
6667
logger.Error("failed to create manager")
@@ -71,7 +72,7 @@ var (
7172
}),
7273

7374
// Start the controller manager
74-
cell.Invoke(func(l logrus.FieldLogger, lifecycle cell.Lifecycle, ctrlManager ctrl.Manager) {
75+
cell.Invoke(func(l *slog.Logger, lifecycle cell.Lifecycle, ctrlManager ctrl.Manager) {
7576
var wp *workerpool.WorkerPool
7677
lifecycle.Append(
7778
cell.Hook{
@@ -99,7 +100,7 @@ var (
99100
type Daemon struct {
100101
clientset k8sClient.Clientset
101102

102-
log logrus.FieldLogger
103+
log *slog.Logger
103104
monitorAgent monitoragent.Agent
104105
pluginManager *pluginmanager.PluginManager
105106
HTTPServer *servermanager.HTTPServer
@@ -108,7 +109,6 @@ type Daemon struct {
108109
k8swatcher *watchers.K8sWatcher
109110
localNodeStore *node.LocalNodeStore
110111
ipc *ipcache.IPCache
111-
svcCache k8s.ServiceCache
112112
hubble hubblecell.HubbleIntegration
113113
}
114114

@@ -124,33 +124,34 @@ func newDaemon(params *daemonParams) *Daemon {
124124
k8swatcher: params.K8sWatcher,
125125
localNodeStore: params.Lnds,
126126
ipc: params.IPC,
127-
svcCache: params.SvcCache,
128127
hubble: params.Hubble,
129128
}
130129
}
131130

132131
func (d *Daemon) Run(ctx context.Context) error {
133132
// Start K8s watcher
134-
d.log.WithField("localNodeStore", d.localNodeStore).Info("Starting local node store")
133+
d.log.Info("Starting local node store", "localNodeStore", d.localNodeStore)
135134

136135
// Start K8s watcher. Will block till sync is complete or timeout.
137136
// If sync doesn't complete within timeout (3 minutes), causes fatal error.
138137
retinak8s.Start(ctx, d.k8swatcher)
139138

139+
d.log.Info("Starting generateEvents goroutine", "eventChanCap", cap(d.eventChan))
140140
go d.generateEvents(ctx)
141141
return nil
142142
}
143143

144144
func (d *Daemon) generateEvents(ctx context.Context) {
145+
d.log.Info("generateEvents started, waiting for events on eventChan")
145146
for {
146147
select {
147148
case <-ctx.Done():
149+
d.log.Info("generateEvents context done, exiting")
148150
return
149151
case event := <-d.eventChan:
150-
d.log.WithField("event", event).Debug("Sending event to monitor agent")
151152
err := d.monitorAgent.SendEvent(0, event)
152153
if err != nil {
153-
d.log.WithError(err).Error("Unable to send event to monitor agent")
154+
d.log.Error("Unable to send event to monitor agent", "error", err)
154155
}
155156
}
156157
}

0 commit comments

Comments
 (0)