예제 #1
0
func (m *MetricStorage) getNodeMetrics(node string) *metrics.NodeMetrics {
	batch := m.metricSink.GetLatestDataBatch()
	if batch == nil {
		return nil
	}

	ms, found := batch.MetricSets[core.NodeKey(node)]
	if !found {
		return nil
	}

	usage, err := util.ParseResourceList(ms)
	if err != nil {
		return nil
	}

	return &metrics.NodeMetrics{
		ObjectMeta: api.ObjectMeta{
			Name:              node,
			CreationTimestamp: unversioned.NewTime(time.Now()),
		},
		Timestamp: unversioned.NewTime(batch.Timestamp),
		Window:    unversioned.Duration{Duration: time.Minute},
		Usage:     usage,
	}
}
예제 #2
0
func (this *NodeAutoscalingEnricher) Process(batch *core.DataBatch) (*core.DataBatch, error) {
	nodes, err := this.nodeLister.List()
	if err != nil {
		return nil, err
	}
	for _, node := range nodes.Items {
		if metricSet, found := batch.MetricSets[core.NodeKey(node.Name)]; found {
			metricSet.Labels[core.LabelLabels.Key] = util.LabelsToString(node.Labels, ",")
			availableCpu, _ := node.Status.Capacity[kube_api.ResourceCPU]
			availableMem, _ := node.Status.Capacity[kube_api.ResourceMemory]

			cpuRequested := getInt(metricSet, &core.MetricCpuRequest)
			cpuUsed := getInt(metricSet, &core.MetricCpuUsageRate)
			memRequested := getInt(metricSet, &core.MetricMemoryRequest)
			memUsed := getInt(metricSet, &core.MetricMemoryUsage)

			if availableCpu.MilliValue() != 0 {
				setFloat(metricSet, &core.MetricNodeCpuUtilization, float32(cpuUsed)/float32(availableCpu.MilliValue()))
				setFloat(metricSet, &core.MetricNodeCpuReservation, float32(cpuRequested)/float32(availableCpu.MilliValue()))
				setFloat(metricSet, &core.MetricNodeCpuCapacity, float32(availableCpu.MilliValue()))
			}

			if availableMem.Value() != 0 {
				setFloat(metricSet, &core.MetricNodeMemoryUtilization, float32(memUsed)/float32(availableMem.Value()))
				setFloat(metricSet, &core.MetricNodeMemoryReservation, float32(memRequested)/float32(availableMem.Value()))
				setFloat(metricSet, &core.MetricNodeMemoryCapacity, float32(availableMem.Value()))
			}
		}
	}
	return batch, nil
}
예제 #3
0
func (a *Api) getNodeMetrics(node string) *v1alpha1.NodeMetrics {
	batch := a.metricSink.GetLatestDataBatch()
	if batch == nil {
		return nil
	}

	ms, found := batch.MetricSets[core.NodeKey(node)]
	if !found {
		return nil
	}

	usage, err := parseResourceList(ms)
	if err != nil {
		return nil
	}

	return &v1alpha1.NodeMetrics{
		ObjectMeta: kube_v1.ObjectMeta{
			Name:              node,
			CreationTimestamp: kube_unversioned.NewTime(time.Now()),
		},
		Timestamp: kube_unversioned.NewTime(batch.Timestamp),
		Window:    kube_unversioned.Duration{Duration: time.Minute},
		Usage:     usage,
	}
}
예제 #4
0
func (this *NodeAggregator) Process(batch *core.DataBatch) (*core.DataBatch, error) {
	for key, metricSet := range batch.MetricSets {
		if metricSetType, found := metricSet.Labels[core.LabelMetricSetType.Key]; found && metricSetType == core.MetricSetTypePod {
			// Aggregating pods
			nodeName, found := metricSet.Labels[core.LabelNodename.Key]
			if nodeName == "" {
				glog.V(8).Infof("Skipping pod %s: no node info", key)
				continue
			}
			if found {
				nodeKey := core.NodeKey(nodeName)
				node, found := batch.MetricSets[nodeKey]
				if !found {
					glog.Warningf("Failed to find node: %s", nodeKey)
				} else if err := aggregate(metricSet, node, this.MetricsToAggregate); err != nil {
					return nil, err
				}
			} else {
				glog.Errorf("No node info in pod %s: %v", key, metricSet.Labels)
			}
		}
	}
	return batch, nil
}
예제 #5
0
// nodeMetrics returns a metric timeseries for a metric of the Node entity.
func (a *Api) nodeMetrics(request *restful.Request, response *restful.Response) {
	a.processMetricRequest(core.NodeKey(request.PathParameter("node-name")),
		request, response)
}
예제 #6
0
func TestDecodeSummaryMetrics(t *testing.T) {
	ms := testingSummaryMetricsSource()
	summary := stats.Summary{
		Node: stats.NodeStats{
			NodeName:  nodeInfo.NodeName,
			StartTime: unversioned.NewTime(startTime),
			CPU:       genTestSummaryCPU(seedNode),
			Memory:    genTestSummaryMemory(seedNode),
			Network:   genTestSummaryNetwork(seedNode),
			SystemContainers: []stats.ContainerStats{
				genTestSummaryContainer(stats.SystemContainerKubelet, seedKubelet),
				genTestSummaryContainer(stats.SystemContainerRuntime, seedRuntime),
				genTestSummaryContainer(stats.SystemContainerMisc, seedMisc),
			},
			Fs: genTestSummaryFsStats(seedNode),
		},
		Pods: []stats.PodStats{{
			PodRef: stats.PodReference{
				Name:      pName0,
				Namespace: namespace0,
			},
			StartTime: unversioned.NewTime(startTime),
			Network:   genTestSummaryNetwork(seedPod0),
			Containers: []stats.ContainerStats{
				genTestSummaryContainer(cName00, seedPod0Container0),
				genTestSummaryContainer(cName01, seedPod0Container1),
			},
		}, {
			PodRef: stats.PodReference{
				Name:      pName1,
				Namespace: namespace0,
			},
			StartTime: unversioned.NewTime(startTime),
			Network:   genTestSummaryNetwork(seedPod1),
			Containers: []stats.ContainerStats{
				genTestSummaryContainer(cName10, seedPod1Container),
			},
			VolumeStats: []stats.VolumeStats{{
				Name:    "A",
				FsStats: *genTestSummaryFsStats(seedPod1),
			}, {
				Name:    "B",
				FsStats: *genTestSummaryFsStats(seedPod1),
			}},
		}, {
			PodRef: stats.PodReference{
				Name:      pName2,
				Namespace: namespace1,
			},
			StartTime: unversioned.NewTime(startTime),
			Network:   genTestSummaryNetwork(seedPod2),
			Containers: []stats.ContainerStats{
				genTestSummaryContainer(cName20, seedPod2Container),
			},
		}},
	}

	containerFs := []string{"/", "logs"}
	expectations := []struct {
		key     string
		setType string
		seed    int64
		cpu     bool
		memory  bool
		network bool
		fs      []string
	}{{
		key:     core.NodeKey(nodeInfo.NodeName),
		setType: core.MetricSetTypeNode,
		seed:    seedNode,
		cpu:     true,
		memory:  true,
		network: true,
		fs:      []string{"/"},
	}, {
		key:     core.NodeContainerKey(nodeInfo.NodeName, "kubelet"),
		setType: core.MetricSetTypeSystemContainer,
		seed:    seedKubelet,
		cpu:     true,
		memory:  true,
	}, {
		key:     core.NodeContainerKey(nodeInfo.NodeName, "docker-daemon"),
		setType: core.MetricSetTypeSystemContainer,
		seed:    seedRuntime,
		cpu:     true,
		memory:  true,
	}, {
		key:     core.NodeContainerKey(nodeInfo.NodeName, "system"),
		setType: core.MetricSetTypeSystemContainer,
		seed:    seedMisc,
		cpu:     true,
		memory:  true,
	}, {
		key:     core.PodKey(namespace0, pName0),
		setType: core.MetricSetTypePod,
		seed:    seedPod0,
		network: true,
	}, {
		key:     core.PodKey(namespace0, pName1),
		setType: core.MetricSetTypePod,
		seed:    seedPod1,
		network: true,
		fs:      []string{"Volume:A", "Volume:B"},
	}, {
		key:     core.PodKey(namespace1, pName2),
		setType: core.MetricSetTypePod,
		seed:    seedPod2,
		network: true,
	}, {
		key:     core.PodContainerKey(namespace0, pName0, cName00),
		setType: core.MetricSetTypePodContainer,
		seed:    seedPod0Container0,
		cpu:     true,
		memory:  true,
		fs:      containerFs,
	}, {
		key:     core.PodContainerKey(namespace0, pName0, cName01),
		setType: core.MetricSetTypePodContainer,
		seed:    seedPod0Container1,
		cpu:     true,
		memory:  true,
		fs:      containerFs,
	}, {
		key:     core.PodContainerKey(namespace0, pName1, cName10),
		setType: core.MetricSetTypePodContainer,
		seed:    seedPod1Container,
		cpu:     true,
		memory:  true,
		fs:      containerFs,
	}, {
		key:     core.PodContainerKey(namespace1, pName2, cName20),
		setType: core.MetricSetTypePodContainer,
		seed:    seedPod2Container,
		cpu:     true,
		memory:  true,
		fs:      containerFs,
	}}

	metrics := ms.decodeSummary(&summary)
	for _, e := range expectations {
		m, ok := metrics[e.key]
		if !assert.True(t, ok, "missing metric %q", e.key) {
			continue
		}
		assert.Equal(t, m.Labels[core.LabelMetricSetType.Key], e.setType, e.key)
		assert.Equal(t, m.CreateTime, startTime, e.key)
		assert.Equal(t, m.ScrapeTime, scrapeTime, e.key)
		if e.cpu {
			checkIntMetric(t, m, e.key, core.MetricCpuUsage, e.seed+offsetCPUUsageCoreSeconds)
		}
		if e.memory {
			checkIntMetric(t, m, e.key, core.MetricMemoryUsage, e.seed+offsetMemUsageBytes)
			checkIntMetric(t, m, e.key, core.MetricMemoryWorkingSet, e.seed+offsetMemWorkingSetBytes)
			checkIntMetric(t, m, e.key, core.MetricMemoryPageFaults, e.seed+offsetMemPageFaults)
			checkIntMetric(t, m, e.key, core.MetricMemoryMajorPageFaults, e.seed+offsetMemMajorPageFaults)
		}
		if e.network {
			checkIntMetric(t, m, e.key, core.MetricNetworkRx, e.seed+offsetNetRxBytes)
			checkIntMetric(t, m, e.key, core.MetricNetworkRxErrors, e.seed+offsetNetRxErrors)
			checkIntMetric(t, m, e.key, core.MetricNetworkTx, e.seed+offsetNetTxBytes)
			checkIntMetric(t, m, e.key, core.MetricNetworkTxErrors, e.seed+offsetNetTxErrors)
		}
		for _, label := range e.fs {
			checkFsMetric(t, m, e.key, label, core.MetricFilesystemAvailable, e.seed+offsetFsAvailable)
			checkFsMetric(t, m, e.key, label, core.MetricFilesystemLimit, e.seed+offsetFsCapacity)
			checkFsMetric(t, m, e.key, label, core.MetricFilesystemUsage, e.seed+offsetFsUsed)
		}
		delete(metrics, e.key)
	}

	for k, v := range metrics {
		assert.Fail(t, "unexpected metric", "%q: %+v", k, v)
	}
}
예제 #7
0
func TestNodeAggregate(t *testing.T) {
	batch := core.DataBatch{
		Timestamp: time.Now(),
		MetricSets: map[string]*core.MetricSet{
			core.PodKey("ns1", "pod1"): {
				Labels: map[string]string{
					core.LabelMetricSetType.Key: core.MetricSetTypePod,
					core.LabelNamespaceName.Key: "ns1",
					core.LabelNodename.Key:      "h1",
				},
				MetricValues: map[string]core.MetricValue{
					"m1": {
						ValueType:  core.ValueInt64,
						MetricType: core.MetricGauge,
						IntValue:   10,
					},
					"m2": {
						ValueType:  core.ValueInt64,
						MetricType: core.MetricGauge,
						IntValue:   222,
					},
				},
			},

			core.PodKey("ns1", "pod2"): {
				Labels: map[string]string{
					core.LabelMetricSetType.Key: core.MetricSetTypePod,
					core.LabelNamespaceName.Key: "ns1",
					core.LabelNodename.Key:      "h1",
				},
				MetricValues: map[string]core.MetricValue{
					"m1": {
						ValueType:  core.ValueInt64,
						MetricType: core.MetricGauge,
						IntValue:   100,
					},
					"m3": {
						ValueType:  core.ValueInt64,
						MetricType: core.MetricGauge,
						IntValue:   30,
					},
				},
			},

			core.NodeKey("h1"): {
				Labels: map[string]string{
					core.LabelMetricSetType.Key: core.MetricSetTypeNode,
					core.LabelNodename.Key:      "h1",
				},
				MetricValues: map[string]core.MetricValue{},
			},
		},
	}
	processor := NodeAggregator{
		MetricsToAggregate: []string{"m1", "m3"},
	}
	result, err := processor.Process(&batch)
	assert.NoError(t, err)
	node, found := result.MetricSets[core.NodeKey("h1")]
	assert.True(t, found)

	m1, found := node.MetricValues["m1"]
	assert.True(t, found)
	assert.Equal(t, 110, m1.IntValue)

	m3, found := node.MetricValues["m3"]
	assert.True(t, found)
	assert.Equal(t, 30, m3.IntValue)
}