Update to latest cadvisor - cleanup mesos/rkt

Change-Id: Ib5ae0cb13b93f8c87bb74e3ba33040df5f3d6a6f
This commit is contained in:
Davanum Srinivas
2019-04-09 13:11:33 -04:00
parent ca55432599
commit 70d562a6ac
143 changed files with 554 additions and 190406 deletions

View File

@@ -10,8 +10,9 @@ go_library(
importpath = "github.com/google/cadvisor/container",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/google/cadvisor/fs:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/manager/watcher:go_default_library",
"//vendor/github.com/google/cadvisor/watcher:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)
@@ -32,9 +33,7 @@ filegroup(
"//vendor/github.com/google/cadvisor/container/crio:all-srcs",
"//vendor/github.com/google/cadvisor/container/docker:all-srcs",
"//vendor/github.com/google/cadvisor/container/libcontainer:all-srcs",
"//vendor/github.com/google/cadvisor/container/mesos:all-srcs",
"//vendor/github.com/google/cadvisor/container/raw:all-srcs",
"//vendor/github.com/google/cadvisor/container/rkt:all-srcs",
"//vendor/github.com/google/cadvisor/container/systemd:all-srcs",
],
tags = ["automanaged"],

View File

@@ -7,6 +7,7 @@ go_library(
"factory.go",
"grpc.go",
"handler.go",
"plugin.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/container/containerd",
importpath = "github.com/google/cadvisor/container/containerd",
@@ -25,7 +26,7 @@ go_library(
"//vendor/github.com/google/cadvisor/container/libcontainer:go_default_library",
"//vendor/github.com/google/cadvisor/fs:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/manager/watcher:go_default_library",
"//vendor/github.com/google/cadvisor/watcher:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
"//vendor/github.com/opencontainers/runtime-spec/specs-go:go_default_library",
@@ -44,7 +45,10 @@ filegroup(
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
srcs = [
":package-srcs",
"//vendor/github.com/google/cadvisor/container/containerd/install:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -31,11 +31,6 @@ import (
"google.golang.org/grpc"
)
const (
// k8sNamespace is the namespace we use to connect containerd.
k8sNamespace = "k8s.io"
)
type client struct {
containerService containersapi.ContainersClient
taskService tasksapi.TasksClient
@@ -52,13 +47,12 @@ var once sync.Once
var ctrdClient containerdClient = nil
const (
address = "/run/containerd/containerd.sock"
maxBackoffDelay = 3 * time.Second
connectionTimeout = 2 * time.Second
)
// Client creates a containerd client
func Client() (containerdClient, error) {
func Client(address, namespace string) (containerdClient, error) {
var retErr error
once.Do(func() {
tryConn, err := net.DialTimeout("unix", address, connectionTimeout)
@@ -75,7 +69,7 @@ func Client() (containerdClient, error) {
grpc.WithBackoffMaxDelay(maxBackoffDelay),
grpc.WithTimeout(connectionTimeout),
}
unary, stream := newNSInterceptors(k8sNamespace)
unary, stream := newNSInterceptors(namespace)
gopts = append(gopts,
grpc.WithUnaryInterceptor(unary),
grpc.WithStreamInterceptor(stream),

View File

@@ -28,10 +28,11 @@ import (
"github.com/google/cadvisor/container/libcontainer"
"github.com/google/cadvisor/fs"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/manager/watcher"
"github.com/google/cadvisor/watcher"
)
var ArgContainerdEndpoint = flag.String("containerd", "unix:///var/run/containerd.sock", "containerd endpoint")
var ArgContainerdEndpoint = flag.String("containerd", "/run/containerd/containerd.sock", "containerd endpoint")
var ArgContainerdNamespace = flag.String("containerd-namespace", "k8s.io", "containerd namespace")
// The namespace under which containerd aliases are unique.
const k8sContainerdNamespace = "containerd"
@@ -56,7 +57,7 @@ func (self *containerdFactory) String() string {
}
func (self *containerdFactory) NewContainerHandler(name string, inHostNamespace bool) (handler container.ContainerHandler, err error) {
client, err := Client()
client, err := Client(*ArgContainerdEndpoint, *ArgContainerdNamespace)
if err != nil {
return
}
@@ -118,7 +119,7 @@ func (self *containerdFactory) DebugInfo() map[string][]string {
// Register root container before running this function!
func Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, includedMetrics container.MetricSet) error {
client, err := Client()
client, err := Client(*ArgContainerdEndpoint, *ArgContainerdNamespace)
if err != nil {
return fmt.Errorf("unable to create containerd client: %v", err)
}

View File

@@ -2,15 +2,13 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["rkt.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/manager/watcher/rkt",
importpath = "github.com/google/cadvisor/manager/watcher/rkt",
srcs = ["install.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/container/containerd/install",
importpath = "github.com/google/cadvisor/container/containerd/install",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/coreos/rkt/api/v1alpha:go_default_library",
"//vendor/github.com/google/cadvisor/container/rkt:go_default_library",
"//vendor/github.com/google/cadvisor/manager/watcher:go_default_library",
"//vendor/golang.org/x/net/context:go_default_library",
"//vendor/github.com/google/cadvisor/container:go_default_library",
"//vendor/github.com/google/cadvisor/container/containerd:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)

View File

@@ -0,0 +1,29 @@
// 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 containerd.NewPlugin() as the "containerd" container provider when imported
package install
import (
"github.com/google/cadvisor/container"
"github.com/google/cadvisor/container/containerd"
"k8s.io/klog"
)
func init() {
err := container.RegisterPlugin("containerd", containerd.NewPlugin())
if err != nil {
klog.Fatalf("Failed to register containerd plugin: %v", err)
}
}

View File

@@ -0,0 +1,38 @@
// 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 containerd
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
}

View File

@@ -6,6 +6,7 @@ go_library(
"client.go",
"factory.go",
"handler.go",
"plugin.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/container/crio",
importpath = "github.com/google/cadvisor/container/crio",
@@ -16,7 +17,7 @@ go_library(
"//vendor/github.com/google/cadvisor/container/libcontainer:go_default_library",
"//vendor/github.com/google/cadvisor/fs:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/manager/watcher:go_default_library",
"//vendor/github.com/google/cadvisor/watcher:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
@@ -32,7 +33,10 @@ filegroup(
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
srcs = [
":package-srcs",
"//vendor/github.com/google/cadvisor/container/crio/install:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -122,6 +122,13 @@ func (c *crioClientImpl) ContainerInfo(id string) (*ContainerInfo, error) {
return nil, err
}
defer resp.Body.Close()
// golang's http.Do doesn't return an error if non 200 response code is returned
// handle this case here, rather than failing to decode the body
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("Error finding container %s: Status %d returned error %s", id, resp.StatusCode, resp.Body)
}
cInfo := ContainerInfo{}
if err := json.NewDecoder(resp.Body).Decode(&cInfo); err != nil {
return nil, err

View File

@@ -24,7 +24,7 @@ import (
"github.com/google/cadvisor/container/libcontainer"
"github.com/google/cadvisor/fs"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/manager/watcher"
"github.com/google/cadvisor/watcher"
"k8s.io/klog"
)

View File

@@ -0,0 +1,28 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["install.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/container/crio/install",
importpath = "github.com/google/cadvisor/container/crio/install",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/google/cadvisor/container:go_default_library",
"//vendor/github.com/google/cadvisor/container/crio:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,29 @@
// 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 crio.NewPlugin() as the "crio" container provider when imported
package install
import (
"github.com/google/cadvisor/container"
"github.com/google/cadvisor/container/crio"
"k8s.io/klog"
)
func init() {
err := container.RegisterPlugin("crio", crio.NewPlugin())
if err != nil {
klog.Fatalf("Failed to register crio plugin: %v", err)
}
}

View File

@@ -0,0 +1,50 @@
// 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 crio
import (
"github.com/google/cadvisor/container"
"github.com/google/cadvisor/fs"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/watcher"
"k8s.io/klog"
)
// 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 {
crioClient, err := Client()
if err != nil {
return err
}
crioInfo, err := crioClient.Info()
if err != nil {
klog.V(5).Infof("CRI-O not connected: %v", err)
} else {
context.Crio = fs.CrioContext{Root: crioInfo.StorageRoot}
}
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
}

View File

@@ -7,6 +7,7 @@ go_library(
"docker.go",
"factory.go",
"handler.go",
"plugin.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/container/docker",
importpath = "github.com/google/cadvisor/container/docker",
@@ -24,8 +25,8 @@ go_library(
"//vendor/github.com/google/cadvisor/fs:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/machine:go_default_library",
"//vendor/github.com/google/cadvisor/manager/watcher:go_default_library",
"//vendor/github.com/google/cadvisor/utils/docker:go_default_library",
"//vendor/github.com/google/cadvisor/watcher:go_default_library",
"//vendor/github.com/google/cadvisor/zfs:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
@@ -43,7 +44,10 @@ filegroup(
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
srcs = [
":package-srcs",
"//vendor/github.com/google/cadvisor/container/docker/install:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -31,8 +31,8 @@ import (
"github.com/google/cadvisor/fs"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/machine"
"github.com/google/cadvisor/manager/watcher"
dockerutil "github.com/google/cadvisor/utils/docker"
"github.com/google/cadvisor/watcher"
"github.com/google/cadvisor/zfs"
docker "github.com/docker/docker/client"

View File

@@ -2,15 +2,13 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["raw.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/manager/watcher/raw",
importpath = "github.com/google/cadvisor/manager/watcher/raw",
srcs = ["install.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/container/docker/install",
importpath = "github.com/google/cadvisor/container/docker/install",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/google/cadvisor/container/common:go_default_library",
"//vendor/github.com/google/cadvisor/container/libcontainer:go_default_library",
"//vendor/github.com/google/cadvisor/manager/watcher:go_default_library",
"//vendor/github.com/sigma/go-inotify:go_default_library",
"//vendor/github.com/google/cadvisor/container:go_default_library",
"//vendor/github.com/google/cadvisor/container/docker:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)

View File

@@ -0,0 +1,29 @@
// 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 docker.NewPlugin() as the "docker" container provider when imported
package install
import (
"github.com/google/cadvisor/container"
"github.com/google/cadvisor/container/docker"
"k8s.io/klog"
)
func init() {
err := container.RegisterPlugin("docker", docker.NewPlugin())
if err != nil {
klog.Fatalf("Failed to register docker plugin: %v", err)
}
}

View File

@@ -0,0 +1,77 @@
// 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 docker
import (
"time"
"github.com/google/cadvisor/container"
"github.com/google/cadvisor/fs"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/watcher"
"golang.org/x/net/context"
"k8s.io/klog"
)
const dockerClientTimeout = 10 * time.Second
// 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 {
SetTimeout(dockerClientTimeout)
// Try to connect to docker indefinitely on startup.
dockerStatus := retryDockerStatus()
context.Docker = fs.DockerContext{
Root: RootDir(),
Driver: dockerStatus.Driver,
DriverStatus: dockerStatus.DriverStatus,
}
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
}
func retryDockerStatus() info.DockerStatus {
startupTimeout := dockerClientTimeout
maxTimeout := 4 * startupTimeout
for {
ctx, _ := context.WithTimeout(context.Background(), startupTimeout)
dockerStatus, err := StatusWithContext(ctx)
if err == nil {
return dockerStatus
}
switch err {
case context.DeadlineExceeded:
klog.Warningf("Timeout trying to communicate with docker during initialization, will retry")
default:
klog.V(5).Infof("Docker not connected: %v", err)
return info.DockerStatus{}
}
startupTimeout = 2 * startupTimeout
if startupTimeout > maxTimeout {
startupTimeout = maxTimeout
}
}
}

View File

@@ -18,7 +18,9 @@ import (
"fmt"
"sync"
"github.com/google/cadvisor/manager/watcher"
"github.com/google/cadvisor/fs"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/watcher"
"k8s.io/klog"
)
@@ -71,6 +73,61 @@ func (ms MetricSet) Add(mk MetricKind) {
ms[mk] = struct{}{}
}
// All registered auth provider plugins.
var pluginsLock sync.Mutex
var plugins = make(map[string]Plugin)
type Plugin interface {
// InitializeFSContext is invoked when populating an fs.Context object for a new manager.
// A returned error here is fatal.
InitializeFSContext(context *fs.Context) error
// Register is invoked when starting a manager. It can optionally return a container watcher.
// A returned error is logged, but is not fatal.
Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, includedMetrics MetricSet) (watcher.ContainerWatcher, error)
}
func RegisterPlugin(name string, plugin Plugin) error {
pluginsLock.Lock()
defer pluginsLock.Unlock()
if _, found := plugins[name]; found {
return fmt.Errorf("Plugin %q was registered twice", name)
}
klog.V(4).Infof("Registered Plugin %q", name)
plugins[name] = plugin
return nil
}
func InitializeFSContext(context *fs.Context) error {
pluginsLock.Lock()
defer pluginsLock.Unlock()
for name, plugin := range plugins {
err := plugin.InitializeFSContext(context)
if err != nil {
klog.V(5).Infof("Initialization of the %s context failed: %v", name, err)
return err
}
}
return nil
}
func InitializePlugins(factory info.MachineInfoFactory, fsInfo fs.FsInfo, includedMetrics MetricSet) []watcher.ContainerWatcher {
pluginsLock.Lock()
defer pluginsLock.Unlock()
containerWatchers := []watcher.ContainerWatcher{}
for name, plugin := range plugins {
watcher, err := plugin.Register(factory, fsInfo, includedMetrics)
if err != nil {
klog.V(5).Infof("Registration of the %s container factory failed: %v", name, err)
}
if watcher != nil {
containerWatchers = append(containerWatchers, watcher)
}
}
return containerWatchers
}
// TODO(vmarmol): Consider not making this global.
// Global list of factories.
var (

View File

@@ -1,47 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"client.go",
"factory.go",
"handler.go",
"mesos_agent.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/container/mesos",
importpath = "github.com/google/cadvisor/container/mesos",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/Rican7/retry:go_default_library",
"//vendor/github.com/Rican7/retry/strategy:go_default_library",
"//vendor/github.com/google/cadvisor/container:go_default_library",
"//vendor/github.com/google/cadvisor/container/common:go_default_library",
"//vendor/github.com/google/cadvisor/container/libcontainer:go_default_library",
"//vendor/github.com/google/cadvisor/fs:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/manager/watcher:go_default_library",
"//vendor/github.com/mesos/mesos-go/api/v1/lib:go_default_library",
"//vendor/github.com/mesos/mesos-go/api/v1/lib/agent:go_default_library",
"//vendor/github.com/mesos/mesos-go/api/v1/lib/agent/calls:go_default_library",
"//vendor/github.com/mesos/mesos-go/api/v1/lib/client:go_default_library",
"//vendor/github.com/mesos/mesos-go/api/v1/lib/encoding/codecs:go_default_library",
"//vendor/github.com/mesos/mesos-go/api/v1/lib/httpcli:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -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"
"github.com/Rican7/retry"
"github.com/Rican7/retry/strategy"
"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"
"net/url"
"sync"
)
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
}
// Client is an interface to query mesos agent http endpoints
func Client() (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 (self *client) ContainerInfo(id string) (*containerInfo, error) {
c, err := self.getContainer(id)
if err != nil {
return nil, err
}
// Get labels of the container
l, err := self.getLabels(c)
if err != nil {
return nil, err
}
return &containerInfo{
cntr: c,
labels: l,
}, nil
}
// Get the Pid of the container
func (self *client) ContainerPid(id string) (int, error) {
var pid int
var err error
err = retry.Retry(
func(attempt uint) error {
c, err := self.ContainerInfo(id)
if err != nil {
return err
}
if c.cntr.ContainerStatus != 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 (self *client) getContainer(id string) (*mContainer, error) {
// Get all containers
cntrs, err := self.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 (self *client) getVersion() (string, error) {
req := calls.NonStreaming(calls.GetVersion())
result, err := self.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 (self *client) getContainers() (mContainers, error) {
req := calls.NonStreaming(calls.GetContainers())
result, err := self.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 (self *client) getLabels(c *mContainer) (map[string]string, error) {
// Get mesos agent state which contains all containers labels
var s state
req := calls.NonStreaming(calls.GetState())
result, err := self.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(c.FrameworkID.Value, c.ExecutorID.Value)
if err != nil {
return labels, fmt.Errorf("error while fetching labels from executor: %v", err)
}
return labels, nil
}
func (self *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
}

View File

@@ -1,148 +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"
"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/manager/watcher"
"k8s.io/klog"
)
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 libcontainer.CgroupSubsystems
// Information about mounted filesystems.
fsInfo fs.FsInfo
includedMetrics map[container.MetricKind]struct{}
client mesosAgentClient
}
func (self *mesosFactory) String() string {
return MesosNamespace
}
func (self *mesosFactory) NewContainerHandler(name string, inHostNamespace bool) (container.ContainerHandler, error) {
client, err := Client()
if err != nil {
return nil, err
}
return newMesosContainerHandler(
name,
&self.cgroupSubsystems,
self.machineInfoFactory,
self.fsInfo,
self.includedMetrics,
inHostNamespace,
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 (self *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 = self.client.ContainerInfo(id)
if err != nil {
return false, true, fmt.Errorf("error getting running container: %v", err)
}
return true, true, nil
}
func (self *mesosFactory) DebugInfo() map[string][]string {
return map[string][]string{}
}
func Register(
machineInfoFactory info.MachineInfoFactory,
fsInfo fs.FsInfo,
includedMetrics container.MetricSet,
) error {
client, err := Client()
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
}

View File

@@ -1,209 +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"
cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs"
)
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 isRootCgroup(name string) bool {
return name == "/"
}
func newMesosContainerHandler(
name string,
cgroupSubsystems *containerlibcontainer.CgroupSubsystems,
machineInfoFactory info.MachineInfoFactory,
fsInfo fs.FsInfo,
includedMetrics container.MetricSet,
inHostNamespace bool,
client mesosAgentClient,
) (container.ContainerHandler, error) {
cgroupPaths := common.MakeCgroupPaths(cgroupSubsystems.MountPoints, name)
// Generate the equivalent cgroup manager for this container.
cgroupManager := &cgroupfs.Manager{
Cgroups: &libcontainerconfigs.Cgroup{
Name: name,
},
Paths: cgroupPaths,
}
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 (self *mesosContainerHandler) ContainerReference() (info.ContainerReference, error) {
// We only know the container by its one name.
return self.reference, nil
}
// Nothing to start up.
func (self *mesosContainerHandler) Start() {}
// Nothing to clean up.
func (self *mesosContainerHandler) Cleanup() {}
func (self *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(self.cgroupPaths, self.machineInfoFactory, hasNetwork, hasFilesystem)
if err != nil {
return spec, err
}
spec.Labels = self.labels
return spec, nil
}
func (self *mesosContainerHandler) getFsStats(stats *info.ContainerStats) error {
mi, err := self.machineInfoFactory.GetMachineInfo()
if err != nil {
return err
}
if self.includedMetrics.Has(container.DiskIOMetrics) {
common.AssignDeviceNamesToDiskStats((*common.MachineInfoNamer)(mi), &stats.DiskIo)
}
return nil
}
func (self *mesosContainerHandler) GetStats() (*info.ContainerStats, error) {
stats, err := self.libcontainerHandler.GetStats()
if err != nil {
return stats, err
}
// Get filesystem stats.
err = self.getFsStats(stats)
if err != nil {
return stats, err
}
return stats, nil
}
func (self *mesosContainerHandler) GetCgroupPath(resource string) (string, error) {
path, ok := self.cgroupPaths[resource]
if !ok {
return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, self.name)
}
return path, nil
}
func (self *mesosContainerHandler) GetContainerLabels() map[string]string {
return self.labels
}
func (self *mesosContainerHandler) GetContainerIPAddress() string {
// the IP address for the mesos container corresponds to the system ip address.
return "127.0.0.1"
}
func (self *mesosContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
return common.ListContainers(self.name, self.cgroupPaths, listType)
}
func (self *mesosContainerHandler) ListProcesses(listType container.ListType) ([]int, error) {
return self.libcontainerHandler.GetProcesses()
}
func (self *mesosContainerHandler) Exists() bool {
return common.CgroupExists(self.cgroupPaths)
}
func (self *mesosContainerHandler) Type() container.ContainerType {
return container.ContainerTypeMesos
}

View File

@@ -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"
"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.Source
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
}

View File

@@ -5,6 +5,7 @@ go_library(
srcs = [
"factory.go",
"handler.go",
"watcher.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/container/raw",
importpath = "github.com/google/cadvisor/container/raw",
@@ -16,9 +17,10 @@ go_library(
"//vendor/github.com/google/cadvisor/fs:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/machine:go_default_library",
"//vendor/github.com/google/cadvisor/manager/watcher:go_default_library",
"//vendor/github.com/google/cadvisor/watcher:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
"//vendor/github.com/sigma/go-inotify:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)

View File

@@ -24,7 +24,7 @@ import (
"github.com/google/cadvisor/container/libcontainer"
"github.com/google/cadvisor/fs"
info "github.com/google/cadvisor/info/v1"
watch "github.com/google/cadvisor/manager/watcher"
watch "github.com/google/cadvisor/watcher"
"k8s.io/klog"
)

View File

@@ -25,7 +25,7 @@ import (
"github.com/google/cadvisor/container/common"
"github.com/google/cadvisor/container/libcontainer"
"github.com/google/cadvisor/manager/watcher"
"github.com/google/cadvisor/watcher"
inotify "github.com/sigma/go-inotify"
"k8s.io/klog"

View File

@@ -1,43 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"client.go",
"factory.go",
"handler.go",
"helpers.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/container/rkt",
importpath = "github.com/google/cadvisor/container/rkt",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/blang/semver:go_default_library",
"//vendor/github.com/coreos/rkt/api/v1alpha:go_default_library",
"//vendor/github.com/google/cadvisor/container:go_default_library",
"//vendor/github.com/google/cadvisor/container/common:go_default_library",
"//vendor/github.com/google/cadvisor/container/libcontainer:go_default_library",
"//vendor/github.com/google/cadvisor/fs:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/manager/watcher:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
"//vendor/golang.org/x/net/context:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -1,96 +0,0 @@
// Copyright 2016 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 rkt
import (
"fmt"
"net"
"sync"
"time"
"github.com/blang/semver"
rktapi "github.com/coreos/rkt/api/v1alpha"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
const (
defaultRktAPIServiceAddr = "localhost:15441"
timeout = 2 * time.Second
minimumRktBinVersion = "1.6.0"
)
var (
rktClient rktapi.PublicAPIClient
rktClientErr error
once sync.Once
)
func Client() (rktapi.PublicAPIClient, error) {
once.Do(func() {
conn, err := net.DialTimeout("tcp", defaultRktAPIServiceAddr, timeout)
if err != nil {
rktClient = nil
rktClientErr = fmt.Errorf("rkt: cannot tcp Dial rkt api service: %v", err)
return
}
conn.Close()
apisvcConn, err := grpc.Dial(defaultRktAPIServiceAddr, grpc.WithInsecure(), grpc.WithTimeout(timeout))
if err != nil {
rktClient = nil
rktClientErr = fmt.Errorf("rkt: cannot grpc Dial rkt api service: %v", err)
return
}
apisvc := rktapi.NewPublicAPIClient(apisvcConn)
resp, err := apisvc.GetInfo(context.Background(), &rktapi.GetInfoRequest{})
if err != nil {
rktClientErr = fmt.Errorf("rkt: GetInfo() failed: %v", err)
return
}
binVersion, err := semver.Make(resp.Info.RktVersion)
if err != nil {
rktClientErr = fmt.Errorf("rkt: couldn't parse RtVersion: %v", err)
return
}
if binVersion.LT(semver.MustParse(minimumRktBinVersion)) {
rktClientErr = fmt.Errorf("rkt: binary version is too old(%v), requires at least %v", resp.Info.RktVersion, minimumRktBinVersion)
return
}
rktClient = apisvc
})
return rktClient, rktClientErr
}
func RktPath() (string, error) {
client, err := Client()
if err != nil {
return "", err
}
resp, err := client.GetInfo(context.Background(), &rktapi.GetInfoRequest{})
if err != nil {
return "", fmt.Errorf("couldn't GetInfo from rkt api service: %v", err)
}
return resp.Info.GlobalFlags.Dir, nil
}

View File

@@ -1,99 +0,0 @@
// Copyright 2016 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 rkt
import (
"fmt"
"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/manager/watcher"
"k8s.io/klog"
)
const RktNamespace = "rkt"
type rktFactory struct {
machineInfoFactory info.MachineInfoFactory
cgroupSubsystems *libcontainer.CgroupSubsystems
fsInfo fs.FsInfo
includedMetrics container.MetricSet
rktPath string
}
func (self *rktFactory) String() string {
return "rkt"
}
func (self *rktFactory) NewContainerHandler(name string, inHostNamespace bool) (container.ContainerHandler, error) {
client, err := Client()
if err != nil {
return nil, err
}
rootFs := "/"
if !inHostNamespace {
rootFs = "/rootfs"
}
return newRktContainerHandler(name, client, self.rktPath, self.cgroupSubsystems, self.machineInfoFactory, self.fsInfo, rootFs, self.includedMetrics)
}
func (self *rktFactory) CanHandleAndAccept(name string) (bool, bool, error) {
accept, err := verifyPod(name)
return accept, accept, err
}
func (self *rktFactory) DebugInfo() map[string][]string {
return map[string][]string{}
}
func Register(machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, includedMetrics container.MetricSet) error {
_, err := Client()
if err != nil {
return fmt.Errorf("unable to communicate with Rkt api service: %v", err)
}
rktPath, err := RktPath()
if err != nil {
return fmt.Errorf("unable to get the RktPath variable %v", err)
}
cgroupSubsystems, err := libcontainer.GetCgroupSubsystems(includedMetrics)
if err != nil {
return fmt.Errorf("failed to get cgroup subsystems: %v", err)
}
if len(cgroupSubsystems.Mounts) == 0 {
return fmt.Errorf("failed to find supported cgroup mounts for the raw factory")
}
klog.V(1).Infof("Registering Rkt factory")
factory := &rktFactory{
machineInfoFactory: machineInfoFactory,
fsInfo: fsInfo,
cgroupSubsystems: &cgroupSubsystems,
includedMetrics: includedMetrics,
rktPath: rktPath,
}
container.RegisterContainerHandlerFactory(factory, []watcher.ContainerWatchSource{watcher.Rkt})
return nil
}

View File

@@ -1,280 +0,0 @@
// Copyright 2016 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 "rkt" containers.
package rkt
import (
"fmt"
"os"
rktapi "github.com/coreos/rkt/api/v1alpha"
"github.com/google/cadvisor/container"
"github.com/google/cadvisor/container/common"
"github.com/google/cadvisor/container/libcontainer"
"github.com/google/cadvisor/fs"
info "github.com/google/cadvisor/info/v1"
"golang.org/x/net/context"
cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
"github.com/opencontainers/runc/libcontainer/configs"
"k8s.io/klog"
)
type rktContainerHandler struct {
machineInfoFactory info.MachineInfoFactory
// Absolute path to the cgroup hierarchies of this container.
// (e.g.: "cpu" -> "/sys/fs/cgroup/cpu/test")
cgroupPaths map[string]string
fsInfo fs.FsInfo
isPod bool
rootfsStorageDir string
// Filesystem handler.
fsHandler common.FsHandler
includedMetrics container.MetricSet
apiPod *rktapi.Pod
labels map[string]string
reference info.ContainerReference
libcontainerHandler *libcontainer.Handler
}
func newRktContainerHandler(name string, rktClient rktapi.PublicAPIClient, rktPath string, cgroupSubsystems *libcontainer.CgroupSubsystems, machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, rootFs string, includedMetrics container.MetricSet) (container.ContainerHandler, error) {
aliases := make([]string, 1)
isPod := false
apiPod := &rktapi.Pod{}
parsed, err := parseName(name)
if err != nil {
return nil, fmt.Errorf("this should be impossible!, new handler failing, but factory allowed, name = %s", name)
}
// rktnetes uses containerID: rkt://fff40827-b994-4e3a-8f88-6427c2c8a5ac:nginx
if parsed.Container == "" {
isPod = true
aliases = append(aliases, "rkt://"+parsed.Pod)
} else {
aliases = append(aliases, "rkt://"+parsed.Pod+":"+parsed.Container)
}
pid := os.Getpid()
labels := make(map[string]string)
resp, err := rktClient.InspectPod(context.Background(), &rktapi.InspectPodRequest{
Id: parsed.Pod,
})
if err != nil {
return nil, err
}
annotations := resp.Pod.Annotations
if parsed.Container != "" { // As not empty string, an App container
if contAnnotations, ok := findAnnotations(resp.Pod.Apps, parsed.Container); !ok {
klog.Warningf("couldn't find app %v in pod", parsed.Container)
} else {
annotations = append(annotations, contAnnotations...)
}
} else { // The Pod container
pid = int(resp.Pod.Pid)
apiPod = resp.Pod
}
labels = createLabels(annotations)
cgroupPaths := common.MakeCgroupPaths(cgroupSubsystems.MountPoints, name)
// Generate the equivalent cgroup manager for this container.
cgroupManager := &cgroupfs.Manager{
Cgroups: &configs.Cgroup{
Name: name,
},
Paths: cgroupPaths,
}
libcontainerHandler := libcontainer.NewHandler(cgroupManager, rootFs, pid, includedMetrics)
rootfsStorageDir := getRootFs(rktPath, parsed)
containerReference := info.ContainerReference{
Name: name,
Aliases: aliases,
Namespace: RktNamespace,
}
handler := &rktContainerHandler{
machineInfoFactory: machineInfoFactory,
cgroupPaths: cgroupPaths,
fsInfo: fsInfo,
isPod: isPod,
rootfsStorageDir: rootfsStorageDir,
includedMetrics: includedMetrics,
apiPod: apiPod,
labels: labels,
reference: containerReference,
libcontainerHandler: libcontainerHandler,
}
if includedMetrics.Has(container.DiskUsageMetrics) {
handler.fsHandler = common.NewFsHandler(common.DefaultPeriod, rootfsStorageDir, "", fsInfo)
}
return handler, nil
}
func findAnnotations(apps []*rktapi.App, container string) ([]*rktapi.KeyValue, bool) {
for _, app := range apps {
if app.Name == container {
return app.Annotations, true
}
}
return nil, false
}
func createLabels(annotations []*rktapi.KeyValue) map[string]string {
labels := make(map[string]string)
for _, kv := range annotations {
labels[kv.Key] = kv.Value
}
return labels
}
func (handler *rktContainerHandler) ContainerReference() (info.ContainerReference, error) {
return handler.reference, nil
}
func (handler *rktContainerHandler) Start() {
handler.fsHandler.Start()
}
func (handler *rktContainerHandler) Cleanup() {
handler.fsHandler.Stop()
}
func (handler *rktContainerHandler) GetSpec() (info.ContainerSpec, error) {
hasNetwork := handler.isPod && handler.includedMetrics.Has(container.NetworkUsageMetrics)
hasFilesystem := handler.includedMetrics.Has(container.DiskUsageMetrics)
spec, err := common.GetSpec(handler.cgroupPaths, handler.machineInfoFactory, hasNetwork, hasFilesystem)
spec.Labels = handler.labels
return spec, err
}
func (handler *rktContainerHandler) getFsStats(stats *info.ContainerStats) error {
mi, err := handler.machineInfoFactory.GetMachineInfo()
if err != nil {
return err
}
if handler.includedMetrics.Has(container.DiskIOMetrics) {
common.AssignDeviceNamesToDiskStats((*common.MachineInfoNamer)(mi), &stats.DiskIo)
}
if !handler.includedMetrics.Has(container.DiskUsageMetrics) {
return nil
}
deviceInfo, err := handler.fsInfo.GetDirFsDevice(handler.rootfsStorageDir)
if err != nil {
return err
}
var limit uint64 = 0
// Use capacity as limit.
for _, fs := range mi.Filesystems {
if fs.Device == deviceInfo.Device {
limit = fs.Capacity
break
}
}
fsStat := info.FsStats{Device: deviceInfo.Device, Limit: limit}
usage := handler.fsHandler.Usage()
fsStat.BaseUsage = usage.BaseUsageBytes
fsStat.Usage = usage.TotalUsageBytes
fsStat.Inodes = usage.InodeUsage
stats.Filesystem = append(stats.Filesystem, fsStat)
return nil
}
func (handler *rktContainerHandler) GetStats() (*info.ContainerStats, error) {
stats, err := handler.libcontainerHandler.GetStats()
if err != nil {
return stats, err
}
// Get filesystem stats.
err = handler.getFsStats(stats)
if err != nil {
return stats, err
}
return stats, nil
}
func (self *rktContainerHandler) GetContainerIPAddress() string {
// attempt to return the ip address of the pod
// if a specific ip address of the pod could not be determined, return the system ip address
if self.isPod && len(self.apiPod.Networks) > 0 {
address := self.apiPod.Networks[0].Ipv4
if address != "" {
return address
} else {
return self.apiPod.Networks[0].Ipv6
}
} else {
return "127.0.0.1"
}
}
func (handler *rktContainerHandler) GetCgroupPath(resource string) (string, error) {
path, ok := handler.cgroupPaths[resource]
if !ok {
return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, handler.reference.Name)
}
return path, nil
}
func (handler *rktContainerHandler) GetContainerLabels() map[string]string {
return handler.labels
}
func (handler *rktContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
return common.ListContainers(handler.reference.Name, handler.cgroupPaths, listType)
}
func (handler *rktContainerHandler) ListProcesses(listType container.ListType) ([]int, error) {
return handler.libcontainerHandler.GetProcesses()
}
func (handler *rktContainerHandler) Exists() bool {
return common.CgroupExists(handler.cgroupPaths)
}
func (handler *rktContainerHandler) Type() container.ContainerType {
return container.ContainerTypeRkt
}

View File

@@ -1,141 +0,0 @@
// Copyright 2016 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 rkt
import (
"fmt"
"io/ioutil"
"path"
"strings"
rktapi "github.com/coreos/rkt/api/v1alpha"
"golang.org/x/net/context"
"k8s.io/klog"
)
type parsedName struct {
Pod string
Container string
}
func verifyPod(name string) (bool, error) {
pod, err := cgroupToPod(name)
if err != nil || pod == nil {
return false, err
}
// Anything handler can handle is also accepted.
// Accept cgroups that are sub the pod cgroup, except "system.slice"
// - "system.slice" doesn't contain any processes itself
accept := !strings.HasSuffix(name, "/system.slice")
return accept, nil
}
func cgroupToPod(name string) (*rktapi.Pod, error) {
rktClient, err := Client()
if err != nil {
return nil, fmt.Errorf("couldn't get rkt api service: %v", err)
}
resp, err := rktClient.ListPods(context.Background(), &rktapi.ListPodsRequest{
Filters: []*rktapi.PodFilter{
{
States: []rktapi.PodState{rktapi.PodState_POD_STATE_RUNNING},
PodSubCgroups: []string{name},
},
},
})
if err != nil {
return nil, fmt.Errorf("failed to list pods: %v", err)
}
if len(resp.Pods) == 0 {
return nil, nil
}
if len(resp.Pods) != 1 {
return nil, fmt.Errorf("returned %d (expected 1) pods for cgroup %v", len(resp.Pods), name)
}
return resp.Pods[0], nil
}
/* Parse cgroup name into a pod/container name struct
Example cgroup fs name
pod - /machine.slice/machine-rkt\\x2df556b64a\\x2d17a7\\x2d47d7\\x2d93ec\\x2def2275c3d67e.scope/
or /system.slice/k8s-..../
container under pod - /machine.slice/machine-rkt\\x2df556b64a\\x2d17a7\\x2d47d7\\x2d93ec\\x2def2275c3d67e.scope/system.slice/alpine-sh.service
or /system.slice/k8s-..../system.slice/pause.service
*/
func parseName(name string) (*parsedName, error) {
pod, err := cgroupToPod(name)
if err != nil {
return nil, fmt.Errorf("parseName: couldn't convert %v to a rkt pod: %v", name, err)
}
if pod == nil {
return nil, fmt.Errorf("parseName: didn't return a pod for %v", name)
}
splits := strings.Split(name, "/")
parsed := &parsedName{}
if len(splits) == 3 || len(splits) == 5 {
parsed.Pod = pod.Id
if len(splits) == 5 {
parsed.Container = strings.Replace(splits[4], ".service", "", -1)
}
return parsed, nil
}
return nil, fmt.Errorf("%s not handled by rkt handler", name)
}
// Gets a Rkt container's overlay upper dir
func getRootFs(root string, parsed *parsedName) string {
/* Example of where it stores the upper dir key
for container
/var/lib/rkt/pods/run/bc793ec6-c48f-4480-99b5-6bec16d52210/appsinfo/alpine-sh/treeStoreID
for pod
/var/lib/rkt/pods/run/f556b64a-17a7-47d7-93ec-ef2275c3d67e/stage1TreeStoreID
*/
var tree string
if parsed.Container == "" {
tree = path.Join(root, "pods/run", parsed.Pod, "stage1TreeStoreID")
} else {
tree = path.Join(root, "pods/run", parsed.Pod, "appsinfo", parsed.Container, "treeStoreID")
}
bytes, err := ioutil.ReadFile(tree)
if err != nil {
klog.Errorf("ReadFile failed, couldn't read %v to get upper dir: %v", tree, err)
return ""
}
s := string(bytes)
/* Example of where the upper dir is stored via key read above
/var/lib/rkt/pods/run/bc793ec6-c48f-4480-99b5-6bec16d52210/overlay/deps-sha512-82a099e560a596662b15dec835e9adabab539cad1f41776a30195a01a8f2f22b/
*/
return path.Join(root, "pods/run", parsed.Pod, "overlay", s)
}

View File

@@ -2,7 +2,10 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["factory.go"],
srcs = [
"factory.go",
"plugin.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/container/systemd",
importpath = "github.com/google/cadvisor/container/systemd",
visibility = ["//visibility:public"],
@@ -10,7 +13,7 @@ go_library(
"//vendor/github.com/google/cadvisor/container:go_default_library",
"//vendor/github.com/google/cadvisor/fs:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/manager/watcher:go_default_library",
"//vendor/github.com/google/cadvisor/watcher:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)
@@ -24,7 +27,10 @@ filegroup(
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
srcs = [
":package-srcs",
"//vendor/github.com/google/cadvisor/container/systemd/install:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -21,7 +21,7 @@ import (
"github.com/google/cadvisor/container"
"github.com/google/cadvisor/fs"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/manager/watcher"
"github.com/google/cadvisor/watcher"
"k8s.io/klog"
)

View File

@@ -0,0 +1,28 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["install.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/container/systemd/install",
importpath = "github.com/google/cadvisor/container/systemd/install",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/google/cadvisor/container:go_default_library",
"//vendor/github.com/google/cadvisor/container/systemd:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,29 @@
// 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 systemd.NewPlugin() as the "systemd" container provider when imported
package install
import (
"github.com/google/cadvisor/container"
"github.com/google/cadvisor/container/systemd"
"k8s.io/klog"
)
func init() {
err := container.RegisterPlugin("systemd", systemd.NewPlugin())
if err != nil {
klog.Fatalf("Failed to register systemd plugin: %v", err)
}
}

View File

@@ -0,0 +1,38 @@
// 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 systemd
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
}

View File

@@ -91,23 +91,6 @@ type RealFsInfo struct {
fsUUIDToDeviceName map[string]string
}
type Context struct {
// docker root directory.
Docker DockerContext
RktPath string
Crio CrioContext
}
type DockerContext struct {
Root string
Driver string
DriverStatus map[string]string
}
type CrioContext struct {
Root string
}
func NewFsInfo(context Context) (FsInfo, error) {
mounts, err := mount.GetMounts(nil)
if err != nil {
@@ -410,8 +393,13 @@ func (self *RealFsInfo) GetFsInfoForPath(mountSet map[string]struct{}) ([]Fs, er
klog.V(5).Infof("got devicemapper fs capacity stats: capacity: %v free: %v available: %v:", fs.Capacity, fs.Free, fs.Available)
fs.Type = DeviceMapper
case ZFS.String():
fs.Capacity, fs.Free, fs.Available, err = getZfstats(device)
fs.Type = ZFS
if _, devzfs := os.Stat("/dev/zfs"); os.IsExist(devzfs) {
fs.Capacity, fs.Free, fs.Available, err = getZfstats(device)
fs.Type = ZFS
break
}
// if /dev/zfs is not present default to VFS
fallthrough
default:
var inodes, inodesFree uint64
if utils.FileExists(partition.mountpoint) {

View File

@@ -18,6 +18,23 @@ import (
"errors"
)
type Context struct {
// docker root directory.
Docker DockerContext
RktPath string
Crio CrioContext
}
type DockerContext struct {
Root string
Driver string
DriverStatus map[string]string
}
type CrioContext struct {
Root string
}
type DeviceInfo struct {
Device string
Major uint

View File

@@ -15,28 +15,20 @@ go_library(
"//vendor/github.com/google/cadvisor/cache/memory:go_default_library",
"//vendor/github.com/google/cadvisor/collector:go_default_library",
"//vendor/github.com/google/cadvisor/container:go_default_library",
"//vendor/github.com/google/cadvisor/container/containerd:go_default_library",
"//vendor/github.com/google/cadvisor/container/crio:go_default_library",
"//vendor/github.com/google/cadvisor/container/docker:go_default_library",
"//vendor/github.com/google/cadvisor/container/mesos:go_default_library",
"//vendor/github.com/google/cadvisor/container/raw:go_default_library",
"//vendor/github.com/google/cadvisor/container/rkt:go_default_library",
"//vendor/github.com/google/cadvisor/container/systemd:go_default_library",
"//vendor/github.com/google/cadvisor/events:go_default_library",
"//vendor/github.com/google/cadvisor/fs:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/info/v2:go_default_library",
"//vendor/github.com/google/cadvisor/machine:go_default_library",
"//vendor/github.com/google/cadvisor/manager/watcher:go_default_library",
"//vendor/github.com/google/cadvisor/manager/watcher/raw:go_default_library",
"//vendor/github.com/google/cadvisor/manager/watcher/rkt:go_default_library",
"//vendor/github.com/google/cadvisor/summary:go_default_library",
"//vendor/github.com/google/cadvisor/utils/cpuload:go_default_library",
"//vendor/github.com/google/cadvisor/utils/oomparser:go_default_library",
"//vendor/github.com/google/cadvisor/utils/sysfs:go_default_library",
"//vendor/github.com/google/cadvisor/version:go_default_library",
"//vendor/github.com/google/cadvisor/watcher:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library",
"//vendor/golang.org/x/net/context:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
"//vendor/k8s.io/utils/clock:go_default_library",
],
@@ -51,10 +43,7 @@ filegroup(
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/github.com/google/cadvisor/manager/watcher:all-srcs",
],
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -30,27 +30,19 @@ import (
"github.com/google/cadvisor/cache/memory"
"github.com/google/cadvisor/collector"
"github.com/google/cadvisor/container"
"github.com/google/cadvisor/container/containerd"
"github.com/google/cadvisor/container/crio"
"github.com/google/cadvisor/container/docker"
"github.com/google/cadvisor/container/mesos"
"github.com/google/cadvisor/container/raw"
"github.com/google/cadvisor/container/rkt"
"github.com/google/cadvisor/container/systemd"
"github.com/google/cadvisor/events"
"github.com/google/cadvisor/fs"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/info/v2"
"github.com/google/cadvisor/machine"
"github.com/google/cadvisor/manager/watcher"
rawwatcher "github.com/google/cadvisor/manager/watcher/raw"
rktwatcher "github.com/google/cadvisor/manager/watcher/rkt"
"github.com/google/cadvisor/utils/oomparser"
"github.com/google/cadvisor/utils/sysfs"
"github.com/google/cadvisor/version"
"github.com/google/cadvisor/watcher"
"github.com/opencontainers/runc/libcontainer/cgroups"
"golang.org/x/net/context"
"k8s.io/klog"
"k8s.io/utils/clock"
)
@@ -62,8 +54,6 @@ var eventStorageAgeLimit = flag.String("event_storage_age_limit", "default=24h",
var eventStorageEventLimit = flag.String("event_storage_event_limit", "default=100000", "Max number of events to store (per type). Value is a comma separated list of key values, where the keys are event types (e.g.: creation, oom) or \"default\" and the value is an integer. Default is applied to all non-specified event types")
var applicationMetricsCountLimit = flag.Int("application_metrics_count_limit", 100, "Max number of application metrics to store (per container)")
const dockerClientTimeout = 10 * time.Second
// The Manager interface defines operations for starting a manager and getting
// container and machine information.
type Manager interface {
@@ -155,40 +145,12 @@ func New(memoryCache *memory.InMemoryCache, sysfs sysfs.SysFs, maxHousekeepingIn
}
klog.V(2).Infof("cAdvisor running in container: %q", selfContainer)
var (
dockerStatus info.DockerStatus
rktPath string
)
docker.SetTimeout(dockerClientTimeout)
// Try to connect to docker indefinitely on startup.
dockerStatus = retryDockerStatus()
context := fs.Context{}
if tmpRktPath, err := rkt.RktPath(); err != nil {
klog.V(5).Infof("Rkt not connected: %v", err)
} else {
rktPath = tmpRktPath
}
crioClient, err := crio.Client()
if err != nil {
if err := container.InitializeFSContext(&context); err != nil {
return nil, err
}
crioInfo, err := crioClient.Info()
if err != nil {
klog.V(5).Infof("CRI-O not connected: %v", err)
}
context := fs.Context{
Docker: fs.DockerContext{
Root: docker.RootDir(),
Driver: dockerStatus.Driver,
DriverStatus: dockerStatus.DriverStatus,
},
RktPath: rktPath,
Crio: fs.CrioContext{
Root: crioInfo.StorageRoot,
},
}
fsInfo, err := fs.NewFsInfo(context)
if err != nil {
return nil, err
@@ -240,31 +202,6 @@ func New(memoryCache *memory.InMemoryCache, sysfs sysfs.SysFs, maxHousekeepingIn
return newManager, nil
}
func retryDockerStatus() info.DockerStatus {
startupTimeout := dockerClientTimeout
maxTimeout := 4 * startupTimeout
for {
ctx, _ := context.WithTimeout(context.Background(), startupTimeout)
dockerStatus, err := docker.StatusWithContext(ctx)
if err == nil {
return dockerStatus
}
switch err {
case context.DeadlineExceeded:
klog.Warningf("Timeout trying to communicate with docker during initialization, will retry")
default:
klog.V(5).Infof("Docker not connected: %v", err)
return info.DockerStatus{}
}
startupTimeout = 2 * startupTimeout
if startupTimeout > maxTimeout {
startupTimeout = maxTimeout
}
}
}
// A namespaced container name.
type namespacedContainerName struct {
// The namespace of the container. Can be empty for the root namespace.
@@ -300,48 +237,14 @@ type manager struct {
// Start the container manager.
func (self *manager) Start() error {
err := docker.Register(self, self.fsInfo, self.includedMetrics)
if err != nil {
klog.V(5).Infof("Registration of the Docker container factory failed: %v.", err)
}
self.containerWatchers = container.InitializePlugins(self, self.fsInfo, self.includedMetrics)
err = rkt.Register(self, self.fsInfo, self.includedMetrics)
if err != nil {
klog.V(5).Infof("Registration of the rkt container factory failed: %v", err)
} else {
watcher, err := rktwatcher.NewRktContainerWatcher()
if err != nil {
return err
}
self.containerWatchers = append(self.containerWatchers, watcher)
}
err = containerd.Register(self, self.fsInfo, self.includedMetrics)
if err != nil {
klog.V(5).Infof("Registration of the containerd container factory failed: %v", err)
}
err = crio.Register(self, self.fsInfo, self.includedMetrics)
if err != nil {
klog.V(5).Infof("Registration of the crio container factory failed: %v", err)
}
err = mesos.Register(self, self.fsInfo, self.includedMetrics)
if err != nil {
klog.V(5).Infof("Registration of the mesos container factory failed: %v", err)
}
err = systemd.Register(self, self.fsInfo, self.includedMetrics)
if err != nil {
klog.V(5).Infof("Registration of the systemd container factory failed: %v", err)
}
err = raw.Register(self, self.fsInfo, self.includedMetrics, self.rawContainerCgroupPathPrefixWhiteList)
err := raw.Register(self, self.fsInfo, self.includedMetrics, self.rawContainerCgroupPathPrefixWhiteList)
if err != nil {
klog.Errorf("Registration of the raw container factory failed: %v", err)
}
rawWatcher, err := rawwatcher.NewRawContainerWatcher()
rawWatcher, err := raw.NewRawContainerWatcher()
if err != nil {
return err
}

View File

@@ -1,154 +0,0 @@
// Copyright 2016 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 rkt implements the watcher interface for rkt
package rkt
import (
"path/filepath"
"time"
"github.com/google/cadvisor/container/rkt"
"github.com/google/cadvisor/manager/watcher"
rktapi "github.com/coreos/rkt/api/v1alpha"
"golang.org/x/net/context"
"k8s.io/klog"
)
type rktContainerWatcher struct {
// Signal for watcher thread to stop.
stopWatcher chan error
}
func NewRktContainerWatcher() (watcher.ContainerWatcher, error) {
watcher := &rktContainerWatcher{
stopWatcher: make(chan error),
}
return watcher, nil
}
func (self *rktContainerWatcher) Start(events chan watcher.ContainerEvent) error {
go self.detectRktContainers(events)
return nil
}
func (self *rktContainerWatcher) Stop() error {
// Rendezvous with the watcher thread.
self.stopWatcher <- nil
return nil
}
func (self *rktContainerWatcher) detectRktContainers(events chan watcher.ContainerEvent) {
klog.V(1).Infof("Starting detectRktContainers thread")
ticker := time.Tick(10 * time.Second)
curpods := make(map[string]*rktapi.Pod)
for {
select {
case <-ticker:
pods, err := listRunningPods()
if err != nil {
klog.Errorf("detectRktContainers: listRunningPods failed: %v", err)
continue
}
curpods = self.syncRunningPods(pods, events, curpods)
case <-self.stopWatcher:
klog.Infof("Exiting rktContainer Thread")
return
}
}
}
func (self *rktContainerWatcher) syncRunningPods(pods []*rktapi.Pod, events chan watcher.ContainerEvent, curpods map[string]*rktapi.Pod) map[string]*rktapi.Pod {
newpods := make(map[string]*rktapi.Pod)
for _, pod := range pods {
newpods[pod.Id] = pod
// if pods become mutable, have to handle this better
if _, ok := curpods[pod.Id]; !ok {
// should create all cgroups not including system.slice
// i.e. /system.slice/rkt-test.service and /system.slice/rkt-test.service/system.slice/pause.service
for _, cgroup := range podToCgroup(pod) {
self.sendUpdateEvent(cgroup, events)
}
}
}
for id, pod := range curpods {
if _, ok := newpods[id]; !ok {
for _, cgroup := range podToCgroup(pod) {
klog.V(2).Infof("cgroup to delete = %v", cgroup)
self.sendDestroyEvent(cgroup, events)
}
}
}
return newpods
}
func (self *rktContainerWatcher) sendUpdateEvent(cgroup string, events chan watcher.ContainerEvent) {
events <- watcher.ContainerEvent{
EventType: watcher.ContainerAdd,
Name: cgroup,
WatchSource: watcher.Rkt,
}
}
func (self *rktContainerWatcher) sendDestroyEvent(cgroup string, events chan watcher.ContainerEvent) {
events <- watcher.ContainerEvent{
EventType: watcher.ContainerDelete,
Name: cgroup,
WatchSource: watcher.Rkt,
}
}
func listRunningPods() ([]*rktapi.Pod, error) {
client, err := rkt.Client()
if err != nil {
return nil, err
}
resp, err := client.ListPods(context.Background(), &rktapi.ListPodsRequest{
// Specify the request: Fetch and print only running pods and their details.
Detail: true,
Filters: []*rktapi.PodFilter{
{
States: []rktapi.PodState{rktapi.PodState_POD_STATE_RUNNING},
},
},
})
if err != nil {
return nil, err
}
return resp.Pods, nil
}
func podToCgroup(pod *rktapi.Pod) []string {
cgroups := make([]string, 1+len(pod.Apps), 1+len(pod.Apps))
baseCgroup := pod.Cgroup
cgroups[0] = baseCgroup
for i, app := range pod.Apps {
cgroups[i+1] = filepath.Join(baseCgroup, "system.slice", app.Name+".service")
}
return cgroups
}

View File

@@ -2,20 +2,11 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"aws.go",
"azure.go",
"cloudinfo.go",
"gce.go",
],
srcs = ["cloudinfo.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/utils/cloudinfo",
importpath = "github.com/google/cadvisor/utils/cloudinfo",
visibility = ["//visibility:public"],
deps = [
"//vendor/cloud.google.com/go/compute/metadata:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/aws:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/aws/ec2metadata:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/aws/session:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],

View File

@@ -1,69 +0,0 @@
// Copyright 2015 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 cloudinfo
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session"
"io/ioutil"
"os"
"strings"
info "github.com/google/cadvisor/info/v1"
)
const (
ProductVerFileName = "/sys/class/dmi/id/product_version"
BiosVerFileName = "/sys/class/dmi/id/bios_vendor"
Amazon = "amazon"
)
func onAWS() bool {
var dataProduct []byte
var dataBios []byte
if _, err := os.Stat(ProductVerFileName); err == nil {
dataProduct, err = ioutil.ReadFile(ProductVerFileName)
if err != nil {
return false
}
}
if _, err := os.Stat(BiosVerFileName); err == nil {
dataBios, err = ioutil.ReadFile(BiosVerFileName)
if err != nil {
return false
}
}
return strings.Contains(string(dataProduct), Amazon) || strings.Contains(strings.ToLower(string(dataBios)), Amazon)
}
func getAwsMetadata(name string) string {
client := ec2metadata.New(session.New(&aws.Config{}))
data, err := client.GetMetadata(name)
if err != nil {
return info.UnknownInstance
}
return data
}
func getAwsInstanceType() info.InstanceType {
return info.InstanceType(getAwsMetadata("instance-type"))
}
func getAwsInstanceID() info.InstanceID {
return info.InstanceID(getAwsMetadata("instance-id"))
}

View File

@@ -1,48 +0,0 @@
// Copyright 2015 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 cloudinfo
import (
info "github.com/google/cadvisor/info/v1"
"io/ioutil"
"strings"
)
const (
SysVendorFileName = "/sys/class/dmi/id/sys_vendor"
BiosUUIDFileName = "/sys/class/dmi/id/product_uuid"
MicrosoftCorporation = "Microsoft Corporation"
)
func onAzure() bool {
data, err := ioutil.ReadFile(SysVendorFileName)
if err != nil {
return false
}
return strings.Contains(string(data), MicrosoftCorporation)
}
// TODO: Implement method.
func getAzureInstanceType() info.InstanceType {
return info.UnknownInstance
}
func getAzureInstanceID() info.InstanceID {
data, err := ioutil.ReadFile(BiosUUIDFileName)
if err != nil {
return info.UnNamedInstance
}
return info.InstanceID(strings.TrimSuffix(string(data), "\n"))
}

View File

@@ -18,6 +18,7 @@ package cloudinfo
import (
info "github.com/google/cadvisor/info/v1"
"k8s.io/klog"
)
type CloudInfo interface {
@@ -26,6 +27,29 @@ type CloudInfo interface {
GetInstanceID() info.InstanceID
}
// CloudProvider is an abstraction for providing cloud-specific information.
type CloudProvider interface {
// IsActiveProvider determines whether this is the cloud provider operating
// this instance.
IsActiveProvider() bool
// GetInstanceType gets the type of instance this process is running on.
// The behavior is undefined if this is not the active provider.
GetInstanceType() info.InstanceType
// GetInstanceType gets the ID of the instance this process is running on.
// The behavior is undefined if this is not the active provider.
GetInstanceID() info.InstanceID
}
var providers = map[info.CloudProvider]CloudProvider{}
// RegisterCloudProvider registers the given cloud provider
func RegisterCloudProvider(name info.CloudProvider, provider CloudProvider) {
if _, alreadyRegistered := providers[name]; alreadyRegistered {
klog.Warningf("Duplicate registration of CloudProvider %s", name)
}
providers[name] = provider
}
type realCloudInfo struct {
cloudProvider info.CloudProvider
instanceType info.InstanceType
@@ -33,13 +57,21 @@ type realCloudInfo struct {
}
func NewRealCloudInfo() CloudInfo {
cloudProvider := detectCloudProvider()
instanceType := detectInstanceType(cloudProvider)
instanceID := detectInstanceID(cloudProvider)
for name, provider := range providers {
if provider.IsActiveProvider() {
return &realCloudInfo{
cloudProvider: name,
instanceType: provider.GetInstanceType(),
instanceID: provider.GetInstanceID(),
}
}
}
// No registered active provider.
return &realCloudInfo{
cloudProvider: cloudProvider,
instanceType: instanceType,
instanceID: instanceID,
cloudProvider: info.UnknownProvider,
instanceType: info.UnknownInstance,
instanceID: info.UnNamedInstance,
}
}
@@ -54,50 +86,3 @@ func (self *realCloudInfo) GetInstanceType() info.InstanceType {
func (self *realCloudInfo) GetInstanceID() info.InstanceID {
return self.instanceID
}
func detectCloudProvider() info.CloudProvider {
switch {
case onGCE():
return info.GCE
case onAWS():
return info.AWS
case onAzure():
return info.Azure
case onBaremetal():
return info.Baremetal
}
return info.UnknownProvider
}
func detectInstanceType(cloudProvider info.CloudProvider) info.InstanceType {
switch cloudProvider {
case info.GCE:
return getGceInstanceType()
case info.AWS:
return getAwsInstanceType()
case info.Azure:
return getAzureInstanceType()
case info.Baremetal:
return info.NoInstance
}
return info.UnknownInstance
}
func detectInstanceID(cloudProvider info.CloudProvider) info.InstanceID {
switch cloudProvider {
case info.GCE:
return getGceInstanceID()
case info.AWS:
return getAwsInstanceID()
case info.Azure:
return getAzureInstanceID()
case info.Baremetal:
return info.UnNamedInstance
}
return info.UnNamedInstance
}
// TODO: Implement method.
func onBaremetal() bool {
return false
}

View File

@@ -1,57 +0,0 @@
// Copyright 2015 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 cloudinfo
import (
"io/ioutil"
"strings"
info "github.com/google/cadvisor/info/v1"
"cloud.google.com/go/compute/metadata"
"k8s.io/klog"
)
const (
gceProductName = "/sys/class/dmi/id/product_name"
google = "Google"
)
func onGCE() bool {
data, err := ioutil.ReadFile(gceProductName)
if err != nil {
klog.V(2).Infof("Error while reading product_name: %v", err)
return false
}
return strings.Contains(string(data), google)
}
func getGceInstanceType() info.InstanceType {
machineType, err := metadata.Get("instance/machine-type")
if err != nil {
return info.UnknownInstance
}
responseParts := strings.Split(machineType, "/") // Extract the instance name from the machine type.
return info.InstanceType(responseParts[len(responseParts)-1])
}
func getGceInstanceID() info.InstanceID {
instanceID, err := metadata.Get("instance/id")
if err != nil {
return info.UnknownInstance
}
return info.InstanceID(info.InstanceType(instanceID))
}

View File

@@ -3,8 +3,8 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["watcher.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/manager/watcher",
importpath = "github.com/google/cadvisor/manager/watcher",
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/watcher",
importpath = "github.com/google/cadvisor/watcher",
visibility = ["//visibility:public"],
)
@@ -17,11 +17,7 @@ filegroup(
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/github.com/google/cadvisor/manager/watcher/raw:all-srcs",
"//vendor/github.com/google/cadvisor/manager/watcher/rkt:all-srcs",
],
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)