example.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package kubemodel
  2. import "github.com/opencost/opencost/core/pkg/stats"
  3. type ContainerCosts struct {
  4. Container
  5. CPUCost float64
  6. RAMCost float64
  7. StorageCost float64
  8. }
  9. // ApplyContainerCosts is a simplified example of a consumer of the
  10. // KubeModelSet data structure, which applies Node and PersistentVolume
  11. // pricing to container resources to assign container costs.
  12. func ApplyContainerCosts(kms *KubeModelSet, pm PricingModel, out chan map[string]*ContainerCosts) {
  13. // 1. Option that uses the flat structure
  14. flatAlgorithm(kms, pm, out)
  15. // 2. Option that uses the cost-priority hierarchical structure
  16. hierarchyAlgorithm(kms, pm, out)
  17. }
  18. // O(C * avg(PVC))
  19. // 42 lines
  20. // 2 loops
  21. // 3 max indentation
  22. func flatAlgorithm(kms *KubeModelSet, pm PricingModel, out chan map[string]*ContainerCosts) {
  23. // O(1) -- slight advantage in being able to allocate memory for the whole set of Containers
  24. ccs := make(map[string]*ContainerCosts, len(kms.Containers))
  25. // O(C)
  26. for _, container := range kms.Containers {
  27. // O(1)
  28. cc := &ContainerCosts{Container: *container}
  29. // O(1)
  30. pod := kms.Pods[container.PodUID]
  31. // O(1)
  32. node := kms.Nodes[pod.NodeUID]
  33. // O(1) -- presumably
  34. nodePricing := pm.GetNodePricing(node)
  35. // O(1)
  36. cc.CPUCost = float64(container.CPUAllocationMillicoreSeconds) * nodePricing[ResourceCPU].Price
  37. cc.RAMCost = float64(container.RAMAllocationByteSeconds) * nodePricing[ResourceMemory].Price
  38. // O(PVC)
  39. for pvcUID, mountedVolume := range container.PVCMounts {
  40. // O(1)
  41. pvc := kms.PersistentVolumeClaims[pvcUID]
  42. // O(1)
  43. pv := kms.PersistentVolumes[pvc.PersistentVolumeUID]
  44. // O(1)
  45. pvPricing := pm.GetPersistentVolumePricing(pv)
  46. // O(1)
  47. cc.StorageCost += float64(mountedVolume.StorageCapacityBytes) * pvPricing[ResourceStorage].Price
  48. }
  49. // O(1)
  50. ccs[container.UID] = cc
  51. }
  52. // O(1)
  53. out <- ccs
  54. }
  55. // O(N * avg(P) * avg(C) * avg(PVC)) == O(C * avg(PVC))
  56. // 42 lines
  57. // 4 loops
  58. // 5 max indentation
  59. func hierarchyAlgorithm(kms *KubeModelSet, pm PricingModel, out chan map[string]*ContainerCosts) {
  60. // O(1) -- total number of containers would have to be indexed / cached
  61. ccs := map[string]*ContainerCosts{}
  62. // O(N)
  63. for _, node := range kms.Cluster.Nodes {
  64. // O(avg(P))
  65. for _, pod := range node.Pods {
  66. // O(avg(C))
  67. for _, container := range pod.Containers {
  68. // O(1)
  69. cc := &ContainerCosts{Container: *container}
  70. // O(1) -- presumably
  71. nodePricing := pm.GetNodePricing(node)
  72. // O(1)
  73. cc.CPUCost = container.Resources[ResourceCPU].Values[stats.Val] * nodePricing[ResourceCPU].Price
  74. cc.RAMCost = container.Resources[ResourceMemory].Values[stats.Val] * nodePricing[ResourceMemory].Price
  75. // O(PVC) -- going to need to use the same access pattern as the
  76. // flat data structure, anyways, unless somehow PVCs / PVs will
  77. // be nested within Containers (e.g. under VolumeMounts?)
  78. for pvcUID, storage := range container.VolumeMounts {
  79. // O(1)
  80. pvc := kms.PersistentVolumeClaims[pvcUID]
  81. // O(1)
  82. pv := kms.PersistentVolumes[pvc.PersistentVolumeUID]
  83. // O(1)
  84. pvPricing := pm.GetPersistentVolumePricing(pv)
  85. // O(1)
  86. cc.StorageCost += storage.Values[stats.Val] * pvPricing[ResourceStorage].Price
  87. }
  88. ccs[container.UID] = cc
  89. }
  90. }
  91. }
  92. out <- ccs
  93. }
  94. type PricingModel interface {
  95. GetNodePricing(node *Node) Pricing
  96. GetPersistentVolumePricing(pv *PersistentVolume) Pricing
  97. }
  98. type Pricing map[Resource]ResourcePricing
  99. type ResourcePricing struct {
  100. Resource Resource
  101. Unit Unit
  102. Price float64
  103. }