...

Source file src/k8s.io/kubernetes/pkg/kubelet/server/stats/summary_test.go

Documentation: k8s.io/kubernetes/pkg/kubelet/server/stats

     1  //go:build !windows
     2  // +build !windows
     3  
     4  /*
     5  Copyright 2016 The Kubernetes Authors.
     6  
     7  Licensed under the Apache License, Version 2.0 (the "License");
     8  you may not use this file except in compliance with the License.
     9  You may obtain a copy of the License at
    10  
    11      http://www.apache.org/licenses/LICENSE-2.0
    12  
    13  Unless required by applicable law or agreed to in writing, software
    14  distributed under the License is distributed on an "AS IS" BASIS,
    15  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  See the License for the specific language governing permissions and
    17  limitations under the License.
    18  */
    19  
    20  package stats
    21  
    22  import (
    23  	"context"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/golang/mock/gomock"
    28  	fuzz "github.com/google/gofuzz"
    29  	"github.com/stretchr/testify/assert"
    30  
    31  	v1 "k8s.io/api/core/v1"
    32  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    33  	statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
    34  	"k8s.io/kubernetes/pkg/kubelet/cm"
    35  	statstest "k8s.io/kubernetes/pkg/kubelet/server/stats/testing"
    36  )
    37  
    38  var (
    39  	imageFsStats = getFsStats()
    40  	rootFsStats  = getFsStats()
    41  	node         = &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "test-node"}}
    42  	nodeConfig   = cm.NodeConfig{
    43  		RuntimeCgroupsName: "/runtime",
    44  		SystemCgroupsName:  "/misc",
    45  		KubeletCgroupsName: "/kubelet",
    46  	}
    47  	cgroupRoot  = "/kubepods"
    48  	rlimitStats = getRlimitStats()
    49  )
    50  
    51  func TestSummaryProviderGetStatsNoSplitFileSystem(t *testing.T) {
    52  	ctx := context.Background()
    53  	assert := assert.New(t)
    54  
    55  	podStats := []statsapi.PodStats{
    56  		{
    57  			PodRef:      statsapi.PodReference{Name: "test-pod", Namespace: "test-namespace", UID: "UID_test-pod"},
    58  			StartTime:   metav1.NewTime(time.Now()),
    59  			Containers:  []statsapi.ContainerStats{*getContainerStats()},
    60  			Network:     getNetworkStats(),
    61  			VolumeStats: []statsapi.VolumeStats{*getVolumeStats()},
    62  		},
    63  	}
    64  	cgroupStatsMap := map[string]struct {
    65  		cs *statsapi.ContainerStats
    66  		ns *statsapi.NetworkStats
    67  	}{
    68  		"/":        {cs: getContainerStats(), ns: getNetworkStats()},
    69  		"/runtime": {cs: getContainerStats(), ns: getNetworkStats()},
    70  		"/misc":    {cs: getContainerStats(), ns: getNetworkStats()},
    71  		"/kubelet": {cs: getContainerStats(), ns: getNetworkStats()},
    72  		"/pods":    {cs: getContainerStats(), ns: getNetworkStats()},
    73  	}
    74  
    75  	mockCtrl := gomock.NewController(t)
    76  	defer mockCtrl.Finish()
    77  	mockStatsProvider := statstest.NewMockProvider(mockCtrl)
    78  
    79  	mockStatsProvider.EXPECT().GetNode().Return(node, nil)
    80  	mockStatsProvider.EXPECT().GetNodeConfig().Return(nodeConfig)
    81  	mockStatsProvider.EXPECT().GetPodCgroupRoot().Return(cgroupRoot)
    82  	mockStatsProvider.EXPECT().ListPodStats(ctx).Return(podStats, nil).AnyTimes()
    83  	mockStatsProvider.EXPECT().ListPodStatsAndUpdateCPUNanoCoreUsage(ctx).Return(podStats, nil)
    84  	mockStatsProvider.EXPECT().ImageFsStats(ctx).Return(imageFsStats, imageFsStats, nil)
    85  	mockStatsProvider.EXPECT().RootFsStats().Return(rootFsStats, nil)
    86  	mockStatsProvider.EXPECT().RlimitStats().Return(rlimitStats, nil)
    87  	mockStatsProvider.EXPECT().GetCgroupStats("/", true).Return(cgroupStatsMap["/"].cs, cgroupStatsMap["/"].ns, nil)
    88  	mockStatsProvider.EXPECT().GetCgroupStats("/runtime", false).Return(cgroupStatsMap["/runtime"].cs, cgroupStatsMap["/runtime"].ns, nil)
    89  	mockStatsProvider.EXPECT().GetCgroupStats("/misc", false).Return(cgroupStatsMap["/misc"].cs, cgroupStatsMap["/misc"].ns, nil)
    90  	mockStatsProvider.EXPECT().GetCgroupStats("/kubelet", false).Return(cgroupStatsMap["/kubelet"].cs, cgroupStatsMap["/kubelet"].ns, nil)
    91  	mockStatsProvider.EXPECT().GetCgroupStats("/kubepods", true).Return(cgroupStatsMap["/pods"].cs, cgroupStatsMap["/pods"].ns, nil)
    92  
    93  	kubeletCreationTime := metav1.Now()
    94  	systemBootTime := metav1.Now()
    95  	provider := summaryProviderImpl{kubeletCreationTime: kubeletCreationTime, systemBootTime: systemBootTime, provider: mockStatsProvider}
    96  	summary, err := provider.Get(ctx, true)
    97  	assert.NoError(err)
    98  
    99  	assert.Equal(summary.Node.NodeName, "test-node")
   100  	assert.Equal(summary.Node.StartTime, systemBootTime)
   101  	assert.Equal(summary.Node.CPU, cgroupStatsMap["/"].cs.CPU)
   102  	assert.Equal(summary.Node.Memory, cgroupStatsMap["/"].cs.Memory)
   103  	assert.Equal(summary.Node.Swap, cgroupStatsMap["/"].cs.Swap)
   104  	assert.Equal(summary.Node.Network, cgroupStatsMap["/"].ns)
   105  	assert.Equal(summary.Node.Fs, rootFsStats)
   106  	assert.Equal(summary.Node.Runtime, &statsapi.RuntimeStats{ContainerFs: imageFsStats, ImageFs: imageFsStats})
   107  
   108  	assert.Equal(len(summary.Node.SystemContainers), 4)
   109  	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
   110  		Name:               "kubelet",
   111  		StartTime:          kubeletCreationTime,
   112  		CPU:                cgroupStatsMap["/kubelet"].cs.CPU,
   113  		Memory:             cgroupStatsMap["/kubelet"].cs.Memory,
   114  		Accelerators:       cgroupStatsMap["/kubelet"].cs.Accelerators,
   115  		UserDefinedMetrics: cgroupStatsMap["/kubelet"].cs.UserDefinedMetrics,
   116  		Swap:               cgroupStatsMap["/kubelet"].cs.Swap,
   117  	})
   118  	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
   119  		Name:               "misc",
   120  		StartTime:          cgroupStatsMap["/misc"].cs.StartTime,
   121  		CPU:                cgroupStatsMap["/misc"].cs.CPU,
   122  		Memory:             cgroupStatsMap["/misc"].cs.Memory,
   123  		Accelerators:       cgroupStatsMap["/misc"].cs.Accelerators,
   124  		UserDefinedMetrics: cgroupStatsMap["/misc"].cs.UserDefinedMetrics,
   125  		Swap:               cgroupStatsMap["/misc"].cs.Swap,
   126  	})
   127  	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
   128  		Name:               "runtime",
   129  		StartTime:          cgroupStatsMap["/runtime"].cs.StartTime,
   130  		CPU:                cgroupStatsMap["/runtime"].cs.CPU,
   131  		Memory:             cgroupStatsMap["/runtime"].cs.Memory,
   132  		Accelerators:       cgroupStatsMap["/runtime"].cs.Accelerators,
   133  		UserDefinedMetrics: cgroupStatsMap["/runtime"].cs.UserDefinedMetrics,
   134  		Swap:               cgroupStatsMap["/runtime"].cs.Swap,
   135  	})
   136  	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
   137  		Name:               "pods",
   138  		StartTime:          cgroupStatsMap["/pods"].cs.StartTime,
   139  		CPU:                cgroupStatsMap["/pods"].cs.CPU,
   140  		Memory:             cgroupStatsMap["/pods"].cs.Memory,
   141  		Accelerators:       cgroupStatsMap["/pods"].cs.Accelerators,
   142  		UserDefinedMetrics: cgroupStatsMap["/pods"].cs.UserDefinedMetrics,
   143  		Swap:               cgroupStatsMap["/pods"].cs.Swap,
   144  	})
   145  	assert.Equal(summary.Pods, podStats)
   146  }
   147  
   148  func TestSummaryProviderGetStatsSplitImageFs(t *testing.T) {
   149  	ctx := context.Background()
   150  	assert := assert.New(t)
   151  
   152  	podStats := []statsapi.PodStats{
   153  		{
   154  			PodRef:      statsapi.PodReference{Name: "test-pod", Namespace: "test-namespace", UID: "UID_test-pod"},
   155  			StartTime:   metav1.NewTime(time.Now()),
   156  			Containers:  []statsapi.ContainerStats{*getContainerStats()},
   157  			Network:     getNetworkStats(),
   158  			VolumeStats: []statsapi.VolumeStats{*getVolumeStats()},
   159  		},
   160  	}
   161  	cgroupStatsMap := map[string]struct {
   162  		cs *statsapi.ContainerStats
   163  		ns *statsapi.NetworkStats
   164  	}{
   165  		"/":        {cs: getContainerStats(), ns: getNetworkStats()},
   166  		"/runtime": {cs: getContainerStats(), ns: getNetworkStats()},
   167  		"/misc":    {cs: getContainerStats(), ns: getNetworkStats()},
   168  		"/kubelet": {cs: getContainerStats(), ns: getNetworkStats()},
   169  		"/pods":    {cs: getContainerStats(), ns: getNetworkStats()},
   170  	}
   171  
   172  	mockCtrl := gomock.NewController(t)
   173  	defer mockCtrl.Finish()
   174  	mockStatsProvider := statstest.NewMockProvider(mockCtrl)
   175  
   176  	mockStatsProvider.EXPECT().GetNode().Return(node, nil)
   177  	mockStatsProvider.EXPECT().GetNodeConfig().Return(nodeConfig)
   178  	mockStatsProvider.EXPECT().GetPodCgroupRoot().Return(cgroupRoot)
   179  	mockStatsProvider.EXPECT().ListPodStats(ctx).Return(podStats, nil).AnyTimes()
   180  	mockStatsProvider.EXPECT().ListPodStatsAndUpdateCPUNanoCoreUsage(ctx).Return(podStats, nil)
   181  	mockStatsProvider.EXPECT().RootFsStats().Return(rootFsStats, nil)
   182  	mockStatsProvider.EXPECT().RlimitStats().Return(rlimitStats, nil)
   183  	mockStatsProvider.EXPECT().GetCgroupStats("/", true).Return(cgroupStatsMap["/"].cs, cgroupStatsMap["/"].ns, nil)
   184  	mockStatsProvider.EXPECT().GetCgroupStats("/runtime", false).Return(cgroupStatsMap["/runtime"].cs, cgroupStatsMap["/runtime"].ns, nil)
   185  	mockStatsProvider.EXPECT().GetCgroupStats("/misc", false).Return(cgroupStatsMap["/misc"].cs, cgroupStatsMap["/misc"].ns, nil)
   186  	mockStatsProvider.EXPECT().GetCgroupStats("/kubelet", false).Return(cgroupStatsMap["/kubelet"].cs, cgroupStatsMap["/kubelet"].ns, nil)
   187  	mockStatsProvider.EXPECT().GetCgroupStats("/kubepods", true).Return(cgroupStatsMap["/pods"].cs, cgroupStatsMap["/pods"].ns, nil)
   188  
   189  	mockStatsProvider.EXPECT().ImageFsStats(ctx).Return(imageFsStats, rootFsStats, nil)
   190  
   191  	kubeletCreationTime := metav1.Now()
   192  	systemBootTime := metav1.Now()
   193  	provider := summaryProviderImpl{kubeletCreationTime: kubeletCreationTime, systemBootTime: systemBootTime, provider: mockStatsProvider}
   194  	summary, err := provider.Get(ctx, true)
   195  	assert.NoError(err)
   196  
   197  	assert.Equal(summary.Node.NodeName, "test-node")
   198  	assert.Equal(summary.Node.StartTime, systemBootTime)
   199  	assert.Equal(summary.Node.CPU, cgroupStatsMap["/"].cs.CPU)
   200  	assert.Equal(summary.Node.Memory, cgroupStatsMap["/"].cs.Memory)
   201  	assert.Equal(summary.Node.Swap, cgroupStatsMap["/"].cs.Swap)
   202  	assert.Equal(summary.Node.Network, cgroupStatsMap["/"].ns)
   203  	assert.Equal(summary.Node.Fs, rootFsStats)
   204  	// Since we are a split filesystem we want root filesystem to be container fs and image to be image filesystem
   205  	assert.Equal(summary.Node.Runtime, &statsapi.RuntimeStats{ContainerFs: rootFsStats, ImageFs: imageFsStats})
   206  
   207  	assert.Equal(len(summary.Node.SystemContainers), 4)
   208  	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
   209  		Name:               "kubelet",
   210  		StartTime:          kubeletCreationTime,
   211  		CPU:                cgroupStatsMap["/kubelet"].cs.CPU,
   212  		Memory:             cgroupStatsMap["/kubelet"].cs.Memory,
   213  		Accelerators:       cgroupStatsMap["/kubelet"].cs.Accelerators,
   214  		UserDefinedMetrics: cgroupStatsMap["/kubelet"].cs.UserDefinedMetrics,
   215  		Swap:               cgroupStatsMap["/kubelet"].cs.Swap,
   216  	})
   217  	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
   218  		Name:               "misc",
   219  		StartTime:          cgroupStatsMap["/misc"].cs.StartTime,
   220  		CPU:                cgroupStatsMap["/misc"].cs.CPU,
   221  		Memory:             cgroupStatsMap["/misc"].cs.Memory,
   222  		Accelerators:       cgroupStatsMap["/misc"].cs.Accelerators,
   223  		UserDefinedMetrics: cgroupStatsMap["/misc"].cs.UserDefinedMetrics,
   224  		Swap:               cgroupStatsMap["/misc"].cs.Swap,
   225  	})
   226  	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
   227  		Name:               "runtime",
   228  		StartTime:          cgroupStatsMap["/runtime"].cs.StartTime,
   229  		CPU:                cgroupStatsMap["/runtime"].cs.CPU,
   230  		Memory:             cgroupStatsMap["/runtime"].cs.Memory,
   231  		Accelerators:       cgroupStatsMap["/runtime"].cs.Accelerators,
   232  		UserDefinedMetrics: cgroupStatsMap["/runtime"].cs.UserDefinedMetrics,
   233  		Swap:               cgroupStatsMap["/runtime"].cs.Swap,
   234  	})
   235  	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
   236  		Name:               "pods",
   237  		StartTime:          cgroupStatsMap["/pods"].cs.StartTime,
   238  		CPU:                cgroupStatsMap["/pods"].cs.CPU,
   239  		Memory:             cgroupStatsMap["/pods"].cs.Memory,
   240  		Accelerators:       cgroupStatsMap["/pods"].cs.Accelerators,
   241  		UserDefinedMetrics: cgroupStatsMap["/pods"].cs.UserDefinedMetrics,
   242  		Swap:               cgroupStatsMap["/pods"].cs.Swap,
   243  	})
   244  	assert.Equal(summary.Pods, podStats)
   245  }
   246  
   247  func TestSummaryProviderGetCPUAndMemoryStats(t *testing.T) {
   248  	ctx := context.Background()
   249  	assert := assert.New(t)
   250  
   251  	podStats := []statsapi.PodStats{
   252  		{
   253  			PodRef:     statsapi.PodReference{Name: "test-pod", Namespace: "test-namespace", UID: "UID_test-pod"},
   254  			StartTime:  metav1.NewTime(time.Now()),
   255  			Containers: []statsapi.ContainerStats{*getContainerStats()},
   256  		},
   257  	}
   258  	cgroupStatsMap := map[string]struct {
   259  		cs *statsapi.ContainerStats
   260  	}{
   261  		"/":        {cs: getVolumeCPUAndMemoryStats()},
   262  		"/runtime": {cs: getVolumeCPUAndMemoryStats()},
   263  		"/misc":    {cs: getVolumeCPUAndMemoryStats()},
   264  		"/kubelet": {cs: getVolumeCPUAndMemoryStats()},
   265  		"/pods":    {cs: getVolumeCPUAndMemoryStats()},
   266  	}
   267  
   268  	mockCtrl := gomock.NewController(t)
   269  	defer mockCtrl.Finish()
   270  	mockStatsProvider := statstest.NewMockProvider(mockCtrl)
   271  
   272  	mockStatsProvider.EXPECT().GetNode().Return(node, nil)
   273  	mockStatsProvider.EXPECT().GetNodeConfig().Return(nodeConfig)
   274  	mockStatsProvider.EXPECT().GetPodCgroupRoot().Return(cgroupRoot)
   275  	mockStatsProvider.EXPECT().ListPodCPUAndMemoryStats(ctx).Return(podStats, nil)
   276  	mockStatsProvider.EXPECT().GetCgroupCPUAndMemoryStats("/", false).Return(cgroupStatsMap["/"].cs, nil)
   277  	mockStatsProvider.EXPECT().GetCgroupCPUAndMemoryStats("/runtime", false).Return(cgroupStatsMap["/runtime"].cs, nil)
   278  	mockStatsProvider.EXPECT().GetCgroupCPUAndMemoryStats("/misc", false).Return(cgroupStatsMap["/misc"].cs, nil)
   279  	mockStatsProvider.EXPECT().GetCgroupCPUAndMemoryStats("/kubelet", false).Return(cgroupStatsMap["/kubelet"].cs, nil)
   280  	mockStatsProvider.EXPECT().GetCgroupCPUAndMemoryStats("/kubepods", false).Return(cgroupStatsMap["/pods"].cs, nil)
   281  
   282  	provider := NewSummaryProvider(mockStatsProvider)
   283  	summary, err := provider.GetCPUAndMemoryStats(ctx)
   284  	assert.NoError(err)
   285  
   286  	assert.Equal(summary.Node.NodeName, "test-node")
   287  	assert.Equal(summary.Node.StartTime, cgroupStatsMap["/"].cs.StartTime)
   288  	assert.Equal(summary.Node.CPU, cgroupStatsMap["/"].cs.CPU)
   289  	assert.Equal(summary.Node.Memory, cgroupStatsMap["/"].cs.Memory)
   290  	assert.Nil(summary.Node.Network)
   291  	assert.Nil(summary.Node.Fs)
   292  	assert.Nil(summary.Node.Runtime)
   293  
   294  	assert.Equal(len(summary.Node.SystemContainers), 4)
   295  	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
   296  		Name:      "kubelet",
   297  		StartTime: cgroupStatsMap["/kubelet"].cs.StartTime,
   298  		CPU:       cgroupStatsMap["/kubelet"].cs.CPU,
   299  		Memory:    cgroupStatsMap["/kubelet"].cs.Memory,
   300  	})
   301  	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
   302  		Name:      "misc",
   303  		StartTime: cgroupStatsMap["/misc"].cs.StartTime,
   304  		CPU:       cgroupStatsMap["/misc"].cs.CPU,
   305  		Memory:    cgroupStatsMap["/misc"].cs.Memory,
   306  	})
   307  	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
   308  		Name:      "runtime",
   309  		StartTime: cgroupStatsMap["/runtime"].cs.StartTime,
   310  		CPU:       cgroupStatsMap["/runtime"].cs.CPU,
   311  		Memory:    cgroupStatsMap["/runtime"].cs.Memory,
   312  	})
   313  	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
   314  		Name:      "pods",
   315  		StartTime: cgroupStatsMap["/pods"].cs.StartTime,
   316  		CPU:       cgroupStatsMap["/pods"].cs.CPU,
   317  		Memory:    cgroupStatsMap["/pods"].cs.Memory,
   318  	})
   319  	assert.Equal(summary.Pods, podStats)
   320  }
   321  
   322  func getFsStats() *statsapi.FsStats {
   323  	f := fuzz.New().NilChance(0)
   324  	v := &statsapi.FsStats{}
   325  	f.Fuzz(v)
   326  	return v
   327  }
   328  
   329  func getContainerStats() *statsapi.ContainerStats {
   330  	f := fuzz.New().NilChance(0)
   331  	v := &statsapi.ContainerStats{}
   332  	f.Fuzz(v)
   333  	return v
   334  }
   335  func getVolumeCPUAndMemoryStats() *statsapi.ContainerStats {
   336  	f := fuzz.New().NilChance(0)
   337  	v := &statsapi.ContainerStats{}
   338  	f.Fuzz(&v.Name)
   339  	f.Fuzz(&v.StartTime)
   340  	f.Fuzz(v.CPU)
   341  	f.Fuzz(v.Memory)
   342  	return v
   343  }
   344  
   345  func getVolumeStats() *statsapi.VolumeStats {
   346  	f := fuzz.New().NilChance(0)
   347  	v := &statsapi.VolumeStats{}
   348  	f.Fuzz(v)
   349  	return v
   350  }
   351  
   352  func getNetworkStats() *statsapi.NetworkStats {
   353  	f := fuzz.New().NilChance(0)
   354  	v := &statsapi.NetworkStats{}
   355  	f.Fuzz(v)
   356  	return v
   357  }
   358  
   359  func getRlimitStats() *statsapi.RlimitStats {
   360  	f := fuzz.New().NilChance(0)
   361  	v := &statsapi.RlimitStats{}
   362  	f.Fuzz(v)
   363  	return v
   364  }
   365  

View as plain text