来自 docker 统计数据与 cgroups 的 cpuPercent 指标
cpuPercent metric from docker stats vs cgroups
我是 cgroups 的新手,正在尝试使用 cgroups 获取容器统计信息。以前我使用的是 docker stats
,但我也尝试使用 cgroups
收集类似的指标。
在 docker 统计中,cpu 统计部分如下所示:
"cpu_usage": {
"total_usage": 27120642519,
"percpu_usage": [27120642519],
"usage_in_kernelmode": 4550000000,
"usage_in_usermode": 19140000000
},
"system_cpu_usage": 42803030000000,
并且,cpu% 指标是使用以下等式计算的:
cpuDelta = float64(v.CpuStats.CpuUsage.TotalUsage - previousCPU)
systemDelta = float64(v.CpuStats.SystemUsage - previousSystem)
cpuPct = cpuDelta/systemDelta
我正在查看 cgroups 以收集 systemUsage
和 totalUsage
,但它似乎没有类似的指标:
cgroups 有一个伪文件 cpuacct.stats,其中有 user
和 system
刻度,但它们仅与 usage_in_user_mode
和 usage_in_kernel_mode
匹配 docker stats
输出.
和 cpuacct.usage_per_cpu 伪文件每个 cpu 都有一个用法,这与上面 docker 统计输出中的 total_usage
相匹配。
$cat cpuacct.stat
user 1914
system 455
$cat cpuacct.usage_percpu
27120642519
但是,我找不到任何方法来弄清楚如何从 cgroups 收集 "systemUsage"。
任何线索都会有很大帮助!
谢谢!
您问题的答案不在 cgroup 中。请参考以下几点:
func calculateCPUPercentUnix(previousCPU, previousSystem uint64, v *types.StatsJSON) float64 {
var (
cpuPercent = 0.0
// calculate the change for the cpu usage of the container in between readings
cpuDelta = float64(v.CPUStats.CPUUsage.TotalUsage) - float64(previousCPU)
// calculate the change for the entire system between readings
systemDelta = float64(v.CPUStats.SystemUsage) - float64(previousSystem)
)
if systemDelta > 0.0 && cpuDelta > 0.0 {
cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100.0
}
return cpuPercent
}
- Docker统计API的"system_cpu_usage"是指主机的CPU使用情况。
- Docker 统计数据 API 的 "cpu_usage" > "total_usage" 是指容器的每个 CPU 使用情况。
- 因此,在计算 (cpuDelta/systemDelta) 后,我们得到每个系统的每个 CPU 使用量 CPU.
- 现在我们需要将第 3 步的结果与分配给 docker 容器的 CPU 总数相乘,得到每个系统的总 CPU 使用量 CPU.
- 第 4 步的结果乘以 100 得到 CPU 百分比利用率。
回到问题:
系统CPU是如何通过docker计算出来的?
要计算系统 CPU 使用情况 docker 使用 POSIX 定义的“/proc/stat”。它查找 CPU 统计行,然后汇总提供的前七个字段。下面提到了为执行所需步骤而编写的 golang 代码。
// getSystemCPUUsage returns the host system's cpu usage in
// nanoseconds. An error is returned if the format of the underlying
// file does not match.
//
// Uses /proc/stat defined by POSIX. Looks for the cpu
// statistics line and then sums up the first seven fields
// provided. See `man 5 proc` for details on specific field
// information.
func (s *statsCollector) getSystemCPUUsage() (uint64, error) {
var line string
f, err := os.Open("/proc/stat")
if err != nil {
return 0, err
}
defer func() {
s.bufReader.Reset(nil)
f.Close()
}()
s.bufReader.Reset(f)
err = nil
for err == nil {
line, err = s.bufReader.ReadString('\n')
if err != nil {
break
}
parts := strings.Fields(line)
switch parts[0] {
case "cpu":
if len(parts) < 8 {
return 0, derr.ErrorCodeBadCPUFields
}
var totalClockTicks uint64
for _, i := range parts[1:8] {
v, err := strconv.ParseUint(i, 10, 64)
if err != nil {
return 0, derr.ErrorCodeBadCPUInt.WithArgs(i, err)
}
totalClockTicks += v
}
return (totalClockTicks * nanoSecondsPerSecond) /
s.clockTicksPerSecond, nil
}
}
return 0, derr.ErrorCodeBadStatFormat
}
请将 docker 统计数据 API 的 "system_cpu_usage" 与下面提到的命令的输出进行匹配以确认:
cat /proc/stat|grep -w cpu|awk '{split([=12=],a,\" \"); sum=0; for(i=2;i<8;i++)(sum+=a[i])} END{print sum }'
我是 cgroups 的新手,正在尝试使用 cgroups 获取容器统计信息。以前我使用的是 docker stats
,但我也尝试使用 cgroups
收集类似的指标。
在 docker 统计中,cpu 统计部分如下所示:
"cpu_usage": {
"total_usage": 27120642519,
"percpu_usage": [27120642519],
"usage_in_kernelmode": 4550000000,
"usage_in_usermode": 19140000000
},
"system_cpu_usage": 42803030000000,
并且,cpu% 指标是使用以下等式计算的:
cpuDelta = float64(v.CpuStats.CpuUsage.TotalUsage - previousCPU)
systemDelta = float64(v.CpuStats.SystemUsage - previousSystem)
cpuPct = cpuDelta/systemDelta
我正在查看 cgroups 以收集 systemUsage
和 totalUsage
,但它似乎没有类似的指标:
cgroups 有一个伪文件 cpuacct.stats,其中有 user
和 system
刻度,但它们仅与 usage_in_user_mode
和 usage_in_kernel_mode
匹配 docker stats
输出.
和 cpuacct.usage_per_cpu 伪文件每个 cpu 都有一个用法,这与上面 docker 统计输出中的 total_usage
相匹配。
$cat cpuacct.stat
user 1914
system 455
$cat cpuacct.usage_percpu
27120642519
但是,我找不到任何方法来弄清楚如何从 cgroups 收集 "systemUsage"。
任何线索都会有很大帮助!
谢谢!
您问题的答案不在 cgroup 中。请参考以下几点:
func calculateCPUPercentUnix(previousCPU, previousSystem uint64, v *types.StatsJSON) float64 {
var (
cpuPercent = 0.0
// calculate the change for the cpu usage of the container in between readings
cpuDelta = float64(v.CPUStats.CPUUsage.TotalUsage) - float64(previousCPU)
// calculate the change for the entire system between readings
systemDelta = float64(v.CPUStats.SystemUsage) - float64(previousSystem)
)
if systemDelta > 0.0 && cpuDelta > 0.0 {
cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100.0
}
return cpuPercent
}
- Docker统计API的"system_cpu_usage"是指主机的CPU使用情况。
- Docker 统计数据 API 的 "cpu_usage" > "total_usage" 是指容器的每个 CPU 使用情况。
- 因此,在计算 (cpuDelta/systemDelta) 后,我们得到每个系统的每个 CPU 使用量 CPU.
- 现在我们需要将第 3 步的结果与分配给 docker 容器的 CPU 总数相乘,得到每个系统的总 CPU 使用量 CPU.
- 第 4 步的结果乘以 100 得到 CPU 百分比利用率。
回到问题: 系统CPU是如何通过docker计算出来的?
要计算系统 CPU 使用情况 docker 使用 POSIX 定义的“/proc/stat”。它查找 CPU 统计行,然后汇总提供的前七个字段。下面提到了为执行所需步骤而编写的 golang 代码。
// getSystemCPUUsage returns the host system's cpu usage in
// nanoseconds. An error is returned if the format of the underlying
// file does not match.
//
// Uses /proc/stat defined by POSIX. Looks for the cpu
// statistics line and then sums up the first seven fields
// provided. See `man 5 proc` for details on specific field
// information.
func (s *statsCollector) getSystemCPUUsage() (uint64, error) {
var line string
f, err := os.Open("/proc/stat")
if err != nil {
return 0, err
}
defer func() {
s.bufReader.Reset(nil)
f.Close()
}()
s.bufReader.Reset(f)
err = nil
for err == nil {
line, err = s.bufReader.ReadString('\n')
if err != nil {
break
}
parts := strings.Fields(line)
switch parts[0] {
case "cpu":
if len(parts) < 8 {
return 0, derr.ErrorCodeBadCPUFields
}
var totalClockTicks uint64
for _, i := range parts[1:8] {
v, err := strconv.ParseUint(i, 10, 64)
if err != nil {
return 0, derr.ErrorCodeBadCPUInt.WithArgs(i, err)
}
totalClockTicks += v
}
return (totalClockTicks * nanoSecondsPerSecond) /
s.clockTicksPerSecond, nil
}
}
return 0, derr.ErrorCodeBadStatFormat
}
请将 docker 统计数据 API 的 "system_cpu_usage" 与下面提到的命令的输出进行匹配以确认:
cat /proc/stat|grep -w cpu|awk '{split([=12=],a,\" \"); sum=0; for(i=2;i<8;i++)(sum+=a[i])} END{print sum }'