Merge pull request #59743 from feiskyer/stats

Automatic merge from submit-queue (batch tested with PRs 59286, 59743, 59883, 60190, 60165). 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 image file system stats for windows nodes

**What this PR does / why we need it**:

Kubelet is reporting `invalid capacity 0 on image filesystem` on windows nodes and image GC always fails.

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #59742

**Special notes for your reviewer**:

**Release note**:

```release-note
Fix image file system stats for windows nodes
```
pull/6/head
Kubernetes Submit Queue 2018-02-23 20:09:32 -08:00 committed by GitHub
commit bc2e3cea8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 110 additions and 51 deletions

View File

@ -78,5 +78,5 @@ func (cu *cadvisorClient) WatchEvents(request *events.Request) (*events.EventCha
}
func (cu *cadvisorClient) GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error) {
return cadvisorapiv2.FsInfo{}, nil
return cu.winStatsClient.GetDirFsInfo(path)
}

View File

@ -127,6 +127,7 @@ go_library(
] + select({
"@io_bazel_rules_go//go/platform:windows": [
"//pkg/features:go_default_library",
"//pkg/kubelet/winstats:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
"//conditions:default": [],

View File

@ -21,19 +21,36 @@ package dockershim
import (
"time"
"github.com/golang/glog"
"golang.org/x/net/context"
runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
"k8s.io/kubernetes/pkg/kubelet/winstats"
)
// ImageFsInfo returns information of the filesystem that is used to store images.
func (ds *dockerService) ImageFsInfo(_ context.Context, _ *runtimeapi.ImageFsInfoRequest) (*runtimeapi.ImageFsInfoResponse, error) {
// For Windows Stats to work correctly, a file system must be provided. For now, provide a fake filesystem.
info, err := ds.client.Info()
if err != nil {
glog.Errorf("Failed to get docker info: %v", err)
return nil, err
}
statsClient := &winstats.StatsClient{}
fsinfo, err := statsClient.GetDirFsInfo(info.DockerRootDir)
if err != nil {
glog.Errorf("Failed to get dir fsInfo for %q: %v", info.DockerRootDir, err)
return nil, err
}
filesystems := []*runtimeapi.FilesystemUsage{
{
Timestamp: time.Now().UnixNano(),
UsedBytes: &runtimeapi.UInt64Value{Value: 0},
UsedBytes: &runtimeapi.UInt64Value{Value: fsinfo.Usage},
InodesUsed: &runtimeapi.UInt64Value{Value: 0},
FsId: &runtimeapi.FilesystemIdentifier{
Mountpoint: info.DockerRootDir,
},
},
}

View File

@ -1,6 +1,49 @@
package(default_visibility = ["//visibility:public"])
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
licenses(["notice"])
go_library(
name = "go_default_library",
srcs = select({
"@io_bazel_rules_go//go/platform:windows": [
"perfcounter_nodestats.go",
"perfcounters.go",
"version.go",
"winstats.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/kubelet/winstats",
visibility = ["//visibility:public"],
deps = select({
"@io_bazel_rules_go//go/platform:windows": [
"//vendor/github.com/JeffAshton/win_pdh:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/info/v2:go_default_library",
"//vendor/golang.org/x/sys/windows:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
],
"//conditions:default": [],
}),
)
go_test(
name = "go_default_test",
srcs = select({
"@io_bazel_rules_go//go/platform:windows": [
"winstats_test.go",
],
"//conditions:default": [],
}),
embed = [":go_default_library"],
deps = select({
"@io_bazel_rules_go//go/platform:windows": [
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/info/v2:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
],
"//conditions:default": [],
}),
)
filegroup(
name = "package-srcs",
@ -13,44 +56,5 @@ filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"winstats.go",
] + select({
"@io_bazel_rules_go//go/platform:windows": [
"perfcounter_nodestats.go",
"perfcounters.go",
"version.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/kubelet/winstats",
deps = [
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/info/v2:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:windows": [
"//vendor/github.com/JeffAshton/win_pdh:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/golang.org/x/sys/windows:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
],
"//conditions:default": [],
}),
)
go_test(
name = "go_default_test",
srcs = ["winstats_test.go"],
embed = [":go_default_library"],
deps = [
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/info/v2:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
],
visibility = ["//visibility:public"],
)

View File

@ -1,3 +1,5 @@
// +build windows
/*
Copyright 2017 The Kubernetes Authors.
@ -18,21 +20,28 @@ limitations under the License.
package winstats
import (
"syscall"
"time"
"unsafe"
cadvisorapi "github.com/google/cadvisor/info/v1"
cadvisorapiv2 "github.com/google/cadvisor/info/v2"
)
var (
procGetDiskFreeSpaceEx = modkernel32.NewProc("GetDiskFreeSpaceExW")
)
// Client is an interface that is used to get stats information.
type Client interface {
WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error)
WinMachineInfo() (*cadvisorapi.MachineInfo, error)
WinVersionInfo() (*cadvisorapi.VersionInfo, error)
GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error)
}
// StatsClient is a client that implements the Client interface
type statsClient struct {
type StatsClient struct {
client winNodeStatsClient
}
@ -61,7 +70,7 @@ type nodeInfo struct {
// newClient constructs a Client.
func newClient(statsNodeClient winNodeStatsClient) (Client, error) {
statsClient := new(statsClient)
statsClient := new(StatsClient)
statsClient.client = statsNodeClient
err := statsClient.client.startMonitoring()
@ -74,7 +83,7 @@ func newClient(statsNodeClient winNodeStatsClient) (Client, error) {
// WinContainerInfos returns a map of container infos. The map contains node and
// pod level stats. Analogous to cadvisor GetContainerInfoV2 method.
func (c *statsClient) WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error) {
func (c *StatsClient) WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error) {
infos := make(map[string]cadvisorapiv2.ContainerInfo)
rootContainerInfo, err := c.createRootContainerInfo()
if err != nil {
@ -88,17 +97,17 @@ func (c *statsClient) WinContainerInfos() (map[string]cadvisorapiv2.ContainerInf
// WinMachineInfo returns a cadvisorapi.MachineInfo with details about the
// node machine. Analogous to cadvisor MachineInfo method.
func (c *statsClient) WinMachineInfo() (*cadvisorapi.MachineInfo, error) {
func (c *StatsClient) WinMachineInfo() (*cadvisorapi.MachineInfo, error) {
return c.client.getMachineInfo()
}
// WinVersionInfo returns a cadvisorapi.VersionInfo with version info of
// the kernel and docker runtime. Analogous to cadvisor VersionInfo method.
func (c *statsClient) WinVersionInfo() (*cadvisorapi.VersionInfo, error) {
func (c *StatsClient) WinVersionInfo() (*cadvisorapi.VersionInfo, error) {
return c.client.getVersionInfo()
}
func (c *statsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, error) {
func (c *StatsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, error) {
nodeMetrics, err := c.client.getNodeMetrics()
if err != nil {
@ -134,3 +143,29 @@ func (c *statsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, e
return &rootInfo, nil
}
func (c *StatsClient) GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error) {
var freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes int64
var err error
ret, _, err := syscall.Syscall6(
procGetDiskFreeSpaceEx.Addr(),
4,
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
uintptr(unsafe.Pointer(&freeBytesAvailable)),
uintptr(unsafe.Pointer(&totalNumberOfBytes)),
uintptr(unsafe.Pointer(&totalNumberOfFreeBytes)),
0,
0,
)
if ret == 0 {
return cadvisorapiv2.FsInfo{}, err
}
return cadvisorapiv2.FsInfo{
Timestamp: time.Now(),
Capacity: uint64(totalNumberOfBytes),
Available: uint64(freeBytesAvailable),
Usage: uint64(totalNumberOfBytes - freeBytesAvailable),
}, nil
}

View File

@ -1,3 +1,5 @@
// +build windows
/*
Copyright 2017 The Kubernetes Authors.