Filesystem stats are now per container. As of now, fs stats are reported only for the
root cgroup. To make cadvisor detect all the disks, the rootfs of host needs to mounted inside cadvisor.
This commit is contained in:
parent
946b18f789
commit
b9e70f0240
@ -12,6 +12,7 @@ To quickly tryout cAdvisor on your machine with Docker (version 0.11 or above),
|
|||||||
|
|
||||||
```
|
```
|
||||||
sudo docker run \
|
sudo docker run \
|
||||||
|
--volume=/:/rootfs:ro \
|
||||||
--volume=/var/run:/var/run:rw \
|
--volume=/var/run:/var/run:rw \
|
||||||
--volume=/sys:/sys:ro \
|
--volume=/sys:/sys:ro \
|
||||||
--volume=/var/lib/docker/:/var/lib/docker:ro \
|
--volume=/var/lib/docker/:/var/lib/docker:ro \
|
||||||
|
@ -41,7 +41,7 @@ type rawContainerHandler struct {
|
|||||||
watcher *inotify.Watcher
|
watcher *inotify.Watcher
|
||||||
stopWatcher chan error
|
stopWatcher chan error
|
||||||
watches map[string]struct{}
|
watches map[string]struct{}
|
||||||
fsInfo fs.FsInfo
|
fsInfo fs.FsInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRawContainerHandler(name string, cgroupSubsystems *cgroupSubsystems, machineInfoFactory info.MachineInfoFactory) (container.ContainerHandler, error) {
|
func newRawContainerHandler(name string, cgroupSubsystems *cgroupSubsystems, machineInfoFactory info.MachineInfoFactory) (container.ContainerHandler, error) {
|
||||||
@ -55,7 +55,7 @@ func newRawContainerHandler(name string, cgroupSubsystems *cgroupSubsystems, mac
|
|||||||
machineInfoFactory: machineInfoFactory,
|
machineInfoFactory: machineInfoFactory,
|
||||||
stopWatcher: make(chan error),
|
stopWatcher: make(chan error),
|
||||||
watches: make(map[string]struct{}),
|
watches: make(map[string]struct{}),
|
||||||
fsInfo: fs.NewFsInfo(),
|
fsInfo: fs.NewFsInfo(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,6 +144,10 @@ func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fs.
|
||||||
|
if self.name == "/" {
|
||||||
|
spec.HasFs = true
|
||||||
|
}
|
||||||
return spec, nil
|
return spec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,12 +156,14 @@ func (self *rawContainerHandler) GetStats() (*info.ContainerStats, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Get Filesystem information
|
// Get Filesystem information only for the root cgroup.
|
||||||
fsStats, err := self.fsInfo.GetFsStats(self.name)
|
if self.name == "/" {
|
||||||
if err != nil {
|
stats.Fs, err = self.fsInfo.GetFsStats()
|
||||||
return nil, err
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stats.FsStats = fsStats
|
|
||||||
return stats, nil
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ MAINTAINER dengnan@google.com vmarmol@google.com vishnuk@google.com
|
|||||||
|
|
||||||
# Grab cadvisor from the staging directory.
|
# Grab cadvisor from the staging directory.
|
||||||
ADD cadvisor /usr/bin/cadvisor
|
ADD cadvisor /usr/bin/cadvisor
|
||||||
|
RUN mkdir /rootfs
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
ENTRYPOINT ["/usr/bin/cadvisor"]
|
ENTRYPOINT ["/usr/bin/cadvisor"]
|
||||||
|
27
fs/fs.go
27
fs/fs.go
@ -10,6 +10,7 @@ package fs
|
|||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@ -17,33 +18,41 @@ import (
|
|||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
const EXT_SUPER_MAGIC = 0xEF53
|
|
||||||
|
|
||||||
type FsInfoImpl struct{}
|
type FsInfoImpl struct{}
|
||||||
|
|
||||||
func NewFsInfo() FsInfo {
|
func NewFsInfo() FsInfo {
|
||||||
return &FsInfoImpl{}
|
return &FsInfoImpl{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*FsInfoImpl) GetFsStats(containerName string) ([]FsStat, error) {
|
func (*FsInfoImpl) GetFsStats() ([]FsStat, error) {
|
||||||
filesystems := make([]FsStat, 0)
|
filesystems := make([]FsStat, 0)
|
||||||
if containerName != "/" {
|
|
||||||
return filesystems, nil
|
|
||||||
}
|
|
||||||
mounts, err := mount.GetMounts()
|
mounts, err := mount.GetMounts()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
processedPartitions := make(map[string]bool, 0)
|
||||||
for _, mount := range mounts {
|
for _, mount := range mounts {
|
||||||
if !strings.HasPrefix("ext", mount.FsType) || mount.Mountpoint != mount.Root {
|
if !strings.HasPrefix(mount.Fstype, "ext") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Avoid bind mounts.
|
||||||
|
if _, ok := processedPartitions[mount.Source]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
total, free, err := getVfsStats(mount.Mountpoint)
|
total, free, err := getVfsStats(mount.Mountpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Statvfs failed. Error: %v", err)
|
glog.Errorf("Statvfs failed. Error: %v", err)
|
||||||
} else {
|
} else {
|
||||||
glog.V(1).Infof("%s is an ext partition at %s. Total: %d, Free: %d", mount.Source, mount.Mountpoint, total, free)
|
glog.V(1).Infof("%s is an %s partition at %s. Total: %d, Free: %d", mount.Source, mount.Fstype, mount.Mountpoint, total, free)
|
||||||
filesystems = append(filesystems, FsStat{mount.Source, total, free})
|
fsStat := FsStat{
|
||||||
|
Device: mount.Source,
|
||||||
|
Major: uint(mount.Major),
|
||||||
|
Minor: uint(mount.Minor),
|
||||||
|
Capacity: total,
|
||||||
|
Free: free,
|
||||||
|
}
|
||||||
|
filesystems = append(filesystems, fsStat)
|
||||||
|
processedPartitions[mount.Source] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return filesystems, nil
|
return filesystems, nil
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
package fs
|
package fs
|
||||||
|
|
||||||
type FsStat struct {
|
type FsStat struct {
|
||||||
Name string `json:"name"`
|
Device string `json:"device,omitempty"`
|
||||||
|
Major uint `json:"major"`
|
||||||
|
Minor uint `json:"minor"`
|
||||||
Capacity uint64 `json:"capacity"`
|
Capacity uint64 `json:"capacity"`
|
||||||
Free uint64 `json:"free"`
|
Free uint64 `json:"free"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FsInfo interface {
|
type FsInfo interface {
|
||||||
// Returns capacity and free space, in bytes, of all the ext2, ext3, ext4 filesystems used by container 'containerName'.
|
// Returns capacity and free space, in bytes, of all the ext2, ext3, ext4 filesystems on the host.
|
||||||
GetFsStats(containerName string) ([]FsStat, error)
|
GetFsStats() ([]FsStat, error)
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ package info
|
|||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/cadvisor/fs"
|
"github.com/google/cadvisor/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -49,6 +49,8 @@ type ContainerSpec struct {
|
|||||||
Memory MemorySpec `json:"memory,omitempty"`
|
Memory MemorySpec `json:"memory,omitempty"`
|
||||||
|
|
||||||
HasNetwork bool `json:"has_network"`
|
HasNetwork bool `json:"has_network"`
|
||||||
|
|
||||||
|
HasFs bool `json:"has_fs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container reference contains enough information to uniquely identify a container
|
// Container reference contains enough information to uniquely identify a container
|
||||||
@ -239,7 +241,7 @@ type ContainerStats struct {
|
|||||||
Memory *MemoryStats `json:"memory,omitempty"`
|
Memory *MemoryStats `json:"memory,omitempty"`
|
||||||
Network *NetworkStats `json:"network,omitempty"`
|
Network *NetworkStats `json:"network,omitempty"`
|
||||||
// Filesystem statistics
|
// Filesystem statistics
|
||||||
FsStats []fs.FsStat `json:"fs_stats,omitempty"`
|
Fs []fs.FsStat `json:"fs,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Makes a deep copy of the ContainerStats and returns a pointer to the new
|
// Makes a deep copy of the ContainerStats and returns a pointer to the new
|
||||||
|
Loading…
Reference in New Issue
Block a user