helpers.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Copyright 2014 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package libcontainer
  15. import (
  16. "fmt"
  17. info "github.com/google/cadvisor/info/v1"
  18. "github.com/opencontainers/runc/libcontainer/cgroups"
  19. "github.com/google/cadvisor/container"
  20. fs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
  21. fs2 "github.com/opencontainers/runc/libcontainer/cgroups/fs2"
  22. configs "github.com/opencontainers/runc/libcontainer/configs"
  23. "k8s.io/klog/v2"
  24. )
  25. // GetCgroupSubsystems returns information about the cgroup subsystems that are
  26. // of interest as a map of cgroup controllers to their mount points.
  27. // For example, "cpu" -> "/sys/fs/cgroup/cpu".
  28. //
  29. // The incudeMetrics arguments specifies which metrics are requested,
  30. // and is used to filter out some cgroups and their mounts. If nil,
  31. // all supported cgroup subsystems are included.
  32. //
  33. // For cgroup v2, includedMetrics argument is unused, the only map key is ""
  34. // (empty string), and the value is the unified cgroup mount point.
  35. func GetCgroupSubsystems(includedMetrics container.MetricSet) (map[string]string, error) {
  36. if cgroups.IsCgroup2UnifiedMode() {
  37. return map[string]string{"": fs2.UnifiedMountpoint}, nil
  38. }
  39. // Get all cgroup mounts.
  40. allCgroups, err := cgroups.GetCgroupMounts(true)
  41. if err != nil {
  42. return nil, err
  43. }
  44. return getCgroupSubsystemsHelper(allCgroups, includedMetrics)
  45. }
  46. func getCgroupSubsystemsHelper(allCgroups []cgroups.Mount, includedMetrics container.MetricSet) (map[string]string, error) {
  47. if len(allCgroups) == 0 {
  48. return nil, fmt.Errorf("failed to find cgroup mounts")
  49. }
  50. // Trim the mounts to only the subsystems we care about.
  51. mountPoints := make(map[string]string, len(allCgroups))
  52. for _, mount := range allCgroups {
  53. for _, subsystem := range mount.Subsystems {
  54. if !needSubsys(subsystem, includedMetrics) {
  55. continue
  56. }
  57. if _, ok := mountPoints[subsystem]; ok {
  58. // duplicate mount for this subsystem; use the first one we saw
  59. klog.V(5).Infof("skipping %s, already using mount at %s", mount.Mountpoint, mountPoints[subsystem])
  60. continue
  61. }
  62. mountPoints[subsystem] = mount.Mountpoint
  63. }
  64. }
  65. return mountPoints, nil
  66. }
  67. // A map of cgroup subsystems we support listing (should be the minimal set
  68. // we need stats from) to a respective MetricKind.
  69. var supportedSubsystems = map[string]container.MetricKind{
  70. "cpu": container.CpuUsageMetrics,
  71. "cpuacct": container.CpuUsageMetrics,
  72. "memory": container.MemoryUsageMetrics,
  73. "hugetlb": container.HugetlbUsageMetrics,
  74. "pids": container.ProcessMetrics,
  75. "cpuset": container.CPUSetMetrics,
  76. "blkio": container.DiskIOMetrics,
  77. "io": container.DiskIOMetrics,
  78. "devices": "",
  79. "perf_event": container.PerfMetrics,
  80. }
  81. // Check if this cgroup subsystem/controller is of use.
  82. func needSubsys(name string, metrics container.MetricSet) bool {
  83. // Check if supported.
  84. metric, supported := supportedSubsystems[name]
  85. if !supported {
  86. return false
  87. }
  88. // Check if needed.
  89. if metrics == nil || metric == "" {
  90. return true
  91. }
  92. return metrics.Has(metric)
  93. }
  94. func diskStatsCopy0(major, minor uint64) *info.PerDiskStats {
  95. disk := info.PerDiskStats{
  96. Major: major,
  97. Minor: minor,
  98. }
  99. disk.Stats = make(map[string]uint64)
  100. return &disk
  101. }
  102. type diskKey struct {
  103. Major uint64
  104. Minor uint64
  105. }
  106. func diskStatsCopy1(diskStat map[diskKey]*info.PerDiskStats) []info.PerDiskStats {
  107. i := 0
  108. stat := make([]info.PerDiskStats, len(diskStat))
  109. for _, disk := range diskStat {
  110. stat[i] = *disk
  111. i++
  112. }
  113. return stat
  114. }
  115. func diskStatsCopy(blkioStats []cgroups.BlkioStatEntry) (stat []info.PerDiskStats) {
  116. if len(blkioStats) == 0 {
  117. return
  118. }
  119. diskStat := make(map[diskKey]*info.PerDiskStats)
  120. for i := range blkioStats {
  121. major := blkioStats[i].Major
  122. minor := blkioStats[i].Minor
  123. key := diskKey{
  124. Major: major,
  125. Minor: minor,
  126. }
  127. diskp, ok := diskStat[key]
  128. if !ok {
  129. diskp = diskStatsCopy0(major, minor)
  130. diskStat[key] = diskp
  131. }
  132. op := blkioStats[i].Op
  133. if op == "" {
  134. op = "Count"
  135. }
  136. diskp.Stats[op] = blkioStats[i].Value
  137. }
  138. return diskStatsCopy1(diskStat)
  139. }
  140. func NewCgroupManager(name string, paths map[string]string) (cgroups.Manager, error) {
  141. config := &configs.Cgroup{
  142. Name: name,
  143. Resources: &configs.Resources{},
  144. }
  145. if cgroups.IsCgroup2UnifiedMode() {
  146. path := paths[""]
  147. return fs2.NewManager(config, path)
  148. }
  149. return fs.NewManager(config, paths)
  150. }