diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 59b8b550ac..5bc244c65a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,7 +5,7 @@ jobs: strategy: matrix: go-versions: ['1.25'] - platform: [ubuntu-22.04] + platform: [ubuntu-24.04] environment-variables: [build/config/plain.sh, build/config/libpfm4.sh, build/config/libipmctl.sh] runs-on: ${{ matrix.platform }} timeout-minutes: 30 @@ -32,7 +32,7 @@ jobs: strategy: matrix: go-versions: ['1.25'] - platform: [ubuntu-22.04] + platform: [ubuntu-24.04] environment-variables: [build/config/plain.sh, build/config/libpfm4.sh, build/config/libipmctl.sh] runs-on: ${{ matrix.platform }} timeout-minutes: 30 diff --git a/build/integration.sh b/build/integration.sh index a743ebcc70..bc158badc9 100755 --- a/build/integration.sh +++ b/build/integration.sh @@ -33,6 +33,34 @@ fi TEST_PID=$$ printf "" # Refresh sudo credentials if necessary. + +# Diagnostic logging for docker/containerd debugging +echo ">> Diagnostic information:" +echo "=== Docker version ===" +docker version || echo "docker version failed" +echo "=== Docker info ===" +docker info || echo "docker info failed" +echo "=== Containerd socket check ===" +ls -la /run/containerd/ 2>/dev/null || echo "/run/containerd/ not found" +ls -la /var/run/containerd/ 2>/dev/null || echo "/var/run/containerd/ not found" +ls -la /var/run/docker/containerd/ 2>/dev/null || echo "/var/run/docker/containerd/ not found" +echo "=== Find all containerd sockets ===" +find /var/run /run -name "*.sock" 2>/dev/null | head -20 || echo "No sockets found" +echo "=== Docker socket check ===" +ls -la /var/run/docker.sock 2>/dev/null || echo "/var/run/docker.sock not found" +echo "=== Running processes (docker/containerd) ===" +ps aux | grep -E "(docker|containerd)" | grep -v grep || echo "No docker/containerd processes found" +echo "=== Kernel version ===" +uname -r +echo "=== End diagnostic information ===" + +# Detect containerd socket path - Docker-in-Docker uses a different path +CONTAINERD_SOCK="/run/containerd/containerd.sock" +if [ -S "/run/docker/containerd/containerd.sock" ]; then + CONTAINERD_SOCK="/run/docker/containerd/containerd.sock" + echo ">> Using Docker-embedded containerd socket: $CONTAINERD_SOCK" +fi + function start { set +e # We want to handle errors if cAdvisor crashes. echo ">> starting cAdvisor locally" @@ -41,7 +69,7 @@ function start { cadvisor_prereqs=sudo fi # cpu, cpuset, percpu, memory, disk, diskIO, network, perf_event metrics should be enabled. - GORACE="halt_on_error=1" $cadvisor_prereqs $cadvisor_bin --enable_metrics="cpu,cpuset,percpu,memory,disk,diskIO,network,perf_event" --env_metadata_whitelist=TEST_VAR --v=6 --logtostderr $CADVISOR_ARGS &> "$log_file" + GORACE="halt_on_error=1" $cadvisor_prereqs $cadvisor_bin --enable_metrics="cpu,cpuset,percpu,memory,disk,diskIO,network,perf_event" --env_metadata_whitelist=TEST_VAR --containerd="$CONTAINERD_SOCK" --v=6 --logtostderr $CADVISOR_ARGS &> "$log_file" exit_code=$? if [ $exit_code != 0 ]; then echo "!! cAdvisor exited unexpectedly with Exit $exit_code" diff --git a/cmd/go.mod b/cmd/go.mod index ec585065bb..4be9dee7ae 100644 --- a/cmd/go.mod +++ b/cmd/go.mod @@ -14,16 +14,13 @@ require github.com/google/cadvisor v0.0.0 replace github.com/google/cadvisor => ../ require ( - github.com/Rican7/retry v0.3.1 github.com/SeanDolphin/bqschema v1.0.0 github.com/Shopify/sarama v1.38.1 github.com/abbot/go-http-auth v0.4.0 github.com/gomodule/redigo v1.9.2 github.com/influxdb/influxdb v1.7.9 - github.com/mesos/mesos-go v0.0.11 github.com/onsi/ginkgo v1.16.5 // indirect github.com/onsi/gomega v1.24.1 // indirect - github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 // indirect github.com/prometheus/client_golang v1.22.0 github.com/stretchr/testify v1.10.0 golang.org/x/oauth2 v0.30.0 diff --git a/cmd/go.sum b/cmd/go.sum index 63c68813cd..f3f59181bf 100644 --- a/cmd/go.sum +++ b/cmd/go.sum @@ -8,8 +8,6 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOEl github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/Rican7/retry v0.3.1 h1:scY4IbO8swckzoA/11HgBwaZRJEyY9vaNJshcdhp1Mc= -github.com/Rican7/retry v0.3.1/go.mod h1:CxSDrhAyXmTMeEuRAnArMu1FHu48vtfjLREWqVl7Vw0= github.com/SeanDolphin/bqschema v1.0.0 h1:iCYFd5Qsw6caM2k5/SsITSL9+3kQCr+oz6pnNjWTq90= github.com/SeanDolphin/bqschema v1.0.0/go.mod h1:TYInVncsPIZH7kybQoIUNJ4pFX1cUc8LoP9RSOxIs6c= github.com/Shopify/sarama v1.38.1 h1:lqqPUPQZ7zPqYlWpTh+LQ9bhYNu2xJL6k1SJN4WVe2A= @@ -189,8 +187,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/mesos/mesos-go v0.0.11 h1:jMp9+W3zLu46g8EuP2su2Sjj7ipBh4N/g65c0kzGl/8= -github.com/mesos/mesos-go v0.0.11/go.mod h1:kPYCMQ9gsOXVAle1OsoY4I1+9kPu8GHkf88aV59fDr4= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible h1:aKW/4cBs+yK6gpqU3K/oIwk9Q/XICqd3zOX/UFuvqmk= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= @@ -238,8 +234,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20= -github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= diff --git a/cmd/internal/container/install/install.go b/cmd/internal/container/install/install.go index 5d3153c727..324c341656 100644 --- a/cmd/internal/container/install/install.go +++ b/cmd/internal/container/install/install.go @@ -17,7 +17,6 @@ package install import ( // Register all included container providers. - _ "github.com/google/cadvisor/cmd/internal/container/mesos/install" _ "github.com/google/cadvisor/container/containerd/install" _ "github.com/google/cadvisor/container/crio/install" _ "github.com/google/cadvisor/container/docker/install" diff --git a/cmd/internal/container/mesos/client.go b/cmd/internal/container/mesos/client.go deleted file mode 100644 index b5a5b384fb..0000000000 --- a/cmd/internal/container/mesos/client.go +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// 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 mesos - -import ( - "fmt" - "net/url" - "sync" - - "github.com/Rican7/retry" - "github.com/Rican7/retry/strategy" - mesos "github.com/mesos/mesos-go/api/v1/lib" - "github.com/mesos/mesos-go/api/v1/lib/agent" - "github.com/mesos/mesos-go/api/v1/lib/agent/calls" - mclient "github.com/mesos/mesos-go/api/v1/lib/client" - "github.com/mesos/mesos-go/api/v1/lib/encoding/codecs" - "github.com/mesos/mesos-go/api/v1/lib/httpcli" -) - -const ( - maxRetryAttempts = 3 - invalidPID = -1 -) - -var ( - mesosClientOnce sync.Once - mesosClient *client -) - -type client struct { - hc *httpcli.Client -} - -type mesosAgentClient interface { - containerInfo(id string) (*containerInfo, error) - containerPID(id string) (int, error) -} - -type containerInfo struct { - cntr *mContainer - labels map[string]string -} - -// newClient is an interface to query mesos agent http endpoints -func newClient() (mesosAgentClient, error) { - mesosClientOnce.Do(func() { - // Start Client - apiURL := url.URL{ - Scheme: "http", - Host: *MesosAgentAddress, - Path: "/api/v1", - } - - mesosClient = &client{ - hc: httpcli.New( - httpcli.Endpoint(apiURL.String()), - httpcli.Codec(codecs.ByMediaType[codecs.MediaTypeProtobuf]), - httpcli.Do(httpcli.With(httpcli.Timeout(*MesosAgentTimeout))), - ), - } - }) - - _, err := mesosClient.getVersion() - if err != nil { - return nil, fmt.Errorf("failed to get version") - } - return mesosClient, nil -} - -// containerInfo returns the container information of the given container id -func (c *client) containerInfo(id string) (*containerInfo, error) { - container, err := c.getContainer(id) - if err != nil { - return nil, err - } - - // Get labels of the container - l, err := c.getLabels(container) - if err != nil { - return nil, err - } - - return &containerInfo{ - cntr: container, - labels: l, - }, nil -} - -// Get the Pid of the container -func (c *client) containerPID(id string) (int, error) { - var pid int - err := retry.Retry( - func(attempt uint) error { - c, err := c.containerInfo(id) - if err != nil { - return err - } - - if c.cntr.ContainerStatus != nil && c.cntr.ContainerStatus.ExecutorPID != nil { - pid = int(*c.cntr.ContainerStatus.ExecutorPID) - } else { - err = fmt.Errorf("error fetching Pid") - } - return err - }, - strategy.Limit(maxRetryAttempts), - ) - if err != nil { - return invalidPID, fmt.Errorf("failed to fetch pid") - } - return pid, err -} - -func (c *client) getContainer(id string) (*mContainer, error) { - // Get all containers - cntrs, err := c.getContainers() - if err != nil { - return nil, err - } - - // Check if there is a container with given id and return the container - for _, c := range cntrs.Containers { - if c.ContainerID.Value == id { - return &c, nil - } - } - return nil, fmt.Errorf("can't locate container %s", id) -} - -func (c *client) getVersion() (string, error) { - req := calls.NonStreaming(calls.GetVersion()) - result, err := c.fetchAndDecode(req) - if err != nil { - return "", fmt.Errorf("failed to get mesos version: %v", err) - } - version := result.GetVersion - - if version == nil { - return "", fmt.Errorf("failed to get mesos version") - } - return version.VersionInfo.Version, nil -} - -func (c *client) getContainers() (mContainers, error) { - req := calls.NonStreaming(calls.GetContainers()) - result, err := c.fetchAndDecode(req) - if err != nil { - return nil, fmt.Errorf("failed to get mesos containers: %v", err) - } - cntrs := result.GetContainers - - if cntrs == nil { - return nil, fmt.Errorf("failed to get mesos containers") - } - return cntrs, nil -} - -func (c *client) getLabels(container *mContainer) (map[string]string, error) { - // Get mesos agent state which contains all containers labels - var s state - req := calls.NonStreaming(calls.GetState()) - result, err := c.fetchAndDecode(req) - if err != nil { - return map[string]string{}, fmt.Errorf("failed to get mesos agent state: %v", err) - } - s.st = result.GetState - - // Fetch labels from state object - labels, err := s.FetchLabels(container.FrameworkID.Value, container.ExecutorID.Value) - if err != nil { - return labels, fmt.Errorf("error while fetching labels from executor: %v", err) - } - - return labels, nil -} - -func (c *client) fetchAndDecode(req calls.RequestFunc) (*agent.Response, error) { - var res mesos.Response - var err error - - // Send request - err = retry.Retry( - func(attempt uint) error { - res, err = mesosClient.hc.Send(req, mclient.ResponseClassSingleton, nil) - return err - }, - strategy.Limit(maxRetryAttempts), - ) - if err != nil { - return nil, fmt.Errorf("error fetching %s: %s", req.Call(), err) - } - - // Decode the result - var target agent.Response - err = res.Decode(&target) - if err != nil { - return nil, fmt.Errorf("error while decoding response body from %s: %s", res, err) - } - - return &target, nil -} diff --git a/cmd/internal/container/mesos/client_test.go b/cmd/internal/container/mesos/client_test.go deleted file mode 100644 index 6650d8b42e..0000000000 --- a/cmd/internal/container/mesos/client_test.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// 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 mesos - -import "fmt" - -type FakeMesosAgentClient struct { - cntrInfo map[string]*containerInfo - err error -} - -func (c *FakeMesosAgentClient) containerInfo(id string) (*containerInfo, error) { - if c.err != nil { - return nil, c.err - } - cInfo, ok := c.cntrInfo[id] - if !ok { - return nil, fmt.Errorf("can't locate container %s", id) - } - return cInfo, nil -} - -func (c *FakeMesosAgentClient) containerPID(id string) (int, error) { - if c.err != nil { - return invalidPID, c.err - } - cInfo, ok := c.cntrInfo[id] - if !ok { - return invalidPID, fmt.Errorf("can't locate container %s", id) - } - - if cInfo.cntr.ContainerStatus == nil { - return invalidPID, fmt.Errorf("error fetching Pid") - } - - pid := int(*cInfo.cntr.ContainerStatus.ExecutorPID) - return pid, nil -} - -func fakeMesosAgentClient(cntrInfo map[string]*containerInfo, err error) mesosAgentClient { - return &FakeMesosAgentClient{ - err: err, - cntrInfo: cntrInfo, - } -} diff --git a/cmd/internal/container/mesos/factory.go b/cmd/internal/container/mesos/factory.go deleted file mode 100644 index d0324c48e5..0000000000 --- a/cmd/internal/container/mesos/factory.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// 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 mesos - -import ( - "flag" - "fmt" - "path" - "regexp" - "strings" - "time" - - "k8s.io/klog/v2" - - "github.com/google/cadvisor/container" - "github.com/google/cadvisor/container/libcontainer" - "github.com/google/cadvisor/fs" - info "github.com/google/cadvisor/info/v1" - "github.com/google/cadvisor/watcher" -) - -var MesosAgentAddress = flag.String("mesos_agent", "127.0.0.1:5051", "Mesos agent address") -var MesosAgentTimeout = flag.Duration("mesos_agent_timeout", 10*time.Second, "Mesos agent timeout") - -// The namespace under which mesos aliases are unique. -const MesosNamespace = "mesos" - -// Regexp that identifies mesos cgroups, containers started with -// --cgroup-parent have another prefix than 'mesos' -var mesosCgroupRegexp = regexp.MustCompile(`([a-z-0-9]{36})`) - -// mesosFactory implements the interface ContainerHandlerFactory -type mesosFactory struct { - machineInfoFactory info.MachineInfoFactory - - // Information about the cgroup subsystems. - cgroupSubsystems map[string]string - - // Information about mounted filesystems. - fsInfo fs.FsInfo - - includedMetrics map[container.MetricKind]struct{} - - client mesosAgentClient -} - -func (f *mesosFactory) String() string { - return MesosNamespace -} - -func (f *mesosFactory) NewContainerHandler(name string, metadataEnvAllowList []string, inHostNamespace bool) (container.ContainerHandler, error) { - client, err := newClient() - if err != nil { - return nil, err - } - - return newMesosContainerHandler( - name, - f.cgroupSubsystems, - f.machineInfoFactory, - f.fsInfo, - f.includedMetrics, - inHostNamespace, - metadataEnvAllowList, - client, - ) -} - -// ContainerNameToMesosId returns the Mesos ID from the full container name. -func ContainerNameToMesosId(name string) string { - id := path.Base(name) - - if matches := mesosCgroupRegexp.FindStringSubmatch(id); matches != nil { - return matches[1] - } - - return id -} - -// isContainerName returns true if the cgroup with associated name -// corresponds to a mesos container. -func isContainerName(name string) bool { - // always ignore .mount cgroup even if associated with mesos and delegate to systemd - if strings.HasSuffix(name, ".mount") { - return false - } - return mesosCgroupRegexp.MatchString(path.Base(name)) -} - -// The mesos factory can handle any container. -func (f *mesosFactory) CanHandleAndAccept(name string) (handle bool, accept bool, err error) { - // if the container is not associated with mesos, we can't handle it or accept it. - if !isContainerName(name) { - return false, false, nil - } - - // Check if the container is known to mesos and it is active. - id := ContainerNameToMesosId(name) - - _, err = f.client.containerInfo(id) - if err != nil { - return false, true, fmt.Errorf("error getting running container: %v", err) - } - - return true, true, nil -} - -func (f *mesosFactory) DebugInfo() map[string][]string { - return map[string][]string{} -} - -func Register( - machineInfoFactory info.MachineInfoFactory, - fsInfo fs.FsInfo, - includedMetrics container.MetricSet, -) error { - client, err := newClient() - - if err != nil { - return fmt.Errorf("unable to create mesos agent client: %v", err) - } - - cgroupSubsystems, err := libcontainer.GetCgroupSubsystems(includedMetrics) - if err != nil { - return fmt.Errorf("failed to get cgroup subsystems: %v", err) - } - - klog.V(1).Infof("Registering mesos factory") - factory := &mesosFactory{ - machineInfoFactory: machineInfoFactory, - cgroupSubsystems: cgroupSubsystems, - fsInfo: fsInfo, - includedMetrics: includedMetrics, - client: client, - } - container.RegisterContainerHandlerFactory(factory, []watcher.ContainerWatchSource{watcher.Raw}) - return nil -} diff --git a/cmd/internal/container/mesos/factory_test.go b/cmd/internal/container/mesos/factory_test.go deleted file mode 100644 index 1b7e57b392..0000000000 --- a/cmd/internal/container/mesos/factory_test.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// 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 mesos - -import ( - "testing" - - mesos "github.com/mesos/mesos-go/api/v1/lib" - "github.com/stretchr/testify/assert" -) - -func TestIsContainerName(t *testing.T) { - tests := []struct { - name string - expected bool - }{ - { - name: "/system.slice/var-lib-mesos-provisioner-containers-04e20821-d67d3-4bf7-96b4-7d4495f50b28-backends-overlay-rootfses-6d97be39-7359-4bb7-a46b-e55c6771da81.mount", - expected: false, - }, - { - name: "/mesos/04e20821-67d3-4bf7-96b4-7d4495f50b28", - expected: true, - }, - } - for _, test := range tests { - if actual := isContainerName(test.name); actual != test.expected { - t.Errorf("%s: expected: %v, actual: %v", test.name, test.expected, actual) - } - } -} -func TestCanHandleAndAccept(t *testing.T) { - as := assert.New(t) - testContainers := make(map[string]*containerInfo) - var pid uint32 = 123 - testContainer := &containerInfo{ - cntr: &mContainer{ - ContainerStatus: &mesos.ContainerStatus{ - ExecutorPID: &pid, - }, - }, - } - - testContainers["04e20821-67d3-4bf7-96b4-7d4495f50b28"] = testContainer - - f := &mesosFactory{ - machineInfoFactory: nil, - cgroupSubsystems: nil, - fsInfo: nil, - includedMetrics: nil, - client: fakeMesosAgentClient(testContainers, nil), - } - tests := []struct { - name string - expected bool - }{ - { - name: "/mesos/04e20821-67d3-4bf7-96b4-7d4495f50b28", - expected: true, - }, - { - name: "/system.slice/var-lib-mesos-provisioner-containers-04e20821-d67d3-4bf7-96b4-7d4495f50b28-backends-overlay-rootfses-6d97be39-7359-4bb7-a46b-e55c6771da81.mount", - expected: false, - }, - } - - for _, test := range tests { - b1, b2, err := f.CanHandleAndAccept(test.name) - as.Nil(err) - as.Equal(b1, test.expected) - as.Equal(b2, test.expected) - } -} diff --git a/cmd/internal/container/mesos/handler.go b/cmd/internal/container/mesos/handler.go deleted file mode 100644 index cda397875f..0000000000 --- a/cmd/internal/container/mesos/handler.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// 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. - -// Handler for "mesos" containers. -package mesos - -import ( - "fmt" - - "github.com/google/cadvisor/container" - "github.com/google/cadvisor/container/common" - containerlibcontainer "github.com/google/cadvisor/container/libcontainer" - "github.com/google/cadvisor/fs" - info "github.com/google/cadvisor/info/v1" -) - -type mesosContainerHandler struct { - // Name of the container for this handler. - name string - - // machineInfoFactory provides info.MachineInfo - machineInfoFactory info.MachineInfoFactory - - // Absolute path to the cgroup hierarchies of this container. - // (e.g.: "cpu" -> "/sys/fs/cgroup/cpu/test") - cgroupPaths map[string]string - - // File System Info - fsInfo fs.FsInfo - - // Metrics to be included. - includedMetrics container.MetricSet - - labels map[string]string - - // Reference to the container - reference info.ContainerReference - - libcontainerHandler *containerlibcontainer.Handler -} - -func newMesosContainerHandler( - name string, - cgroupSubsystems map[string]string, - machineInfoFactory info.MachineInfoFactory, - fsInfo fs.FsInfo, - includedMetrics container.MetricSet, - inHostNamespace bool, - metadataEnvAllowList []string, - client mesosAgentClient, -) (container.ContainerHandler, error) { - cgroupPaths := common.MakeCgroupPaths(cgroupSubsystems, name) - - // Generate the equivalent cgroup manager for this container. - cgroupManager, err := containerlibcontainer.NewCgroupManager(name, cgroupPaths) - if err != nil { - return nil, err - } - - rootFs := "/" - if !inHostNamespace { - rootFs = "/rootfs" - } - - id := ContainerNameToMesosId(name) - - cinfo, err := client.containerInfo(id) - - if err != nil { - return nil, err - } - - labels := cinfo.labels - pid, err := client.containerPID(id) - if err != nil { - return nil, err - } - - libcontainerHandler := containerlibcontainer.NewHandler(cgroupManager, rootFs, pid, includedMetrics) - - reference := info.ContainerReference{ - Id: id, - Name: name, - Namespace: MesosNamespace, - Aliases: []string{id, name}, - } - - handler := &mesosContainerHandler{ - name: name, - machineInfoFactory: machineInfoFactory, - cgroupPaths: cgroupPaths, - fsInfo: fsInfo, - includedMetrics: includedMetrics, - labels: labels, - reference: reference, - libcontainerHandler: libcontainerHandler, - } - - return handler, nil -} - -func (h *mesosContainerHandler) ContainerReference() (info.ContainerReference, error) { - // We only know the container by its one name. - return h.reference, nil -} - -// Nothing to start up. -func (h *mesosContainerHandler) Start() {} - -// Nothing to clean up. -func (h *mesosContainerHandler) Cleanup() {} - -func (h *mesosContainerHandler) GetSpec() (info.ContainerSpec, error) { - // TODO: Since we dont collect disk usage and network stats for mesos containers, we set - // hasFilesystem and hasNetwork to false. Revisit when we support disk usage, network - // stats for mesos containers. - hasNetwork := false - hasFilesystem := false - - spec, err := common.GetSpec(h.cgroupPaths, h.machineInfoFactory, hasNetwork, hasFilesystem) - if err != nil { - return spec, err - } - - spec.Labels = h.labels - - return spec, nil -} - -func (h *mesosContainerHandler) getFsStats(stats *info.ContainerStats) error { - - mi, err := h.machineInfoFactory.GetMachineInfo() - if err != nil { - return err - } - - if h.includedMetrics.Has(container.DiskIOMetrics) { - common.AssignDeviceNamesToDiskStats((*common.MachineInfoNamer)(mi), &stats.DiskIo) - } - - return nil -} - -func (h *mesosContainerHandler) GetStats() (*info.ContainerStats, error) { - stats, err := h.libcontainerHandler.GetStats() - if err != nil { - return stats, err - } - - // Get filesystem stats. - err = h.getFsStats(stats) - if err != nil { - return stats, err - } - - return stats, nil -} - -func (h *mesosContainerHandler) GetCgroupPath(resource string) (string, error) { - path, ok := h.cgroupPaths[resource] - if !ok { - return "", fmt.Errorf("could not find path for resource %q for container %q", resource, h.name) - } - return path, nil -} - -func (h *mesosContainerHandler) GetContainerLabels() map[string]string { - return h.labels -} - -func (h *mesosContainerHandler) GetContainerIPAddress() string { - // the IP address for the mesos container corresponds to the system ip address. - return "127.0.0.1" -} - -func (h *mesosContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) { - return common.ListContainers(h.name, h.cgroupPaths, listType) -} - -func (h *mesosContainerHandler) ListProcesses(listType container.ListType) ([]int, error) { - return h.libcontainerHandler.GetProcesses() -} - -func (h *mesosContainerHandler) Exists() bool { - return common.CgroupExists(h.cgroupPaths) -} - -func (h *mesosContainerHandler) Type() container.ContainerType { - return container.ContainerTypeMesos -} diff --git a/cmd/internal/container/mesos/handler_test.go b/cmd/internal/container/mesos/handler_test.go deleted file mode 100644 index c43b59d73a..0000000000 --- a/cmd/internal/container/mesos/handler_test.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// 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 mesos - -import ( - "fmt" - "testing" - - mesos "github.com/mesos/mesos-go/api/v1/lib" - "github.com/stretchr/testify/assert" - - "github.com/google/cadvisor/container" - "github.com/google/cadvisor/fs" - info "github.com/google/cadvisor/info/v1" -) - -func PopulateContainer() *mContainer { - var pid uint32 = 123 - cntr := &mContainer{ - ContainerStatus: &mesos.ContainerStatus{ExecutorPID: &pid}, - } - return cntr -} - -func TestContainerReference(t *testing.T) { - as := assert.New(t) - type testCase struct { - client mesosAgentClient - name string - machineInfoFactory info.MachineInfoFactory - fsInfo fs.FsInfo - cgroupSubsystems map[string]string - inHostNamespace bool - metadataEnvAllowList []string - includedMetrics container.MetricSet - - hasErr bool - errContains string - checkReference *info.ContainerReference - } - for _, ts := range []testCase{ - { - fakeMesosAgentClient(nil, fmt.Errorf("no client returned")), - "/mesos/04e20821-67d3-4bf7-96b4-7d4495f50b28", - nil, - nil, - nil, - false, - []string{}, - nil, - - true, - "no client returned", - nil, - }, - { - fakeMesosAgentClient(nil, nil), - "/mesos/04e20821-67d3-4bf7-96b4-7d4495f50b28", - nil, - nil, - nil, - false, - []string{}, - nil, - - true, - "can't locate container 04e20821-67d3-4bf7-96b4-7d4495f50b28", - nil, - }, - { - fakeMesosAgentClient(map[string]*containerInfo{"04e20821-67d3-4bf7-96b4-7d4495f50b28": {cntr: PopulateContainer()}}, nil), - "/mesos/04e20821-67d3-4bf7-96b4-7d4495f50b28", - nil, - nil, - nil, - false, - []string{}, - nil, - - false, - "", - &info.ContainerReference{ - Id: "04e20821-67d3-4bf7-96b4-7d4495f50b28", - Name: "/mesos/04e20821-67d3-4bf7-96b4-7d4495f50b28", - Aliases: []string{"04e20821-67d3-4bf7-96b4-7d4495f50b28", "/mesos/04e20821-67d3-4bf7-96b4-7d4495f50b28"}, - Namespace: MesosNamespace, - }, - }, - } { - handler, err := newMesosContainerHandler(ts.name, ts.cgroupSubsystems, ts.machineInfoFactory, ts.fsInfo, ts.includedMetrics, ts.inHostNamespace, ts.metadataEnvAllowList, ts.client) - if ts.hasErr { - as.NotNil(err) - if ts.errContains != "" { - as.Contains(err.Error(), ts.errContains) - } - } - if ts.checkReference != nil { - cr, err := handler.ContainerReference() - as.Nil(err) - as.Equal(*ts.checkReference, cr) - } - } -} diff --git a/cmd/internal/container/mesos/install/install.go b/cmd/internal/container/mesos/install/install.go deleted file mode 100644 index 0ab18f5a8c..0000000000 --- a/cmd/internal/container/mesos/install/install.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 Google Inc. All Rights Reserved. -// -// 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. - -// The install package registers mesos.NewPlugin() as the "mesos" container provider when imported -package install - -import ( - "k8s.io/klog/v2" - - "github.com/google/cadvisor/cmd/internal/container/mesos" - "github.com/google/cadvisor/container" -) - -func init() { - err := container.RegisterPlugin("mesos", mesos.NewPlugin()) - if err != nil { - klog.Fatalf("Failed to register mesos plugin: %v", err) - } -} diff --git a/cmd/internal/container/mesos/mesos_agent.go b/cmd/internal/container/mesos/mesos_agent.go deleted file mode 100644 index f26513d0d9..0000000000 --- a/cmd/internal/container/mesos/mesos_agent.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// 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 mesos - -import ( - "fmt" - - mesos "github.com/mesos/mesos-go/api/v1/lib" - "github.com/mesos/mesos-go/api/v1/lib/agent" -) - -const ( - cpus = "cpus" - schedulerSLA = "scheduler_sla" - framework = "framework" - source = "source" - revocable = "revocable" - nonRevocable = "non_revocable" -) - -type mContainers *agent.Response_GetContainers -type mContainer = agent.Response_GetContainers_Container - -type ( - state struct { - st *agent.Response_GetState - } -) - -// GetFramework finds a framework with the given id and returns nil if not found. Note that -// this is different from the framework name. -func (s *state) GetFramework(id string) (*mesos.FrameworkInfo, error) { - for _, fw := range s.st.GetFrameworks.Frameworks { - if fw.FrameworkInfo.ID.Value == id { - return &fw.FrameworkInfo, nil - } - } - return nil, fmt.Errorf("unable to find framework id %s", id) -} - -// GetExecutor finds an executor with the given ID and returns nil if not found. Note that -// this is different from the executor name. -func (s *state) GetExecutor(id string) (*mesos.ExecutorInfo, error) { - for _, exec := range s.st.GetExecutors.Executors { - if exec.ExecutorInfo.ExecutorID.Value == id { - return &exec.ExecutorInfo, nil - } - } - return nil, fmt.Errorf("unable to find executor with id %s", id) -} - -// GetTask returns a task launched by given executor. -func (s *state) GetTask(exID string) (*mesos.Task, error) { - // Check if task is in Launched Tasks list - for _, t := range s.st.GetTasks.LaunchedTasks { - if s.isMatchingTask(&t, exID) { - return &t, nil - } - } - - // Check if task is in Queued Tasks list - for _, t := range s.st.GetTasks.QueuedTasks { - if s.isMatchingTask(&t, exID) { - return &t, nil - } - } - return nil, fmt.Errorf("unable to find task matching executor id %s", exID) -} - -func (s *state) isMatchingTask(t *mesos.Task, exID string) bool { - // MESOS-9111: For tasks launched through mesos command/default executor, the - // executorID(which is same as the taskID) field is not filled in the TaskInfo object. - // The workaround is compare with taskID field if executorID is empty - if t.ExecutorID != nil { - if t.ExecutorID.Value == exID { - return true - } - } else { - if t.TaskID.Value == exID { - return true - } - } - - return false -} - -func (s *state) fetchLabelsFromTask(exID string, labels map[string]string) error { - t, err := s.GetTask(exID) - if err != nil { - return err - } - - // Identify revocability. Can be removed once we have a proper label - for _, resource := range t.Resources { - if resource.Name == cpus { - if resource.Revocable != nil { - labels[schedulerSLA] = revocable - } else { - labels[schedulerSLA] = nonRevocable - } - break - } - } - - if t.Labels != nil { - for _, l := range t.Labels.Labels { - labels[l.Key] = *l.Value - } - } - - return nil -} - -func (s *state) FetchLabels(fwID string, exID string) (map[string]string, error) { - labels := make(map[string]string) - - // Look for the framework which launched the container. - fw, err := s.GetFramework(fwID) - if err != nil { - return labels, fmt.Errorf("framework ID %q not found: %v", fwID, err) - } - labels[framework] = fw.Name - - // Get the executor info of the container which contains all the task info. - exec, err := s.GetExecutor(exID) - if err != nil { - return labels, fmt.Errorf("executor ID %q not found: %v", exID, err) - } - - labels[source] = exec.GetSource() - - err = s.fetchLabelsFromTask(exID, labels) - if err != nil { - return labels, fmt.Errorf("failed to fetch labels from task with executor ID %s", exID) - } - - return labels, nil -} diff --git a/cmd/internal/container/mesos/mesos_agent_test.go b/cmd/internal/container/mesos/mesos_agent_test.go deleted file mode 100644 index 2ea1b183c2..0000000000 --- a/cmd/internal/container/mesos/mesos_agent_test.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// 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 mesos - -import ( - "fmt" - "testing" - - mesos "github.com/mesos/mesos-go/api/v1/lib" - "github.com/mesos/mesos-go/api/v1/lib/agent" - "github.com/stretchr/testify/assert" -) - -func PopulateFrameworks(fwID string) *agent.Response_GetFrameworks { - fws := &agent.Response_GetFrameworks{} - fws.Frameworks = make([]agent.Response_GetFrameworks_Framework, 1) - fw := &agent.Response_GetFrameworks_Framework{} - fw.FrameworkInfo = mesos.FrameworkInfo{ - ID: &mesos.FrameworkID{Value: fwID}, - Name: "TestFramework", - } - fws.Frameworks[0] = *fw - return fws -} - -func PopulateExecutors(exID string) *agent.Response_GetExecutors { - execs := &agent.Response_GetExecutors{} - execs.Executors = make([]agent.Response_GetExecutors_Executor, 1) - exec := &agent.Response_GetExecutors_Executor{} - source := "source1" - exec.ExecutorInfo = mesos.ExecutorInfo{ - ExecutorID: mesos.ExecutorID{Value: exID}, - Source: &source, - } - execs.Executors[0] = *exec - return execs -} - -func PopulateTasks(taskID string, exID string) *agent.Response_GetTasks { - tasks := &agent.Response_GetTasks{} - tasks.LaunchedTasks = make([]mesos.Task, 1) - - task := mesos.Task{ - TaskID: mesos.TaskID{Value: taskID}, - } - if len(exID) > 0 { - task.ExecutorID = &mesos.ExecutorID{Value: exID} - } - - task.Resources = make([]mesos.Resource, 1) - resource := mesos.Resource{ - Name: cpus, - Revocable: nil, - } - task.Resources[0] = resource - - task.Labels = &mesos.Labels{ - Labels: make([]mesos.Label, 1), - } - labelValue := "value1" - label := mesos.Label{ - Key: "key1", - Value: &labelValue, - } - task.Labels.Labels[0] = label - - tasks.LaunchedTasks[0] = task - return tasks -} - -func TestFetchLabels(t *testing.T) { - type testCase struct { - frameworkID string - executorID string - agentState *agent.Response_GetState - expectedError error - expectedLabels map[string]string - } - - for _, ts := range []testCase{ - { - frameworkID: "fw-id1", - executorID: "exec-id1", - agentState: &agent.Response_GetState{ - GetFrameworks: PopulateFrameworks("fw-id1"), - GetExecutors: PopulateExecutors("exec-id1"), - GetTasks: PopulateTasks("task-id1", "exec-id1"), - }, - expectedError: nil, - expectedLabels: map[string]string{ - framework: "TestFramework", - source: "source1", - schedulerSLA: nonRevocable, - "key1": "value1", - }, - }, - { - frameworkID: "fw-id1", - executorID: "task-id1", - agentState: &agent.Response_GetState{ - GetFrameworks: PopulateFrameworks("fw-id1"), - GetExecutors: PopulateExecutors("task-id1"), - GetTasks: PopulateTasks("task-id1", ""), - }, - expectedError: nil, - expectedLabels: map[string]string{ - framework: "TestFramework", - source: "source1", - schedulerSLA: nonRevocable, - "key1": "value1", - }, - }, - { - frameworkID: "fw-id2", - executorID: "exec-id1", - agentState: &agent.Response_GetState{ - GetFrameworks: PopulateFrameworks("fw-id1"), - GetExecutors: PopulateExecutors("exec-id1"), - GetTasks: PopulateTasks("task-id1", "exec-id1"), - }, - expectedError: fmt.Errorf("framework ID \"fw-id2\" not found: unable to find framework id fw-id2"), - expectedLabels: map[string]string{}, - }, - } { - - var s state - s.st = ts.agentState - - actualLabels, err := s.FetchLabels(ts.frameworkID, ts.executorID) - if ts.expectedError == nil { - assert.Nil(t, err) - } else { - assert.Equal(t, ts.expectedError.Error(), err.Error()) - } - assert.Equal(t, ts.expectedLabels, actualLabels) - } -} diff --git a/cmd/internal/container/mesos/plugin.go b/cmd/internal/container/mesos/plugin.go deleted file mode 100644 index 3f327ddb51..0000000000 --- a/cmd/internal/container/mesos/plugin.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2019 Google Inc. All Rights Reserved. -// -// 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 mesos - -import ( - "github.com/google/cadvisor/container" - "github.com/google/cadvisor/fs" - info "github.com/google/cadvisor/info/v1" - "github.com/google/cadvisor/watcher" -) - -// NewPlugin returns an implementation of container.Plugin suitable for passing to container.RegisterPlugin() -func NewPlugin() container.Plugin { - return &plugin{} -} - -type plugin struct{} - -func (p *plugin) InitializeFSContext(context *fs.Context) error { - return nil -} - -func (p *plugin) Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, includedMetrics container.MetricSet) (watcher.ContainerWatcher, error) { - err := Register(factory, fsInfo, includedMetrics) - return nil, err -} diff --git a/container/container.go b/container/container.go index 4c435a0e81..2e17258e04 100644 --- a/container/container.go +++ b/container/container.go @@ -34,7 +34,6 @@ const ( ContainerTypeDocker ContainerTypeCrio ContainerTypeContainerd - ContainerTypeMesos ContainerTypePodman ) diff --git a/container/containerd/client.go b/container/containerd/client.go index 34134baf3e..2c41a2d551 100644 --- a/container/containerd/client.go +++ b/container/containerd/client.go @@ -54,6 +54,7 @@ var ( var once sync.Once var ctrdClient ContainerdClient = nil +var ctrdClientErr error = nil const ( maxBackoffDelay = 3 * time.Second @@ -64,11 +65,10 @@ const ( // Client creates a containerd client func Client(address, namespace string) (ContainerdClient, error) { - var retErr error once.Do(func() { tryConn, err := net.DialTimeout("unix", address, connectionTimeout) if err != nil { - retErr = fmt.Errorf("containerd: cannot unix dial containerd api service: %v", err) + ctrdClientErr = fmt.Errorf("containerd: cannot unix dial containerd api service: %v", err) return } tryConn.Close() @@ -97,7 +97,7 @@ func Client(address, namespace string) (ContainerdClient, error) { //nolint:staticcheck // SA1019 conn, err := grpc.DialContext(ctx, dialer.DialAddress(address), gopts...) if err != nil { - retErr = err + ctrdClientErr = err return } ctrdClient = &client{ @@ -106,7 +106,7 @@ func Client(address, namespace string) (ContainerdClient, error) { versionService: versionapi.NewVersionClient(conn), } }) - return ctrdClient, retErr + return ctrdClient, ctrdClientErr } func (c *client) LoadContainer(ctx context.Context, id string) (*containers.Container, error) {