Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for RHEL 4.18 kernels #1175

Merged
merged 7 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ See [Documentation](https://grafana.com/docs/beyla/) and the [tutorials](https:/
enabled. BTF became enabled by default on most Linux distributions with kernel 5.14 or higher.
You can check if your kernel has BTF enabled by verifying if `/sys/kernel/btf/vmlinux` exists on your system.
If you need to recompile your kernel to enable BTF, the configuration option `CONFIG_DEBUG_INFO_BTF=y` must be
set.
- eBPF enabled on the host
set.
- Beyla supports Linux distributions running RedHat Enterprise Linux 4.18 kernels build 348 and above as they have the required kernel backports. These include CentOS, AlmaLinux, and Oracle Linux.
- eBPF enabled on the host.
- For instrumenting Go programs, they must have been compiled with at least Go 1.17. We currently
support Go applications built with a major **Go version no earlier than 3 versions** behind the current
stable major release.
stable major release.
- Some level of elevated permissions to execute the instrumenter:
- On host systems, running Beyla requires `sudo`.
- For Kubernetes we have detailed configuration example on how to run with minimum
Expand Down
1 change: 1 addition & 0 deletions docs/sources/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Beyla offers the following features:
You can check if your kernel has BTF enabled by verifying if `/sys/kernel/btf/vmlinux` exists on your system.
If you need to recompile your kernel to enable BTF, the configuration option `CONFIG_DEBUG_INFO_BTF=y` must be
set.
- Alternatively, RHEL 4.18 Linux kernels (at least build 348) are also supported, due to their heavily backported nature.
- eBPF enabled in the host.
- For instrumenting Go programs, they must have been compiled with at least Go 1.17. We currently
support Go applications built with a major **Go version no earlier than 3 versions** behind the current
Expand Down
8 changes: 6 additions & 2 deletions pkg/beyla/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@ import (
"github.com/grafana/beyla/pkg/internal/helpers"
)

// Minimum required Kernel version: 5.8
const minKernMaj, minKernMin = 5, 8
// Minimum required Kernel version: 4.18
const minKernMaj, minKernMin = 4, 18

var kernelVersion = ebpfcommon.KernelVersion

func KernelVersion() (major, minor int) {
return kernelVersion()
}

// CheckOSSupport returns an error if the running operating system does not support
// the minimum required Beyla features.
func CheckOSSupport() error {
Expand Down
4 changes: 2 additions & 2 deletions pkg/beyla/os_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ func TestCheckOSSupport_Unsupported(t *testing.T) {
for _, tc := range []testCase{
{maj: 0, min: 0},
{maj: 3, min: 11},
{maj: 5, min: 0},
{maj: 5, min: 7},
{maj: 4, min: 0},
{maj: 4, min: 17},
} {
t.Run(fmt.Sprintf("%d.%d", tc.maj, tc.min), func(t *testing.T) {
overrideKernelVersion(tc)
Expand Down
6 changes: 5 additions & 1 deletion pkg/internal/ebpf/instrumenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ func (i *instrumenter) kprobes(p KprobesTracer) error {
log.Debug("going to add kprobe to function", "function", kfunc, "probes", kprobes)

if err := i.kprobe(kfunc, kprobes); err != nil {
return fmt.Errorf("instrumenting function %q: %w", kfunc, err)
if kprobes.Required {
return fmt.Errorf("instrumenting function %q: %w", kfunc, err)
}

log.Debug("error instrumenting kprobe", "function", kfunc, "error", err)
}
p.AddCloser(i.closables...)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/internal/ebpf/ktracer/ktracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ func (p *Tracer) KProbes() map[string]ebpfcommon.FunctionPrograms {
End: p.bpfObjects.KretprobeSysClone,
},
"sys_clone3": {
Required: true,
Required: false,
End: p.bpfObjects.KretprobeSysClone,
},
"sys_exit": {
Expand Down
2 changes: 1 addition & 1 deletion test/integration/multiprocess_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func TestMultiProcess(t *testing.T) {
assert.Empty(t, results)
})

if kprobeTraces {
if kprobeTracesEnabled() {
t.Run("Nested traces with kprobes: rust -> java -> node -> go -> python -> rails", func(t *testing.T) {
testNestedHTTPTracesKProbes(t)
})
Expand Down
2 changes: 1 addition & 1 deletion test/integration/red_test_nodeclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func testNodeClientWithMethodAndStatusCode(t *testing.T, method string, statusCo
We check that the traceID has that 16 character 0 suffix and then we
use the first 16 characters for looking up by Parent span.
*/
if kprobeTraces {
if kprobeTracesEnabled() {
assert.NotEmpty(t, span.TraceID)
assert.Truef(t, strings.HasSuffix(span.TraceID, traceIDLookup),
"string %q should have suffix %q", span.TraceID, traceIDLookup)
Expand Down
2 changes: 1 addition & 1 deletion test/integration/red_test_rust.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func testREDMetricsForRustHTTPLibrary(t *testing.T, url, comm, namespace string,
require.Len(t, res, 1)
parent := res[0]
require.NotEmpty(t, parent.TraceID)
if kprobeTraces {
if kprobeTracesEnabled() {
require.Equal(t, traceID, parent.TraceID)
// Validate that "parent" is a CHILD_OF the traceparent's "parent-id"
childOfPID := trace.ChildrenOf(parentID)
Expand Down
17 changes: 16 additions & 1 deletion test/integration/suites_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ import (

"github.com/stretchr/testify/require"

"github.com/grafana/beyla/pkg/beyla"
"github.com/grafana/beyla/test/integration/components/docker"
)

var kprobeTraces = true // allow tests to run distributed traces tests
func kprobeTracesEnabled() bool {
major, minor := beyla.KernelVersion()

return major > 5 || (major == 5 && minor >= 17)
}

func TestSuite(t *testing.T) {
compose, err := docker.ComposeSuite("docker-compose.yml", path.Join(pathOutput, "test-suite.log"))
Expand Down Expand Up @@ -492,6 +497,11 @@ func TestSuite_OverrideServiceName(t *testing.T) {
}

func TestSuiteNodeClient(t *testing.T) {
if !kprobeTracesEnabled() {
t.Skip("distributed traces not supported")
return
}

compose, err := docker.ComposeSuite("docker-compose-nodeclient.yml", path.Join(pathOutput, "test-suite-nodeclient.log"))
compose.Env = append(compose.Env, `BEYLA_EXECUTABLE_NAME=node`, `NODE_APP=client`)
require.NoError(t, err)
Expand All @@ -505,6 +515,11 @@ func TestSuiteNodeClient(t *testing.T) {
}

func TestSuiteNodeClientTLS(t *testing.T) {
if !kprobeTracesEnabled() {
t.Skip("distributed traces not supported")
return
}

compose, err := docker.ComposeSuite("docker-compose-nodeclient.yml", path.Join(pathOutput, "test-suite-nodeclient-tls.log"))
compose.Env = append(compose.Env, `BEYLA_EXECUTABLE_NAME=node`, `NODE_APP=client_tls`)
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion test/integration/traces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ func testHTTPTracesKProbes(t *testing.T) {
require.Len(t, res, 1)
parent := res[0]
require.NotEmpty(t, parent.TraceID)
if kprobeTraces {
if kprobeTracesEnabled() {
require.Equal(t, traceID, parent.TraceID)
// Validate that "parent" is a CHILD_OF the traceparent's "parent-id"
childOfPID := trace.ChildrenOf(parentID)
Expand Down
Loading