-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add cgroup v2 support for container id detector #3508
base: main
Are you sure you want to change the base?
Changes from 6 commits
4e26e1a
aa3640c
82e8099
f5ce8d2
a245a1b
cef565e
dd75a26
840d2ac
5a73738
1f5bf29
f34b099
5eaaa5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||
|
||
import ( | ||
"regexp" | ||
) | ||
|
||
const cgroupV1Path = "/proc/self/cgroup" | ||
|
||
var cgroupV1ContainerIDRe = regexp.MustCompile(`^.*/(?:.*-)?([0-9a-f]+)(?:\.|\s*$)`) | ||
|
||
func getContainerIDFromCGroupV1() (string, error) { | ||
return getContainerIDFromCGroupFile(cgroupV1Path, getContainerIDFromCgroupV1Line) | ||
} | ||
|
||
// getContainerIDFromCgroupV1Line returns the ID of the container from one string line. | ||
func getContainerIDFromCgroupV1Line(line string) string { | ||
matches := cgroupV1ContainerIDRe.FindStringSubmatch(line) | ||
if len(matches) <= 1 { | ||
return "" | ||
} | ||
return matches[1] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestGetContainerIDFromCgroupV1Line(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
line string | ||
expectedContainerID string | ||
}{ | ||
{ | ||
name: "with suffix", | ||
line: "13:name=systemd:/podruntime/docker/kubepods/ac679f8a8319c8cf7d38e1adf263bc08d23.aaaa", | ||
expectedContainerID: "ac679f8a8319c8cf7d38e1adf263bc08d23", | ||
}, | ||
{ | ||
name: "with prefix and suffix", | ||
line: "13:name=systemd:/podruntime/docker/kubepods/crio-dc679f8a8319c8cf7d38e1adf263bc08d23.stuff", | ||
expectedContainerID: "dc679f8a8319c8cf7d38e1adf263bc08d23", | ||
}, | ||
{ | ||
name: "no prefix and suffix", | ||
line: "13:name=systemd:/pod/d86d75589bf6cc254f3e2cc29debdf85dde404998aa128997a819ff991827356", | ||
expectedContainerID: "d86d75589bf6cc254f3e2cc29debdf85dde404998aa128997a819ff991827356", | ||
}, | ||
{ | ||
name: "with space", | ||
line: " 13:name=systemd:/pod/d86d75589bf6cc254f3e2cc29debdf85dde404998aa128997a819ff991827356 ", | ||
expectedContainerID: "d86d75589bf6cc254f3e2cc29debdf85dde404998aa128997a819ff991827356", | ||
}, | ||
{ | ||
name: "invalid hex string", | ||
line: "13:name=systemd:/podruntime/docker/kubepods/ac679f8a8319c8cf7d38e1adf263bc08d23zzzz", | ||
}, | ||
{ | ||
name: "no container id - 1", | ||
line: "pids: /", | ||
}, | ||
{ | ||
name: "no container id - 2", | ||
line: "pids: ", | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
containerID := getContainerIDFromCgroupV1Line(tc.line) | ||
assert.Equal(t, tc.expectedContainerID, containerID) | ||
}) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||
|
||
import ( | ||
"regexp" | ||
) | ||
|
||
const cgroupV2Path = "/proc/self/mountinfo" | ||
|
||
var cgroupV2ContainerIDRe = regexp.MustCompile(`.*/docker/containers/([0-9a-f]{64})/.*`) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is very docker specific. I found with podman there is a different format for the container layers, and I am also checking containerd. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same is used in Java here (https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/ca8e7b1385d95517f28103d834aba960a0baa477/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractor.java#L27), so it would need to be fixed in both. JavaScript is taking a different approach, I remember that we talked about containerd there and making it work: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cc @breedx-splk , @abhee11 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @svrnm Thanks for the heads-up. Looks like you pasted the same link twice, but it reads like the second one intended to link to a js discussion? Curious what the alt approach is... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @breedx-splk thanks for calling out the wrong link, here's the JS one: https://github.com/open-telemetry/opentelemetry-js-contrib/blob/f0a93685cfb43543b7ca577dd370d56576b49e3f/detectors/node/opentelemetry-resource-detector-container/src/detectors/ContainerDetector.ts#L54 |
||
|
||
func getContainerIDFromCGroupV2() (string, error) { | ||
return getContainerIDFromCGroupFile(cgroupV2Path, getContainerIDFromCgroupV2Line) | ||
} | ||
|
||
// getContainerIDFromCgroupV2Line returns the ID of the container from one string line. | ||
func getContainerIDFromCgroupV2Line(line string) string { | ||
matches := cgroupV2ContainerIDRe.FindStringSubmatch(line) | ||
if len(matches) <= 1 { | ||
return "" | ||
} | ||
return matches[1] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package resource // import "go.opentelemetry.io/otel/sdk/resource" | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestGetContainerIDFromCgroupV2Line(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
line string | ||
expectedContainerID string | ||
}{ | ||
{ | ||
name: "empty - 1", | ||
line: "456 375 0:143 / / rw,relatime master:175 - overlay overlay rw,lowerdir=/var/lib/docker/overlay2/l/37L57D2IM7MEWLVE2Q2ECNDT67:/var/lib/docker/overlay2/l/46FCA2JFPCSNFGAR5TSYLLNHLK,upperdir=/var/lib/docker/overlay2/4e82c300793d703c19bdf887bfdad8b0354edda884ea27a8a2df89ab292719a4/diff,workdir=/var/lib/docker/overlay2/4e82c300793d703c19bdf887bfdad8b0354edda884ea27a8a2df89ab292719a4/work", | ||
}, | ||
{ | ||
name: "empty - 2", | ||
line: "457 456 0:146 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw", | ||
}, | ||
{ | ||
name: "empty - 3", | ||
line: "383 457 0:147 /null /proc/kcore rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755", | ||
}, | ||
{ | ||
name: "resolv.conf", | ||
line: "472 456 254:1 /docker/containers/dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/vda1 rw", | ||
expectedContainerID: "dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183", | ||
}, | ||
{ | ||
name: "hostname", | ||
line: "473 456 254:1 /docker/containers/dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183/hostname /etc/hostname rw,relatime - ext4 /dev/vda1 rw", | ||
expectedContainerID: "dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183", | ||
}, | ||
{ | ||
name: "host", | ||
line: "474 456 254:1 /docker/containers/dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183/hosts /etc/hosts rw,relatime - ext4 /dev/vda1 rw", | ||
expectedContainerID: "dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183", | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
containerID := getContainerIDFromCgroupV2Line(tc.line) | ||
assert.Equal(t, tc.expectedContainerID, containerID) | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is still the right way to capture this for V1.
When used with podman I'm capturing the userID of the pod, not a container or an empty string.