mirror of https://github.com/k3s-io/k3s
Merge pull request #52144 from andyxning/fix_network_value_for_stats_summary
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. fix network value for stats summary for multiple network interfaces This PR is part of [Heapster #1788](https://github.com/kubernetes/heapster/pull/1788). The original reason is when there are more than one none `lo`, `docker0`, `veth` network interfaces instead of just one `eth0`, the network interface value is only partial and does not correct. For now, summary stats api only gets the eth0 network interface values. The original issues about this can be find in [Heapster #1058](https://github.com/kubernetes/heapster/issues/1058) and [Cadvisor #1593](https://github.com/google/cadvisor/issues/1593). ```release-note Fix stats summary network value when multiple network interfaces are available. ``` /cc @DirectXMan12 @piosz @xiangpengzhao @vishh @timstclairpull/6/head
commit
8226973ae8
|
@ -141,10 +141,10 @@ type PodReference struct {
|
|||
UID string `json:"uid"`
|
||||
}
|
||||
|
||||
// NetworkStats contains data about network resources.
|
||||
type NetworkStats struct {
|
||||
// The time at which these stats were updated.
|
||||
Time metav1.Time `json:"time"`
|
||||
// InterfaceStats contains resource value data about interface.
|
||||
type InterfaceStats struct {
|
||||
// The name of the interface
|
||||
Name string `json:"name"`
|
||||
// Cumulative count of bytes received.
|
||||
// +optional
|
||||
RxBytes *uint64 `json:"rxBytes,omitempty"`
|
||||
|
@ -159,6 +159,17 @@ type NetworkStats struct {
|
|||
TxErrors *uint64 `json:"txErrors,omitempty"`
|
||||
}
|
||||
|
||||
// NetworkStats contains data about network resources.
|
||||
type NetworkStats struct {
|
||||
// The time at which these stats were updated.
|
||||
Time metav1.Time `json:"time"`
|
||||
|
||||
// Stats for the default interface, if found
|
||||
InterfaceStats `json:",inline"`
|
||||
|
||||
Interfaces []InterfaceStats `json:"interfaces,omitempty"`
|
||||
}
|
||||
|
||||
// CPUStats contains data about CPU usage.
|
||||
type CPUStats struct {
|
||||
// The time at which these stats were updated.
|
||||
|
|
|
@ -138,19 +138,29 @@ func cadvisorInfoToNetworkStats(name string, info *cadvisorapiv2.ContainerInfo)
|
|||
if !found {
|
||||
return nil
|
||||
}
|
||||
for _, inter := range cstat.Network.Interfaces {
|
||||
if inter.Name == network.DefaultInterfaceName {
|
||||
return &statsapi.NetworkStats{
|
||||
Time: metav1.NewTime(cstat.Timestamp),
|
||||
RxBytes: &inter.RxBytes,
|
||||
RxErrors: &inter.RxErrors,
|
||||
TxBytes: &inter.TxBytes,
|
||||
TxErrors: &inter.TxErrors,
|
||||
}
|
||||
}
|
||||
|
||||
iStats := statsapi.NetworkStats{
|
||||
Time: metav1.NewTime(cstat.Timestamp),
|
||||
}
|
||||
glog.V(4).Infof("Missing default interface %q for %s", network.DefaultInterfaceName, name)
|
||||
return nil
|
||||
|
||||
for i := range cstat.Network.Interfaces {
|
||||
inter := cstat.Network.Interfaces[i]
|
||||
iStat := statsapi.InterfaceStats{
|
||||
Name: inter.Name,
|
||||
RxBytes: &inter.RxBytes,
|
||||
RxErrors: &inter.RxErrors,
|
||||
TxBytes: &inter.TxBytes,
|
||||
TxErrors: &inter.TxErrors,
|
||||
}
|
||||
|
||||
if inter.Name == network.DefaultInterfaceName {
|
||||
iStats.InterfaceStats = iStat
|
||||
}
|
||||
|
||||
iStats.Interfaces = append(iStats.Interfaces, iStat)
|
||||
}
|
||||
|
||||
return &iStats
|
||||
}
|
||||
|
||||
// cadvisorInfoToUserDefinedMetrics returns the statsapi.UserDefinedMetric
|
||||
|
|
|
@ -531,10 +531,26 @@ func testTime(base time.Time, seed int) time.Time {
|
|||
func checkNetworkStats(t *testing.T, label string, seed int, stats *statsapi.NetworkStats) {
|
||||
assert.NotNil(t, stats)
|
||||
assert.EqualValues(t, testTime(timestamp, seed).Unix(), stats.Time.Time.Unix(), label+".Net.Time")
|
||||
assert.EqualValues(t, "eth0", stats.Name, "default interface name is not eth0")
|
||||
assert.EqualValues(t, seed+offsetNetRxBytes, *stats.RxBytes, label+".Net.RxBytes")
|
||||
assert.EqualValues(t, seed+offsetNetRxErrors, *stats.RxErrors, label+".Net.RxErrors")
|
||||
assert.EqualValues(t, seed+offsetNetTxBytes, *stats.TxBytes, label+".Net.TxBytes")
|
||||
assert.EqualValues(t, seed+offsetNetTxErrors, *stats.TxErrors, label+".Net.TxErrors")
|
||||
|
||||
assert.EqualValues(t, 2, len(stats.Interfaces), "network interfaces should contain 2 elements")
|
||||
|
||||
assert.EqualValues(t, "eth0", stats.Interfaces[0].Name, "default interface name is ont eth0")
|
||||
assert.EqualValues(t, seed+offsetNetRxBytes, *stats.Interfaces[0].RxBytes, label+".Net.TxErrors")
|
||||
assert.EqualValues(t, seed+offsetNetRxErrors, *stats.Interfaces[0].RxErrors, label+".Net.TxErrors")
|
||||
assert.EqualValues(t, seed+offsetNetTxBytes, *stats.Interfaces[0].TxBytes, label+".Net.TxErrors")
|
||||
assert.EqualValues(t, seed+offsetNetTxErrors, *stats.Interfaces[0].TxErrors, label+".Net.TxErrors")
|
||||
|
||||
assert.EqualValues(t, "cbr0", stats.Interfaces[1].Name, "cbr0 interface name is ont cbr0")
|
||||
assert.EqualValues(t, 100, *stats.Interfaces[1].RxBytes, label+".Net.TxErrors")
|
||||
assert.EqualValues(t, 100, *stats.Interfaces[1].RxErrors, label+".Net.TxErrors")
|
||||
assert.EqualValues(t, 100, *stats.Interfaces[1].TxBytes, label+".Net.TxErrors")
|
||||
assert.EqualValues(t, 100, *stats.Interfaces[1].TxErrors, label+".Net.TxErrors")
|
||||
|
||||
}
|
||||
|
||||
func checkCPUStats(t *testing.T, label string, seed int, stats *statsapi.CPUStats) {
|
||||
|
|
|
@ -169,11 +169,15 @@ var _ = framework.KubeDescribe("Summary API", func() {
|
|||
}),
|
||||
}),
|
||||
"Network": ptrMatchAllFields(gstruct.Fields{
|
||||
"Time": recent(maxStatsAge),
|
||||
"RxBytes": bounded(10, 10*framework.Mb),
|
||||
"RxErrors": bounded(0, 1000),
|
||||
"TxBytes": bounded(10, 10*framework.Mb),
|
||||
"TxErrors": bounded(0, 1000),
|
||||
"Time": recent(maxStatsAge),
|
||||
"InterfaceStats": gstruct.MatchAllFields(gstruct.Fields{
|
||||
"Name": Equal("eth0"),
|
||||
"RxBytes": bounded(10, 10*framework.Mb),
|
||||
"RxErrors": bounded(0, 1000),
|
||||
"TxBytes": bounded(10, 10*framework.Mb),
|
||||
"TxErrors": bounded(0, 1000),
|
||||
}),
|
||||
"Interfaces": Not(BeNil()),
|
||||
}),
|
||||
"CPU": ptrMatchAllFields(gstruct.Fields{
|
||||
"Time": recent(maxStatsAge),
|
||||
|
@ -236,13 +240,17 @@ var _ = framework.KubeDescribe("Summary API", func() {
|
|||
"MajorPageFaults": bounded(0, 100000),
|
||||
}),
|
||||
// TODO(#28407): Handle non-eth0 network interface names.
|
||||
"Network": Or(BeNil(), ptrMatchAllFields(gstruct.Fields{
|
||||
"Time": recent(maxStatsAge),
|
||||
"RxBytes": bounded(1*framework.Mb, 100*framework.Gb),
|
||||
"RxErrors": bounded(0, 100000),
|
||||
"TxBytes": bounded(10*framework.Kb, 10*framework.Gb),
|
||||
"TxErrors": bounded(0, 100000),
|
||||
})),
|
||||
"Network": ptrMatchAllFields(gstruct.Fields{
|
||||
"Time": recent(maxStatsAge),
|
||||
"InterfaceStats": gstruct.MatchAllFields(gstruct.Fields{
|
||||
"Name": Or(BeEmpty(), Equal("eth0")),
|
||||
"RxBytes": Or(BeNil(), bounded(1*framework.Mb, 100*framework.Gb)),
|
||||
"RxErrors": Or(BeNil(), bounded(0, 100000)),
|
||||
"TxBytes": Or(BeNil(), bounded(10*framework.Kb, 10*framework.Gb)),
|
||||
"TxErrors": Or(BeNil(), bounded(0, 100000)),
|
||||
}),
|
||||
"Interfaces": Not(BeNil()),
|
||||
}),
|
||||
"Fs": ptrMatchAllFields(gstruct.Fields{
|
||||
"Time": recent(maxStatsAge),
|
||||
"AvailableBytes": fsCapacityBounds,
|
||||
|
|
Loading…
Reference in New Issue