stats_provider.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package stats
  14. import (
  15. "fmt"
  16. cadvisorapiv1 "github.com/google/cadvisor/info/v1"
  17. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  18. "k8s.io/apimachinery/pkg/types"
  19. internalapi "k8s.io/cri-api/pkg/apis"
  20. statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
  21. "k8s.io/kubernetes/pkg/kubelet/cadvisor"
  22. kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
  23. kubepod "k8s.io/kubernetes/pkg/kubelet/pod"
  24. "k8s.io/kubernetes/pkg/kubelet/server/stats"
  25. "k8s.io/kubernetes/pkg/kubelet/stats/pidlimit"
  26. "k8s.io/kubernetes/pkg/kubelet/status"
  27. )
  28. // NewCRIStatsProvider returns a StatsProvider that provides the node stats
  29. // from cAdvisor and the container stats from CRI.
  30. func NewCRIStatsProvider(
  31. cadvisor cadvisor.Interface,
  32. resourceAnalyzer stats.ResourceAnalyzer,
  33. podManager kubepod.Manager,
  34. runtimeCache kubecontainer.RuntimeCache,
  35. runtimeService internalapi.RuntimeService,
  36. imageService internalapi.ImageManagerService,
  37. logMetricsService LogMetricsService,
  38. osInterface kubecontainer.OSInterface,
  39. ) *StatsProvider {
  40. return newStatsProvider(cadvisor, podManager, runtimeCache, newCRIStatsProvider(cadvisor, resourceAnalyzer,
  41. runtimeService, imageService, logMetricsService, osInterface))
  42. }
  43. // NewCadvisorStatsProvider returns a containerStatsProvider that provides both
  44. // the node and the container stats from cAdvisor.
  45. func NewCadvisorStatsProvider(
  46. cadvisor cadvisor.Interface,
  47. resourceAnalyzer stats.ResourceAnalyzer,
  48. podManager kubepod.Manager,
  49. runtimeCache kubecontainer.RuntimeCache,
  50. imageService kubecontainer.ImageService,
  51. statusProvider status.PodStatusProvider,
  52. ) *StatsProvider {
  53. return newStatsProvider(cadvisor, podManager, runtimeCache, newCadvisorStatsProvider(cadvisor, resourceAnalyzer, imageService, statusProvider))
  54. }
  55. // newStatsProvider returns a new StatsProvider that provides node stats from
  56. // cAdvisor and the container stats using the containerStatsProvider.
  57. func newStatsProvider(
  58. cadvisor cadvisor.Interface,
  59. podManager kubepod.Manager,
  60. runtimeCache kubecontainer.RuntimeCache,
  61. containerStatsProvider containerStatsProvider,
  62. ) *StatsProvider {
  63. return &StatsProvider{
  64. cadvisor: cadvisor,
  65. podManager: podManager,
  66. runtimeCache: runtimeCache,
  67. containerStatsProvider: containerStatsProvider,
  68. }
  69. }
  70. // StatsProvider provides the stats of the node and the pod-managed containers.
  71. type StatsProvider struct {
  72. cadvisor cadvisor.Interface
  73. podManager kubepod.Manager
  74. runtimeCache kubecontainer.RuntimeCache
  75. containerStatsProvider
  76. rlimitStatsProvider
  77. }
  78. // containerStatsProvider is an interface that provides the stats of the
  79. // containers managed by pods.
  80. type containerStatsProvider interface {
  81. ListPodStats() ([]statsapi.PodStats, error)
  82. ListPodStatsAndUpdateCPUNanoCoreUsage() ([]statsapi.PodStats, error)
  83. ListPodCPUAndMemoryStats() ([]statsapi.PodStats, error)
  84. ImageFsStats() (*statsapi.FsStats, error)
  85. ImageFsDevice() (string, error)
  86. }
  87. type rlimitStatsProvider interface {
  88. RlimitStats() (*statsapi.RlimitStats, error)
  89. }
  90. // RlimitStats returns base information about process count
  91. func (p *StatsProvider) RlimitStats() (*statsapi.RlimitStats, error) {
  92. return pidlimit.Stats()
  93. }
  94. // GetCgroupStats returns the stats of the cgroup with the cgroupName. Note that
  95. // this function doesn't generate filesystem stats.
  96. func (p *StatsProvider) GetCgroupStats(cgroupName string, updateStats bool) (*statsapi.ContainerStats, *statsapi.NetworkStats, error) {
  97. info, err := getCgroupInfo(p.cadvisor, cgroupName, updateStats)
  98. if err != nil {
  99. return nil, nil, fmt.Errorf("failed to get cgroup stats for %q: %v", cgroupName, err)
  100. }
  101. // Rootfs and imagefs doesn't make sense for raw cgroup.
  102. s := cadvisorInfoToContainerStats(cgroupName, info, nil, nil)
  103. n := cadvisorInfoToNetworkStats(cgroupName, info)
  104. return s, n, nil
  105. }
  106. // GetCgroupCPUAndMemoryStats returns the CPU and memory stats of the cgroup with the cgroupName. Note that
  107. // this function doesn't generate filesystem stats.
  108. func (p *StatsProvider) GetCgroupCPUAndMemoryStats(cgroupName string, updateStats bool) (*statsapi.ContainerStats, error) {
  109. info, err := getCgroupInfo(p.cadvisor, cgroupName, updateStats)
  110. if err != nil {
  111. return nil, fmt.Errorf("failed to get cgroup stats for %q: %v", cgroupName, err)
  112. }
  113. // Rootfs and imagefs doesn't make sense for raw cgroup.
  114. s := cadvisorInfoToContainerCPUAndMemoryStats(cgroupName, info)
  115. return s, nil
  116. }
  117. // RootFsStats returns the stats of the node root filesystem.
  118. func (p *StatsProvider) RootFsStats() (*statsapi.FsStats, error) {
  119. rootFsInfo, err := p.cadvisor.RootFsInfo()
  120. if err != nil {
  121. return nil, fmt.Errorf("failed to get rootFs info: %v", err)
  122. }
  123. var nodeFsInodesUsed *uint64
  124. if rootFsInfo.Inodes != nil && rootFsInfo.InodesFree != nil {
  125. nodeFsIU := *rootFsInfo.Inodes - *rootFsInfo.InodesFree
  126. nodeFsInodesUsed = &nodeFsIU
  127. }
  128. // Get the root container stats's timestamp, which will be used as the
  129. // imageFs stats timestamp. Dont force a stats update, as we only want the timestamp.
  130. rootStats, err := getCgroupStats(p.cadvisor, "/", false)
  131. if err != nil {
  132. return nil, fmt.Errorf("failed to get root container stats: %v", err)
  133. }
  134. return &statsapi.FsStats{
  135. Time: metav1.NewTime(rootStats.Timestamp),
  136. AvailableBytes: &rootFsInfo.Available,
  137. CapacityBytes: &rootFsInfo.Capacity,
  138. UsedBytes: &rootFsInfo.Usage,
  139. InodesFree: rootFsInfo.InodesFree,
  140. Inodes: rootFsInfo.Inodes,
  141. InodesUsed: nodeFsInodesUsed,
  142. }, nil
  143. }
  144. // GetContainerInfo returns stats (from cAdvisor) for a container.
  145. func (p *StatsProvider) GetContainerInfo(podFullName string, podUID types.UID, containerName string, req *cadvisorapiv1.ContainerInfoRequest) (*cadvisorapiv1.ContainerInfo, error) {
  146. // Resolve and type convert back again.
  147. // We need the static pod UID but the kubecontainer API works with types.UID.
  148. podUID = types.UID(p.podManager.TranslatePodUID(podUID))
  149. pods, err := p.runtimeCache.GetPods()
  150. if err != nil {
  151. return nil, err
  152. }
  153. pod := kubecontainer.Pods(pods).FindPod(podFullName, podUID)
  154. container := pod.FindContainerByName(containerName)
  155. if container == nil {
  156. return nil, kubecontainer.ErrContainerNotFound
  157. }
  158. ci, err := p.cadvisor.DockerContainer(container.ID.ID, req)
  159. if err != nil {
  160. return nil, err
  161. }
  162. return &ci, nil
  163. }
  164. // GetRawContainerInfo returns the stats (from cadvisor) for a non-Kubernetes
  165. // container.
  166. func (p *StatsProvider) GetRawContainerInfo(containerName string, req *cadvisorapiv1.ContainerInfoRequest, subcontainers bool) (map[string]*cadvisorapiv1.ContainerInfo, error) {
  167. if subcontainers {
  168. return p.cadvisor.SubcontainerInfo(containerName, req)
  169. }
  170. containerInfo, err := p.cadvisor.ContainerInfo(containerName, req)
  171. if err != nil {
  172. return nil, err
  173. }
  174. return map[string]*cadvisorapiv1.ContainerInfo{
  175. containerInfo.Name: containerInfo,
  176. }, nil
  177. }
  178. // HasDedicatedImageFs returns true if a dedicated image filesystem exists for storing images.
  179. func (p *StatsProvider) HasDedicatedImageFs() (bool, error) {
  180. device, err := p.containerStatsProvider.ImageFsDevice()
  181. if err != nil {
  182. return false, err
  183. }
  184. rootFsInfo, err := p.cadvisor.RootFsInfo()
  185. if err != nil {
  186. return false, err
  187. }
  188. return device != rootFsInfo.Device, nil
  189. }