|
@@ -0,0 +1,277 @@
|
|
|
+
|
|
|
+Copyright 2016 The Kubernetes Authors.
|
|
|
+
|
|
|
+Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
+you may not use this file except in compliance with the License.
|
|
|
+You may obtain a copy of the License at
|
|
|
+
|
|
|
+ http:
|
|
|
+
|
|
|
+Unless required by applicable law or agreed to in writing, software
|
|
|
+distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
+See the License for the specific language governing permissions and
|
|
|
+limitations under the License.
|
|
|
+*/
|
|
|
+
|
|
|
+package priorities
|
|
|
+
|
|
|
+import (
|
|
|
+ "encoding/json"
|
|
|
+ "fmt"
|
|
|
+ "strings"
|
|
|
+
|
|
|
+ _ "github.com/go-sql-driver/mysql"
|
|
|
+ client "github.com/influxdata/influxdb1-client/v2"
|
|
|
+ "k8s.io/klog"
|
|
|
+)
|
|
|
+
|
|
|
+var (
|
|
|
+ nodeSelectionPriority = &CustomAllocationPriority{"NodeSelection", nodeSelectionScorer}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ NodeSelectionPriorityMap = nodeSelectionPriority.PriorityMap
|
|
|
+)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+var cores = map[string][]int{
|
|
|
+ "kube-01": []int{},
|
|
|
+ "kube-02": []int{},
|
|
|
+ "kube-03": []int{},
|
|
|
+ "kube-04": []int{},
|
|
|
+ "kube-05": []int{0, 1, 2, 3},
|
|
|
+ "kube-06": []int{12, 13, 14, 15, 16, 17, 18, 19},
|
|
|
+ "kube-07": []int{4, 5, 6, 7, 8, 9, 10, 11, 24, 25, 26, 27, 28, 29, 30, 31},
|
|
|
+ "kube-08": []int{20, 21, 22, 23, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47},
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+type scorerInput struct {
|
|
|
+ metricName string
|
|
|
+ metrics map[string]float64
|
|
|
+}
|
|
|
+
|
|
|
+func OneScorer(si scorerInput) float64 {
|
|
|
+ return si.metrics[si.metricName]
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+func calculateWeightedAverageCores(response *client.Response,
|
|
|
+ numberOfRows, numberOfMetrics, numberOfCores int) (map[string]float64, error) {
|
|
|
+
|
|
|
+ metrics := make(map[string]float64, numberOfMetrics)
|
|
|
+ rows := response.Results[0].Series[0]
|
|
|
+ for i := 1; i < len(rows.Columns); i++ {
|
|
|
+ for j := 0; j < numberOfRows; j++ {
|
|
|
+ avg := 0.0
|
|
|
+ for k := 0; k < numberOfCores; k++ {
|
|
|
+ val, err := rows.Values[j*numberOfCores+k][i].(json.Number).Float64()
|
|
|
+ if err != nil {
|
|
|
+ klog.Infof("Error while calculating %v", rows.Columns[i])
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ avg += val
|
|
|
+ }
|
|
|
+ metrics[rows.Columns[i]] += avg * float64(numberOfRows-j)
|
|
|
+ }
|
|
|
+ metrics[rows.Columns[i]] = metrics[rows.Columns[i]] / float64((numberOfRows * (numberOfRows + 1) / 2))
|
|
|
+ klog.Infof("%v : %v", rows.Columns[i], metrics[rows.Columns[i]])
|
|
|
+ }
|
|
|
+
|
|
|
+ return metrics, nil
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+func queryInfluxDbCores(metrics []string, uuid string, socket,
|
|
|
+ time int, cfg Config, c client.Client, cores []int) (map[string]float64, error) {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ numberOfRows := int(float32(time) / cfg.MonitoringSpecs.TimeInterval)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ numberOfRows *= len(cores)
|
|
|
+
|
|
|
+ columns := strings.Join(metrics, ", ")
|
|
|
+
|
|
|
+
|
|
|
+ var coresPart strings.Builder
|
|
|
+ fmt.Fprintf(&coresPart, "core_id='%d'", cores[0])
|
|
|
+ for i := 1; i < len(cores); i++ {
|
|
|
+ fmt.Fprintf(&coresPart, " or core_id='%d'", cores[i])
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ var command strings.Builder
|
|
|
+ fmt.Fprintf(&command, "SELECT %s from core_metrics where uuid = '%s' and socket_id='%d' and %s order by time desc limit %d", columns, uuid, socket, coresPart.String(), numberOfRows)
|
|
|
+ q := client.NewQuery(command.String(), cfg.Database.Name, "")
|
|
|
+ response, err := c.Query(q)
|
|
|
+ if err != nil {
|
|
|
+ klog.Infof("Error while executing the query: %v", err.Error())
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ return calculateWeightedAverageCores(response, numberOfRows, len(metrics), len(cores))
|
|
|
+}
|
|
|
+
|
|
|
+func nodeSelectionScorer(nodeName string) (float64, error) {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ var cfg Config
|
|
|
+ err := readFile(&cfg, "/etc/kubernetes/scheduler-monitoringDB.yaml")
|
|
|
+ if err != nil {
|
|
|
+ return 0, err
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ -------------------------------------*/
|
|
|
+
|
|
|
+
|
|
|
+ c, err := connectToInfluxDB(cfg)
|
|
|
+ if err != nil {
|
|
|
+ return 0, err
|
|
|
+ }
|
|
|
+
|
|
|
+ defer c.Close()
|
|
|
+
|
|
|
+
|
|
|
+ curr_uuid, ok := nodes[nodeName]
|
|
|
+ socket, _ := sockets[nodeName]
|
|
|
+ cores, _ := cores[nodeName]
|
|
|
+ if ok {
|
|
|
+
|
|
|
+
|
|
|
+ results, err := queryInfluxDbCores([]string{"c6res"}, curr_uuid, socket, 20, cfg, c, cores)
|
|
|
+ if err != nil {
|
|
|
+ klog.Infof("Error in querying or calculating average: %v", err.Error())
|
|
|
+ return 0, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ res := calculateScore(results, OneScorer)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ klog.Infof("Node name %s, has score %v\n", nodeName, res)
|
|
|
+ return res, nil
|
|
|
+ } else {
|
|
|
+ klog.Infof("Error finding the uuid: %v", ok)
|
|
|
+ return 0, nil
|
|
|
+ }
|
|
|
+}
|