来自码头统计vs cgroup的cpuPercent度量

问题描述:

我是cgroups的新手,并试图使用cgroup获取容器统计信息。以前我使用的是docker stats,但是也试图收集类似的指标,cgroups也是如此。来自码头统计vs cgroup的cpuPercent度量

在泊坞窗统计,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 

我在看的cgroup收集systemUsagetotalUsage,但它似乎没有类似的指标:

cgroups有一个伪文件cpuacct.stats其中有usersystem刻度,但这些仅与来自docker stats输出的usage_in_user_modeusage_in_kernel_mode相匹配。

和cpuacct.usage_per_cpu伪文件每个cpu有一个用法,它与上面docker stats输出中的total_usage匹配。

$cat cpuacct.stat 
user 1914 
system 455 

$cat cpuacct.usage_percpu 
27120642519 

但是,我找不到任何方法来弄清楚如何从cgroups收集“systemUsage”。

任何线索都会有很大的帮助!

谢谢!

您的问题的答案不在于cgroups。请参考下文提到的一点:

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 
} 
  1. 的“system_cpu_usage”的泊坞窗统计API指的是主机的CPU使用情况。
  2. Docker统计信息API的“cpu_usage”>“total_usage”指的是容器的每CPU使用情况。
  3. 因此,在计算(cpuDelta/systemDelta)之后,我们得到每个系统CPU的每CPU使用量。
  4. 现在我们需要将步骤3的结果和分配给docker容器的CPU总数相乘,以获得每个系统CPU的总CPU使用量。
  5. 步骤4乘以100后的结果为我们提供了百分比的CPU利用率。

返回到问题: 系统CPU如何由docker进行计算?

要计算系统CPU使用率,docker使用POSIX定义的“/ proc/stat”。它查找CPU统计数据行,然后总结提供的前七个字段。下面将介绍为执行所需步骤而编写的golang代码。

https://github.com/rancher/docker/blob/3f1b16e236ad4626e02f3da4643023454d7dbb3f/daemon/stats_collector_unix.go#L137

// 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 
} 

请匹配搬运工的 “system_cpu_usage” 统计API与下面提到命令的输出,以确认:

cat /proc/stat|grep -w cpu|awk '{split($0,a,\" \"); sum=0; for(i=2;i<8;i++)(sum+=a[i])} END{print sum }'