|
@@ -150,9 +150,12 @@ const (
|
|
|
*
|
|
*
|
|
|
on (persistentvolumeclaim, namespace, cluster_id) group_right(storageclass, volumename)
|
|
on (persistentvolumeclaim, namespace, cluster_id) group_right(storageclass, volumename)
|
|
|
sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace, cluster_id)`
|
|
sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace, cluster_id)`
|
|
|
- queryPVCAllocation = `avg_over_time(pod_pvc_allocation[24h])`
|
|
|
|
|
- queryPVHourlyCost = `avg_over_time(pv_hourly_cost[24h])`
|
|
|
|
|
- queryNSLabels = `avg_over_time(kube_namespace_labels[24h])`
|
|
|
|
|
|
|
+ queryPVCAllocation = `avg_over_time(pod_pvc_allocation[%s])`
|
|
|
|
|
+ queryPVHourlyCost = `avg_over_time(pv_hourly_cost[%s])`
|
|
|
|
|
+ queryNSLabels = `avg_over_time(kube_namespace_labels[%s])`
|
|
|
|
|
+ queryPodLabels = `avg_over_time(kube_pod_labels[%s])`
|
|
|
|
|
+ queryDeploymentLabels = `avg_over_time(deployment_match_labels[%s])`
|
|
|
|
|
+ queryServiceLabels = `avg_over_time(service_selector_labels[%s])`
|
|
|
queryZoneNetworkUsage = `sum(increase(kubecost_pod_network_egress_bytes_total{internet="false", sameZone="false", sameRegion="true"}[%s] %s)) by (namespace,pod_name,cluster_id) / 1024 / 1024 / 1024`
|
|
queryZoneNetworkUsage = `sum(increase(kubecost_pod_network_egress_bytes_total{internet="false", sameZone="false", sameRegion="true"}[%s] %s)) by (namespace,pod_name,cluster_id) / 1024 / 1024 / 1024`
|
|
|
queryRegionNetworkUsage = `sum(increase(kubecost_pod_network_egress_bytes_total{internet="false", sameZone="false", sameRegion="false"}[%s] %s)) by (namespace,pod_name,cluster_id) / 1024 / 1024 / 1024`
|
|
queryRegionNetworkUsage = `sum(increase(kubecost_pod_network_egress_bytes_total{internet="false", sameZone="false", sameRegion="false"}[%s] %s)) by (namespace,pod_name,cluster_id) / 1024 / 1024 / 1024`
|
|
|
queryInternetNetworkUsage = `sum(increase(kubecost_pod_network_egress_bytes_total{internet="true"}[%s] %s)) by (namespace,pod_name,cluster_id) / 1024 / 1024 / 1024`
|
|
queryInternetNetworkUsage = `sum(increase(kubecost_pod_network_egress_bytes_total{internet="true"}[%s] %s)) by (namespace,pod_name,cluster_id) / 1024 / 1024 / 1024`
|
|
@@ -347,12 +350,12 @@ func (cm *CostModel) ComputeCostData(cli prometheusClient.Client, clientset kube
|
|
|
go func() {
|
|
go func() {
|
|
|
defer wg.Done()
|
|
defer wg.Done()
|
|
|
|
|
|
|
|
- podDeploymentsMapping, k8sErr = getPodDeployments(cm.Cache, podlist)
|
|
|
|
|
|
|
+ podDeploymentsMapping, k8sErr = getPodDeployments(cm.Cache, podlist, clusterID)
|
|
|
if k8sErr != nil {
|
|
if k8sErr != nil {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- podServicesMapping, k8sErr = getPodServices(cm.Cache, podlist)
|
|
|
|
|
|
|
+ podServicesMapping, k8sErr = getPodServices(cm.Cache, podlist, clusterID)
|
|
|
if k8sErr != nil {
|
|
if k8sErr != nil {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
@@ -477,9 +480,12 @@ func (cm *CostModel) ComputeCostData(cli prometheusClient.Client, clientset kube
|
|
|
if _, ok := nodes[nodeName]; ok {
|
|
if _, ok := nodes[nodeName]; ok {
|
|
|
nodeData = nodes[nodeName]
|
|
nodeData = nodes[nodeName]
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ nsKey := ns + "," + clusterID
|
|
|
|
|
+
|
|
|
var podDeployments []string
|
|
var podDeployments []string
|
|
|
- if _, ok := podDeploymentsMapping[ns]; ok {
|
|
|
|
|
- if ds, ok := podDeploymentsMapping[ns][pod.GetObjectMeta().GetName()]; ok {
|
|
|
|
|
|
|
+ if _, ok := podDeploymentsMapping[nsKey]; ok {
|
|
|
|
|
+ if ds, ok := podDeploymentsMapping[nsKey][pod.GetObjectMeta().GetName()]; ok {
|
|
|
podDeployments = ds
|
|
podDeployments = ds
|
|
|
} else {
|
|
} else {
|
|
|
podDeployments = []string{}
|
|
podDeployments = []string{}
|
|
@@ -508,8 +514,8 @@ func (cm *CostModel) ComputeCostData(cli prometheusClient.Client, clientset kube
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
var podServices []string
|
|
var podServices []string
|
|
|
- if _, ok := podServicesMapping[ns]; ok {
|
|
|
|
|
- if svcs, ok := podServicesMapping[ns][pod.GetObjectMeta().GetName()]; ok {
|
|
|
|
|
|
|
+ if _, ok := podServicesMapping[nsKey]; ok {
|
|
|
|
|
+ if svcs, ok := podServicesMapping[nsKey][pod.GetObjectMeta().GetName()]; ok {
|
|
|
podServices = svcs
|
|
podServices = svcs
|
|
|
} else {
|
|
} else {
|
|
|
podServices = []string{}
|
|
podServices = []string{}
|
|
@@ -1082,25 +1088,25 @@ func getNodeCost(cache ClusterCache, cp costAnalyzerCloud.Provider) (map[string]
|
|
|
return nodes, nil
|
|
return nodes, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func getPodServices(cache ClusterCache, podList []*v1.Pod) (map[string]map[string][]string, error) {
|
|
|
|
|
|
|
+func getPodServices(cache ClusterCache, podList []*v1.Pod, clusterID string) (map[string]map[string][]string, error) {
|
|
|
servicesList := cache.GetAllServices()
|
|
servicesList := cache.GetAllServices()
|
|
|
podServicesMapping := make(map[string]map[string][]string)
|
|
podServicesMapping := make(map[string]map[string][]string)
|
|
|
for _, service := range servicesList {
|
|
for _, service := range servicesList {
|
|
|
namespace := service.GetObjectMeta().GetNamespace()
|
|
namespace := service.GetObjectMeta().GetNamespace()
|
|
|
name := service.GetObjectMeta().GetName()
|
|
name := service.GetObjectMeta().GetName()
|
|
|
-
|
|
|
|
|
- if _, ok := podServicesMapping[namespace]; !ok {
|
|
|
|
|
- podServicesMapping[namespace] = make(map[string][]string)
|
|
|
|
|
|
|
+ key := namespace + "," + clusterID
|
|
|
|
|
+ if _, ok := podServicesMapping[key]; !ok {
|
|
|
|
|
+ podServicesMapping[key] = make(map[string][]string)
|
|
|
}
|
|
}
|
|
|
s := labels.Set(service.Spec.Selector).AsSelectorPreValidated()
|
|
s := labels.Set(service.Spec.Selector).AsSelectorPreValidated()
|
|
|
for _, pod := range podList {
|
|
for _, pod := range podList {
|
|
|
labelSet := labels.Set(pod.GetObjectMeta().GetLabels())
|
|
labelSet := labels.Set(pod.GetObjectMeta().GetLabels())
|
|
|
if s.Matches(labelSet) && pod.GetObjectMeta().GetNamespace() == namespace {
|
|
if s.Matches(labelSet) && pod.GetObjectMeta().GetNamespace() == namespace {
|
|
|
- services, ok := podServicesMapping[namespace][pod.GetObjectMeta().GetName()]
|
|
|
|
|
|
|
+ services, ok := podServicesMapping[key][pod.GetObjectMeta().GetName()]
|
|
|
if ok {
|
|
if ok {
|
|
|
- podServicesMapping[namespace][pod.GetObjectMeta().GetName()] = append(services, name)
|
|
|
|
|
|
|
+ podServicesMapping[key][pod.GetObjectMeta().GetName()] = append(services, name)
|
|
|
} else {
|
|
} else {
|
|
|
- podServicesMapping[namespace][pod.GetObjectMeta().GetName()] = []string{name}
|
|
|
|
|
|
|
+ podServicesMapping[key][pod.GetObjectMeta().GetName()] = []string{name}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1108,14 +1114,16 @@ func getPodServices(cache ClusterCache, podList []*v1.Pod) (map[string]map[strin
|
|
|
return podServicesMapping, nil
|
|
return podServicesMapping, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func getPodDeployments(cache ClusterCache, podList []*v1.Pod) (map[string]map[string][]string, error) {
|
|
|
|
|
|
|
+func getPodDeployments(cache ClusterCache, podList []*v1.Pod, clusterID string) (map[string]map[string][]string, error) {
|
|
|
deploymentsList := cache.GetAllDeployments()
|
|
deploymentsList := cache.GetAllDeployments()
|
|
|
podDeploymentsMapping := make(map[string]map[string][]string) // namespace: podName: [deploymentNames]
|
|
podDeploymentsMapping := make(map[string]map[string][]string) // namespace: podName: [deploymentNames]
|
|
|
for _, deployment := range deploymentsList {
|
|
for _, deployment := range deploymentsList {
|
|
|
namespace := deployment.GetObjectMeta().GetNamespace()
|
|
namespace := deployment.GetObjectMeta().GetNamespace()
|
|
|
name := deployment.GetObjectMeta().GetName()
|
|
name := deployment.GetObjectMeta().GetName()
|
|
|
- if _, ok := podDeploymentsMapping[namespace]; !ok {
|
|
|
|
|
- podDeploymentsMapping[namespace] = make(map[string][]string)
|
|
|
|
|
|
|
+
|
|
|
|
|
+ key := namespace + "," + clusterID
|
|
|
|
|
+ if _, ok := podDeploymentsMapping[key]; !ok {
|
|
|
|
|
+ podDeploymentsMapping[key] = make(map[string][]string)
|
|
|
}
|
|
}
|
|
|
s, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector)
|
|
s, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -1124,18 +1132,102 @@ func getPodDeployments(cache ClusterCache, podList []*v1.Pod) (map[string]map[st
|
|
|
for _, pod := range podList {
|
|
for _, pod := range podList {
|
|
|
labelSet := labels.Set(pod.GetObjectMeta().GetLabels())
|
|
labelSet := labels.Set(pod.GetObjectMeta().GetLabels())
|
|
|
if s.Matches(labelSet) && pod.GetObjectMeta().GetNamespace() == namespace {
|
|
if s.Matches(labelSet) && pod.GetObjectMeta().GetNamespace() == namespace {
|
|
|
- deployments, ok := podDeploymentsMapping[namespace][pod.GetObjectMeta().GetName()]
|
|
|
|
|
|
|
+ deployments, ok := podDeploymentsMapping[key][pod.GetObjectMeta().GetName()]
|
|
|
|
|
+ if ok {
|
|
|
|
|
+ podDeploymentsMapping[key][pod.GetObjectMeta().GetName()] = append(deployments, name)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ podDeploymentsMapping[key][pod.GetObjectMeta().GetName()] = []string{name}
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return podDeploymentsMapping, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func getPodDeploymentsWithMetrics(deploymentLabels map[string]map[string]string, podLabels map[string]map[string]string) (map[string]map[string][]string, error) {
|
|
|
|
|
+ podDeploymentsMapping := make(map[string]map[string][]string)
|
|
|
|
|
+
|
|
|
|
|
+ for depKey, depLabels := range deploymentLabels {
|
|
|
|
|
+ kt, err := NewKeyTuple(depKey)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ namespace := kt.Namespace
|
|
|
|
|
+ name := kt.Key
|
|
|
|
|
+ clusterID := kt.ClusterID
|
|
|
|
|
+
|
|
|
|
|
+ key := namespace + "," + clusterID
|
|
|
|
|
+ if _, ok := podDeploymentsMapping[key]; !ok {
|
|
|
|
|
+ podDeploymentsMapping[key] = make(map[string][]string)
|
|
|
|
|
+ }
|
|
|
|
|
+ s := labels.Set(depLabels).AsSelectorPreValidated()
|
|
|
|
|
+ for podKey, pLabels := range podLabels {
|
|
|
|
|
+ pkey, err := NewKeyTuple(podKey)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+ podNamespace := pkey.Namespace
|
|
|
|
|
+ podName := pkey.Key
|
|
|
|
|
+ podClusterID := pkey.ClusterID
|
|
|
|
|
+
|
|
|
|
|
+ labelSet := labels.Set(pLabels)
|
|
|
|
|
+ if s.Matches(labelSet) && podNamespace == namespace && podClusterID == clusterID {
|
|
|
|
|
+ deployments, ok := podDeploymentsMapping[key][podName]
|
|
|
if ok {
|
|
if ok {
|
|
|
- podDeploymentsMapping[namespace][pod.GetObjectMeta().GetName()] = append(deployments, name)
|
|
|
|
|
|
|
+ podDeploymentsMapping[key][podName] = append(deployments, name)
|
|
|
} else {
|
|
} else {
|
|
|
- podDeploymentsMapping[namespace][pod.GetObjectMeta().GetName()] = []string{name}
|
|
|
|
|
|
|
+ podDeploymentsMapping[key][podName] = []string{name}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
return podDeploymentsMapping, nil
|
|
return podDeploymentsMapping, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func getPodServicesWithMetrics(serviceLabels map[string]map[string]string, podLabels map[string]map[string]string) (map[string]map[string][]string, error) {
|
|
|
|
|
+ podServicesMapping := make(map[string]map[string][]string)
|
|
|
|
|
+
|
|
|
|
|
+ for servKey, servLabels := range serviceLabels {
|
|
|
|
|
+ kt, err := NewKeyTuple(servKey)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ namespace := kt.Namespace
|
|
|
|
|
+ name := kt.Key
|
|
|
|
|
+ clusterID := kt.ClusterID
|
|
|
|
|
+
|
|
|
|
|
+ key := namespace + "," + clusterID
|
|
|
|
|
+ if _, ok := podServicesMapping[key]; !ok {
|
|
|
|
|
+ podServicesMapping[key] = make(map[string][]string)
|
|
|
|
|
+ }
|
|
|
|
|
+ s := labels.Set(servLabels).AsSelectorPreValidated()
|
|
|
|
|
+
|
|
|
|
|
+ for podKey, pLabels := range podLabels {
|
|
|
|
|
+ pkey, err := NewKeyTuple(podKey)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+ podNamespace := pkey.Namespace
|
|
|
|
|
+ podName := pkey.Key
|
|
|
|
|
+ podClusterID := pkey.ClusterID
|
|
|
|
|
+
|
|
|
|
|
+ labelSet := labels.Set(pLabels)
|
|
|
|
|
+ if s.Matches(labelSet) && podNamespace == namespace && podClusterID == clusterID {
|
|
|
|
|
+ services, ok := podServicesMapping[key][podName]
|
|
|
|
|
+ if ok {
|
|
|
|
|
+ podServicesMapping[key][podName] = append(services, name)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ podServicesMapping[key][podName] = []string{name}
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return podServicesMapping, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func costDataPassesFilters(costs *CostData, namespace string, cluster string) bool {
|
|
func costDataPassesFilters(costs *CostData, namespace string, cluster string) bool {
|
|
|
passesNamespace := namespace == "" || costs.Namespace == namespace
|
|
passesNamespace := namespace == "" || costs.Namespace == namespace
|
|
|
passesCluster := cluster == "" || costs.ClusterID == cluster
|
|
passesCluster := cluster == "" || costs.ClusterID == cluster
|
|
@@ -1184,7 +1276,7 @@ func (cm *CostModel) ComputeCostDataRange(cli prometheusClient.Client, clientset
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
var wg sync.WaitGroup
|
|
var wg sync.WaitGroup
|
|
|
- wg.Add(14)
|
|
|
|
|
|
|
+ wg.Add(17)
|
|
|
|
|
|
|
|
var promErr error
|
|
var promErr error
|
|
|
var resultRAMRequests interface{}
|
|
var resultRAMRequests interface{}
|
|
@@ -1234,17 +1326,32 @@ func (cm *CostModel) ComputeCostDataRange(cli prometheusClient.Client, clientset
|
|
|
}()
|
|
}()
|
|
|
var pvPodAllocationResults interface{}
|
|
var pvPodAllocationResults interface{}
|
|
|
go func() {
|
|
go func() {
|
|
|
- pvPodAllocationResults, promErr = Query(cli, queryPVCAllocation)
|
|
|
|
|
|
|
+ pvPodAllocationResults, promErr = QueryRange(cli, fmt.Sprintf(queryPVCAllocation, window), start, end, window)
|
|
|
defer wg.Done()
|
|
defer wg.Done()
|
|
|
}()
|
|
}()
|
|
|
var pvCostResults interface{}
|
|
var pvCostResults interface{}
|
|
|
go func() {
|
|
go func() {
|
|
|
- pvCostResults, promErr = Query(cli, queryPVHourlyCost)
|
|
|
|
|
|
|
+ pvCostResults, promErr = QueryRange(cli, fmt.Sprintf(queryPVHourlyCost, window), start, end, window)
|
|
|
defer wg.Done()
|
|
defer wg.Done()
|
|
|
}()
|
|
}()
|
|
|
var nsLabelsResults interface{}
|
|
var nsLabelsResults interface{}
|
|
|
go func() {
|
|
go func() {
|
|
|
- nsLabelsResults, promErr = Query(cli, queryNSLabels)
|
|
|
|
|
|
|
+ nsLabelsResults, promErr = QueryRange(cli, fmt.Sprintf(queryNSLabels, window), start, end, window)
|
|
|
|
|
+ defer wg.Done()
|
|
|
|
|
+ }()
|
|
|
|
|
+ var podLabelsResults interface{}
|
|
|
|
|
+ go func() {
|
|
|
|
|
+ podLabelsResults, promErr = QueryRange(cli, fmt.Sprintf(queryPodLabels, window), start, end, window)
|
|
|
|
|
+ defer wg.Done()
|
|
|
|
|
+ }()
|
|
|
|
|
+ var serviceLabelsResults interface{}
|
|
|
|
|
+ go func() {
|
|
|
|
|
+ serviceLabelsResults, promErr = QueryRange(cli, fmt.Sprintf(queryServiceLabels, window), start, end, window)
|
|
|
|
|
+ defer wg.Done()
|
|
|
|
|
+ }()
|
|
|
|
|
+ var deploymentLabelsResults interface{}
|
|
|
|
|
+ go func() {
|
|
|
|
|
+ deploymentLabelsResults, promErr = QueryRange(cli, fmt.Sprintf(queryDeploymentLabels, window), start, end, window)
|
|
|
defer wg.Done()
|
|
defer wg.Done()
|
|
|
}()
|
|
}()
|
|
|
var normalizationResults interface{}
|
|
var normalizationResults interface{}
|
|
@@ -1261,12 +1368,12 @@ func (cm *CostModel) ComputeCostDataRange(cli prometheusClient.Client, clientset
|
|
|
go func() {
|
|
go func() {
|
|
|
defer wg.Done()
|
|
defer wg.Done()
|
|
|
|
|
|
|
|
- podDeploymentsMapping, k8sErr = getPodDeployments(cm.Cache, podlist)
|
|
|
|
|
|
|
+ podDeploymentsMapping, k8sErr = getPodDeployments(cm.Cache, podlist, clusterID)
|
|
|
if k8sErr != nil {
|
|
if k8sErr != nil {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- podServicesMapping, k8sErr = getPodServices(cm.Cache, podlist)
|
|
|
|
|
|
|
+ podServicesMapping, k8sErr = getPodServices(cm.Cache, podlist, clusterID)
|
|
|
if k8sErr != nil {
|
|
if k8sErr != nil {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
@@ -1308,12 +1415,12 @@ func (cm *CostModel) ComputeCostDataRange(cli prometheusClient.Client, clientset
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- pvCostMapping, err := getPVCostMetrics(pvCostResults, clusterID)
|
|
|
|
|
|
|
+ pvCostMapping, err := GetPVCostMetrics(pvCostResults, clusterID)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
klog.V(1).Infof("Unable to get PV Hourly Cost Data: %s", err.Error())
|
|
klog.V(1).Infof("Unable to get PV Hourly Cost Data: %s", err.Error())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- pvAllocationMapping, err := getPVAllocationMetrics(pvPodAllocationResults, clusterID)
|
|
|
|
|
|
|
+ pvAllocationMapping, err := GetPVAllocationMetrics(pvPodAllocationResults, clusterID)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
klog.V(1).Infof("Unable to get PV Allocation Cost Data: %s", err.Error())
|
|
klog.V(1).Infof("Unable to get PV Allocation Cost Data: %s", err.Error())
|
|
|
}
|
|
}
|
|
@@ -1329,6 +1436,33 @@ func (cm *CostModel) ComputeCostDataRange(cli prometheusClient.Client, clientset
|
|
|
appendNamespaceLabels(namespaceLabelsMapping, nsLabels)
|
|
appendNamespaceLabels(namespaceLabelsMapping, nsLabels)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ podLabels, err := GetPodLabelsMetrics(podLabelsResults)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ klog.V(1).Infof("Unable to get Pod Labels for Metrics: %s", err.Error())
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ serviceLabels, err := GetServiceSelectorLabelsMetrics(serviceLabelsResults)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ klog.V(1).Infof("Unable to get Service Selector Labels for Metrics: %s", err.Error())
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ deploymentLabels, err := GetDeploymentMatchLabelsMetrics(deploymentLabelsResults)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ klog.V(1).Infof("Unable to get Deployment Match Labels for Metrics: %s", err.Error())
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ podDeploymentsMetricsMapping, err := getPodDeploymentsWithMetrics(deploymentLabels, podLabels)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ klog.V(1).Infof("Unable to get match Deployment Labels Metrics to Pods: %s", err.Error())
|
|
|
|
|
+ }
|
|
|
|
|
+ appendLabelsList(podDeploymentsMapping, podDeploymentsMetricsMapping)
|
|
|
|
|
+
|
|
|
|
|
+ podServicesMetricsMapping, err := getPodServicesWithMetrics(serviceLabels, podLabels)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ klog.V(1).Infof("Unable to get match Service Labels Metrics to Pods: %s", err.Error())
|
|
|
|
|
+ }
|
|
|
|
|
+ appendLabelsList(podServicesMapping, podServicesMetricsMapping)
|
|
|
|
|
+
|
|
|
networkUsageMap, err := GetNetworkUsageData(resultNetZoneRequests, resultNetRegionRequests, resultNetInternetRequests, clusterID)
|
|
networkUsageMap, err := GetNetworkUsageData(resultNetZoneRequests, resultNetRegionRequests, resultNetInternetRequests, clusterID)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
klog.V(1).Infof("Unable to get Network Cost Data: %s", err.Error())
|
|
klog.V(1).Infof("Unable to get Network Cost Data: %s", err.Error())
|
|
@@ -1563,18 +1697,49 @@ func (cm *CostModel) ComputeCostDataRange(cli prometheusClient.Client, clientset
|
|
|
missingNodes[c.NodeName] = node
|
|
missingNodes[c.NodeName] = node
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- namespacelabels, ok := namespaceLabelsMapping[c.Namespace+","+c.ClusterID]
|
|
|
|
|
|
|
+
|
|
|
|
|
+ nsKey := c.Namespace + "," + c.ClusterID
|
|
|
|
|
+ podKey := c.Namespace + "," + c.PodName + "," + c.ClusterID
|
|
|
|
|
+
|
|
|
|
|
+ namespaceLabels, ok := namespaceLabelsMapping[nsKey]
|
|
|
if !ok {
|
|
if !ok {
|
|
|
klog.V(3).Infof("Missing data for namespace %s", c.Namespace)
|
|
klog.V(3).Infof("Missing data for namespace %s", c.Namespace)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ pLabels := podLabels[podKey]
|
|
|
|
|
+ if pLabels == nil {
|
|
|
|
|
+ pLabels = make(map[string]string)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for k, v := range namespaceLabels {
|
|
|
|
|
+ pLabels[k] = v
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var podDeployments []string
|
|
|
|
|
+ if _, ok := podDeploymentsMapping[nsKey]; ok {
|
|
|
|
|
+ if ds, ok := podDeploymentsMapping[nsKey][c.PodName]; ok {
|
|
|
|
|
+ podDeployments = ds
|
|
|
|
|
+ } else {
|
|
|
|
|
+ podDeployments = []string{}
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var podServices []string
|
|
|
|
|
+ if _, ok := podServicesMapping[nsKey]; ok {
|
|
|
|
|
+ if svcs, ok := podServicesMapping[nsKey][c.PodName]; ok {
|
|
|
|
|
+ podServices = svcs
|
|
|
|
|
+ } else {
|
|
|
|
|
+ podServices = []string{}
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
var podPVs []*PersistentVolumeClaimData
|
|
var podPVs []*PersistentVolumeClaimData
|
|
|
var podNetCosts []*Vector
|
|
var podNetCosts []*Vector
|
|
|
|
|
|
|
|
// For PVC data, we'll need to find the claim mapping and cost data. Will need to append
|
|
// For PVC data, we'll need to find the claim mapping and cost data. Will need to append
|
|
|
// cost data since that was populated by cluster data previously. We do this with
|
|
// cost data since that was populated by cluster data previously. We do this with
|
|
|
// the pod_pvc_allocation metric
|
|
// the pod_pvc_allocation metric
|
|
|
- podPVData, ok := pvAllocationMapping[c.Namespace+","+c.PodName+","+c.ClusterID]
|
|
|
|
|
|
|
+ podPVData, ok := pvAllocationMapping[podKey]
|
|
|
if !ok {
|
|
if !ok {
|
|
|
klog.V(4).Infof("Failed to locate pv allocation mapping for missing pod.")
|
|
klog.V(4).Infof("Failed to locate pv allocation mapping for missing pod.")
|
|
|
}
|
|
}
|
|
@@ -1582,7 +1747,7 @@ func (cm *CostModel) ComputeCostDataRange(cli prometheusClient.Client, clientset
|
|
|
// For network costs, we'll use existing map since it should still contain the
|
|
// For network costs, we'll use existing map since it should still contain the
|
|
|
// correct data.
|
|
// correct data.
|
|
|
var podNetworkCosts []*Vector
|
|
var podNetworkCosts []*Vector
|
|
|
- if usage, ok := networkUsageMap[c.Namespace+","+c.PodName+","+c.ClusterID]; ok {
|
|
|
|
|
|
|
+ if usage, ok := networkUsageMap[podKey]; ok {
|
|
|
netCosts, err := GetNetworkCost(usage, cp)
|
|
netCosts, err := GetNetworkCost(usage, cp)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
klog.V(3).Infof("Error pulling network costs: %s", err.Error())
|
|
klog.V(3).Infof("Error pulling network costs: %s", err.Error())
|
|
@@ -1593,7 +1758,6 @@ func (cm *CostModel) ComputeCostDataRange(cli prometheusClient.Client, clientset
|
|
|
|
|
|
|
|
// Check to see if any other data has been recorded for this namespace, pod, clusterId
|
|
// Check to see if any other data has been recorded for this namespace, pod, clusterId
|
|
|
// Follow the pattern of only allowing claims data per pod
|
|
// Follow the pattern of only allowing claims data per pod
|
|
|
- podKey := c.Namespace + "," + c.PodName + "," + c.ClusterID
|
|
|
|
|
if !otherClusterPVRecorded[podKey] {
|
|
if !otherClusterPVRecorded[podKey] {
|
|
|
otherClusterPVRecorded[podKey] = true
|
|
otherClusterPVRecorded[podKey] = true
|
|
|
|
|
|
|
@@ -1607,13 +1771,15 @@ func (cm *CostModel) ComputeCostDataRange(cli prometheusClient.Client, clientset
|
|
|
NodeName: c.NodeName,
|
|
NodeName: c.NodeName,
|
|
|
NodeData: node,
|
|
NodeData: node,
|
|
|
Namespace: c.Namespace,
|
|
Namespace: c.Namespace,
|
|
|
|
|
+ Services: podServices,
|
|
|
|
|
+ Deployments: podDeployments,
|
|
|
RAMReq: RAMReqV,
|
|
RAMReq: RAMReqV,
|
|
|
RAMUsed: RAMUsedV,
|
|
RAMUsed: RAMUsedV,
|
|
|
CPUReq: CPUReqV,
|
|
CPUReq: CPUReqV,
|
|
|
CPUUsed: CPUUsedV,
|
|
CPUUsed: CPUUsedV,
|
|
|
GPUReq: GPUReqV,
|
|
GPUReq: GPUReqV,
|
|
|
- Labels: namespacelabels,
|
|
|
|
|
- NamespaceLabels: namespacelabels,
|
|
|
|
|
|
|
+ Labels: pLabels,
|
|
|
|
|
+ NamespaceLabels: namespaceLabels,
|
|
|
PVCData: podPVs,
|
|
PVCData: podPVs,
|
|
|
NetworkData: podNetCosts,
|
|
NetworkData: podNetCosts,
|
|
|
ClusterID: c.ClusterID,
|
|
ClusterID: c.ClusterID,
|
|
@@ -1678,6 +1844,14 @@ func appendNamespaceLabels(nsLabels map[string]map[string]string, labels map[str
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func appendLabelsList(mainLabels map[string]map[string][]string, labels map[string]map[string][]string) {
|
|
|
|
|
+ for k, v := range labels {
|
|
|
|
|
+ if _, ok := mainLabels[k]; !ok {
|
|
|
|
|
+ mainLabels[k] = v
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func getNamespaceLabels(cache ClusterCache, clusterID string) (map[string]map[string]string, error) {
|
|
func getNamespaceLabels(cache ClusterCache, clusterID string) (map[string]map[string]string, error) {
|
|
|
nsToLabels := make(map[string]map[string]string)
|
|
nsToLabels := make(map[string]map[string]string)
|
|
|
nss := cache.GetAllNamespaces()
|
|
nss := cache.GetAllNamespaces()
|
|
@@ -2203,6 +2377,24 @@ func newContainerMetricFromPrometheus(metrics map[string]interface{}, defaultClu
|
|
|
}, nil
|
|
}, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+type KeyTuple struct {
|
|
|
|
|
+ Namespace string
|
|
|
|
|
+ Key string
|
|
|
|
|
+ ClusterID string
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func NewKeyTuple(key string) (*KeyTuple, error) {
|
|
|
|
|
+ r := strings.Split(key, ",")
|
|
|
|
|
+ if len(r) != 3 {
|
|
|
|
|
+ return nil, fmt.Errorf("NewKeyTuple() Provided key not containing exactly 3 components.")
|
|
|
|
|
+ }
|
|
|
|
|
+ return &KeyTuple{
|
|
|
|
|
+ Namespace: r[0],
|
|
|
|
|
+ Key: r[1],
|
|
|
|
|
+ ClusterID: r[2],
|
|
|
|
|
+ }, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func GetContainerMetricVector(qr interface{}, normalize bool, normalizationValue float64, defaultClusterID string) (map[string][]*Vector, error) {
|
|
func GetContainerMetricVector(qr interface{}, normalize bool, normalizationValue float64, defaultClusterID string) (map[string][]*Vector, error) {
|
|
|
data, ok := qr.(map[string]interface{})["data"]
|
|
data, ok := qr.(map[string]interface{})["data"]
|
|
|
if !ok {
|
|
if !ok {
|