Skip to content

Add LXC cgroup parsing so container.id is populated for LXC workloads #344

@ricardoamaro

Description

@ricardoamaro

Summary

Quark resolves container.id / container.name by parsing the process cgroup path in kube_parse_cgroup() (quark.c). Today that parser recognizes Kubernetes and OCI runtime scopes only. LXC has no pattern, so for LXC workloads qp->container stays NULL and ecs_container() never emits container.id, container.name, or container.runtime.

This blocks per container attribution on LXC hosts. Host level eBPF already sees every process across all LXC namespaces with one sensor per host, but the events cannot be tied back to a specific LXC container.

Evidence

  • quark.c: kube_parse_cgroup(const char *cgroup, char *container_id, size_t) is the only cgroup to id mapping.
  • quark-test.c: the supported patterns are containerd, cri-containerd and cri-o scopes:
    foo/cri-containerd-abc123.scope -> containerd://abc123
    foo/containerd-abc123.scope     -> containerd://abc123
    foo/crio-0123456789.scope       -> cri-o://0123456789
    
    There is no LXC case.
  • ecs.c: ecs_container() emits id, name, runtime only when a container is attached to the process.
  • go/quark/quark.go: the ECS path (quark_event_to_ecs via GetEventAsECS) emits the container block directly from C, so fixing the C parser is enough for ECS consumers. The structured Go Process struct does not expose a Container field today (it copies Cgroup only); structured consumers would need a separate binding change, out of scope here.

Proposed change

  1. Add an LXC cgroup matcher alongside the existing runtime patterns. Recognize at least:
    • lxc.payload.<name> (systemd cgroup driver, cgroup v2)
    • lxc/<name> and /lxc/<name> (classic layouts)
  2. Populate quark_container with the LXC name as id and name, and set runtime to lxc.
  3. Confirm container_runtime() in ecs.c maps the new runtime to "lxc".
  4. Consider making the matcher extensible. Some orchestrators set custom cgroup names, so a small table of known prefixes or an optional configurable pattern would cover non standard layouts without recompiling.

Tests

  • Add cases to quark-test.c for the LXC layouts above, asserting parsed id and name (tests first).
  • Negative case: a non container cgroup must still return no match.

Context

@haesbaert this comes from a real Linux host fleet running LXC plus custom orchestration. The host eBPF visibility is solid; the missing piece is the LXC to container.id mapping in the parser. Flagging you as the Quark owner to confirm the approach and which cgroup patterns we should support. Commercial and account context lives in a private tracking issue (linked from there).

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions