Kaynağa Gözat

Merge pull request #543 from kubecost/AjayTripathy-pv-reconciliation

Ajay tripathy pv reconciliation
Ajay Tripathy 5 yıl önce
ebeveyn
işleme
d84ae12469

+ 19 - 0
pkg/cloud/awsprovider.go

@@ -460,6 +460,7 @@ type awsPVKey struct {
 	StorageClassName       string
 	Name                   string
 	DefaultRegion          string
+	ProviderID             string
 }
 
 func (aws *AWS) GetPVKey(pv *v1.PersistentVolume, parameters map[string]string, defaultRegion string) PVKey {
@@ -469,9 +470,14 @@ func (aws *AWS) GetPVKey(pv *v1.PersistentVolume, parameters map[string]string,
 		StorageClassParameters: parameters,
 		Name:                   pv.Name,
 		DefaultRegion:          defaultRegion,
+		ProviderID:             pv.Spec.AWSElasticBlockStore.VolumeID,
 	}
 }
 
+func (key *awsPVKey) ID() string {
+	return key.ProviderID
+}
+
 func (key *awsPVKey) GetStorageClass() string {
 	return key.StorageClassName
 }
@@ -2446,3 +2452,16 @@ func (aws *AWS) ParseID(id string) string {
 
 	return match[1]
 }
+
+func (aws *AWS) ParsePVID(id string) string {
+	rx := regexp.MustCompile("aws:/[^/]*/[^/]*/([^/]+)") // Capture "vol-0fc54c5e83b8d2b76" from "aws://us-east-2a/vol-0fc54c5e83b8d2b76"
+	match := rx.FindStringSubmatch(id)
+	if len(match) < 2 {
+		if id != "" {
+			log.Infof("awsprovider.ParseID: failed to parse %s", id)
+		}
+		return id
+	}
+
+	return match[1]
+}

+ 8 - 0
pkg/cloud/azureprovider.go

@@ -685,6 +685,10 @@ func (az *Azure) GetPVKey(pv *v1.PersistentVolume, parameters map[string]string,
 	}
 }
 
+func (key *azurePvKey) ID() string {
+	return ""
+}
+
 func (key *azurePvKey) GetStorageClass() string {
 	return key.StorageClass
 }
@@ -842,3 +846,7 @@ func (az *Azure) CombinedDiscountForNode(instanceType string, isPreemptible bool
 func (az *Azure) ParseID(id string) string {
 	return id
 }
+
+func (az *Azure) ParsePVID(id string) string {
+	return id
+}

+ 8 - 0
pkg/cloud/csvprovider.go

@@ -256,6 +256,10 @@ type csvPVKey struct {
 	DefaultRegion          string
 }
 
+func (key *csvPVKey) ID() string {
+	return ""
+}
+
 func (key *csvPVKey) GetStorageClass() string {
 	return key.StorageClassName
 }
@@ -306,3 +310,7 @@ func (c *CSVProvider) CombinedDiscountForNode(instanceType string, isPreemptible
 func (c *CSVProvider) ParseID(id string) string {
 	return id
 }
+
+func (c *CSVProvider) ParsePVID(id string) string {
+	return id
+}

+ 4 - 0
pkg/cloud/customprovider.go

@@ -311,3 +311,7 @@ func (cp *CustomProvider) CombinedDiscountForNode(instanceType string, isPreempt
 func (cp *CustomProvider) ParseID(id string) string {
 	return id
 }
+
+func (cp *CustomProvider) ParsePVID(id string) string {
+	return id
+}

+ 8 - 0
pkg/cloud/gcpprovider.go

@@ -1297,6 +1297,10 @@ type pvKey struct {
 	DefaultRegion          string
 }
 
+func (key *pvKey) ID() string {
+	return ""
+}
+
 func (key *pvKey) GetStorageClass() string {
 	return key.StorageClass
 }
@@ -1458,3 +1462,7 @@ func (gcp *GCP) ParseID(id string) string {
 
 	return match[1]
 }
+
+func (gcp *GCP) ParsePVID(id string) string {
+	return id
+}

+ 3 - 0
pkg/cloud/provider.go

@@ -98,6 +98,7 @@ type PV struct {
 	Class      string            `json:"storageClass"`
 	Size       string            `json:"size"`
 	Region     string            `json:"region"`
+	ProviderID string            `json:"providerID,omitempty"`
 	Parameters map[string]string `json:"parameters"`
 }
 
@@ -111,6 +112,7 @@ type Key interface {
 type PVKey interface {
 	Features() string
 	GetStorageClass() string
+	ID() string
 }
 
 // OutOfClusterAllocation represents a cloud provider cost not associated with kubernetes
@@ -207,6 +209,7 @@ type Provider interface {
 	ClusterManagementPricing() (string, float64, error)
 	CombinedDiscountForNode(string, bool, float64, float64) float64
 	ParseID(string) string
+	ParsePVID(string) string
 }
 
 // ClusterName returns the name defined in cluster info, defaulting to the

+ 5 - 1
pkg/costmodel/cluster.go

@@ -139,7 +139,7 @@ func ClusterDisks(client prometheus.Client, provider cloud.Provider, duration, o
 	costPerGBHr := 0.04 / 730.0
 
 	ctx := prom.NewContext(client)
-	queryPVCost := fmt.Sprintf(`sum_over_time((avg(kube_persistentvolume_capacity_bytes) by (cluster_id, persistentvolume) * avg(pv_hourly_cost) by (cluster_id, persistentvolume))[%s:%dm]%s)/1024/1024/1024 * %f`, durationStr, minsPerResolution, offsetStr, hourlyToCumulative)
+	queryPVCost := fmt.Sprintf(`sum_over_time((avg(kube_persistentvolume_capacity_bytes) by (cluster_id, persistentvolume)  * on(cluster_id, persistentvolume) group_right avg(pv_hourly_cost) by (cluster_id, persistentvolume,provider_id))[%s:%dm]%s)/1024/1024/1024 * %f`, durationStr, minsPerResolution, offsetStr, hourlyToCumulative)
 	queryPVSize := fmt.Sprintf(`avg_over_time(kube_persistentvolume_capacity_bytes[%s:%dm]%s)`, durationStr, minsPerResolution, offsetStr)
 	queryActiveMins := fmt.Sprintf(`count(pv_hourly_cost) by (cluster_id, persistentvolume)[%s:%dm]%s`, durationStr, minsPerResolution, offsetStr)
 
@@ -193,6 +193,10 @@ func ClusterDisks(client prometheus.Client, provider cloud.Provider, duration, o
 			}
 		}
 		diskMap[key].Cost += cost
+		providerID, _ := result.GetString("provider_id") // just put the providerID set up here, it's the simplest query.
+		if providerID != "" {
+			diskMap[key].ProviderID = provider.ParsePVID(providerID)
+		}
 	}
 
 	for _, result := range resPVSize {

+ 1 - 0
pkg/costmodel/costmodel.go

@@ -913,6 +913,7 @@ func GetPVCost(pv *costAnalyzerCloud.PV, kpv *v1.PersistentVolume, cp costAnalyz
 		return nil // set default cost
 	}
 	pv.Cost = pvWithCost.Cost
+	pv.ProviderID = key.ID()
 	return nil
 }
 

+ 1 - 1
pkg/costmodel/metrics.go

@@ -593,7 +593,7 @@ func StartCostModelMetricRecording(a *Accesses) bool {
 					}
 					GetPVCost(cacPv, pv, a.Cloud, region)
 					c, _ := strconv.ParseFloat(cacPv.Cost, 64)
-					a.PersistentVolumePriceRecorder.WithLabelValues(pv.Name, pv.Name).Set(c)
+					a.PersistentVolumePriceRecorder.WithLabelValues(pv.Name, pv.Name, cacPv.ProviderID).Set(c)
 					labelKey := getKeyFromLabelStrings(pv.Name, pv.Name)
 					pvSeen[labelKey] = true
 				}

+ 1 - 1
pkg/costmodel/router.go

@@ -862,7 +862,7 @@ func Initialize(additionalConfigWatchers ...ConfigWatchers) {
 	pvGv := prometheus.NewGaugeVec(prometheus.GaugeOpts{
 		Name: "pv_hourly_cost",
 		Help: "pv_hourly_cost Cost per GB per hour on a persistent disk",
-	}, []string{"volumename", "persistentvolume"})
+	}, []string{"volumename", "persistentvolume", "provider_id"})
 
 	RAMAllocation := prometheus.NewGaugeVec(prometheus.GaugeOpts{
 		Name: "container_memory_allocation_bytes",