Unverified Commit c4f8f3e2 authored by Hussein Galal's avatar Hussein Galal Committed by GitHub

Update to v1.20.14 (#4759)

* Update to v1.20.14 Signed-off-by: 's avatargalal-hussein <hussein.galal.ahmed.11@gmail.com> * Update go mod Signed-off-by: 's avatargalal-hussein <hussein.galal.ahmed.11@gmail.com> * Update to v1.20.14 Signed-off-by: 's avatargalal-hussein <hussein.galal.ahmed.11@gmail.com>
parent 1e1fb73e
...@@ -38,34 +38,34 @@ replace ( ...@@ -38,34 +38,34 @@ replace (
google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63
google.golang.org/grpc => google.golang.org/grpc v1.27.1 google.golang.org/grpc => google.golang.org/grpc v1.27.1
gopkg.in/square/go-jose.v2 => gopkg.in/square/go-jose.v2 v2.2.2 gopkg.in/square/go-jose.v2 => gopkg.in/square/go-jose.v2 v2.2.2
k8s.io/api => github.com/k3s-io/kubernetes/staging/src/k8s.io/api v1.20.13-k3s1 k8s.io/api => github.com/k3s-io/kubernetes/staging/src/k8s.io/api v1.20.14-k3s1
k8s.io/apiextensions-apiserver => github.com/k3s-io/kubernetes/staging/src/k8s.io/apiextensions-apiserver v1.20.13-k3s1 k8s.io/apiextensions-apiserver => github.com/k3s-io/kubernetes/staging/src/k8s.io/apiextensions-apiserver v1.20.14-k3s1
k8s.io/apimachinery => github.com/k3s-io/kubernetes/staging/src/k8s.io/apimachinery v1.20.13-k3s1 k8s.io/apimachinery => github.com/k3s-io/kubernetes/staging/src/k8s.io/apimachinery v1.20.14-k3s1
k8s.io/apiserver => github.com/k3s-io/kubernetes/staging/src/k8s.io/apiserver v1.20.13-k3s1 k8s.io/apiserver => github.com/k3s-io/kubernetes/staging/src/k8s.io/apiserver v1.20.14-k3s1
k8s.io/cli-runtime => github.com/k3s-io/kubernetes/staging/src/k8s.io/cli-runtime v1.20.13-k3s1 k8s.io/cli-runtime => github.com/k3s-io/kubernetes/staging/src/k8s.io/cli-runtime v1.20.14-k3s1
k8s.io/client-go => github.com/k3s-io/kubernetes/staging/src/k8s.io/client-go v1.20.13-k3s1 k8s.io/client-go => github.com/k3s-io/kubernetes/staging/src/k8s.io/client-go v1.20.14-k3s1
k8s.io/cloud-provider => github.com/k3s-io/kubernetes/staging/src/k8s.io/cloud-provider v1.20.13-k3s1 k8s.io/cloud-provider => github.com/k3s-io/kubernetes/staging/src/k8s.io/cloud-provider v1.20.14-k3s1
k8s.io/cluster-bootstrap => github.com/k3s-io/kubernetes/staging/src/k8s.io/cluster-bootstrap v1.20.13-k3s1 k8s.io/cluster-bootstrap => github.com/k3s-io/kubernetes/staging/src/k8s.io/cluster-bootstrap v1.20.14-k3s1
k8s.io/code-generator => github.com/k3s-io/kubernetes/staging/src/k8s.io/code-generator v1.20.13-k3s1 k8s.io/code-generator => github.com/k3s-io/kubernetes/staging/src/k8s.io/code-generator v1.20.14-k3s1
k8s.io/component-base => github.com/k3s-io/kubernetes/staging/src/k8s.io/component-base v1.20.13-k3s1 k8s.io/component-base => github.com/k3s-io/kubernetes/staging/src/k8s.io/component-base v1.20.14-k3s1
k8s.io/component-helpers => github.com/k3s-io/kubernetes/staging/src/k8s.io/component-helpers v1.20.13-k3s1 k8s.io/component-helpers => github.com/k3s-io/kubernetes/staging/src/k8s.io/component-helpers v1.20.14-k3s1
k8s.io/controller-manager => github.com/k3s-io/kubernetes/staging/src/k8s.io/controller-manager v1.20.13-k3s1 k8s.io/controller-manager => github.com/k3s-io/kubernetes/staging/src/k8s.io/controller-manager v1.20.14-k3s1
k8s.io/cri-api => github.com/k3s-io/kubernetes/staging/src/k8s.io/cri-api v1.20.13-k3s1 k8s.io/cri-api => github.com/k3s-io/kubernetes/staging/src/k8s.io/cri-api v1.20.14-k3s1
k8s.io/csi-translation-lib => github.com/k3s-io/kubernetes/staging/src/k8s.io/csi-translation-lib v1.20.13-k3s1 k8s.io/csi-translation-lib => github.com/k3s-io/kubernetes/staging/src/k8s.io/csi-translation-lib v1.20.14-k3s1
k8s.io/kube-aggregator => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-aggregator v1.20.13-k3s1 k8s.io/kube-aggregator => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-aggregator v1.20.14-k3s1
k8s.io/kube-controller-manager => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-controller-manager v1.20.13-k3s1 k8s.io/kube-controller-manager => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-controller-manager v1.20.14-k3s1
k8s.io/kube-proxy => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-proxy v1.20.13-k3s1 k8s.io/kube-proxy => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-proxy v1.20.14-k3s1
k8s.io/kube-scheduler => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-scheduler v1.20.13-k3s1 k8s.io/kube-scheduler => github.com/k3s-io/kubernetes/staging/src/k8s.io/kube-scheduler v1.20.14-k3s1
k8s.io/kubectl => github.com/k3s-io/kubernetes/staging/src/k8s.io/kubectl v1.20.13-k3s1 k8s.io/kubectl => github.com/k3s-io/kubernetes/staging/src/k8s.io/kubectl v1.20.14-k3s1
k8s.io/kubelet => github.com/k3s-io/kubernetes/staging/src/k8s.io/kubelet v1.20.13-k3s1 k8s.io/kubelet => github.com/k3s-io/kubernetes/staging/src/k8s.io/kubelet v1.20.14-k3s1
k8s.io/kubernetes => github.com/k3s-io/kubernetes v1.20.13-k3s1 k8s.io/kubernetes => github.com/k3s-io/kubernetes v1.20.14-k3s1
k8s.io/legacy-cloud-providers => github.com/k3s-io/kubernetes/staging/src/k8s.io/legacy-cloud-providers v1.20.13-k3s1 k8s.io/legacy-cloud-providers => github.com/k3s-io/kubernetes/staging/src/k8s.io/legacy-cloud-providers v1.20.14-k3s1
k8s.io/metrics => github.com/k3s-io/kubernetes/staging/src/k8s.io/metrics v1.20.13-k3s1 k8s.io/metrics => github.com/k3s-io/kubernetes/staging/src/k8s.io/metrics v1.20.14-k3s1
k8s.io/mount-utils => github.com/k3s-io/kubernetes/staging/src/k8s.io/mount-utils v1.20.13-k3s1 k8s.io/mount-utils => github.com/k3s-io/kubernetes/staging/src/k8s.io/mount-utils v1.20.14-k3s1
k8s.io/node-api => github.com/k3s-io/kubernetes/staging/src/k8s.io/node-api v1.20.13-k3s1 k8s.io/node-api => github.com/k3s-io/kubernetes/staging/src/k8s.io/node-api v1.20.14-k3s1
k8s.io/sample-apiserver => github.com/k3s-io/kubernetes/staging/src/k8s.io/sample-apiserver v1.20.13-k3s1 k8s.io/sample-apiserver => github.com/k3s-io/kubernetes/staging/src/k8s.io/sample-apiserver v1.20.14-k3s1
k8s.io/sample-cli-plugin => github.com/k3s-io/kubernetes/staging/src/k8s.io/sample-cli-plugin v1.20.13-k3s1 k8s.io/sample-cli-plugin => github.com/k3s-io/kubernetes/staging/src/k8s.io/sample-cli-plugin v1.20.14-k3s1
k8s.io/sample-controller => github.com/k3s-io/kubernetes/staging/src/k8s.io/sample-controller v1.20.13-k3s1 k8s.io/sample-controller => github.com/k3s-io/kubernetes/staging/src/k8s.io/sample-controller v1.20.14-k3s1
mvdan.cc/unparam => mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34 mvdan.cc/unparam => mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34
) )
...@@ -122,17 +122,17 @@ require ( ...@@ -122,17 +122,17 @@ require (
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 golang.org/x/sys v0.0.0-20210426230700-d19ff857e887
google.golang.org/grpc v1.33.2 google.golang.org/grpc v1.33.2
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
k8s.io/api v1.20.11 k8s.io/api v0.20.14
k8s.io/apimachinery v1.20.11 k8s.io/apimachinery v0.20.14
k8s.io/apiserver v1.20.11 k8s.io/apiserver v0.20.14
k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible
k8s.io/cloud-provider v1.20.11 k8s.io/cloud-provider v0.20.14
k8s.io/component-base v1.20.11 k8s.io/component-base v0.20.14
k8s.io/controller-manager v1.20.11 k8s.io/controller-manager v0.20.14
k8s.io/cri-api v1.20.11 k8s.io/cri-api v0.20.14
k8s.io/klog v1.0.0 k8s.io/klog v1.0.0
k8s.io/kubectl v1.20.11 k8s.io/kubectl v0.20.14
k8s.io/kubernetes v1.20.13 k8s.io/kubernetes v1.20.14
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 k8s.io/utils v0.0.0-20201110183641-67b214c5f920
sigs.k8s.io/yaml v1.2.0 sigs.k8s.io/yaml v1.2.0
) )
...@@ -3,8 +3,8 @@ package version ...@@ -3,8 +3,8 @@ package version
var ( var (
gitMajor = "1" gitMajor = "1"
gitMinor = "20" gitMinor = "20"
gitVersion = "v1.20.13-k3s1" gitVersion = "v1.20.14-k3s1"
gitCommit = "00ac75d2198c72709eea88425cbc3d71993bdb6d" gitCommit = "c9ccd1687e39f0ae9ff460dbeed44d8a528d8f47"
gitTreeState = "clean" gitTreeState = "clean"
buildDate = "2021-11-17T22:42:11Z" buildDate = "2021-12-15T21:14:12Z"
) )
...@@ -3,8 +3,8 @@ package version ...@@ -3,8 +3,8 @@ package version
var ( var (
gitMajor = "1" gitMajor = "1"
gitMinor = "20" gitMinor = "20"
gitVersion = "v1.20.13-k3s1" gitVersion = "v1.20.14-k3s1"
gitCommit = "00ac75d2198c72709eea88425cbc3d71993bdb6d" gitCommit = "c9ccd1687e39f0ae9ff460dbeed44d8a528d8f47"
gitTreeState = "clean" gitTreeState = "clean"
buildDate = "2021-11-17T22:42:11Z" buildDate = "2021-12-15T21:14:12Z"
) )
...@@ -72,6 +72,7 @@ go_test( ...@@ -72,6 +72,7 @@ go_test(
"//staging/src/k8s.io/client-go/tools/record:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library",
"//staging/src/k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1:go_default_library", "//staging/src/k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1:go_default_library",
"//staging/src/k8s.io/kubelet/pkg/apis/pluginregistration/v1:go_default_library", "//staging/src/k8s.io/kubelet/pkg/apis/pluginregistration/v1:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library", "//vendor/github.com/stretchr/testify/require:go_default_library",
], ],
......
...@@ -2,13 +2,19 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") ...@@ -2,13 +2,19 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = ["checkpoint.go"], srcs = [
"checkpoint.go",
"checkpointv1.go",
],
importpath = "k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/checkpoint", importpath = "k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/checkpoint",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//pkg/kubelet/checkpointmanager:go_default_library", "//pkg/kubelet/checkpointmanager:go_default_library",
"//pkg/kubelet/checkpointmanager/checksum:go_default_library", "//pkg/kubelet/checkpointmanager/checksum:go_default_library",
"//pkg/kubelet/checkpointmanager/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/k8s.io/klog/v2:go_default_library",
], ],
) )
......
...@@ -27,7 +27,7 @@ import ( ...@@ -27,7 +27,7 @@ import (
// DeviceManagerCheckpoint defines the operations to retrieve pod devices // DeviceManagerCheckpoint defines the operations to retrieve pod devices
type DeviceManagerCheckpoint interface { type DeviceManagerCheckpoint interface {
checkpointmanager.Checkpoint checkpointmanager.Checkpoint
GetData() ([]PodDevicesEntry, map[string][]string) GetDataInLatestFormat() ([]PodDevicesEntry, map[string][]string)
} }
// DevicesPerNUMA represents device ids obtained from device plugin per NUMA node id // DevicesPerNUMA represents device ids obtained from device plugin per NUMA node id
...@@ -72,9 +72,13 @@ func (dev DevicesPerNUMA) Devices() sets.String { ...@@ -72,9 +72,13 @@ func (dev DevicesPerNUMA) Devices() sets.String {
return result return result
} }
// New returns an instance of Checkpoint // New returns an instance of Checkpoint - must be an alias for the most recent version
func New(devEntries []PodDevicesEntry, func New(devEntries []PodDevicesEntry, devices map[string][]string) DeviceManagerCheckpoint {
devices map[string][]string) DeviceManagerCheckpoint { return NewV2(devEntries, devices)
}
// NewV2 returns an instance of Checkpoint (k8s >= 1.20)
func NewV2(devEntries []PodDevicesEntry, devices map[string][]string) DeviceManagerCheckpoint {
return &Data{ return &Data{
Data: checkpointData{ Data: checkpointData{
PodDeviceEntries: devEntries, PodDeviceEntries: devEntries,
...@@ -99,7 +103,8 @@ func (cp *Data) VerifyChecksum() error { ...@@ -99,7 +103,8 @@ func (cp *Data) VerifyChecksum() error {
return cp.Checksum.Verify(cp.Data) return cp.Checksum.Verify(cp.Data)
} }
// GetData returns device entries and registered devices // GetDataInLatestFormat returns device entries and registered devices in the *most recent*
func (cp *Data) GetData() ([]PodDevicesEntry, map[string][]string) { // checkpoint format, *not* in the original format stored on disk.
func (cp *Data) GetDataInLatestFormat() ([]PodDevicesEntry, map[string][]string) {
return cp.Data.PodDeviceEntries, cp.Data.RegisteredDevices return cp.Data.PodDeviceEntries, cp.Data.RegisteredDevices
} }
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package checkpoint
import (
"encoding/json"
"hash/fnv"
"strings"
"github.com/davecgh/go-spew/spew"
"k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum"
"k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors"
)
// PodDevicesEntryV1 connects pod information to devices, without topology information (k8s <= 1.19)
type PodDevicesEntryV1 struct {
PodUID string
ContainerName string
ResourceName string
DeviceIDs []string
AllocResp []byte
}
// checkpointDataV1 struct is used to store pod to device allocation information
// in a checkpoint file, without topology information (k8s <= 1.19)
type checkpointDataV1 struct {
PodDeviceEntries []PodDevicesEntryV1
RegisteredDevices map[string][]string
}
// checksum compute the checksum using the same algorithms (and data type names) k8s 1.19 used.
// We need this special code path to be able to correctly validate the checksum k8s 1.19 wrote.
// credits to https://github.com/kubernetes/kubernetes/pull/102717/commits/353f93895118d2ffa2d59a29a1fbc225160ea1d6
func (cp checkpointDataV1) checksum() checksum.Checksum {
printer := spew.ConfigState{
Indent: " ",
SortKeys: true,
DisableMethods: true,
SpewKeys: true,
}
object := printer.Sprintf("%#v", cp)
object = strings.Replace(object, "checkpointDataV1", "checkpointData", 1)
object = strings.Replace(object, "PodDevicesEntryV1", "PodDevicesEntry", -1)
hash := fnv.New32a()
printer.Fprintf(hash, "%v", object)
return checksum.Checksum(hash.Sum32())
}
// DataV1 holds checkpoint data and its checksum, in V1 (k8s <= 1.19) format
type DataV1 struct {
Data checkpointDataV1
Checksum checksum.Checksum
}
// NewV1 returns an instance of Checkpoint, in V1 (k8s <= 1.19) format.
// Users should avoid creating checkpoints in formats different than the most recent one,
// use the old formats only to validate existing checkpoint and convert them to most recent
// format. The only exception should be test code.
func NewV1(devEntries []PodDevicesEntryV1,
devices map[string][]string) DeviceManagerCheckpoint {
return &DataV1{
Data: checkpointDataV1{
PodDeviceEntries: devEntries,
RegisteredDevices: devices,
},
}
}
// MarshalCheckpoint is needed to implement the Checkpoint interface, but should not be called anymore
func (cp *DataV1) MarshalCheckpoint() ([]byte, error) {
klog.InfoS("Marshalling a device manager V1 checkpoint")
cp.Checksum = cp.Data.checksum()
return json.Marshal(*cp)
}
// UnmarshalCheckpoint returns unmarshalled data
func (cp *DataV1) UnmarshalCheckpoint(blob []byte) error {
return json.Unmarshal(blob, cp)
}
// VerifyChecksum verifies that passed checksum is same as calculated checksum
func (cp *DataV1) VerifyChecksum() error {
if cp.Checksum != cp.Data.checksum() {
return errors.ErrCorruptCheckpoint
}
return nil
}
// GetDataInLatestFormat returns device entries and registered devices in the *most recent*
// checkpoint format, *not* in the original format stored on disk.
func (cp *DataV1) GetDataInLatestFormat() ([]PodDevicesEntry, map[string][]string) {
var podDevs []PodDevicesEntry
for _, entryV1 := range cp.Data.PodDeviceEntries {
devsPerNuma := NewDevicesPerNUMA()
// no NUMA cell affinity was recorded. The only possible choice
// is to set all the devices affine to node 0.
devsPerNuma[0] = entryV1.DeviceIDs
podDevs = append(podDevs, PodDevicesEntry{
PodUID: entryV1.PodUID,
ContainerName: entryV1.ContainerName,
ResourceName: entryV1.ResourceName,
DeviceIDs: devsPerNuma,
AllocResp: entryV1.AllocResp,
})
}
return podDevs, cp.Data.RegisteredDevices
}
...@@ -585,20 +585,32 @@ func (m *ManagerImpl) writeCheckpoint() error { ...@@ -585,20 +585,32 @@ func (m *ManagerImpl) writeCheckpoint() error {
// Reads device to container allocation information from disk, and populates // Reads device to container allocation information from disk, and populates
// m.allocatedDevices accordingly. // m.allocatedDevices accordingly.
func (m *ManagerImpl) readCheckpoint() error { func (m *ManagerImpl) readCheckpoint() error {
registeredDevs := make(map[string][]string) // the vast majority of time we restore a compatible checkpoint, so we try
devEntries := make([]checkpoint.PodDevicesEntry, 0) // the current version first. Trying to restore older format checkpoints is
cp := checkpoint.New(devEntries, registeredDevs) // relevant only in the kubelet upgrade flow, which happens once in a
err := m.checkpointManager.GetCheckpoint(kubeletDeviceManagerCheckpoint, cp) // (long) while.
cp, err := m.getCheckpointV2()
if err != nil { if err != nil {
if err == errors.ErrCheckpointNotFound { if err == errors.ErrCheckpointNotFound {
klog.Warningf("Failed to retrieve checkpoint for %q: %v", kubeletDeviceManagerCheckpoint, err) klog.Warningf("Failed to retrieve checkpoint for %q: %v", kubeletDeviceManagerCheckpoint, err)
return nil return nil
} }
return err
var errv1 error
// one last try: maybe it's a old format checkpoint?
cp, errv1 = m.getCheckpointV1()
if errv1 != nil {
klog.InfoS("Failed to read checkpoint V1 file", "err", errv1)
// intentionally return the parent error. We expect to restore V1 checkpoints
// a tiny fraction of time, so what matters most is the current checkpoint read error.
return err
}
klog.InfoS("Read data from a V1 checkpoint", "checkpoint", kubeletDeviceManagerCheckpoint)
} }
m.mutex.Lock() m.mutex.Lock()
defer m.mutex.Unlock() defer m.mutex.Unlock()
podDevices, registeredDevs := cp.GetData() podDevices, registeredDevs := cp.GetDataInLatestFormat()
m.podDevices.fromCheckpointData(podDevices) m.podDevices.fromCheckpointData(podDevices)
m.allocatedDevices = m.podDevices.devices() m.allocatedDevices = m.podDevices.devices()
for resource := range registeredDevs { for resource := range registeredDevs {
...@@ -611,6 +623,22 @@ func (m *ManagerImpl) readCheckpoint() error { ...@@ -611,6 +623,22 @@ func (m *ManagerImpl) readCheckpoint() error {
return nil return nil
} }
func (m *ManagerImpl) getCheckpointV2() (checkpoint.DeviceManagerCheckpoint, error) {
registeredDevs := make(map[string][]string)
devEntries := make([]checkpoint.PodDevicesEntry, 0)
cp := checkpoint.New(devEntries, registeredDevs)
err := m.checkpointManager.GetCheckpoint(kubeletDeviceManagerCheckpoint, cp)
return cp, err
}
func (m *ManagerImpl) getCheckpointV1() (checkpoint.DeviceManagerCheckpoint, error) {
registeredDevs := make(map[string][]string)
devEntries := make([]checkpoint.PodDevicesEntryV1, 0)
cp := checkpoint.NewV1(devEntries, registeredDevs)
err := m.checkpointManager.GetCheckpoint(kubeletDeviceManagerCheckpoint, cp)
return cp, err
}
// UpdateAllocatedDevices frees any Devices that are bound to terminated pods. // UpdateAllocatedDevices frees any Devices that are bound to terminated pods.
func (m *ManagerImpl) UpdateAllocatedDevices() { func (m *ManagerImpl) UpdateAllocatedDevices() {
activePods := m.activePods() activePods := m.activePods()
......
...@@ -24,20 +24,12 @@ import ( ...@@ -24,20 +24,12 @@ import (
"path/filepath" "path/filepath"
"time" "time"
"k8s.io/klog/v2"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
) )
// 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) {
info, err := ds.client.Info() bytes, inodes, err := dirSize(filepath.Join(ds.dockerRootDir, "image"))
if err != nil {
klog.Errorf("Failed to get docker info: %v", err)
return nil, err
}
bytes, inodes, err := dirSize(filepath.Join(info.DockerRootDir, "image"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -47,7 +39,7 @@ func (ds *dockerService) ImageFsInfo(_ context.Context, _ *runtimeapi.ImageFsInf ...@@ -47,7 +39,7 @@ func (ds *dockerService) ImageFsInfo(_ context.Context, _ *runtimeapi.ImageFsInf
{ {
Timestamp: time.Now().Unix(), Timestamp: time.Now().Unix(),
FsId: &runtimeapi.FilesystemIdentifier{ FsId: &runtimeapi.FilesystemIdentifier{
Mountpoint: info.DockerRootDir, Mountpoint: ds.dockerRootDir,
}, },
UsedBytes: &runtimeapi.UInt64Value{ UsedBytes: &runtimeapi.UInt64Value{
Value: uint64(bytes), Value: uint64(bytes),
......
...@@ -30,16 +30,10 @@ import ( ...@@ -30,16 +30,10 @@ import (
// 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) {
info, err := ds.client.Info()
if err != nil {
klog.Errorf("Failed to get docker info: %v", err)
return nil, err
}
statsClient := &winstats.StatsClient{} statsClient := &winstats.StatsClient{}
fsinfo, err := statsClient.GetDirFsInfo(info.DockerRootDir) fsinfo, err := statsClient.GetDirFsInfo(ds.dockerRootDir)
if err != nil { if err != nil {
klog.Errorf("Failed to get dir fsInfo for %q: %v", info.DockerRootDir, err) klog.Errorf("Failed to get dir fsInfo for %q: %v", ds.dockerRootDir, err)
return nil, err return nil, err
} }
...@@ -48,7 +42,7 @@ func (ds *dockerService) ImageFsInfo(_ context.Context, _ *runtimeapi.ImageFsInf ...@@ -48,7 +42,7 @@ func (ds *dockerService) ImageFsInfo(_ context.Context, _ *runtimeapi.ImageFsInf
Timestamp: time.Now().UnixNano(), Timestamp: time.Now().UnixNano(),
UsedBytes: &runtimeapi.UInt64Value{Value: fsinfo.Usage}, UsedBytes: &runtimeapi.UInt64Value{Value: fsinfo.Usage},
FsId: &runtimeapi.FilesystemIdentifier{ FsId: &runtimeapi.FilesystemIdentifier{
Mountpoint: info.DockerRootDir, Mountpoint: ds.dockerRootDir,
}, },
}, },
} }
......
...@@ -255,16 +255,17 @@ func NewDockerService(config *ClientConfig, podSandboxImage string, streamingCon ...@@ -255,16 +255,17 @@ func NewDockerService(config *ClientConfig, podSandboxImage string, streamingCon
ds.network = network.NewPluginManager(plug) ds.network = network.NewPluginManager(plug)
klog.Infof("Docker cri networking managed by %v", plug.Name()) klog.Infof("Docker cri networking managed by %v", plug.Name())
dockerInfo, err := ds.client.Info()
if err != nil {
return nil, fmt.Errorf("Failed to execute Info() call to the Docker client")
}
klog.InfoS("Docker Info", "dockerInfo", dockerInfo)
ds.dockerRootDir = dockerInfo.DockerRootDir
// skipping cgroup driver checks for Windows // skipping cgroup driver checks for Windows
if runtime.GOOS == "linux" { if runtime.GOOS == "linux" {
// NOTE: cgroup driver is only detectable in docker 1.11+
cgroupDriver := defaultCgroupDriver cgroupDriver := defaultCgroupDriver
dockerInfo, err := ds.client.Info() if len(dockerInfo.CgroupDriver) == 0 {
klog.Infof("Docker Info: %+v", dockerInfo)
if err != nil {
klog.Errorf("Failed to execute Info() call to the Docker client: %v", err)
klog.Warningf("Falling back to use the default driver: %q", cgroupDriver)
} else if len(dockerInfo.CgroupDriver) == 0 {
klog.Warningf("No cgroup driver is set in Docker") klog.Warningf("No cgroup driver is set in Docker")
klog.Warningf("Falling back to use the default driver: %q", cgroupDriver) klog.Warningf("Falling back to use the default driver: %q", cgroupDriver)
} else { } else {
...@@ -312,6 +313,9 @@ type dockerService struct { ...@@ -312,6 +313,9 @@ type dockerService struct {
// the docker daemon every time we need to do such checks. // the docker daemon every time we need to do such checks.
versionCache *cache.ObjectCache versionCache *cache.ObjectCache
// docker root directory
dockerRootDir string
// containerCleanupInfos maps container IDs to the `containerCleanupInfo` structs // containerCleanupInfos maps container IDs to the `containerCleanupInfo` structs
// needed to clean up after containers have been removed. // needed to clean up after containers have been removed.
// (see `applyPlatformSpecificDockerConfig` and `performPlatformSpecificContainerCleanup` // (see `applyPlatformSpecificDockerConfig` and `performPlatformSpecificContainerCleanup`
......
...@@ -20,13 +20,24 @@ package dockershim ...@@ -20,13 +20,24 @@ package dockershim
import ( import (
"context" "context"
"fmt"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
) )
// ContainerStats returns stats for a container stats request based on container id. // ContainerStats returns stats for a container stats request based on container id.
func (ds *dockerService) ContainerStats(_ context.Context, r *runtimeapi.ContainerStatsRequest) (*runtimeapi.ContainerStatsResponse, error) { func (ds *dockerService) ContainerStats(ctx context.Context, r *runtimeapi.ContainerStatsRequest) (*runtimeapi.ContainerStatsResponse, error) {
stats, err := ds.getContainerStats(r.ContainerId) filter := &runtimeapi.ContainerFilter{
Id: r.ContainerId,
}
listResp, err := ds.ListContainers(ctx, &runtimeapi.ListContainersRequest{Filter: filter})
if err != nil {
return nil, err
}
if len(listResp.Containers) != 1 {
return nil, fmt.Errorf("container with id %s not found", r.ContainerId)
}
stats, err := ds.getContainerStats(listResp.Containers[0])
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -51,7 +62,7 @@ func (ds *dockerService) ListContainerStats(ctx context.Context, r *runtimeapi.L ...@@ -51,7 +62,7 @@ func (ds *dockerService) ListContainerStats(ctx context.Context, r *runtimeapi.L
var stats []*runtimeapi.ContainerStats var stats []*runtimeapi.ContainerStats
for _, container := range listResp.Containers { for _, container := range listResp.Containers {
containerStats, err := ds.getContainerStats(container.Id) containerStats, err := ds.getContainerStats(container)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -19,42 +19,30 @@ limitations under the License. ...@@ -19,42 +19,30 @@ limitations under the License.
package dockershim package dockershim
import ( import (
"context"
"time" "time"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
) )
func (ds *dockerService) getContainerStats(containerID string) (*runtimeapi.ContainerStats, error) { func (ds *dockerService) getContainerStats(c *runtimeapi.Container) (*runtimeapi.ContainerStats, error) {
info, err := ds.client.Info() statsJSON, err := ds.client.GetContainerStats(c.Id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
statsJSON, err := ds.client.GetContainerStats(containerID) containerJSON, err := ds.client.InspectContainerWithSize(c.Id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
containerJSON, err := ds.client.InspectContainerWithSize(containerID)
if err != nil {
return nil, err
}
statusResp, err := ds.ContainerStatus(context.Background(), &runtimeapi.ContainerStatusRequest{ContainerId: containerID})
if err != nil {
return nil, err
}
status := statusResp.GetStatus()
dockerStats := statsJSON.Stats dockerStats := statsJSON.Stats
timestamp := time.Now().UnixNano() timestamp := time.Now().UnixNano()
containerStats := &runtimeapi.ContainerStats{ containerStats := &runtimeapi.ContainerStats{
Attributes: &runtimeapi.ContainerAttributes{ Attributes: &runtimeapi.ContainerAttributes{
Id: containerID, Id: c.Id,
Metadata: status.Metadata, Metadata: c.Metadata,
Labels: status.Labels, Labels: c.Labels,
Annotations: status.Annotations, Annotations: c.Annotations,
}, },
Cpu: &runtimeapi.CpuUsage{ Cpu: &runtimeapi.CpuUsage{
Timestamp: timestamp, Timestamp: timestamp,
...@@ -66,7 +54,7 @@ func (ds *dockerService) getContainerStats(containerID string) (*runtimeapi.Cont ...@@ -66,7 +54,7 @@ func (ds *dockerService) getContainerStats(containerID string) (*runtimeapi.Cont
}, },
WritableLayer: &runtimeapi.FilesystemUsage{ WritableLayer: &runtimeapi.FilesystemUsage{
Timestamp: timestamp, Timestamp: timestamp,
FsId: &runtimeapi.FilesystemIdentifier{Mountpoint: info.DockerRootDir}, FsId: &runtimeapi.FilesystemIdentifier{Mountpoint: ds.dockerRootDir},
UsedBytes: &runtimeapi.UInt64Value{Value: uint64(*containerJSON.SizeRw)}, UsedBytes: &runtimeapi.UInt64Value{Value: uint64(*containerJSON.SizeRw)},
}, },
} }
......
...@@ -24,6 +24,6 @@ import ( ...@@ -24,6 +24,6 @@ import (
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
) )
func (ds *dockerService) getContainerStats(containerID string) (*runtimeapi.ContainerStats, error) { func (ds *dockerService) getContainerStats(c *runtimeapi.Container) (*runtimeapi.ContainerStats, error) {
return nil, fmt.Errorf("not implemented") return nil, fmt.Errorf("not implemented")
} }
...@@ -19,7 +19,6 @@ limitations under the License. ...@@ -19,7 +19,6 @@ limitations under the License.
package dockershim package dockershim
import ( import (
"context"
"strings" "strings"
"time" "time"
...@@ -28,26 +27,21 @@ import ( ...@@ -28,26 +27,21 @@ import (
"k8s.io/klog/v2" "k8s.io/klog/v2"
) )
func (ds *dockerService) getContainerStats(containerID string) (*runtimeapi.ContainerStats, error) { func (ds *dockerService) getContainerStats(c *runtimeapi.Container) (*runtimeapi.ContainerStats, error) {
info, err := ds.client.Info() hcsshimContainer, err := hcsshim.OpenContainer(c.Id)
if err != nil {
return nil, err
}
hcsshimContainer, err := hcsshim.OpenContainer(containerID)
if err != nil { if err != nil {
// As we moved from using Docker stats to hcsshim directly, we may query HCS with already exited container IDs. // As we moved from using Docker stats to hcsshim directly, we may query HCS with already exited container IDs.
// That will typically happen with init-containers in Exited state. Docker still knows about them but the HCS does not. // That will typically happen with init-containers in Exited state. Docker still knows about them but the HCS does not.
// As we don't want to block stats retrieval for other containers, we only log errors. // As we don't want to block stats retrieval for other containers, we only log errors.
if !hcsshim.IsNotExist(err) && !hcsshim.IsAlreadyStopped(err) { if !hcsshim.IsNotExist(err) && !hcsshim.IsAlreadyStopped(err) {
klog.V(4).Infof("Error opening container (stats will be missing) '%s': %v", containerID, err) klog.V(4).Infof("Error opening container (stats will be missing) '%s': %v", c.Id, err)
} }
return nil, nil return nil, nil
} }
defer func() { defer func() {
closeErr := hcsshimContainer.Close() closeErr := hcsshimContainer.Close()
if closeErr != nil { if closeErr != nil {
klog.Errorf("Error closing container '%s': %v", containerID, closeErr) klog.Errorf("Error closing container '%s': %v", c.Id, closeErr)
} }
}() }()
...@@ -60,30 +54,19 @@ func (ds *dockerService) getContainerStats(containerID string) (*runtimeapi.Cont ...@@ -60,30 +54,19 @@ func (ds *dockerService) getContainerStats(containerID string) (*runtimeapi.Cont
// These hcs errors do not have helpers exposed in public package so need to query for the known codes // These hcs errors do not have helpers exposed in public package so need to query for the known codes
// https://github.com/microsoft/hcsshim/blob/master/internal/hcs/errors.go // https://github.com/microsoft/hcsshim/blob/master/internal/hcs/errors.go
// PR to expose helpers in hcsshim: https://github.com/microsoft/hcsshim/pull/933 // PR to expose helpers in hcsshim: https://github.com/microsoft/hcsshim/pull/933
klog.V(4).Infof("Container is not in a state that stats can be accessed '%s': %v. This occurs when the container is created but not started.", containerID, err) klog.V(4).Infof("Container is not in a state that stats can be accessed '%s': %v. This occurs when the container is created but not started.", c.Id, err)
return nil, nil return nil, nil
} }
return nil, err return nil, err
} }
containerJSON, err := ds.client.InspectContainerWithSize(containerID)
if err != nil {
return nil, err
}
statusResp, err := ds.ContainerStatus(context.Background(), &runtimeapi.ContainerStatusRequest{ContainerId: containerID})
if err != nil {
return nil, err
}
status := statusResp.GetStatus()
timestamp := time.Now().UnixNano() timestamp := time.Now().UnixNano()
containerStats := &runtimeapi.ContainerStats{ containerStats := &runtimeapi.ContainerStats{
Attributes: &runtimeapi.ContainerAttributes{ Attributes: &runtimeapi.ContainerAttributes{
Id: containerID, Id: c.Id,
Metadata: status.Metadata, Metadata: c.Metadata,
Labels: status.Labels, Labels: c.Labels,
Annotations: status.Annotations, Annotations: c.Annotations,
}, },
Cpu: &runtimeapi.CpuUsage{ Cpu: &runtimeapi.CpuUsage{
Timestamp: timestamp, Timestamp: timestamp,
...@@ -96,8 +79,11 @@ func (ds *dockerService) getContainerStats(containerID string) (*runtimeapi.Cont ...@@ -96,8 +79,11 @@ func (ds *dockerService) getContainerStats(containerID string) (*runtimeapi.Cont
}, },
WritableLayer: &runtimeapi.FilesystemUsage{ WritableLayer: &runtimeapi.FilesystemUsage{
Timestamp: timestamp, Timestamp: timestamp,
FsId: &runtimeapi.FilesystemIdentifier{Mountpoint: info.DockerRootDir}, FsId: &runtimeapi.FilesystemIdentifier{Mountpoint: ds.dockerRootDir},
UsedBytes: &runtimeapi.UInt64Value{Value: uint64(*containerJSON.SizeRw)}, // used bytes from image are not implemented on Windows
// don't query for it since it is expensive to call docker over named pipe
// https://github.com/moby/moby/blob/1ba54a5fd0ba293db3bea46cd67604b593f2048b/daemon/images/image_windows.go#L11-L14
UsedBytes: &runtimeapi.UInt64Value{Value: 0},
}, },
} }
return containerStats, nil return containerStats, nil
......
...@@ -225,6 +225,7 @@ func convertFakeContainer(f *FakeContainer) *dockertypes.ContainerJSON { ...@@ -225,6 +225,7 @@ func convertFakeContainer(f *FakeContainer) *dockertypes.ContainerJSON {
if f.HostConfig == nil { if f.HostConfig == nil {
f.HostConfig = &dockercontainer.HostConfig{} f.HostConfig = &dockercontainer.HostConfig{}
} }
fakeRWSize := int64(40)
return &dockertypes.ContainerJSON{ return &dockertypes.ContainerJSON{
ContainerJSONBase: &dockertypes.ContainerJSONBase{ ContainerJSONBase: &dockertypes.ContainerJSONBase{
ID: f.ID, ID: f.ID,
...@@ -239,6 +240,7 @@ func convertFakeContainer(f *FakeContainer) *dockertypes.ContainerJSON { ...@@ -239,6 +240,7 @@ func convertFakeContainer(f *FakeContainer) *dockertypes.ContainerJSON {
}, },
Created: dockerTimestampToString(f.CreatedAt), Created: dockerTimestampToString(f.CreatedAt),
HostConfig: f.HostConfig, HostConfig: f.HostConfig,
SizeRw: &fakeRWSize,
}, },
Config: f.Config, Config: f.Config,
NetworkSettings: &dockertypes.NetworkSettings{}, NetworkSettings: &dockertypes.NetworkSettings{},
......
...@@ -506,6 +506,11 @@ func (asw *actualStateOfWorld) AddPodToVolume(markVolumeOpts operationexecutor.M ...@@ -506,6 +506,11 @@ func (asw *actualStateOfWorld) AddPodToVolume(markVolumeOpts operationexecutor.M
// If pod exists, reset remountRequired value // If pod exists, reset remountRequired value
podObj.remountRequired = false podObj.remountRequired = false
podObj.volumeMountStateForPod = markVolumeOpts.VolumeMountState podObj.volumeMountStateForPod = markVolumeOpts.VolumeMountState
if mounter != nil {
// The mounter stored in the object may have old information,
// use the newest one.
podObj.mounter = mounter
}
asw.attachedVolumes[volumeName].mountedPods[podName] = podObj asw.attachedVolumes[volumeName].mountedPods[podName] = podObj
return nil return nil
} }
......
...@@ -375,8 +375,10 @@ func addAllEventHandlers( ...@@ -375,8 +375,10 @@ func addAllEventHandlers(
case *v1.Pod: case *v1.Pod:
return assignedPod(t) return assignedPod(t)
case cache.DeletedFinalStateUnknown: case cache.DeletedFinalStateUnknown:
if pod, ok := t.Obj.(*v1.Pod); ok { if _, ok := t.Obj.(*v1.Pod); ok {
return assignedPod(pod) // The carried object may be stale, so we don't use it to check if
// it's assigned or not. Attempting to cleanup anyways.
return true
} }
utilruntime.HandleError(fmt.Errorf("unable to convert object %T to *v1.Pod in %T", obj, sched)) utilruntime.HandleError(fmt.Errorf("unable to convert object %T to *v1.Pod in %T", obj, sched))
return false return false
...@@ -401,7 +403,9 @@ func addAllEventHandlers( ...@@ -401,7 +403,9 @@ func addAllEventHandlers(
return !assignedPod(t) && responsibleForPod(t, sched.Profiles) return !assignedPod(t) && responsibleForPod(t, sched.Profiles)
case cache.DeletedFinalStateUnknown: case cache.DeletedFinalStateUnknown:
if pod, ok := t.Obj.(*v1.Pod); ok { if pod, ok := t.Obj.(*v1.Pod); ok {
return !assignedPod(pod) && responsibleForPod(pod, sched.Profiles) // The carried object may be stale, so we don't use it to check if
// it's assigned or not.
return responsibleForPod(pod, sched.Profiles)
} }
utilruntime.HandleError(fmt.Errorf("unable to convert object %T to *v1.Pod in %T", obj, sched)) utilruntime.HandleError(fmt.Errorf("unable to convert object %T to *v1.Pod in %T", obj, sched))
return false return false
......
...@@ -51,6 +51,7 @@ var systemDefaultConstraints = []v1.TopologySpreadConstraint{ ...@@ -51,6 +51,7 @@ var systemDefaultConstraints = []v1.TopologySpreadConstraint{
// PodTopologySpread is a plugin that ensures pod's topologySpreadConstraints is satisfied. // PodTopologySpread is a plugin that ensures pod's topologySpreadConstraints is satisfied.
type PodTopologySpread struct { type PodTopologySpread struct {
systemDefaulted bool
defaultConstraints []v1.TopologySpreadConstraint defaultConstraints []v1.TopologySpreadConstraint
sharedLister framework.SharedLister sharedLister framework.SharedLister
services corelisters.ServiceLister services corelisters.ServiceLister
...@@ -92,6 +93,7 @@ func New(plArgs runtime.Object, h framework.Handle) (framework.Plugin, error) { ...@@ -92,6 +93,7 @@ func New(plArgs runtime.Object, h framework.Handle) (framework.Plugin, error) {
} }
if args.DefaultingType == config.SystemDefaulting { if args.DefaultingType == config.SystemDefaulting {
pl.defaultConstraints = systemDefaultConstraints pl.defaultConstraints = systemDefaultConstraints
pl.systemDefaulted = true
} }
if len(pl.defaultConstraints) != 0 { if len(pl.defaultConstraints) != 0 {
if h.SharedInformerFactory() == nil { if h.SharedInformerFactory() == nil {
......
...@@ -57,7 +57,7 @@ func (s *preScoreState) Clone() framework.StateData { ...@@ -57,7 +57,7 @@ func (s *preScoreState) Clone() framework.StateData {
// 1) s.TopologyPairToPodCounts: keyed with both eligible topology pair and node names. // 1) s.TopologyPairToPodCounts: keyed with both eligible topology pair and node names.
// 2) s.IgnoredNodes: the set of nodes that shouldn't be scored. // 2) s.IgnoredNodes: the set of nodes that shouldn't be scored.
// 3) s.TopologyNormalizingWeight: The weight to be given to each constraint based on the number of values in a topology. // 3) s.TopologyNormalizingWeight: The weight to be given to each constraint based on the number of values in a topology.
func (pl *PodTopologySpread) initPreScoreState(s *preScoreState, pod *v1.Pod, filteredNodes []*v1.Node) error { func (pl *PodTopologySpread) initPreScoreState(s *preScoreState, pod *v1.Pod, filteredNodes []*v1.Node, requireAllTopologies bool) error {
var err error var err error
if len(pod.Spec.TopologySpreadConstraints) > 0 { if len(pod.Spec.TopologySpreadConstraints) > 0 {
s.Constraints, err = filterTopologySpreadConstraints(pod.Spec.TopologySpreadConstraints, v1.ScheduleAnyway) s.Constraints, err = filterTopologySpreadConstraints(pod.Spec.TopologySpreadConstraints, v1.ScheduleAnyway)
...@@ -75,7 +75,7 @@ func (pl *PodTopologySpread) initPreScoreState(s *preScoreState, pod *v1.Pod, fi ...@@ -75,7 +75,7 @@ func (pl *PodTopologySpread) initPreScoreState(s *preScoreState, pod *v1.Pod, fi
} }
topoSize := make([]int, len(s.Constraints)) topoSize := make([]int, len(s.Constraints))
for _, node := range filteredNodes { for _, node := range filteredNodes {
if !nodeLabelsMatchSpreadConstraints(node.Labels, s.Constraints) { if requireAllTopologies && !nodeLabelsMatchSpreadConstraints(node.Labels, s.Constraints) {
// Nodes which don't have all required topologyKeys present are ignored // Nodes which don't have all required topologyKeys present are ignored
// when scoring later. // when scoring later.
s.IgnoredNodes.Insert(node.Name) s.IgnoredNodes.Insert(node.Name)
...@@ -126,7 +126,11 @@ func (pl *PodTopologySpread) PreScore( ...@@ -126,7 +126,11 @@ func (pl *PodTopologySpread) PreScore(
IgnoredNodes: sets.NewString(), IgnoredNodes: sets.NewString(),
TopologyPairToPodCounts: make(map[topologyPair]*int64), TopologyPairToPodCounts: make(map[topologyPair]*int64),
} }
err = pl.initPreScoreState(state, pod, filteredNodes) // Only require that nodes have all the topology labels if using
// non-system-default spreading rules. This allows nodes that don't have a
// zone label to still have hostname spreading.
requireAllTopologies := len(pod.Spec.TopologySpreadConstraints) > 0 || !pl.systemDefaulted
err = pl.initPreScoreState(state, pod, filteredNodes, requireAllTopologies)
if err != nil { if err != nil {
return framework.AsStatus(fmt.Errorf("calculating preScoreState: %w", err)) return framework.AsStatus(fmt.Errorf("calculating preScoreState: %w", err))
} }
...@@ -146,7 +150,7 @@ func (pl *PodTopologySpread) PreScore( ...@@ -146,7 +150,7 @@ func (pl *PodTopologySpread) PreScore(
// (1) `node` should satisfy incoming pod's NodeSelector/NodeAffinity // (1) `node` should satisfy incoming pod's NodeSelector/NodeAffinity
// (2) All topologyKeys need to be present in `node` // (2) All topologyKeys need to be present in `node`
if !pluginhelper.PodMatchesNodeSelectorAndAffinityTerms(pod, node) || if !pluginhelper.PodMatchesNodeSelectorAndAffinityTerms(pod, node) ||
!nodeLabelsMatchSpreadConstraints(node.Labels, state.Constraints) { (requireAllTopologies && !nodeLabelsMatchSpreadConstraints(node.Labels, state.Constraints)) {
return return
} }
......
...@@ -549,22 +549,19 @@ func (cache *schedulerCache) RemovePod(pod *v1.Pod) error { ...@@ -549,22 +549,19 @@ func (cache *schedulerCache) RemovePod(pod *v1.Pod) error {
currState, ok := cache.podStates[key] currState, ok := cache.podStates[key]
switch { switch {
// An assumed pod won't have Delete/Remove event. It needs to have Add event case ok:
// before Remove event, in which case the state would change from Assumed to Added.
case ok && !cache.assumedPods[key]:
if currState.pod.Spec.NodeName != pod.Spec.NodeName { if currState.pod.Spec.NodeName != pod.Spec.NodeName {
klog.Errorf("Pod %v was assumed to be on %v but got added to %v", key, pod.Spec.NodeName, currState.pod.Spec.NodeName) klog.Errorf("Pod %v was assumed to be on %v but got added to %v", key, pod.Spec.NodeName, currState.pod.Spec.NodeName)
klog.Fatalf("Schedulercache is corrupted and can badly affect scheduling decisions") if pod.Spec.NodeName != "" {
} // An empty NodeName is possible when the scheduler misses a Delete
err := cache.removePod(currState.pod) // event and it gets the last known state from the informer cache.
if err != nil { klog.Fatalf("Schedulercache is corrupted and can badly affect scheduling decisions")
return err }
} }
delete(cache.podStates, key) return cache.expirePod(key, currState)
default: default:
return fmt.Errorf("pod %v is not found in scheduler cache, so cannot be removed from it", key) return fmt.Errorf("pod %v is not found in scheduler cache, so cannot be removed from it", key)
} }
return nil
} }
func (cache *schedulerCache) IsAssumedPod(pod *v1.Pod) (bool, error) { func (cache *schedulerCache) IsAssumedPod(pod *v1.Pod) (bool, error) {
......
...@@ -55,6 +55,9 @@ const ( ...@@ -55,6 +55,9 @@ const (
SchedulerError = "SchedulerError" SchedulerError = "SchedulerError"
// Percentage of plugin metrics to be sampled. // Percentage of plugin metrics to be sampled.
pluginMetricsSamplePercent = 10 pluginMetricsSamplePercent = 10
// Duration the scheduler will wait before expiring an assumed pod.
// See issue #106361 for more details about this parameter and its value.
durationToExpireAssumedPod = 2 * time.Minute
) )
// Scheduler watches for new unscheduled pods. It attempts to find // Scheduler watches for new unscheduled pods. It attempts to find
...@@ -202,8 +205,7 @@ func New(client clientset.Interface, ...@@ -202,8 +205,7 @@ func New(client clientset.Interface,
opt(&options) opt(&options)
} }
schedulerCache := internalcache.New(30*time.Second, stopEverything) schedulerCache := internalcache.New(durationToExpireAssumedPod, stopEverything)
registry := frameworkplugins.NewInTreeRegistry() registry := frameworkplugins.NewInTreeRegistry()
if err := registry.Merge(options.frameworkOutOfTreeRegistry); err != nil { if err := registry.Merge(options.frameworkOutOfTreeRegistry); err != nil {
return nil, err return nil, err
......
...@@ -1492,11 +1492,11 @@ func (ss *scaleSet) ensureBackendPoolDeletedFromVMSS(service *v1.Service, backen ...@@ -1492,11 +1492,11 @@ func (ss *scaleSet) ensureBackendPoolDeletedFromVMSS(service *v1.Service, backen
// When vmss is being deleted, CreateOrUpdate API would report "the vmss is being deleted" error. // When vmss is being deleted, CreateOrUpdate API would report "the vmss is being deleted" error.
// Since it is being deleted, we shouldn't send more CreateOrUpdate requests for it. // Since it is being deleted, we shouldn't send more CreateOrUpdate requests for it.
if vmss.ProvisioningState != nil && strings.EqualFold(*vmss.ProvisioningState, virtualMachineScaleSetsDeallocating) { if vmss.ProvisioningState != nil && strings.EqualFold(*vmss.ProvisioningState, virtualMachineScaleSetsDeallocating) {
klog.V(3).Infof("ensureVMSSInPool: found vmss %s being deleted, skipping", vmssName) klog.V(3).Infof("ensureBackendPoolDeletedFromVMSS: found vmss %s being deleted, skipping", vmssName)
continue continue
} }
if vmss.VirtualMachineProfile.NetworkProfile.NetworkInterfaceConfigurations == nil { if vmss.VirtualMachineProfile.NetworkProfile.NetworkInterfaceConfigurations == nil {
klog.V(4).Infof("EnsureHostInPool: cannot obtain the primary network interface configuration, of vmss %s", vmssName) klog.V(4).Infof("ensureBackendPoolDeletedFromVMSS: cannot obtain the primary network interface configuration, of vmss %s", vmssName)
continue continue
} }
vmssNIC := *vmss.VirtualMachineProfile.NetworkProfile.NetworkInterfaceConfigurations vmssNIC := *vmss.VirtualMachineProfile.NetworkProfile.NetworkInterfaceConfigurations
...@@ -1615,6 +1615,11 @@ func (ss *scaleSet) EnsureBackendPoolDeleted(service *v1.Service, backendPoolID, ...@@ -1615,6 +1615,11 @@ func (ss *scaleSet) EnsureBackendPoolDeleted(service *v1.Service, backendPoolID,
continue continue
} }
if errors.Is(err, cloudprovider.InstanceNotFound) {
klog.Infof("EnsureBackendPoolDeleted(%s): skipping ip config %s because the corresponding vmss vm is not found", getServiceName(service), ipConfigurationID)
continue
}
klog.Errorf("Failed to GetNodeNameByIPConfigurationID(%s): %v", ipConfigurationID, err) klog.Errorf("Failed to GetNodeNameByIPConfigurationID(%s): %v", ipConfigurationID, err)
allErrs = append(allErrs, err) allErrs = append(allErrs, err)
continue continue
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment