Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement StatsProvider interface using CRI stats #51557

Merged
merged 1 commit into from
Sep 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion pkg/kubelet/apis/cri/testing/fake_image_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ type FakeImageService struct {
Images map[string]*runtimeapi.Image

pulledImages []*pulledImage

FakeFilesystemUsage []*runtimeapi.FilesystemUsage
}

func (r *FakeImageService) SetFakeImages(images []string) {
Expand All @@ -53,6 +55,13 @@ func (r *FakeImageService) SetFakeImageSize(size uint64) {
r.FakeImageSize = size
}

func (r *FakeImageService) SetFakeFilesystemUsage(usage []*runtimeapi.FilesystemUsage) {
r.Lock()
defer r.Unlock()

r.FakeFilesystemUsage = usage
}

func NewFakeImageService() *FakeImageService {
return &FakeImageService{
Called: make([]string, 0),
Expand Down Expand Up @@ -132,7 +141,9 @@ func (r *FakeImageService) ImageFsInfo(req *runtimeapi.ImageFsInfoRequest) (*run

r.Called = append(r.Called, "ImageFsInfo")

return nil, nil
return &runtimeapi.ImageFsInfoResponse{
ImageFilesystems: r.FakeFilesystemUsage,
}, nil
}

func (r *FakeImageService) AssertImagePulledWithAuth(t *testing.T, image *runtimeapi.ImageSpec, auth *runtimeapi.AuthConfig, failMsg string) {
Expand Down
62 changes: 54 additions & 8 deletions pkg/kubelet/apis/cri/testing/fake_runtime_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ type FakeRuntimeService struct {

Called []string

FakeStatus *runtimeapi.RuntimeStatus
Containers map[string]*FakeContainer
Sandboxes map[string]*FakePodSandbox
FakeStatus *runtimeapi.RuntimeStatus
Containers map[string]*FakeContainer
Sandboxes map[string]*FakePodSandbox
FakeContainerStats map[string]*runtimeapi.ContainerStats
}

func (r *FakeRuntimeService) GetContainerID(sandboxID, name string, attempt uint32) (string, error) {
Expand Down Expand Up @@ -102,9 +103,10 @@ func (r *FakeRuntimeService) AssertCalls(calls []string) error {

func NewFakeRuntimeService() *FakeRuntimeService {
return &FakeRuntimeService{
Called: make([]string, 0),
Containers: make(map[string]*FakeContainer),
Sandboxes: make(map[string]*FakePodSandbox),
Called: make([]string, 0),
Containers: make(map[string]*FakeContainer),
Sandboxes: make(map[string]*FakePodSandbox),
FakeContainerStats: make(map[string]*runtimeapi.ContainerStats),
}
}

Expand Down Expand Up @@ -406,10 +408,54 @@ func (r *FakeRuntimeService) UpdateRuntimeConfig(runtimeCOnfig *runtimeapi.Runti
return nil
}

func (r *FakeRuntimeService) SetFakeContainerStats(containerStats []*runtimeapi.ContainerStats) {
r.Lock()
defer r.Unlock()

r.FakeContainerStats = make(map[string]*runtimeapi.ContainerStats)
for _, s := range containerStats {
r.FakeContainerStats[s.Attributes.Id] = s
}
}

func (r *FakeRuntimeService) ContainerStats(req *runtimeapi.ContainerStatsRequest) (*runtimeapi.ContainerStatsResponse, error) {
return nil, fmt.Errorf("Not implemented")
r.Lock()
defer r.Unlock()

r.Called = append(r.Called, "ContainerStats")

s, found := r.FakeContainerStats[req.ContainerId]
if !found {
return nil, fmt.Errorf("no stats for container %q", req.ContainerId)
}
return &runtimeapi.ContainerStatsResponse{Stats: s}, nil
}

func (r *FakeRuntimeService) ListContainerStats(req *runtimeapi.ListContainerStatsRequest) (*runtimeapi.ListContainerStatsResponse, error) {
return nil, fmt.Errorf("Not implemented")
r.Lock()
defer r.Unlock()

r.Called = append(r.Called, "ListContainerStats")

var result []*runtimeapi.ContainerStats
for _, c := range r.Containers {
if req.Filter != nil {
if req.Filter.Id != "" && req.Filter.Id != c.Id {
continue
}
if req.Filter.PodSandboxId != "" && req.Filter.PodSandboxId != c.SandboxID {
continue
}
if req.Filter.LabelSelector != nil && !filterInLabels(req.Filter.LabelSelector, c.GetLabels()) {
continue
}
}
s, found := r.FakeContainerStats[c.Id]
if !found {
continue
}
result = append(result, s)
}

return &runtimeapi.ListContainerStatsResponse{Stats: result}, nil
}
4 changes: 4 additions & 0 deletions pkg/kubelet/cadvisor/testing/cadvisor_fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,7 @@ func (c *Fake) WatchEvents(request *events.Request) (*events.EventChannel, error
func (c *Fake) HasDedicatedImageFs() (bool, error) {
return false, nil
}

func (c *Fake) GetFsInfoByFsUUID(uuid string) (cadvisorapiv2.FsInfo, error) {
return cadvisorapiv2.FsInfo{}, nil
}
5 changes: 5 additions & 0 deletions pkg/kubelet/cadvisor/testing/cadvisor_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,8 @@ func (c *Mock) HasDedicatedImageFs() (bool, error) {
args := c.Called()
return args.Get(0).(bool), args.Error(1)
}

func (c *Mock) GetFsInfoByFsUUID(uuid string) (cadvisorapiv2.FsInfo, error) {
args := c.Called(uuid)
return args.Get(0).(cadvisorapiv2.FsInfo), args.Error(1)
}
4 changes: 4 additions & 0 deletions pkg/kubelet/cadvisor/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@ type Interface interface {

// HasDedicatedImageFs returns true iff a dedicated image filesystem exists for storing images.
HasDedicatedImageFs() (bool, error)

// GetFsInfoByFsUUID returns the stats of the filesystem with the specified
// uuid.
GetFsInfoByFsUUID(uuid string) (cadvisorapiv2.FsInfo, error)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding this without implementing in _unsupported and _windows broke cross-build. fix in #52073

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Forgot about the cross-build. It would be nice if this can be caught in presubmit test.

}
6 changes: 6 additions & 0 deletions pkg/kubelet/stats/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//pkg/kubelet/apis/cri:go_default_library",
"//pkg/kubelet/apis/cri/v1alpha1/runtime:go_default_library",
"//pkg/kubelet/apis/stats/v1alpha1:go_default_library",
"//pkg/kubelet/cadvisor:go_default_library",
"//pkg/kubelet/container:go_default_library",
Expand All @@ -20,6 +21,7 @@ go_library(
"//pkg/kubelet/server/stats:go_default_library",
"//pkg/kubelet/types:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/google/cadvisor/fs:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/info/v2:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
Expand All @@ -45,11 +47,14 @@ go_test(
name = "go_default_test",
srcs = [
"cadvisor_stats_provider_test.go",
"cri_stats_provider_test.go",
"helper_test.go",
"stats_provider_test.go",
],
library = ":go_default_library",
deps = [
"//pkg/kubelet/apis/cri/testing:go_default_library",
"//pkg/kubelet/apis/cri/v1alpha1/runtime:go_default_library",
"//pkg/kubelet/apis/stats/v1alpha1:go_default_library",
"//pkg/kubelet/cadvisor/testing:go_default_library",
"//pkg/kubelet/container:go_default_library",
Expand All @@ -58,6 +63,7 @@ go_test(
"//pkg/kubelet/pod/testing:go_default_library",
"//pkg/kubelet/server/stats:go_default_library",
"//pkg/kubelet/types:go_default_library",
"//vendor/github.com/google/cadvisor/fs:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/info/v2:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
Expand Down
9 changes: 1 addition & 8 deletions pkg/kubelet/stats/cadvisor_stats_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,8 @@ func (p *cadvisorStatsProvider) ImageFsStats() (*statsapi.FsStats, error) {
imageFsInodesUsed = &imageFsIU
}

// Get the root container stats's timestamp, which will be used as the
// imageFs stats timestamp.
rootStats, err := getCgroupStats(p.cadvisor, "/")
if err != nil {
return nil, fmt.Errorf("failed to get root container stats: %v", err)
}

return &statsapi.FsStats{
Time: metav1.NewTime(rootStats.Timestamp),
Time: metav1.NewTime(imageFsInfo.Timestamp),
AvailableBytes: &imageFsInfo.Available,
CapacityBytes: &imageFsInfo.Capacity,
UsedBytes: &imageStats.TotalStorageBytes,
Expand Down
34 changes: 14 additions & 20 deletions pkg/kubelet/stats/cadvisor_stats_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
cadvisorapiv2 "github.com/google/cadvisor/info/v2"
"github.com/stretchr/testify/assert"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
cadvisortest "k8s.io/kubernetes/pkg/kubelet/cadvisor/testing"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
Expand Down Expand Up @@ -74,7 +73,7 @@ func TestRemoveTerminatedContainerInfo(t *testing.T) {
}
}

func TestListPodStats(t *testing.T) {
func TestCadvisorListPodStats(t *testing.T) {
const (
namespace0 = "test0"
namespace2 = "test2"
Expand Down Expand Up @@ -236,36 +235,31 @@ func TestListPodStats(t *testing.T) {
checkNetworkStats(t, "Pod2", seedPod2Infra, ps.Network)
}

func TestImagesFsStats(t *testing.T) {
func TestCadvisorImagesFsStats(t *testing.T) {
var (
assert = assert.New(t)
mockCadvisor = new(cadvisortest.Mock)
mockRuntime = new(containertest.Mock)

seed = 100
options = cadvisorapiv2.RequestOptions{IdType: cadvisorapiv2.TypeName, Count: 2, Recursive: false}
imageFsInfo = getTestFsInfo(100)
containerInfo = map[string]cadvisorapiv2.ContainerInfo{"/": getTestContainerInfo(seed, "test-pod", "test-ns", "test-container")}
imageStats = &kubecontainer.ImageStats{TotalStorageBytes: 100}
seed = 1000
imageFsInfo = getTestFsInfo(seed)
imageStats = &kubecontainer.ImageStats{TotalStorageBytes: 100}
)

mockCadvisor.
On("ImagesFsInfo").Return(imageFsInfo, nil).
On("ContainerInfoV2", "/", options).Return(containerInfo, nil)
mockRuntime.
On("ImageStats").Return(imageStats, nil)
mockCadvisor.On("ImagesFsInfo").Return(imageFsInfo, nil)
mockRuntime.On("ImageStats").Return(imageStats, nil)

provider := newCadvisorStatsProvider(mockCadvisor, &fakeResourceAnalyzer{}, mockRuntime)
stats, err := provider.ImageFsStats()
assert.NoError(err)

assert.Equal(stats.Time, metav1.NewTime(containerInfo["/"].Stats[0].Timestamp))
assert.Equal(*stats.AvailableBytes, imageFsInfo.Available)
assert.Equal(*stats.CapacityBytes, imageFsInfo.Capacity)
assert.Equal(*stats.UsedBytes, imageStats.TotalStorageBytes)
assert.Equal(stats.InodesFree, imageFsInfo.InodesFree)
assert.Equal(stats.Inodes, imageFsInfo.Inodes)
assert.Equal(*stats.InodesUsed, *imageFsInfo.Inodes-*imageFsInfo.InodesFree)
assert.Equal(imageFsInfo.Timestamp, stats.Time.Time)
assert.Equal(imageFsInfo.Available, *stats.AvailableBytes)
assert.Equal(imageFsInfo.Capacity, *stats.CapacityBytes)
assert.Equal(imageStats.TotalStorageBytes, *stats.UsedBytes)
assert.Equal(imageFsInfo.InodesFree, stats.InodesFree)
assert.Equal(imageFsInfo.Inodes, stats.Inodes)
assert.Equal(*imageFsInfo.Inodes-*imageFsInfo.InodesFree, *stats.InodesUsed)

mockCadvisor.AssertExpectations(t)
}
Loading