From 669bc4abfab349e18bc4efbec0f8d13b13602e29 Mon Sep 17 00:00:00 2001 From: Florian Koch Date: Tue, 2 Feb 2016 20:33:11 +0100 Subject: [PATCH] add cgroup quota and period support / add missing tests --- container/raw/handler.go | 10 ++++++++++ info/v1/container.go | 2 ++ info/v2/container.go | 4 ++++ metrics/prometheus.go | 8 +++++++- metrics/prometheus_test.go | 8 +++++++- metrics/testdata/prometheus_metrics | 11 ++++++++++- 6 files changed, 40 insertions(+), 3 deletions(-) diff --git a/container/raw/handler.go b/container/raw/handler.go index b7dd500590..0f2a6e06ac 100644 --- a/container/raw/handler.go +++ b/container/raw/handler.go @@ -207,6 +207,16 @@ func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) { if utils.FileExists(cpuRoot) { spec.HasCpu = true spec.Cpu.Limit = readUInt64(cpuRoot, "cpu.shares") + spec.Cpu.Period = readUInt64(cpuRoot, "cpu.cfs_period_us") + quota := readString(cpuRoot, "cpu.cfs_quota_us") + + if quota != "-1" { + val, err := strconv.ParseUint(quota, 10, 64) + if err != nil { + glog.Errorf("raw driver: Failed to parse CPUQuota from %q: %s", path.Join(cpuRoot, "cpu.cfs_quota_us"), err) + } + spec.Cpu.Quota = val + } } } diff --git a/info/v1/container.go b/info/v1/container.go index bb4fc322e2..ed0d856c64 100644 --- a/info/v1/container.go +++ b/info/v1/container.go @@ -23,6 +23,8 @@ type CpuSpec struct { Limit uint64 `json:"limit"` MaxLimit uint64 `json:"max_limit"` Mask string `json:"mask,omitempty"` + Quota uint64 `json:"quota,omitempty"` + Period uint64 `json:"period,omitempty"` } type MemorySpec struct { diff --git a/info/v2/container.go b/info/v2/container.go index 805f73d30b..d300c525f5 100644 --- a/info/v2/container.go +++ b/info/v2/container.go @@ -36,6 +36,10 @@ type CpuSpec struct { // Cpu affinity mask. // TODO(rjnagal): Add a library to convert mask string to set of cpu bitmask. Mask string `json:"mask,omitempty"` + // CPUQuota Default is disabled + Quota uint64 `json:"quota,omitempty"` + // Period is the CPU reference time in ns e.g the quota is compared aginst this. + Period uint64 `json:"period,omitempty"` } type MemorySpec struct { diff --git a/metrics/prometheus.go b/metrics/prometheus.go index adce51010e..74d369640d 100644 --- a/metrics/prometheus.go +++ b/metrics/prometheus.go @@ -542,10 +542,16 @@ func (c *PrometheusCollector) collectContainersInfo(ch chan<- prometheus.Metric) ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.CreationTime.Unix()), baseLabelValues...) if container.Spec.HasCpu { + desc = prometheus.NewDesc("container_spec_cpu_period", "CPU period of the container.", baseLabels, nil) + ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.Cpu.Period), baseLabelValues...) + if container.Spec.Cpu.Quota != 0 { + desc = prometheus.NewDesc("container_spec_cpu_quota", "CPU quota of the container.", baseLabels, nil) + ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.Cpu.Quota), baseLabelValues...) + } desc := prometheus.NewDesc("container_spec_cpu_shares", "CPU share of the container.", baseLabels, nil) ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(container.Spec.Cpu.Limit), baseLabelValues...) - } + } if container.Spec.HasMemory { desc := prometheus.NewDesc("container_spec_memory_limit_bytes", "Memory limit for the container.", baseLabels, nil) ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, specMemoryValue(container.Spec.Memory.Limit), baseLabelValues...) diff --git a/metrics/prometheus_test.go b/metrics/prometheus_test.go index bef93bfe56..7aafc9483e 100644 --- a/metrics/prometheus_test.go +++ b/metrics/prometheus_test.go @@ -55,7 +55,13 @@ func (p testSubcontainersInfoProvider) SubcontainersInfo(string, *info.Container Aliases: []string{"testcontaineralias"}, }, Spec: info.ContainerSpec{ - Image: "test", + Image: "test", + HasCpu: true, + Cpu: info.CpuSpec{ + Limit: 1000, + Period: 10, + Quota: 10000, + }, CreationTime: time.Unix(1257894000, 0), Labels: map[string]string{ "foo.label": "bar", diff --git a/metrics/testdata/prometheus_metrics b/metrics/testdata/prometheus_metrics index 40e4ca0dee..31f2d2d7ce 100644 --- a/metrics/testdata/prometheus_metrics +++ b/metrics/testdata/prometheus_metrics @@ -116,6 +116,15 @@ container_network_transmit_packets_total{foo_env="prod",foo_label="bar",id="test # HELP container_scrape_error 1 if there was an error while getting container metrics, 0 otherwise # TYPE container_scrape_error gauge container_scrape_error 0 +# HELP container_spec_cpu_period CPU period of the container. +# TYPE container_spec_cpu_period gauge +container_spec_cpu_period{foo_env="prod",foo_label="bar",id="testcontainer",image="test",name="testcontaineralias",zone_name="hello"} 10 +# HELP container_spec_cpu_quota CPU quota of the container. +# TYPE container_spec_cpu_quota gauge +container_spec_cpu_quota{foo_env="prod",foo_label="bar",id="testcontainer",image="test",name="testcontaineralias",zone_name="hello"} 10000 +# HELP container_spec_cpu_shares CPU share of the container. +# TYPE container_spec_cpu_shares gauge +container_spec_cpu_shares{foo_env="prod",foo_label="bar",id="testcontainer",image="test",name="testcontaineralias",zone_name="hello"} 1000 # HELP container_start_time_seconds Start time of the container since unix epoch in seconds. # TYPE container_start_time_seconds gauge container_start_time_seconds{foo_env="prod",foo_label="bar",id="testcontainer",image="test",name="testcontaineralias",zone_name="hello"} 1.257894e+09 @@ -173,4 +182,4 @@ process_resident_memory_bytes 7.74144e+06 process_start_time_seconds 1.42620369439e+09 # HELP process_virtual_memory_bytes Virtual memory size in bytes. # TYPE process_virtual_memory_bytes gauge -process_virtual_memory_bytes 1.16420608e+08 +process_virtual_memory_bytes 1.16420608e+08 \ No newline at end of file