Parcourir la source

Merge pull request #185 from kubecost/Bolt-thanos-remote

Thanos Remote Endpoint
Matt Bolt il y a 6 ans
Parent
commit
cf5c3fc13c
2 fichiers modifiés avec 61 ajouts et 4 suppressions
  1. 8 2
      costmodel/costmodel.go
  2. 53 2
      costmodel/router.go

+ 8 - 2
costmodel/costmodel.go

@@ -38,8 +38,10 @@ const (
 	epConfig          = apiPrefix + "/status/config"
 	epFlags           = apiPrefix + "/status/flags"
 
-	clusterIDKey  = "CLUSTER_ID"
-	remoteEnabled = "REMOTE_WRITE_ENABLED"
+	clusterIDKey   = "CLUSTER_ID"
+	remoteEnabled  = "REMOTE_WRITE_ENABLED"
+	thanosEnabled  = "THANOS_ENABLED"
+	thanosQueryUrl = "THANOS_QUERY_URL"
 )
 
 type CostModel struct {
@@ -1880,6 +1882,10 @@ func Query(cli prometheusClient.Client, query string) (interface{}, error) {
 		klog.V(3).Infof("%s", w)
 	}
 	if err != nil {
+		if resp == nil {
+			return nil, fmt.Errorf("Error %s fetching query %s", err.Error(), query)
+		}
+
 		return nil, fmt.Errorf("%s Error %s fetching query %s", resp.StatusCode, err.Error(), query)
 	}
 	var toReturn interface{}

+ 53 - 2
costmodel/router.go

@@ -42,6 +42,7 @@ var A Accesses
 
 type Accesses struct {
 	PrometheusClient              prometheusClient.Client
+	ThanosClient                  prometheusClient.Client
 	KubeClientSet                 kubernetes.Interface
 	Cloud                         costAnalyzerCloud.Provider
 	CPUPriceRecorder              *prometheus.GaugeVec
@@ -340,7 +341,15 @@ func (a *Accesses) AggregateCostModel(w http.ResponseWriter, r *http.Request, ps
 	}
 	klog.Infof("REMOTE ENABLED: %t", remoteEnabled)
 
-	data, err := a.Model.ComputeCostDataRange(a.PrometheusClient, a.KubeClientSet, a.Cloud, start, end, "1h", namespace, cluster, remoteEnabled)
+	// Use Thanos Client if it exists (enabled) and remote flag set
+	var pClient prometheusClient.Client
+	if remote != "false" && a.ThanosClient != nil {
+		pClient = a.ThanosClient
+	} else {
+		pClient = a.PrometheusClient
+	}
+
+	data, err := a.Model.ComputeCostDataRange(pClient, a.KubeClientSet, a.Cloud, start, end, "1h", namespace, cluster, remoteEnabled)
 	if err != nil {
 		w.Write(wrapData(nil, err))
 		return
@@ -411,7 +420,16 @@ func (a *Accesses) CostDataModelRange(w http.ResponseWriter, r *http.Request, ps
 	if remoteAvailable == "true" && remote != "false" {
 		remoteEnabled = true
 	}
-	data, err := a.Model.ComputeCostDataRange(a.PrometheusClient, a.KubeClientSet, a.Cloud, start, end, window, namespace, cluster, remoteEnabled)
+
+	// Use Thanos Client if it exists (enabled) and remote flag set
+	var pClient prometheusClient.Client
+	if remote != "false" && a.ThanosClient != nil {
+		pClient = a.ThanosClient
+	} else {
+		pClient = a.PrometheusClient
+	}
+
+	data, err := a.Model.ComputeCostDataRange(pClient, a.KubeClientSet, a.Cloud, start, end, window, namespace, cluster, remoteEnabled)
 	if err != nil {
 		w.Write(wrapData(nil, err))
 	}
@@ -955,6 +973,39 @@ func init() {
 		}
 	}
 
+	// Thanos Client
+	if os.Getenv(thanosEnabled) == "true" {
+		thanosUrl := os.Getenv(thanosQueryUrl)
+		if thanosUrl != "" {
+			var thanosRT http.RoundTripper = &http.Transport{
+				Proxy: http.ProxyFromEnvironment,
+				DialContext: (&net.Dialer{
+					Timeout:   120 * time.Second,
+					KeepAlive: 120 * time.Second,
+				}).DialContext,
+				TLSHandshakeTimeout: 10 * time.Second,
+			}
+
+			thanosConfig := prometheusClient.Config{
+				Address:      thanosUrl,
+				RoundTripper: thanosRT,
+			}
+			thanosCli, _ := prometheusClient.NewClient(thanosConfig)
+
+			_, err = ValidatePrometheus(thanosCli)
+			if err != nil {
+				klog.Fatalf("Failed to query Thanos at %s. Error: %s.", thanosUrl, err.Error())
+			} else {
+				klog.V(1).Info("Success: retrieved the 'up' query against Thanos at: " + thanosUrl)
+
+				A.ThanosClient = thanosCli
+			}
+
+		} else {
+			klog.Infof("Error resolving environment variable: $%s", thanosQueryUrl)
+		}
+	}
+
 	err = A.Cloud.DownloadPricingData()
 	if err != nil {
 		klog.V(1).Info("Failed to download pricing data: " + err.Error())