bump containerd/cgroups 5fbad35c2a7e855762d3c60f2e474ffcad0d470a

full diff: c4b9ac5c76...5fbad35c2a

- containerd/cgroups#82 Add go module support
- containerd/cgroups#96 Move metrics proto package to stats/v1
- containerd/cgroups#97 Allow overriding the default /proc folder in blkioController
- containerd/cgroups#98 Allows ignoring memory modules
- containerd/cgroups#99 Add Go 1.13 to Travis
- containerd/cgroups#100 stats/v1: export per-cgroup stats

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2019-10-30 13:06:34 +01:00
parent 7cb46617fc
commit 27552ceb15
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
17 changed files with 1527 additions and 407 deletions

View File

@ -16,7 +16,7 @@ import (
"strings" "strings"
"time" "time"
containerd_cgroups "github.com/containerd/cgroups" v1 "github.com/containerd/cgroups/stats/v1"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/blkiodev" "github.com/docker/docker/api/types/blkiodev"
pblkiodev "github.com/docker/docker/api/types/blkiodev" pblkiodev "github.com/docker/docker/api/types/blkiodev"
@ -1376,7 +1376,7 @@ func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container
return daemon.Unmount(container) return daemon.Unmount(container)
} }
func copyBlkioEntry(entries []*containerd_cgroups.BlkIOEntry) []types.BlkioStatEntry { func copyBlkioEntry(entries []*v1.BlkIOEntry) []types.BlkioStatEntry {
out := make([]types.BlkioStatEntry, len(entries)) out := make([]types.BlkioStatEntry, len(entries))
for i, re := range entries { for i, re := range entries {
out[i] = types.BlkioStatEntry{ out[i] = types.BlkioStatEntry{

View File

@ -3,7 +3,7 @@ package types // import "github.com/docker/docker/libcontainerd/types"
import ( import (
"time" "time"
"github.com/containerd/cgroups" v1 "github.com/containerd/cgroups/stats/v1"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
) )
@ -13,13 +13,13 @@ type Summary struct{}
// Stats holds metrics properties as returned by containerd // Stats holds metrics properties as returned by containerd
type Stats struct { type Stats struct {
Read time.Time Read time.Time
Metrics *cgroups.Metrics Metrics *v1.Metrics
} }
// InterfaceToStats returns a stats object from the platform-specific interface. // InterfaceToStats returns a stats object from the platform-specific interface.
func InterfaceToStats(read time.Time, v interface{}) *Stats { func InterfaceToStats(read time.Time, v interface{}) *Stats {
return &Stats{ return &Stats{
Metrics: v.(*cgroups.Metrics), Metrics: v.(*v1.Metrics),
Read: read, Read: read,
} }
} }

View File

@ -120,7 +120,7 @@ google.golang.org/genproto 694d95ba50e67b2e363f3483057d
github.com/containerd/containerd 36cf5b690dcc00ff0f34ff7799209050c3d0c59a # v1.3.0 github.com/containerd/containerd 36cf5b690dcc00ff0f34ff7799209050c3d0c59a # v1.3.0
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13 github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
github.com/containerd/continuity f2a389ac0a02ce21c09edd7344677a601970f41c github.com/containerd/continuity f2a389ac0a02ce21c09edd7344677a601970f41c
github.com/containerd/cgroups c4b9ac5c7601384c965b9646fc515884e091ebb9 github.com/containerd/cgroups 5fbad35c2a7e855762d3c60f2e474ffcad0d470a
github.com/containerd/console 0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f github.com/containerd/console 0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f
github.com/containerd/go-runc e029b79d8cda8374981c64eba71f28ec38e5526f github.com/containerd/go-runc e029b79d8cda8374981c64eba71f28ec38e5526f
github.com/containerd/typeurl 2a93cfde8c20b23de8eb84a5adbc234ddf7a9e8d github.com/containerd/typeurl 2a93cfde8c20b23de8eb84a5adbc234ddf7a9e8d

View File

@ -26,17 +26,33 @@ import (
"strconv" "strconv"
"strings" "strings"
v1 "github.com/containerd/cgroups/stats/v1"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
) )
func NewBlkio(root string) *blkioController { // NewBlkio returns a Blkio controller given the root folder of cgroups.
return &blkioController{ // It may optionally accept other configuration options, such as ProcRoot(path)
root: filepath.Join(root, string(Blkio)), func NewBlkio(root string, options ...func(controller *blkioController)) *blkioController {
ctrl := &blkioController{
root: filepath.Join(root, string(Blkio)),
procRoot: "/proc",
}
for _, opt := range options {
opt(ctrl)
}
return ctrl
}
// ProcRoot overrides the default location of the "/proc" filesystem
func ProcRoot(path string) func(controller *blkioController) {
return func(c *blkioController) {
c.procRoot = path
} }
} }
type blkioController struct { type blkioController struct {
root string root string
procRoot string
} }
func (b *blkioController) Name() Name { func (b *blkioController) Name() Name {
@ -72,8 +88,8 @@ func (b *blkioController) Update(path string, resources *specs.LinuxResources) e
return b.Create(path, resources) return b.Create(path, resources)
} }
func (b *blkioController) Stat(path string, stats *Metrics) error { func (b *blkioController) Stat(path string, stats *v1.Metrics) error {
stats.Blkio = &BlkIOStat{} stats.Blkio = &v1.BlkIOStat{}
settings := []blkioStatSettings{ settings := []blkioStatSettings{
{ {
name: "throttle.io_serviced", name: "throttle.io_serviced",
@ -122,7 +138,7 @@ func (b *blkioController) Stat(path string, stats *Metrics) error {
}, },
) )
} }
f, err := os.Open("/proc/diskstats") f, err := os.Open(filepath.Join(b.procRoot, "diskstats"))
if err != nil { if err != nil {
return err return err
} }
@ -141,7 +157,7 @@ func (b *blkioController) Stat(path string, stats *Metrics) error {
return nil return nil
} }
func (b *blkioController) readEntry(devices map[deviceKey]string, path, name string, entry *[]*BlkIOEntry) error { func (b *blkioController) readEntry(devices map[deviceKey]string, path, name string, entry *[]*v1.BlkIOEntry) error {
f, err := os.Open(filepath.Join(b.Path(path), fmt.Sprintf("blkio.%s", name))) f, err := os.Open(filepath.Join(b.Path(path), fmt.Sprintf("blkio.%s", name)))
if err != nil { if err != nil {
return err return err
@ -180,7 +196,7 @@ func (b *blkioController) readEntry(devices map[deviceKey]string, path, name str
if err != nil { if err != nil {
return err return err
} }
*entry = append(*entry, &BlkIOEntry{ *entry = append(*entry, &v1.BlkIOEntry{
Device: devices[deviceKey{major, minor}], Device: devices[deviceKey{major, minor}],
Major: major, Major: major,
Minor: minor, Minor: minor,
@ -268,7 +284,7 @@ type blkioSettings struct {
type blkioStatSettings struct { type blkioStatSettings struct {
name string name string
entry *[]*BlkIOEntry entry *[]*v1.BlkIOEntry
} }
func uintf(v interface{}) []byte { func uintf(v interface{}) []byte {

View File

@ -25,6 +25,7 @@ import (
"strings" "strings"
"sync" "sync"
v1 "github.com/containerd/cgroups/stats/v1"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -246,7 +247,7 @@ func (c *cgroup) Delete() error {
} }
// Stat returns the current metrics for the cgroup // Stat returns the current metrics for the cgroup
func (c *cgroup) Stat(handlers ...ErrorHandler) (*Metrics, error) { func (c *cgroup) Stat(handlers ...ErrorHandler) (*v1.Metrics, error) {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
if c.err != nil { if c.err != nil {
@ -256,10 +257,10 @@ func (c *cgroup) Stat(handlers ...ErrorHandler) (*Metrics, error) {
handlers = append(handlers, errPassthrough) handlers = append(handlers, errPassthrough)
} }
var ( var (
stats = &Metrics{ stats = &v1.Metrics{
CPU: &CPUStat{ CPU: &v1.CPUStat{
Throttling: &Throttle{}, Throttling: &v1.Throttle{},
Usage: &CPUUsage{}, Usage: &v1.CPUUsage{},
}, },
} }
wg = &sync.WaitGroup{} wg = &sync.WaitGroup{}

View File

@ -19,6 +19,7 @@ package cgroups
import ( import (
"os" "os"
v1 "github.com/containerd/cgroups/stats/v1"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
) )
@ -68,7 +69,7 @@ type Cgroup interface {
// subsystems are moved one at a time // subsystems are moved one at a time
MoveTo(Cgroup) error MoveTo(Cgroup) error
// Stat returns the stats for all subsystems in the cgroup // Stat returns the stats for all subsystems in the cgroup
Stat(...ErrorHandler) (*Metrics, error) Stat(...ErrorHandler) (*v1.Metrics, error)
// Update updates all the subsystems with the provided resource changes // Update updates all the subsystems with the provided resource changes
Update(resources *specs.LinuxResources) error Update(resources *specs.LinuxResources) error
// Processes returns all the processes in a select subsystem for the cgroup // Processes returns all the processes in a select subsystem for the cgroup

View File

@ -24,6 +24,7 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
v1 "github.com/containerd/cgroups/stats/v1"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
) )
@ -100,7 +101,7 @@ func (c *cpuController) Update(path string, resources *specs.LinuxResources) err
return c.Create(path, resources) return c.Create(path, resources)
} }
func (c *cpuController) Stat(path string, stats *Metrics) error { func (c *cpuController) Stat(path string, stats *v1.Metrics) error {
f, err := os.Open(filepath.Join(c.Path(path), "cpu.stat")) f, err := os.Open(filepath.Join(c.Path(path), "cpu.stat"))
if err != nil { if err != nil {
return err return err

View File

@ -22,6 +22,8 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
v1 "github.com/containerd/cgroups/stats/v1"
) )
const nanosecondsInSecond = 1000000000 const nanosecondsInSecond = 1000000000
@ -46,7 +48,7 @@ func (c *cpuacctController) Path(path string) string {
return filepath.Join(c.root, path) return filepath.Join(c.root, path)
} }
func (c *cpuacctController) Stat(path string, stats *Metrics) error { func (c *cpuacctController) Stat(path string, stats *v1.Metrics) error {
user, kernel, err := c.getUsage(path) user, kernel, err := c.getUsage(path)
if err != nil { if err != nil {
return err return err

13
vendor/github.com/containerd/cgroups/go.mod generated vendored Normal file
View File

@ -0,0 +1,13 @@
module github.com/containerd/cgroups
go 1.12
require (
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
github.com/docker/go-units v0.4.0
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e
github.com/gogo/protobuf v1.2.1
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700
github.com/pkg/errors v0.8.1
golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f
)

View File

@ -23,6 +23,7 @@ import (
"strconv" "strconv"
"strings" "strings"
v1 "github.com/containerd/cgroups/stats/v1"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
) )
@ -67,7 +68,7 @@ func (h *hugetlbController) Create(path string, resources *specs.LinuxResources)
return nil return nil
} }
func (h *hugetlbController) Stat(path string, stats *Metrics) error { func (h *hugetlbController) Stat(path string, stats *v1.Metrics) error {
for _, size := range h.sizes { for _, size := range h.sizes {
s, err := h.readSizeStat(path, size) s, err := h.readSizeStat(path, size)
if err != nil { if err != nil {
@ -78,8 +79,8 @@ func (h *hugetlbController) Stat(path string, stats *Metrics) error {
return nil return nil
} }
func (h *hugetlbController) readSizeStat(path, size string) (*HugetlbStat, error) { func (h *hugetlbController) readSizeStat(path, size string) (*v1.HugetlbStat, error) {
s := HugetlbStat{ s := v1.HugetlbStat{
Pagesize: size, Pagesize: size,
} }
for _, t := range []struct { for _, t := range []struct {

View File

@ -27,19 +27,48 @@ import (
"strings" "strings"
"syscall" "syscall"
"golang.org/x/sys/unix" v1 "github.com/containerd/cgroups/stats/v1"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
"golang.org/x/sys/unix"
) )
func NewMemory(root string) *memoryController { // NewMemory returns a Memory controller given the root folder of cgroups.
return &memoryController{ // It may optionally accept other configuration options, such as IgnoreModules(...)
root: filepath.Join(root, string(Memory)), func NewMemory(root string, options ...func(*memoryController)) *memoryController {
mc := &memoryController{
root: filepath.Join(root, string(Memory)),
ignored: map[string]struct{}{},
}
for _, opt := range options {
opt(mc)
}
return mc
}
// IgnoreModules configure the memory controller to not read memory metrics for some
// module names (e.g. passing "memsw" would avoid all the memory.memsw.* entries)
func IgnoreModules(names ...string) func(*memoryController) {
return func(mc *memoryController) {
for _, name := range names {
mc.ignored[name] = struct{}{}
}
}
}
// OptionalSwap allows the memory controller to not fail if cgroups is not accounting
// Swap memory (there are no memory.memsw.* entries)
func OptionalSwap() func(*memoryController) {
return func(mc *memoryController) {
_, err := os.Stat(filepath.Join(mc.root, "memory.memsw.usage_in_bytes"))
if os.IsNotExist(err) {
mc.ignored["memsw"] = struct{}{}
}
} }
} }
type memoryController struct { type memoryController struct {
root string root string
ignored map[string]struct{}
} }
func (m *memoryController) Name() Name { func (m *memoryController) Name() Name {
@ -97,24 +126,24 @@ func (m *memoryController) Update(path string, resources *specs.LinuxResources)
return m.set(path, settings) return m.set(path, settings)
} }
func (m *memoryController) Stat(path string, stats *Metrics) error { func (m *memoryController) Stat(path string, stats *v1.Metrics) error {
f, err := os.Open(filepath.Join(m.Path(path), "memory.stat")) f, err := os.Open(filepath.Join(m.Path(path), "memory.stat"))
if err != nil { if err != nil {
return err return err
} }
defer f.Close() defer f.Close()
stats.Memory = &MemoryStat{ stats.Memory = &v1.MemoryStat{
Usage: &MemoryEntry{}, Usage: &v1.MemoryEntry{},
Swap: &MemoryEntry{}, Swap: &v1.MemoryEntry{},
Kernel: &MemoryEntry{}, Kernel: &v1.MemoryEntry{},
KernelTCP: &MemoryEntry{}, KernelTCP: &v1.MemoryEntry{},
} }
if err := m.parseStats(f, stats.Memory); err != nil { if err := m.parseStats(f, stats.Memory); err != nil {
return err return err
} }
for _, t := range []struct { for _, t := range []struct {
module string module string
entry *MemoryEntry entry *v1.MemoryEntry
}{ }{
{ {
module: "", module: "",
@ -133,6 +162,9 @@ func (m *memoryController) Stat(path string, stats *Metrics) error {
entry: stats.Memory.KernelTCP, entry: stats.Memory.KernelTCP,
}, },
} { } {
if _, ok := m.ignored[t.module]; ok {
continue
}
for _, tt := range []struct { for _, tt := range []struct {
name string name string
value *uint64 value *uint64
@ -197,7 +229,7 @@ func writeEventFD(root string, cfd, efd uintptr) error {
return err return err
} }
func (m *memoryController) parseStats(r io.Reader, stat *MemoryStat) error { func (m *memoryController) parseStats(r io.Reader, stat *v1.MemoryStat) error {
var ( var (
raw = make(map[string]uint64) raw = make(map[string]uint64)
sc = bufio.NewScanner(r) sc = bufio.NewScanner(r)
@ -282,7 +314,7 @@ func getMemorySettings(resources *specs.LinuxResources) []memorySettings {
value: mem.Limit, value: mem.Limit,
}, },
{ {
name: "soft_limit_in_bytes", name: "soft_limit_in_bytes",
value: mem.Reservation, value: mem.Reservation,
}, },
{ {

View File

@ -23,6 +23,7 @@ import (
"strconv" "strconv"
"strings" "strings"
v1 "github.com/containerd/cgroups/stats/v1"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
) )
@ -62,7 +63,7 @@ func (p *pidsController) Update(path string, resources *specs.LinuxResources) er
return p.Create(path, resources) return p.Create(path, resources)
} }
func (p *pidsController) Stat(path string, stats *Metrics) error { func (p *pidsController) Stat(path string, stats *v1.Metrics) error {
current, err := readUint(filepath.Join(p.Path(path), "pids.current")) current, err := readUint(filepath.Join(p.Path(path), "pids.current"))
if err != nil { if err != nil {
return err return err
@ -77,7 +78,7 @@ func (p *pidsController) Stat(path string, stats *Metrics) error {
return err return err
} }
} }
stats.Pids = &PidsStat{ stats.Pids = &v1.PidsStat{
Current: current, Current: current,
Limit: max, Limit: max,
} }

View File

@ -24,6 +24,7 @@ import (
"strconv" "strconv"
"strings" "strings"
v1 "github.com/containerd/cgroups/stats/v1"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
) )
@ -80,7 +81,7 @@ func (p *rdmaController) Update(path string, resources *specs.LinuxResources) er
return p.Create(path, resources) return p.Create(path, resources)
} }
func parseRdmaKV(raw string, entry *RdmaEntry) { func parseRdmaKV(raw string, entry *v1.RdmaEntry) {
var value uint64 var value uint64
var err error var err error
@ -103,13 +104,13 @@ func parseRdmaKV(raw string, entry *RdmaEntry) {
} }
} }
func toRdmaEntry(strEntries []string) []*RdmaEntry { func toRdmaEntry(strEntries []string) []*v1.RdmaEntry {
var rdmaEntries []*RdmaEntry var rdmaEntries []*v1.RdmaEntry
for i := range strEntries { for i := range strEntries {
parts := strings.Fields(strEntries[i]) parts := strings.Fields(strEntries[i])
switch len(parts) { switch len(parts) {
case 3: case 3:
entry := new(RdmaEntry) entry := new(v1.RdmaEntry)
entry.Device = parts[0] entry.Device = parts[0]
parseRdmaKV(parts[1], entry) parseRdmaKV(parts[1], entry)
parseRdmaKV(parts[2], entry) parseRdmaKV(parts[2], entry)
@ -122,7 +123,7 @@ func toRdmaEntry(strEntries []string) []*RdmaEntry {
return rdmaEntries return rdmaEntries
} }
func (p *rdmaController) Stat(path string, stats *Metrics) error { func (p *rdmaController) Stat(path string, stats *v1.Metrics) error {
currentData, err := ioutil.ReadFile(filepath.Join(p.Path(path), "rdma.current")) currentData, err := ioutil.ReadFile(filepath.Join(p.Path(path), "rdma.current"))
if err != nil { if err != nil {
@ -145,7 +146,7 @@ func (p *rdmaController) Stat(path string, stats *Metrics) error {
currentEntries := toRdmaEntry(currentPerDevices) currentEntries := toRdmaEntry(currentPerDevices)
maxEntries := toRdmaEntry(maxPerDevices) maxEntries := toRdmaEntry(maxPerDevices)
stats.Rdma = &RdmaStat{ stats.Rdma = &v1.RdmaStat{
Current: currentEntries, Current: currentEntries,
Limit: maxEntries, Limit: maxEntries,
} }

17
vendor/github.com/containerd/cgroups/stats/v1/doc.go generated vendored Normal file
View File

@ -0,0 +1,17 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1

View File

@ -12,6 +12,7 @@ message Metrics {
BlkIOStat blkio = 5; BlkIOStat blkio = 5;
RdmaStat rdma = 6; RdmaStat rdma = 6;
repeated NetworkStat network = 7; repeated NetworkStat network = 7;
CgroupStats cgroup_stats = 8;
} }
message HugetlbStat { message HugetlbStat {
@ -134,3 +135,17 @@ message NetworkStat {
uint64 tx_errors = 8; uint64 tx_errors = 8;
uint64 tx_dropped = 9; uint64 tx_dropped = 9;
} }
// CgroupStats exports per-cgroup statistics.
message CgroupStats {
// number of tasks sleeping
uint64 nr_sleeping = 1;
// number of tasks running
uint64 nr_running = 2;
// number of tasks in stopped state
uint64 nr_stopped = 3;
// number of tasks in uninterruptible state
uint64 nr_uninterruptible = 4;
// number of tasks waiting on IO
uint64 nr_io_wait = 5;
}

View File

@ -19,6 +19,7 @@ package cgroups
import ( import (
"fmt" "fmt"
v1 "github.com/containerd/cgroups/stats/v1"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
) )
@ -85,7 +86,7 @@ type deleter interface {
type stater interface { type stater interface {
Subsystem Subsystem
Stat(path string, stats *Metrics) error Stat(path string, stats *v1.Metrics) error
} }
type updater interface { type updater interface {