mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
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 ```
This commit is contained in:
commit
bc2e3cea8f
@ -78,5 +78,5 @@ func (cu *cadvisorClient) WatchEvents(request *events.Request) (*events.EventCha
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cu *cadvisorClient) GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error) {
|
func (cu *cadvisorClient) GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error) {
|
||||||
return cadvisorapiv2.FsInfo{}, nil
|
return cu.winStatsClient.GetDirFsInfo(path)
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,7 @@ go_library(
|
|||||||
] + select({
|
] + select({
|
||||||
"@io_bazel_rules_go//go/platform:windows": [
|
"@io_bazel_rules_go//go/platform:windows": [
|
||||||
"//pkg/features:go_default_library",
|
"//pkg/features:go_default_library",
|
||||||
|
"//pkg/kubelet/winstats:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
],
|
],
|
||||||
"//conditions:default": [],
|
"//conditions:default": [],
|
||||||
|
@ -21,19 +21,36 @@ package dockershim
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
|
||||||
runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
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.
|
// ImageFsInfo returns information of the filesystem that is used to store images.
|
||||||
func (ds *dockerService) ImageFsInfo(_ context.Context, _ *runtimeapi.ImageFsInfoRequest) (*runtimeapi.ImageFsInfoResponse, error) {
|
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{
|
filesystems := []*runtimeapi.FilesystemUsage{
|
||||||
{
|
{
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now().UnixNano(),
|
||||||
UsedBytes: &runtimeapi.UInt64Value{Value: 0},
|
UsedBytes: &runtimeapi.UInt64Value{Value: fsinfo.Usage},
|
||||||
InodesUsed: &runtimeapi.UInt64Value{Value: 0},
|
InodesUsed: &runtimeapi.UInt64Value{Value: 0},
|
||||||
|
FsId: &runtimeapi.FilesystemIdentifier{
|
||||||
|
Mountpoint: info.DockerRootDir,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(
|
filegroup(
|
||||||
name = "package-srcs",
|
name = "package-srcs",
|
||||||
@ -13,44 +56,5 @@ filegroup(
|
|||||||
name = "all-srcs",
|
name = "all-srcs",
|
||||||
srcs = [":package-srcs"],
|
srcs = [":package-srcs"],
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
)
|
visibility = ["//visibility:public"],
|
||||||
|
|
||||||
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",
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
@ -18,21 +20,28 @@ limitations under the License.
|
|||||||
package winstats
|
package winstats
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
cadvisorapi "github.com/google/cadvisor/info/v1"
|
cadvisorapi "github.com/google/cadvisor/info/v1"
|
||||||
cadvisorapiv2 "github.com/google/cadvisor/info/v2"
|
cadvisorapiv2 "github.com/google/cadvisor/info/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
procGetDiskFreeSpaceEx = modkernel32.NewProc("GetDiskFreeSpaceExW")
|
||||||
|
)
|
||||||
|
|
||||||
// Client is an interface that is used to get stats information.
|
// Client is an interface that is used to get stats information.
|
||||||
type Client interface {
|
type Client interface {
|
||||||
WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error)
|
WinContainerInfos() (map[string]cadvisorapiv2.ContainerInfo, error)
|
||||||
WinMachineInfo() (*cadvisorapi.MachineInfo, error)
|
WinMachineInfo() (*cadvisorapi.MachineInfo, error)
|
||||||
WinVersionInfo() (*cadvisorapi.VersionInfo, error)
|
WinVersionInfo() (*cadvisorapi.VersionInfo, error)
|
||||||
|
GetDirFsInfo(path string) (cadvisorapiv2.FsInfo, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatsClient is a client that implements the Client interface
|
// StatsClient is a client that implements the Client interface
|
||||||
type statsClient struct {
|
type StatsClient struct {
|
||||||
client winNodeStatsClient
|
client winNodeStatsClient
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +70,7 @@ type nodeInfo struct {
|
|||||||
|
|
||||||
// newClient constructs a Client.
|
// newClient constructs a Client.
|
||||||
func newClient(statsNodeClient winNodeStatsClient) (Client, error) {
|
func newClient(statsNodeClient winNodeStatsClient) (Client, error) {
|
||||||
statsClient := new(statsClient)
|
statsClient := new(StatsClient)
|
||||||
statsClient.client = statsNodeClient
|
statsClient.client = statsNodeClient
|
||||||
|
|
||||||
err := statsClient.client.startMonitoring()
|
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
|
// WinContainerInfos returns a map of container infos. The map contains node and
|
||||||
// pod level stats. Analogous to cadvisor GetContainerInfoV2 method.
|
// 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)
|
infos := make(map[string]cadvisorapiv2.ContainerInfo)
|
||||||
rootContainerInfo, err := c.createRootContainerInfo()
|
rootContainerInfo, err := c.createRootContainerInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -88,17 +97,17 @@ func (c *statsClient) WinContainerInfos() (map[string]cadvisorapiv2.ContainerInf
|
|||||||
|
|
||||||
// WinMachineInfo returns a cadvisorapi.MachineInfo with details about the
|
// WinMachineInfo returns a cadvisorapi.MachineInfo with details about the
|
||||||
// node machine. Analogous to cadvisor MachineInfo method.
|
// 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()
|
return c.client.getMachineInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// WinVersionInfo returns a cadvisorapi.VersionInfo with version info of
|
// WinVersionInfo returns a cadvisorapi.VersionInfo with version info of
|
||||||
// the kernel and docker runtime. Analogous to cadvisor VersionInfo method.
|
// 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()
|
return c.client.getVersionInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *statsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, error) {
|
func (c *StatsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, error) {
|
||||||
nodeMetrics, err := c.client.getNodeMetrics()
|
nodeMetrics, err := c.client.getNodeMetrics()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -134,3 +143,29 @@ func (c *statsClient) createRootContainerInfo() (*cadvisorapiv2.ContainerInfo, e
|
|||||||
|
|
||||||
return &rootInfo, nil
|
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
|
||||||
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user