Skip to content

Add inspektor-gadget and Headlamp with inspektor-gadget plugin#560

Open
rustyrazorblade wants to merge 1 commit intomainfrom
claude/issue-384-20260312-1735
Open

Add inspektor-gadget and Headlamp with inspektor-gadget plugin#560
rustyrazorblade wants to merge 1 commit intomainfrom
claude/issue-384-20260312-1735

Conversation

@rustyrazorblade
Copy link
Owner

Closes #384

Adds inspektor-gadget eBPF tracing daemon and Headlamp Kubernetes web UI with the inspektor-gadget plugin.

Changes

  • InspektorGadgetManifestBuilder: deploys ig daemon as a privileged DaemonSet on all cluster nodes with RBAC and eBPF host mounts
  • HeadlampManifestBuilder: deploys Headlamp K8s web UI on the control plane (port 4466) with an init container that installs the @inspektor-gadget/headlamp-plugin via npx
  • Both builders registered in ServicesModule, wired into GrafanaUpdateConfig, and covered by K8s integration tests

Generated with Claude Code

- Add InspektorGadgetManifestBuilder: deploys ig daemon as a privileged
  DaemonSet on all cluster nodes with RBAC for K8s API access and
  eBPF host mounts (BPF filesystem, kernel debug, containerd socket)
- Add HeadlampManifestBuilder: deploys Headlamp K8s web UI on the
  control plane (port 4466) with an init container that installs the
  @inspektor-gadget/headlamp-plugin via npx
- Add HEADLAMP_PORT = 4466 to Constants.K8s
- Register both builders in ServicesModule and wire into GrafanaUpdateConfig
- Add K8s integration tests for both builders
- Update configuration/CLAUDE.md with new subpackage documentation

Co-authored-by: Jon Haddad <rustyrazorblade@users.noreply.github.com>
@claude
Copy link

claude bot commented Mar 12, 2026

Code Review

Overall this is well-structured and follows the existing Fabric8 builder pattern consistently. A few items worth addressing:

Import Ordering Violation (ktlint)

In GrafanaUpdateConfig.kt, the new imports are inserted out of alphabetical order:

import com.rustyrazorblade.easydblab.configuration.beyla.BeylaManifestBuilder
import com.rustyrazorblade.easydblab.configuration.headlamp.HeadlampManifestBuilder        // 'h'
import com.rustyrazorblade.easydblab.configuration.inspektorgadget.InspektorGadgetManifestBuilder  // 'i'
import com.rustyrazorblade.easydblab.configuration.clusterPrefix                          // 'c' ← should come before 'h'

clusterPrefix should appear before headlamp. This will likely fail ktlintCheck.

Overly Broad /run Volume Mount

InspektorGadgetManifestBuilder mounts both /run/containerd/containerd.sock and the entire /run directory:

VolumeMountBuilder().withName("containerd-sock").withMountPath("/run/containerd/containerd.sock").build(),
VolumeMountBuilder().withName("run").withMountPath("/run").build(),

The /run mount is very broad (covers all runtime sockets, PIDs, etc.) and makes the containerd-sock mount redundant. Does ig daemon actually need all of /run, or just the containerd socket? If it's only the socket, dropping the run volume reduces the host exposure.

Plugin Installation Requires Internet Access at Pod Start

The Headlamp init container runs:

npx --yes @kinvolk/headlamp-plugin install @inspektor-gadget/headlamp-plugin --dest /headlamp/plugins

This fetches npm packages at pod startup time. In air-gapped or restricted-network environments, the pod will fail to start. Worth noting in docs or adding a comment that network access is required. Also, npx without a pinned package version means the plugin version could change across deployments — consider pinning @kinvolk/headlamp-plugin@<version> for reproducibility.

withRollingUpdate(null) in Headlamp Deployment

.withNewStrategy()
.withType("Recreate")
.withRollingUpdate(null)   // ← unusual
.endStrategy()

Setting the type to "Recreate" is sufficient; Kubernetes ignores rollingUpdate for Recreate strategy. Explicitly passing null here is unusual and could behave unexpectedly depending on Fabric8 serialization. Just omit the .withRollingUpdate(null) call.

No Unit Tests for Manifest Structure

The integration tests verify resources can be applied to a real K8s API, but there are no unit tests verifying the manifest structure (e.g., that the DaemonSet has privileged=true, that the correct ports are set, that the toleration is present). Given the security-sensitive nature of the privileged DaemonSet config, a few unit tests asserting key fields would be valuable — similar to how you'd test that HEADLAMP_PORT constant propagates correctly to container/host ports.

Minor: Test Order Gap

Tests are ordered 20 (inspektor-gadget), 21 (grafana), 23 (headlamp) — skipping 22. Not a bug, just slightly inconsistent with the neighboring sequential numbering. Cosmetic only.

Looks Good

  • RBAC for both builders is appropriately scoped (read-only for Headlamp, CRD write for inspektor-gadget)
  • Toleration with operator: Exists (no key) is correct for running the DaemonSet on all nodes including tainted control-plane nodes
  • ClusterFirstWithHostNet DNS policy is correct when hostNetwork: true
  • factoryOf registration in ServicesModule follows the existing pattern
  • Constants properly placed in Constants.kt
  • CLAUDE.md updated to document both new subpackages

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add inspektor-gadget

1 participant