2017-07-19 4 views
0

Je suis nouveau dans les groupes de contrôle, et j'essaie d'obtenir les statistiques de conteneur en utilisant les groupes de contrôle. Auparavant, j'utilisais docker stats mais, essayant de rassembler des métriques similaires avec cgroups ainsi.métrique cpuPercent à partir de stats docker vs cgroups

Dans les stats docker, section cpu stats est comme ci-dessous:

"cpu_usage": { 
     "total_usage": 27120642519, 
     "percpu_usage": [27120642519], 
     "usage_in_kernelmode": 4550000000, 
     "usage_in_usermode": 19140000000 
    }, 
    "system_cpu_usage": 42803030000000, 

Et, la métrique cpu% est calculée en utilisant l'équation ci-dessous:

cpuDelta = float64(v.CpuStats.CpuUsage.TotalUsage - previousCPU) 
systemDelta = float64(v.CpuStats.SystemUsage - previousSystem) 
cpuPct = cpuDelta/systemDelta 

Je cherche à cgroups pour recueillir systemUsage et le totalUsage, mais il ne semble pas avoir des mesures similaires:

cgroups a un pseudo fichier cpuacct.stats qui a user et system ticks, mais ceux-ci correspondent uniquement à usage_in_user_mode et usage_in_kernel_mode à partir de la sortie docker stats. Et le fichier pseudo cpuacct.usage_per_cpu a une utilisation par cpu, qui correspond à total_usage à partir de la sortie des stats docker ci-dessus.

$cat cpuacct.stat 
user 1914 
system 455 

$cat cpuacct.usage_percpu 
27120642519 

Mais, je ne pouvais pas trouver un moyen de savoir comment recueillir « systemUsage » de cgroups.

Toutes les pistes seront d'une grande aide!

Merci!

Répondre

1

La réponse à votre question ne se trouve pas dans les cgroups. S'il vous plaît se référer au point mentionné ci-dessous:

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. Le « system_cpu_usage » du Docker stats API fait référence à l'utilisation du processeur de l'hôte. Le "cpu_usage"> "total_usage" de l'API de statistiques Docker fait référence à l'utilisation par CPU du conteneur.
  2. Par conséquent, après le calcul du (cpuDelta/systemDelta), nous obtenons l'utilisation par CPU par unité centrale du système.
  3. Maintenant, nous devons multiplier le résultat de l'étape 3 et le nombre total de CPU alloués au conteneur docker pour obtenir l'utilisation totale du processeur par unité centrale du système.
  4. Le résultat de l'étape 4 multiplié par 100 nous donne l'utilisation de l'UC en pourcentage.

Retour à la question: Comment CPU système est calculé par docker?

Pour calculer l'utilisation de l'UC, le docker utilise le "/ proc/stat" défini par POSIX. Il recherche la ligne de statistiques CPU et résume les sept premiers champs fournis. Le code golang écrit pour effectuer les étapes requises est mentionné ci-dessous.

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 
} 

S'il vous plaît correspondre à la "system_cpu_usage" de docker stats API avec la sortie de commande mentionné ci-dessous pour confirmer:

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