resourcequota.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. package kubemodel
  2. import (
  3. "time"
  4. "github.com/opencost/opencost/core/pkg/log"
  5. "github.com/opencost/opencost/core/pkg/model/kubemodel"
  6. "github.com/opencost/opencost/core/pkg/source"
  7. )
  8. func (km *KubeModel) computeResourceQuotas(kms *kubemodel.KubeModelSet, start, end time.Time) error {
  9. grp := source.NewQueryGroup()
  10. metrics := km.ds.Metrics()
  11. rqInfoResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaInfo(start, end))
  12. rqUptimeResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaUptime(start, end))
  13. // spec.hard.requests
  14. rqSpecCPURequestAverageResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaSpecCPURequestAverage(start, end))
  15. rqSpecCPURequestMaxResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaSpecCPURequestMax(start, end))
  16. rqSpecRAMRequestAverageResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaSpecRAMRequestAverage(start, end))
  17. rqSpecRAMRequestMaxResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaSpecRAMRequestMax(start, end))
  18. // spec.hard.limits
  19. rqSpecCPULimitAverageResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaSpecCPULimitAverage(start, end))
  20. rqSpecCPULimitMaxResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaSpecCPULimitMax(start, end))
  21. rqSpecRAMLimitAverageResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaSpecRAMLimitAverage(start, end))
  22. rqSpecRAMLimitMaxResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaSpecRAMLimitMax(start, end))
  23. // status.used.requests
  24. rqStatusUsedCPURequestAverageResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaStatusUsedCPURequestAverage(start, end))
  25. rqStatusUsedCPURequestMaxResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaStatusUsedCPURequestMax(start, end))
  26. rqStatusUsedRAMRequestAverageResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaStatusUsedRAMRequestAverage(start, end))
  27. rqStatusUsedRAMRequestMaxResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaStatusUsedRAMRequestMax(start, end))
  28. // status.used.limits
  29. rqStatusUsedCPULimitAverageResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaStatusUsedCPULimitAverage(start, end))
  30. rqStatusUsedCPULimitMaxResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaStatusUsedCPULimitMax(start, end))
  31. rqStatusUsedRAMLimitAverageResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaStatusUsedRAMLimitAverage(start, end))
  32. rqStatusUsedRAMLimitMaxResultFuture := source.WithGroup(grp, metrics.QueryResourceQuotaStatusUsedRAMLimitMax(start, end))
  33. rqMap := make(map[string]*kubemodel.ResourceQuota)
  34. // Initialize resource quotas from info
  35. rqInfoResult, _ := rqInfoResultFuture.Await()
  36. for _, res := range rqInfoResult {
  37. rqMap[res.UID] = &kubemodel.ResourceQuota{
  38. UID: res.UID,
  39. Name: res.ResourceQuota,
  40. NamespaceUID: res.NamespaceUID,
  41. Spec: &kubemodel.ResourceQuotaSpec{Hard: &kubemodel.ResourceQuotaSpecHard{}},
  42. Status: &kubemodel.ResourceQuotaStatus{Used: &kubemodel.ResourceQuotaStatusUsed{}},
  43. }
  44. }
  45. rqUptimeResult, _ := rqUptimeResultFuture.Await()
  46. for _, res := range rqUptimeResult {
  47. rq, ok := rqMap[res.UID]
  48. if !ok {
  49. log.Warnf("resource quota with UID '%s' has not been initialized to add uptime", res.UID)
  50. continue
  51. }
  52. s, e := res.GetStartEnd(start, end, km.ds.Resolution())
  53. rq.Start = s
  54. rq.End = e
  55. }
  56. rqSpecCPURequestAverageResult, _ := rqSpecCPURequestAverageResultFuture.Await()
  57. for _, res := range rqSpecCPURequestAverageResult {
  58. rq, ok := rqMap[res.UID]
  59. if !ok {
  60. log.Warnf("resource quota with UID '%s' has not been initialized to add spec CPU request average", res.UID)
  61. continue
  62. }
  63. mcpu := res.Value * 1000
  64. rq.Spec.Hard.SetRequest(kubemodel.ResourceCPU, kubemodel.UnitMillicore, kubemodel.StatAvg, mcpu)
  65. }
  66. rqSpecCPURequestMaxResult, _ := rqSpecCPURequestMaxResultFuture.Await()
  67. for _, res := range rqSpecCPURequestMaxResult {
  68. rq, ok := rqMap[res.UID]
  69. if !ok {
  70. log.Warnf("resource quota with UID '%s' has not been initialized to add spec CPU request max", res.UID)
  71. continue
  72. }
  73. mcpu := res.Value * 1000
  74. rq.Spec.Hard.SetRequest(kubemodel.ResourceCPU, kubemodel.UnitMillicore, kubemodel.StatMax, mcpu)
  75. }
  76. rqSpecRAMRequestAverageResult, _ := rqSpecRAMRequestAverageResultFuture.Await()
  77. for _, res := range rqSpecRAMRequestAverageResult {
  78. rq, ok := rqMap[res.UID]
  79. if !ok {
  80. log.Warnf("resource quota with UID '%s' has not been initialized to add spec RAM request average", res.UID)
  81. continue
  82. }
  83. rq.Spec.Hard.SetRequest(kubemodel.ResourceMemory, kubemodel.UnitByte, kubemodel.StatAvg, res.Value)
  84. }
  85. rqSpecRAMRequestMaxResult, _ := rqSpecRAMRequestMaxResultFuture.Await()
  86. for _, res := range rqSpecRAMRequestMaxResult {
  87. rq, ok := rqMap[res.UID]
  88. if !ok {
  89. log.Warnf("resource quota with UID '%s' has not been initialized to add spec RAM request max", res.UID)
  90. continue
  91. }
  92. rq.Spec.Hard.SetRequest(kubemodel.ResourceMemory, kubemodel.UnitByte, kubemodel.StatMax, res.Value)
  93. }
  94. rqSpecCPULimitAverageResult, _ := rqSpecCPULimitAverageResultFuture.Await()
  95. for _, res := range rqSpecCPULimitAverageResult {
  96. rq, ok := rqMap[res.UID]
  97. if !ok {
  98. log.Warnf("resource quota with UID '%s' has not been initialized to add spec CPU limit average", res.UID)
  99. continue
  100. }
  101. mcpu := res.Value * 1000
  102. rq.Spec.Hard.SetLimit(kubemodel.ResourceCPU, kubemodel.UnitMillicore, kubemodel.StatAvg, mcpu)
  103. }
  104. rqSpecCPULimitMaxResult, _ := rqSpecCPULimitMaxResultFuture.Await()
  105. for _, res := range rqSpecCPULimitMaxResult {
  106. rq, ok := rqMap[res.UID]
  107. if !ok {
  108. log.Warnf("resource quota with UID '%s' has not been initialized to add spec CPU limit max", res.UID)
  109. continue
  110. }
  111. mcpu := res.Value * 1000
  112. rq.Spec.Hard.SetLimit(kubemodel.ResourceCPU, kubemodel.UnitMillicore, kubemodel.StatMax, mcpu)
  113. }
  114. rqSpecRAMLimitAverageResult, _ := rqSpecRAMLimitAverageResultFuture.Await()
  115. for _, res := range rqSpecRAMLimitAverageResult {
  116. rq, ok := rqMap[res.UID]
  117. if !ok {
  118. log.Warnf("resource quota with UID '%s' has not been initialized to add spec RAM limit average", res.UID)
  119. continue
  120. }
  121. rq.Spec.Hard.SetLimit(kubemodel.ResourceMemory, kubemodel.UnitByte, kubemodel.StatAvg, res.Value)
  122. }
  123. rqSpecRAMLimitMaxResult, _ := rqSpecRAMLimitMaxResultFuture.Await()
  124. for _, res := range rqSpecRAMLimitMaxResult {
  125. rq, ok := rqMap[res.UID]
  126. if !ok {
  127. log.Warnf("resource quota with UID '%s' has not been initialized to add spec RAM limit max", res.UID)
  128. continue
  129. }
  130. rq.Spec.Hard.SetLimit(kubemodel.ResourceMemory, kubemodel.UnitByte, kubemodel.StatMax, res.Value)
  131. }
  132. rqStatusUsedCPURequestAverageResult, _ := rqStatusUsedCPURequestAverageResultFuture.Await()
  133. for _, res := range rqStatusUsedCPURequestAverageResult {
  134. rq, ok := rqMap[res.UID]
  135. if !ok {
  136. log.Warnf("resource quota with UID '%s' has not been initialized to add status CPU request average", res.UID)
  137. continue
  138. }
  139. mcpu := res.Value * 1000
  140. rq.Status.Used.SetRequest(kubemodel.ResourceCPU, kubemodel.UnitMillicore, kubemodel.StatAvg, mcpu)
  141. }
  142. rqStatusUsedCPURequestMaxResult, _ := rqStatusUsedCPURequestMaxResultFuture.Await()
  143. for _, res := range rqStatusUsedCPURequestMaxResult {
  144. rq, ok := rqMap[res.UID]
  145. if !ok {
  146. log.Warnf("resource quota with UID '%s' has not been initialized to add status CPU request max", res.UID)
  147. continue
  148. }
  149. mcpu := res.Value * 1000
  150. rq.Status.Used.SetRequest(kubemodel.ResourceCPU, kubemodel.UnitMillicore, kubemodel.StatMax, mcpu)
  151. }
  152. rqStatusUsedRAMRequestAverageResult, _ := rqStatusUsedRAMRequestAverageResultFuture.Await()
  153. for _, res := range rqStatusUsedRAMRequestAverageResult {
  154. rq, ok := rqMap[res.UID]
  155. if !ok {
  156. log.Warnf("resource quota with UID '%s' has not been initialized to add status RAM request average", res.UID)
  157. continue
  158. }
  159. rq.Status.Used.SetRequest(kubemodel.ResourceMemory, kubemodel.UnitByte, kubemodel.StatAvg, res.Value)
  160. }
  161. rqStatusUsedRAMRequestMaxResult, _ := rqStatusUsedRAMRequestMaxResultFuture.Await()
  162. for _, res := range rqStatusUsedRAMRequestMaxResult {
  163. rq, ok := rqMap[res.UID]
  164. if !ok {
  165. log.Warnf("resource quota with UID '%s' has not been initialized to add status RAM request max", res.UID)
  166. continue
  167. }
  168. rq.Status.Used.SetRequest(kubemodel.ResourceMemory, kubemodel.UnitByte, kubemodel.StatMax, res.Value)
  169. }
  170. rqStatusUsedCPULimitAverageResult, _ := rqStatusUsedCPULimitAverageResultFuture.Await()
  171. for _, res := range rqStatusUsedCPULimitAverageResult {
  172. rq, ok := rqMap[res.UID]
  173. if !ok {
  174. log.Warnf("resource quota with UID '%s' has not been initialized to add status CPU limit average", res.UID)
  175. continue
  176. }
  177. mcpu := res.Value * 1000
  178. rq.Status.Used.SetLimit(kubemodel.ResourceCPU, kubemodel.UnitMillicore, kubemodel.StatAvg, mcpu)
  179. }
  180. rqStatusUsedCPULimitMaxResult, _ := rqStatusUsedCPULimitMaxResultFuture.Await()
  181. for _, res := range rqStatusUsedCPULimitMaxResult {
  182. rq, ok := rqMap[res.UID]
  183. if !ok {
  184. log.Warnf("resource quota with UID '%s' has not been initialized to add status CPU limit max", res.UID)
  185. continue
  186. }
  187. mcpu := res.Value * 1000
  188. rq.Status.Used.SetLimit(kubemodel.ResourceCPU, kubemodel.UnitMillicore, kubemodel.StatMax, mcpu)
  189. }
  190. rqStatusUsedRAMLimitAverageResult, _ := rqStatusUsedRAMLimitAverageResultFuture.Await()
  191. for _, res := range rqStatusUsedRAMLimitAverageResult {
  192. rq, ok := rqMap[res.UID]
  193. if !ok {
  194. log.Warnf("resource quota with UID '%s' has not been initialized to add status RAM limit average", res.UID)
  195. continue
  196. }
  197. rq.Status.Used.SetLimit(kubemodel.ResourceMemory, kubemodel.UnitByte, kubemodel.StatAvg, res.Value)
  198. }
  199. rqStatusUsedRAMLimitMaxResult, _ := rqStatusUsedRAMLimitMaxResultFuture.Await()
  200. for _, res := range rqStatusUsedRAMLimitMaxResult {
  201. rq, ok := rqMap[res.UID]
  202. if !ok {
  203. log.Warnf("resource quota with UID '%s' has not been initialized to add status RAM limit max", res.UID)
  204. continue
  205. }
  206. rq.Status.Used.SetLimit(kubemodel.ResourceMemory, kubemodel.UnitByte, kubemodel.StatMax, res.Value)
  207. }
  208. for _, resourceQuota := range rqMap {
  209. err := kms.RegisterResourceQuota(resourceQuota)
  210. if err != nil {
  211. log.Warnf("Failed to register resource quota: %s", err.Error())
  212. }
  213. }
  214. return nil
  215. }