rebase: bump k8s.io/kubernetes in the k8s-dependencies group

Bumps the k8s-dependencies group with 1 update: [k8s.io/kubernetes](https://github.com/kubernetes/kubernetes).

Updates `k8s.io/kubernetes` from 1.32.3 to 1.33.0
- [Release notes](https://github.com/kubernetes/kubernetes/releases)
- [Commits](https://github.com/kubernetes/kubernetes/compare/v1.32.3...v1.33.0)

---
updated-dependencies:
- dependency-name: k8s.io/kubernetes
  dependency-version: 1.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: k8s-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
dependabot[bot]
2025-04-28 22:16:28 +00:00
committed by mergify[bot]
parent 4147d5d15a
commit 51895f8619
699 changed files with 51590 additions and 17096 deletions

View File

@ -65,7 +65,7 @@ func (a *clientAdapter) Add(in map[clientfeatures.Feature]clientfeatures.Feature
}
out[featuregate.Feature(name)] = converted
}
return a.mfg.Add(out)
return a.mfg.Add(out) //nolint:forbidigo // No need to support versioned feature gates in client adapter
}
// Set implements the unexported interface that client-go feature gate testing expects for

File diff suppressed because it is too large Load Diff

View File

@ -1,841 +0,0 @@
/*
Copyright 2024 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 features
import (
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
"k8s.io/apimachinery/pkg/util/version"
genericfeatures "k8s.io/apiserver/pkg/features"
"k8s.io/component-base/featuregate"
zpagesfeatures "k8s.io/component-base/zpages/features"
kcmfeatures "k8s.io/controller-manager/pkg/features"
)
// defaultVersionedKubernetesFeatureGates consists of all known Kubernetes-specific feature keys with VersionedSpecs.
// To add a new feature, define a key for it in pkg/features/kube_features.go and add it here. The features will be
// available throughout Kubernetes binaries.
// For features available via specific kubernetes components like apiserver,
// cloud-controller-manager, etc find the respective kube_features.go file
// (eg:staging/src/apiserver/pkg/features/kube_features.go), define the versioned
// feature gate there, and reference it in this file.
// To support n-3 compatibility version, features may only be removed 3 releases after graduation.
//
// Entries are alphabetized.
var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate.VersionedSpecs{
AllowDNSOnlyNodeCSR: {
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Deprecated},
},
AllowInsecureKubeletCertificateSigningRequests: {
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Deprecated},
},
AllowOverwriteTerminationGracePeriodSeconds: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Deprecated},
},
AllowServiceLBStatusOnNonLB: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Deprecated},
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Deprecated, LockToDefault: true}, // remove in 1.35
},
AnyVolumeDataSource: {
{Version: version.MustParse("1.18"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.24"), Default: true, PreRelease: featuregate.Beta},
},
AppArmor: {
{Version: version.MustParse("1.4"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.33
},
AppArmorFields: {
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.33
},
AuthorizeNodeWithSelectors: {
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.Beta},
},
kcmfeatures.CloudControllerManagerWebhook: {
{Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Alpha},
},
ClusterTrustBundle: {
{Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Alpha},
},
ClusterTrustBundleProjection: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
},
ContainerCheckpoint: {
{Version: version.MustParse("1.25"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
},
CPUCFSQuotaPeriod: {
{Version: version.MustParse("1.12"), Default: false, PreRelease: featuregate.Alpha},
},
CPUManager: {
{Version: version.MustParse("1.8"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.10"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.26"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // GA in 1.26
},
CPUManagerPolicyAlphaOptions: {
{Version: version.MustParse("1.23"), Default: false, PreRelease: featuregate.Alpha},
},
CPUManagerPolicyBetaOptions: {
{Version: version.MustParse("1.23"), Default: true, PreRelease: featuregate.Beta},
},
CPUManagerPolicyOptions: {
{Version: version.MustParse("1.22"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.23"), Default: true, PreRelease: featuregate.Beta},
},
CronJobsScheduledAnnotation: {
{Version: version.MustParse("1.28"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.35
},
// inherited features from apiextensions-apiserver, relisted here to get a conflict if it is changed
// unintentionally on either side:
apiextensionsfeatures.CRDValidationRatcheting: {
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
},
CrossNamespaceVolumeDataSource: {
{Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Alpha},
},
CSIMigrationPortworx: {
{Version: version.MustParse("1.23"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.25"), Default: false, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta}, // On by default (requires Portworx CSI driver)
},
CSIVolumeHealth: {
{Version: version.MustParse("1.21"), Default: false, PreRelease: featuregate.Alpha},
},
// inherited features from apiextensions-apiserver, relisted here to get a conflict if it is changed
// unintentionally on either side:
apiextensionsfeatures.CustomResourceFieldSelectors: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, LockToDefault: true, PreRelease: featuregate.GA},
},
DevicePluginCDIDevices: {
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.29"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.33
},
DisableAllocatorDualWrite: {
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha}, // remove after MultiCIDRServiceAllocator is GA
},
DisableCloudProviders: {
{Version: version.MustParse("1.22"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.29"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
DisableKubeletCloudCredentialProviders: {
{Version: version.MustParse("1.23"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.29"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
DisableNodeKubeProxyVersion: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Deprecated},
},
DRAAdminAccess: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
DynamicResourceAllocation: {
{Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Beta},
},
DRAResourceClaimDeviceStatus: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
KubeletCrashLoopBackOffMax: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
ElasticIndexedJob: {
{Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // GA in 1.31, remove in 1.32
},
EventedPLEG: {
{Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Alpha},
},
ExecProbeTimeout: {
{Version: version.MustParse("1.20"), Default: true, PreRelease: featuregate.GA}, // lock to default and remove after v1.22 based on KEP #1972 update
},
ExternalServiceAccountTokenSigner: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
genericfeatures.AdmissionWebhookMatchConditions: {
{Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.28"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
genericfeatures.AggregatedDiscoveryEndpoint: {
{Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
genericfeatures.AllowUnsafeMalformedObjectDeletion: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
genericfeatures.AnonymousAuthConfigurableEndpoints: {
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.Beta},
},
genericfeatures.APIListChunking: {
{Version: version.MustParse("1.8"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.9"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.29"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
genericfeatures.APIResponseCompression: {
{Version: version.MustParse("1.8"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.16"), Default: true, PreRelease: featuregate.Beta},
},
genericfeatures.APIServerIdentity: {
{Version: version.MustParse("1.20"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.26"), Default: true, PreRelease: featuregate.Beta},
},
genericfeatures.APIServerTracing: {
{Version: version.MustParse("1.22"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta},
},
genericfeatures.APIServingWithRoutine: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha},
},
genericfeatures.AuthorizeWithSelectors: {
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.Beta},
},
genericfeatures.BtreeWatchCache: {
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.Beta},
},
genericfeatures.CBORServingAndStorage: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
genericfeatures.ConcurrentWatchObjectDecode: {
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Beta},
},
genericfeatures.ConsistentListFromCache: {
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
},
genericfeatures.CoordinatedLeaderElection: {
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
},
genericfeatures.EfficientWatchResumption: {
{Version: version.MustParse("1.20"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.21"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.24"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
genericfeatures.KMSv1: {
{Version: version.MustParse("1.28"), Default: true, PreRelease: featuregate.Deprecated},
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Deprecated},
},
genericfeatures.MutatingAdmissionPolicy: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
genericfeatures.OpenAPIEnums: {
{Version: version.MustParse("1.23"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.24"), Default: true, PreRelease: featuregate.Beta},
},
genericfeatures.RemainingItemCount: {
{Version: version.MustParse("1.15"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.16"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.29"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
genericfeatures.RemoteRequestHeaderUID: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
genericfeatures.ResilientWatchCacheInitialization: {
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
},
genericfeatures.RetryGenerateName: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, LockToDefault: true, PreRelease: featuregate.GA},
},
genericfeatures.SeparateCacheWatchRPC: {
{Version: version.MustParse("1.28"), Default: true, PreRelease: featuregate.Beta},
},
genericfeatures.StorageVersionAPI: {
{Version: version.MustParse("1.20"), Default: false, PreRelease: featuregate.Alpha},
},
genericfeatures.StorageVersionHash: {
{Version: version.MustParse("1.14"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.15"), Default: true, PreRelease: featuregate.Beta},
},
genericfeatures.StrictCostEnforcementForVAP: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
genericfeatures.StrictCostEnforcementForWebhooks: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
genericfeatures.StructuredAuthenticationConfiguration: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
},
genericfeatures.StructuredAuthorizationConfiguration: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
genericfeatures.UnauthenticatedHTTP2DOSMitigation: {
{Version: version.MustParse("1.25"), Default: false, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.29"), Default: true, PreRelease: featuregate.Beta},
},
genericfeatures.WatchBookmark: {
{Version: version.MustParse("1.15"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.16"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.17"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
genericfeatures.WatchCacheInitializationPostStartHook: {
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Beta},
},
genericfeatures.WatchFromStorageWithoutResourceVersion: {
{Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Beta},
},
genericfeatures.WatchList: {
{Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.Beta},
},
GracefulNodeShutdown: {
{Version: version.MustParse("1.20"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.21"), Default: true, PreRelease: featuregate.Beta},
},
GracefulNodeShutdownBasedOnPodPriority: {
{Version: version.MustParse("1.23"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.24"), Default: true, PreRelease: featuregate.Beta},
},
HonorPVReclaimPolicy: {
{Version: version.MustParse("1.23"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
},
HPAScaleToZero: {
{Version: version.MustParse("1.16"), Default: false, PreRelease: featuregate.Alpha},
},
ImageMaximumGCAge: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
},
ImageVolume: {
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
},
InPlacePodVerticalScaling: {
{Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Alpha},
},
InPlacePodVerticalScalingAllocatedStatus: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
InPlacePodVerticalScalingExclusiveCPUs: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
InTreePluginPortworxUnregister: {
{Version: version.MustParse("1.23"), Default: false, PreRelease: featuregate.Alpha},
},
JobBackoffLimitPerIndex: {
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.29"), Default: true, PreRelease: featuregate.Beta},
},
JobManagedBy: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.Beta},
},
JobPodFailurePolicy: {
{Version: version.MustParse("1.25"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.26"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.33
},
JobPodReplacementPolicy: {
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.29"), Default: true, PreRelease: featuregate.Beta},
},
JobSuccessPolicy: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
},
KubeletCgroupDriverFromCRI: {
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
},
KubeletFineGrainedAuthz: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
KubeletInUserNamespace: {
{Version: version.MustParse("1.22"), Default: false, PreRelease: featuregate.Alpha},
},
KubeletPodResourcesDynamicResources: {
{Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Alpha},
},
KubeletPodResourcesGet: {
{Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Alpha},
},
KubeletRegistrationGetOnExistsOnly: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Deprecated},
},
KubeletSeparateDiskGC: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
},
KubeletTracing: {
{Version: version.MustParse("1.25"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta},
},
KubeProxyDrainingTerminatingNodes: {
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // GA in 1.31; remove in 1.33
},
LoadBalancerIPMode: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
LocalStorageCapacityIsolationFSQuotaMonitoring: {
{Version: version.MustParse("1.15"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Beta},
},
LogarithmicScaleDown: {
{Version: version.MustParse("1.21"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.22"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
MatchLabelKeysInPodAffinity: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
},
MatchLabelKeysInPodTopologySpread: {
{Version: version.MustParse("1.25"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta},
},
MaxUnavailableStatefulSet: {
{Version: version.MustParse("1.24"), Default: false, PreRelease: featuregate.Alpha},
},
MemoryManager: {
{Version: version.MustParse("1.21"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.22"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
},
MemoryQoS: {
{Version: version.MustParse("1.22"), Default: false, PreRelease: featuregate.Alpha},
},
MultiCIDRServiceAllocator: {
{Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Beta},
},
NFTablesProxyMode: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
},
NodeInclusionPolicyInPodTopologySpread: {
{Version: version.MustParse("1.25"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.26"), Default: true, PreRelease: featuregate.Beta},
},
NodeLogQuery: {
{Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Beta},
},
NodeSwap: {
{Version: version.MustParse("1.22"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
},
OrderedNamespaceDeletion: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Beta},
},
PDBUnhealthyPodEvictionPolicy: {
{Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.33
},
PersistentVolumeLastPhaseTransitionTime: {
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.29"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.33
},
PodAndContainerStatsFromCRI: {
{Version: version.MustParse("1.23"), Default: false, PreRelease: featuregate.Alpha},
},
PodDeletionCost: {
{Version: version.MustParse("1.21"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.22"), Default: true, PreRelease: featuregate.Beta},
},
PodDisruptionConditions: {
{Version: version.MustParse("1.25"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.26"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.33
},
PodIndexLabel: {
{Version: version.MustParse("1.28"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.35
},
PodLevelResources: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
PodLifecycleSleepAction: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
},
PodReadyToStartContainersCondition: {
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.29"), Default: true, PreRelease: featuregate.Beta},
},
PodLifecycleSleepActionAllowZero: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
PodSchedulingReadiness: {
{Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // GA in 1.30; remove in 1.32
},
PortForwardWebsockets: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
},
ProcMountType: {
{Version: version.MustParse("1.12"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Beta},
},
QOSReserved: {
{Version: version.MustParse("1.11"), Default: false, PreRelease: featuregate.Alpha},
},
RecoverVolumeExpansionFailure: {
{Version: version.MustParse("1.23"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.Beta},
},
RecursiveReadOnlyMounts: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
},
RelaxedDNSSearchValidation: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
RelaxedEnvironmentVariableValidation: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.Beta},
},
ReloadKubeletServerCertificateFile: {
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
},
ResourceHealthStatus: {
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
},
RotateKubeletServerCertificate: {
{Version: version.MustParse("1.7"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.12"), Default: true, PreRelease: featuregate.Beta},
},
RuntimeClassInImageCriAPI: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
},
SchedulerAsyncPreemption: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
SchedulerQueueingHints: {
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.Beta},
},
SELinuxChangePolicy: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
SELinuxMount: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha},
},
SELinuxMountReadWriteOncePod: {
{Version: version.MustParse("1.25"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.28"), Default: true, PreRelease: featuregate.Beta},
},
SeparateTaintEvictionController: {
{Version: version.MustParse("1.29"), Default: true, PreRelease: featuregate.Beta},
},
StorageNamespaceIndex: {
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
},
ServiceAccountNodeAudienceRestriction: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Beta},
},
ServiceAccountTokenJTI: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.34
},
ServiceAccountTokenNodeBinding: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
},
ServiceAccountTokenNodeBindingValidation: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.34
},
ServiceAccountTokenPodNodeInfo: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.34
},
ServiceTrafficDistribution: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
},
SidecarContainers: {
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.29"), Default: true, PreRelease: featuregate.Beta},
},
SizeMemoryBackedVolumes: {
{Version: version.MustParse("1.20"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.22"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, LockToDefault: true, PreRelease: featuregate.GA},
},
PodLogsQuerySplitStreams: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
StatefulSetAutoDeletePVC: {
{Version: version.MustParse("1.23"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // GA in 1.32, remove in 1.35
},
StatefulSetStartOrdinal: {
{Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // GA in 1.31, remove in 1.33
},
StorageVersionMigrator: {
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha},
},
SupplementalGroupsPolicy: {
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
},
SystemdWatchdog: {
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.Beta},
},
TopologyAwareHints: {
{Version: version.MustParse("1.21"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.23"), Default: false, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.24"), Default: true, PreRelease: featuregate.Beta},
},
TopologyManagerPolicyAlphaOptions: {
{Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Alpha},
},
TopologyManagerPolicyBetaOptions: {
{Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.28"), Default: true, PreRelease: featuregate.Beta},
},
TopologyManagerPolicyOptions: {
{Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.28"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA},
},
TranslateStreamCloseWebsocketRequests: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta},
},
UnknownVersionInteroperabilityProxy: {
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Alpha},
},
UserNamespacesPodSecurityStandards: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
},
UserNamespacesSupport: {
{Version: version.MustParse("1.25"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Beta},
},
VolumeAttributesClass: {
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Beta},
},
VolumeCapacityPriority: {
{Version: version.MustParse("1.21"), Default: false, PreRelease: featuregate.Alpha},
},
WinDSR: {
{Version: version.MustParse("1.14"), Default: false, PreRelease: featuregate.Alpha},
},
WindowsGracefulNodeShutdown: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
WinOverlay: {
{Version: version.MustParse("1.14"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.20"), Default: true, PreRelease: featuregate.Beta},
},
WindowsCPUAndMemoryAffinity: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
WindowsHostNetwork: {
{Version: version.MustParse("1.26"), Default: true, PreRelease: featuregate.Alpha},
},
zpagesfeatures.ComponentFlagz: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
zpagesfeatures.ComponentStatusz: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
},
}

111
vendor/k8s.io/kubernetes/pkg/kubelet/events/event.go generated vendored Normal file
View File

@ -0,0 +1,111 @@
/*
Copyright 2014 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 events
// Container event reason list
const (
CreatedContainer = "Created"
StartedContainer = "Started"
FailedToCreateContainer = "Failed"
FailedToStartContainer = "Failed"
KillingContainer = "Killing"
PreemptContainer = "Preempting"
BackOffStartContainer = "BackOff"
ExceededGracePeriod = "ExceededGracePeriod"
)
// Pod event reason list
const (
FailedToKillPod = "FailedKillPod"
FailedToCreatePodContainer = "FailedCreatePodContainer"
FailedToMakePodDataDirectories = "Failed"
NetworkNotReady = "NetworkNotReady"
ResizeDeferred = "ResizeDeferred"
ResizeInfeasible = "ResizeInfeasible"
)
// Image event reason list
const (
PullingImage = "Pulling"
PulledImage = "Pulled"
FailedToPullImage = "Failed"
FailedToInspectImage = "InspectFailed"
ErrImageNeverPullPolicy = "ErrImageNeverPull"
BackOffPullImage = "BackOff"
)
// kubelet event reason list
const (
NodeReady = "NodeReady"
NodeNotReady = "NodeNotReady"
NodeSchedulable = "NodeSchedulable"
NodeNotSchedulable = "NodeNotSchedulable"
StartingKubelet = "Starting"
KubeletSetupFailed = "KubeletSetupFailed"
FailedAttachVolume = "FailedAttachVolume"
FailedMountVolume = "FailedMount"
VolumeResizeFailed = "VolumeResizeFailed"
VolumeResizeSuccess = "VolumeResizeSuccessful"
FileSystemResizeFailed = "FileSystemResizeFailed"
VolumePermissionChangeInProgress = "VolumePermissionChangeInProgress"
FileSystemResizeSuccess = "FileSystemResizeSuccessful"
FailedMapVolume = "FailedMapVolume"
WarnAlreadyMountedVolume = "AlreadyMountedVolume"
SuccessfulAttachVolume = "SuccessfulAttachVolume"
SuccessfulMountVolume = "SuccessfulMountVolume"
NodeRebooted = "Rebooted"
NodeShutdown = "Shutdown"
ContainerGCFailed = "ContainerGCFailed"
ImageGCFailed = "ImageGCFailed"
FailedNodeAllocatableEnforcement = "FailedNodeAllocatableEnforcement"
SuccessfulNodeAllocatableEnforcement = "NodeAllocatableEnforced"
SandboxChanged = "SandboxChanged"
FailedCreatePodSandBox = "FailedCreatePodSandBox"
FailedStatusPodSandBox = "FailedPodSandBoxStatus"
FailedMountOnFilesystemMismatch = "FailedMountOnFilesystemMismatch"
FailedPrepareDynamicResources = "FailedPrepareDynamicResources"
PossibleMemoryBackedVolumesOnDisk = "PossibleMemoryBackedVolumesOnDisk"
CgroupV1 = "CgroupV1"
)
// Image manager event reason list
const (
InvalidDiskCapacity = "InvalidDiskCapacity"
FreeDiskSpaceFailed = "FreeDiskSpaceFailed"
)
// Probe event reason list
const (
ContainerUnhealthy = "Unhealthy"
ContainerProbeWarning = "ProbeWarning"
)
// Pod worker event reason list
const (
FailedSync = "FailedSync"
)
// Config event reason list
const (
FailedValidation = "FailedValidation"
)
// Lifecycle hooks
const (
FailedPostStartHook = "FailedPostStartHook"
FailedPreStopHook = "FailedPreStopHook"
)

View File

@ -1,172 +0,0 @@
/*
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 filesystem
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"time"
)
// DefaultFs implements Filesystem using same-named functions from "os" and "io"
type DefaultFs struct {
root string
}
var _ Filesystem = &DefaultFs{}
// NewTempFs returns a fake Filesystem in temporary directory, useful for unit tests
func NewTempFs() Filesystem {
path, _ := os.MkdirTemp("", "tmpfs")
return &DefaultFs{
root: path,
}
}
func (fs *DefaultFs) prefix(path string) string {
if len(fs.root) == 0 {
return path
}
return filepath.Join(fs.root, path)
}
// Stat via os.Stat
func (fs *DefaultFs) Stat(name string) (os.FileInfo, error) {
return os.Stat(fs.prefix(name))
}
// Create via os.Create
func (fs *DefaultFs) Create(name string) (File, error) {
file, err := os.Create(fs.prefix(name))
if err != nil {
return nil, err
}
return &defaultFile{file}, nil
}
// Rename via os.Rename
func (fs *DefaultFs) Rename(oldpath, newpath string) error {
if !strings.HasPrefix(oldpath, fs.root) {
oldpath = fs.prefix(oldpath)
}
if !strings.HasPrefix(newpath, fs.root) {
newpath = fs.prefix(newpath)
}
return os.Rename(oldpath, newpath)
}
func (fs *DefaultFs) MkdirAll(path string, perm os.FileMode) error {
return MkdirAll(fs.prefix(path), perm)
}
// MkdirAllWithPathCheck checks if path exists already. If not, it creates a directory
// named path, along with any necessary parents, and returns nil, or else returns an error.
// Permission bits perm (before umask) are used for all directories that
// MkdirAllWithPathCheck creates.
// If path is already a directory, MkdirAllWithPathCheck does nothing and returns nil.
// NOTE: In case of Windows NTFS, mount points are implemented as reparse-point
// (similar to symlink) and do not represent actual directory. Hence Directory existence
// check for windows NTFS will NOT check for dir, but for symlink presence.
func MkdirAllWithPathCheck(path string, perm os.FileMode) error {
if dir, err := os.Lstat(path); err == nil {
// If the path exists already,
// 1. for Unix/Linux OS, check if the path is directory.
// 2. for windows NTFS, check if the path is symlink instead of directory.
if dir.IsDir() ||
(runtime.GOOS == "windows" && (dir.Mode()&os.ModeSymlink != 0)) {
return nil
}
return fmt.Errorf("path %v exists but is not a directory", path)
}
// If existence of path not known, attempt to create it.
if err := MkdirAll(path, perm); err != nil {
return err
}
return nil
}
// Chtimes via os.Chtimes
func (fs *DefaultFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
return os.Chtimes(fs.prefix(name), atime, mtime)
}
// RemoveAll via os.RemoveAll
func (fs *DefaultFs) RemoveAll(path string) error {
return os.RemoveAll(fs.prefix(path))
}
// Remove via os.Remove
func (fs *DefaultFs) Remove(name string) error {
return os.Remove(fs.prefix(name))
}
// ReadFile via os.ReadFile
func (fs *DefaultFs) ReadFile(filename string) ([]byte, error) {
return os.ReadFile(fs.prefix(filename))
}
// TempDir via os.MkdirTemp
func (fs *DefaultFs) TempDir(dir, prefix string) (string, error) {
return os.MkdirTemp(fs.prefix(dir), prefix)
}
// TempFile via os.CreateTemp
func (fs *DefaultFs) TempFile(dir, prefix string) (File, error) {
file, err := os.CreateTemp(fs.prefix(dir), prefix)
if err != nil {
return nil, err
}
return &defaultFile{file}, nil
}
// ReadDir via os.ReadDir
func (fs *DefaultFs) ReadDir(dirname string) ([]os.DirEntry, error) {
return os.ReadDir(fs.prefix(dirname))
}
// Walk via filepath.Walk
func (fs *DefaultFs) Walk(root string, walkFn filepath.WalkFunc) error {
return filepath.Walk(fs.prefix(root), walkFn)
}
// defaultFile implements File using same-named functions from "os"
type defaultFile struct {
file *os.File
}
// Name via os.File.Name
func (file *defaultFile) Name() string {
return file.file.Name()
}
// Write via os.File.Write
func (file *defaultFile) Write(b []byte) (n int, err error) {
return file.file.Write(b)
}
// Sync via os.File.Sync
func (file *defaultFile) Sync() error {
return file.file.Sync()
}
// Close via os.File.Close
func (file *defaultFile) Close() error {
return file.file.Close()
}

View File

@ -1,52 +0,0 @@
/*
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 filesystem
import (
"os"
"path/filepath"
"time"
)
// Filesystem is an interface that we can use to mock various filesystem operations
type Filesystem interface {
// from "os"
Stat(name string) (os.FileInfo, error)
Create(name string) (File, error)
Rename(oldpath, newpath string) error
MkdirAll(path string, perm os.FileMode) error
Chtimes(name string, atime time.Time, mtime time.Time) error
RemoveAll(path string) error
Remove(name string) error
// from "os"
ReadFile(filename string) ([]byte, error)
TempDir(dir, prefix string) (string, error)
TempFile(dir, prefix string) (File, error)
ReadDir(dirname string) ([]os.DirEntry, error)
Walk(root string, walkFn filepath.WalkFunc) error
}
// File is an interface that we can use to mock various filesystem operations typically
// accessed through the File object from the "os" package
type File interface {
// for now, the only os.File methods used are those below, add more as necessary
Name() string
Write(b []byte) (n int, err error)
Sync() error
Close() error
}

View File

@ -1,27 +0,0 @@
/*
Copyright 2024 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 filesystem
import (
"path/filepath"
)
// IsPathClean will replace slashes to Separator (which is OS-specific).
// This will make sure that all slashes are the same before comparing.
func IsPathClean(path string) bool {
return filepath.ToSlash(filepath.Clean(path)) == filepath.ToSlash(path)
}

View File

@ -1,53 +0,0 @@
//go:build freebsd || linux || darwin
// +build freebsd linux darwin
/*
Copyright 2023 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 filesystem
import (
"fmt"
"os"
"path/filepath"
)
// IsUnixDomainSocket returns whether a given file is a AF_UNIX socket file
func IsUnixDomainSocket(filePath string) (bool, error) {
fi, err := os.Stat(filePath)
if err != nil {
return false, fmt.Errorf("stat file %s failed: %v", filePath, err)
}
if fi.Mode()&os.ModeSocket == 0 {
return false, nil
}
return true, nil
}
// Chmod is the same as os.Chmod on Unix.
func Chmod(name string, mode os.FileMode) error {
return os.Chmod(name, mode)
}
// MkdirAll is same as os.MkdirAll on Unix.
func MkdirAll(path string, perm os.FileMode) error {
return os.MkdirAll(path, perm)
}
// IsAbs is same as filepath.IsAbs on Unix.
func IsAbs(path string) bool {
return filepath.IsAbs(path)
}

View File

@ -1,255 +0,0 @@
//go:build windows
// +build windows
/*
Copyright 2023 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 filesystem
import (
"fmt"
"net"
"os"
"path/filepath"
"strings"
"time"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/klog/v2"
"golang.org/x/sys/windows"
)
const (
// Amount of time to wait between attempting to use a Unix domain socket.
// As detailed in https://github.com/kubernetes/kubernetes/issues/104584
// the first attempt will most likely fail, hence the need to retry
socketDialRetryPeriod = 1 * time.Second
// Overall timeout value to dial a Unix domain socket, including retries
socketDialTimeout = 4 * time.Second
)
// IsUnixDomainSocket returns whether a given file is a AF_UNIX socket file
// Note that due to the retry logic inside, it could take up to 4 seconds
// to determine whether or not the file path supplied is a Unix domain socket
func IsUnixDomainSocket(filePath string) (bool, error) {
// Due to the absence of golang support for os.ModeSocket in Windows (https://github.com/golang/go/issues/33357)
// we need to dial the file and check if we receive an error to determine if a file is Unix Domain Socket file.
// Note that querrying for the Reparse Points (https://docs.microsoft.com/en-us/windows/win32/fileio/reparse-points)
// for the file (using FSCTL_GET_REPARSE_POINT) and checking for reparse tag: reparseTagSocket
// does NOT work in 1809 if the socket file is created within a bind mounted directory by a container
// and the FSCTL is issued in the host by the kubelet.
// If the file does not exist, it cannot be a Unix domain socket.
if _, err := os.Stat(filePath); os.IsNotExist(err) {
return false, fmt.Errorf("File %s not found. Err: %v", filePath, err)
}
klog.V(6).InfoS("Function IsUnixDomainSocket starts", "filePath", filePath)
// As detailed in https://github.com/kubernetes/kubernetes/issues/104584 we cannot rely
// on the Unix Domain socket working on the very first try, hence the potential need to
// dial multiple times
var lastSocketErr error
err := wait.PollImmediate(socketDialRetryPeriod, socketDialTimeout,
func() (bool, error) {
klog.V(6).InfoS("Dialing the socket", "filePath", filePath)
var c net.Conn
c, lastSocketErr = net.Dial("unix", filePath)
if lastSocketErr == nil {
c.Close()
klog.V(6).InfoS("Socket dialed successfully", "filePath", filePath)
return true, nil
}
klog.V(6).InfoS("Failed the current attempt to dial the socket, so pausing before retry",
"filePath", filePath, "err", lastSocketErr, "socketDialRetryPeriod",
socketDialRetryPeriod)
return false, nil
})
// PollImmediate will return "timed out waiting for the condition" if the function it
// invokes never returns true
if err != nil {
klog.V(2).InfoS("Failed all attempts to dial the socket so marking it as a non-Unix Domain socket. Last socket error along with the error from PollImmediate follow",
"filePath", filePath, "lastSocketErr", lastSocketErr, "err", err)
return false, nil
}
return true, nil
}
// On Windows os.Mkdir all doesn't set any permissions so call the Chown function below to set
// permissions once the directory is created.
func MkdirAll(path string, perm os.FileMode) error {
klog.V(6).InfoS("Function MkdirAll starts", "path", path, "perm", perm)
err := os.MkdirAll(path, perm)
if err != nil {
return fmt.Errorf("Error creating directory %s: %v", path, err)
}
err = Chmod(path, perm)
if err != nil {
return fmt.Errorf("Error setting permissions for directory %s: %v", path, err)
}
return nil
}
const (
// These aren't defined in the syscall package for Windows :(
USER_READ = 0x100
USER_WRITE = 0x80
USER_EXECUTE = 0x40
GROUP_READ = 0x20
GROUP_WRITE = 0x10
GROUP_EXECUTE = 0x8
OTHERS_READ = 0x4
OTHERS_WRITE = 0x2
OTHERS_EXECUTE = 0x1
USER_ALL = USER_READ | USER_WRITE | USER_EXECUTE
GROUP_ALL = GROUP_READ | GROUP_WRITE | GROUP_EXECUTE
OTHERS_ALL = OTHERS_READ | OTHERS_WRITE | OTHERS_EXECUTE
)
// On Windows os.Chmod only sets the read-only flag on files, so we need to use Windows APIs to set the desired access on files / directories.
// The OWNER mode will set file permissions for the file owner SID, the GROUP mode will set file permissions for the file group SID,
// and the OTHERS mode will set file permissions for BUILTIN\Users.
// Please note that Windows containers can be run as one of two user accounts; ContainerUser or ContainerAdministrator.
// Containers run as ContainerAdministrator will inherit permissions from BUILTIN\Administrators,
// while containers run as ContainerUser will inherit permissions from BUILTIN\Users.
// Windows containers do not have the ability to run as a custom user account that is known to the host so the OTHERS group mode
// is used to grant / deny permissions of files on the hosts to the ContainerUser account.
func Chmod(path string, filemode os.FileMode) error {
klog.V(6).InfoS("Function Chmod starts", "path", path, "filemode", filemode)
// Get security descriptor for the file
sd, err := windows.GetNamedSecurityInfo(
path,
windows.SE_FILE_OBJECT,
windows.DACL_SECURITY_INFORMATION|windows.PROTECTED_DACL_SECURITY_INFORMATION|windows.OWNER_SECURITY_INFORMATION|windows.GROUP_SECURITY_INFORMATION)
if err != nil {
return fmt.Errorf("Error getting security descriptor for file %s: %v", path, err)
}
// Get owner SID from the security descriptor for assigning USER permissions
owner, _, err := sd.Owner()
if err != nil {
return fmt.Errorf("Error getting owner SID for file %s: %v", path, err)
}
ownerString := owner.String()
// Get the group SID from the security descriptor for assigning GROUP permissions
group, _, err := sd.Group()
if err != nil {
return fmt.Errorf("Error getting group SID for file %s: %v", path, err)
}
groupString := group.String()
mask := uint32(windows.ACCESS_MASK(filemode))
// Build a new Discretionary Access Control List (DACL) with the desired permissions using
//the Security Descriptor Definition Language (SDDL) format.
// https://learn.microsoft.com/windows/win32/secauthz/security-descriptor-definition-language
// the DACL is a list of Access Control Entries (ACEs) where each ACE represents the permissions (Allow or Deny) for a specific SID.
// Each ACE has the following format:
// (AceType;AceFlags;Rights;ObjectGuid;InheritObjectGuid;AccountSid)
// We can leave ObjectGuid and InheritObjectGuid empty for our purposes.
dacl := "D:"
// build the owner ACE
dacl += "(A;OICI;"
if mask&USER_ALL == USER_ALL {
dacl += "FA"
} else {
if mask&USER_READ == USER_READ {
dacl += "FR"
}
if mask&USER_WRITE == USER_WRITE {
dacl += "FW"
}
if mask&USER_EXECUTE == USER_EXECUTE {
dacl += "FX"
}
}
dacl += ";;;" + ownerString + ")"
// Build the group ACE
dacl += "(A;OICI;"
if mask&GROUP_ALL == GROUP_ALL {
dacl += "FA"
} else {
if mask&GROUP_READ == GROUP_READ {
dacl += "FR"
}
if mask&GROUP_WRITE == GROUP_WRITE {
dacl += "FW"
}
if mask&GROUP_EXECUTE == GROUP_EXECUTE {
dacl += "FX"
}
}
dacl += ";;;" + groupString + ")"
// Build the others ACE
dacl += "(A;OICI;"
if mask&OTHERS_ALL == OTHERS_ALL {
dacl += "FA"
} else {
if mask&OTHERS_READ == OTHERS_READ {
dacl += "FR"
}
if mask&OTHERS_WRITE == OTHERS_WRITE {
dacl += "FW"
}
if mask&OTHERS_EXECUTE == OTHERS_EXECUTE {
dacl += "FX"
}
}
dacl += ";;;BU)"
klog.V(6).InfoS("Setting new DACL for path", "path", path, "dacl", dacl)
// create a new security descriptor from the DACL string
newSD, err := windows.SecurityDescriptorFromString(dacl)
if err != nil {
return fmt.Errorf("Error creating new security descriptor from DACL string: %v", err)
}
// get the DACL in binary format from the newly created security descriptor
newDACL, _, err := newSD.DACL()
if err != nil {
return fmt.Errorf("Error getting DACL from new security descriptor: %v", err)
}
// Write the new security descriptor to the file
return windows.SetNamedSecurityInfo(
path,
windows.SE_FILE_OBJECT,
windows.DACL_SECURITY_INFORMATION|windows.PROTECTED_DACL_SECURITY_INFORMATION,
nil, // owner SID
nil, // group SID
newDACL,
nil) // SACL
}
// IsAbs returns whether the given path is absolute or not.
// On Windows, filepath.IsAbs will not return True for paths prefixed with a slash, even
// though they can be used as absolute paths (https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats).
//
// WARN: It isn't safe to use this for API values which will propagate across systems (e.g. REST API values
// that get validated on Unix, persisted, then consumed by Windows, etc).
func IsAbs(path string) bool {
return filepath.IsAbs(path) || strings.HasPrefix(path, `\`) || strings.HasPrefix(path, `/`)
}

View File

@ -1,216 +0,0 @@
/*
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 filesystem
import (
"context"
"fmt"
"time"
"github.com/fsnotify/fsnotify"
)
// FSWatcher is a callback-based filesystem watcher abstraction for fsnotify.
type FSWatcher interface {
// Initializes the watcher with the given watch handlers.
// Called before all other methods.
Init(FSEventHandler, FSErrorHandler) error
// Starts listening for events and errors.
// When an event or error occurs, the corresponding handler is called.
Run()
// Add a filesystem path to watch
AddWatch(path string) error
}
// FSEventHandler is called when a fsnotify event occurs.
type FSEventHandler func(event fsnotify.Event)
// FSErrorHandler is called when a fsnotify error occurs.
type FSErrorHandler func(err error)
type fsnotifyWatcher struct {
watcher *fsnotify.Watcher
eventHandler FSEventHandler
errorHandler FSErrorHandler
}
var _ FSWatcher = &fsnotifyWatcher{}
// NewFsnotifyWatcher returns an implementation of FSWatcher that continuously listens for
// fsnotify events and calls the event handler as soon as an event is received.
func NewFsnotifyWatcher() FSWatcher {
return &fsnotifyWatcher{}
}
func (w *fsnotifyWatcher) AddWatch(path string) error {
return w.watcher.Add(path)
}
func (w *fsnotifyWatcher) Init(eventHandler FSEventHandler, errorHandler FSErrorHandler) error {
var err error
w.watcher, err = fsnotify.NewWatcher()
if err != nil {
return err
}
w.eventHandler = eventHandler
w.errorHandler = errorHandler
return nil
}
func (w *fsnotifyWatcher) Run() {
go func() {
defer w.watcher.Close()
for {
select {
case event := <-w.watcher.Events:
if w.eventHandler != nil {
w.eventHandler(event)
}
case err := <-w.watcher.Errors:
if w.errorHandler != nil {
w.errorHandler(err)
}
}
}
}()
}
type watchAddRemover interface {
Add(path string) error
Remove(path string) error
}
type noopWatcher struct{}
func (noopWatcher) Add(path string) error { return nil }
func (noopWatcher) Remove(path string) error { return nil }
// WatchUntil watches the specified path for changes and blocks until ctx is canceled.
// eventHandler() must be non-nil, and pollInterval must be greater than 0.
// eventHandler() is invoked whenever a change event is observed or pollInterval elapses.
// errorHandler() is invoked (if non-nil) whenever an error occurs initializing or watching the specified path.
//
// If path is a directory, only the directory and immediate children are watched.
//
// If path does not exist or cannot be watched, an error is passed to errorHandler() and eventHandler() is called at pollInterval.
//
// Multiple observed events may collapse to a single invocation of eventHandler().
//
// eventHandler() is invoked immediately after successful initialization of the filesystem watch,
// in case the path changed concurrent with calling WatchUntil().
func WatchUntil(ctx context.Context, pollInterval time.Duration, path string, eventHandler func(), errorHandler func(err error)) {
if pollInterval <= 0 {
panic(fmt.Errorf("pollInterval must be > 0"))
}
if eventHandler == nil {
panic(fmt.Errorf("eventHandler must be non-nil"))
}
if errorHandler == nil {
errorHandler = func(err error) {}
}
// Initialize watcher, fall back to no-op
var (
eventsCh chan fsnotify.Event
errorCh chan error
watcher watchAddRemover
)
if w, err := fsnotify.NewWatcher(); err != nil {
errorHandler(fmt.Errorf("error creating file watcher, falling back to poll at interval %s: %w", pollInterval, err))
watcher = noopWatcher{}
} else {
watcher = w
eventsCh = w.Events
errorCh = w.Errors
defer func() {
_ = w.Close()
}()
}
// Initialize background poll
t := time.NewTicker(pollInterval)
defer t.Stop()
attemptPeriodicRewatch := false
// Start watching the path
if err := watcher.Add(path); err != nil {
errorHandler(err)
attemptPeriodicRewatch = true
} else {
// Invoke handle() at least once after successfully registering the listener,
// in case the file changed concurrent with calling WatchUntil.
eventHandler()
}
for {
select {
case <-ctx.Done():
return
case <-t.C:
// Prioritize exiting if context is canceled
if ctx.Err() != nil {
return
}
// Try to re-establish the watcher if we previously got a watch error
if attemptPeriodicRewatch {
_ = watcher.Remove(path)
if err := watcher.Add(path); err != nil {
errorHandler(err)
} else {
attemptPeriodicRewatch = false
}
}
// Handle
eventHandler()
case e := <-eventsCh:
// Prioritize exiting if context is canceled
if ctx.Err() != nil {
return
}
// Try to re-establish the watcher for events which dropped the existing watch
if e.Name == path && (e.Has(fsnotify.Remove) || e.Has(fsnotify.Rename)) {
_ = watcher.Remove(path)
if err := watcher.Add(path); err != nil {
errorHandler(err)
attemptPeriodicRewatch = true
}
}
// Handle
eventHandler()
case err := <-errorCh:
// Prioritize exiting if context is canceled
if ctx.Err() != nil {
return
}
// If the error occurs in response to calling watcher.Add, re-adding here could hot-loop.
// The periodic poll will attempt to re-establish the watch.
errorHandler(err)
attemptPeriodicRewatch = true
}
}
}

View File

@ -16,4 +16,4 @@ limitations under the License.
// Package volume includes internal representations of external volume types
// as well as utility methods required to mount/unmount volumes to kubelets.
package volume // import "k8s.io/kubernetes/pkg/volume"
package volume

View File

@ -37,7 +37,7 @@ type metricsBlock struct {
device string
}
// NewMetricsStatfs creates a new metricsBlock with the device node of the
// NewMetricsBlock creates a new metricsBlock with the device node of the
// Volume.
func NewMetricsBlock(device string) MetricsProvider {
return &metricsBlock{device}

View File

@ -23,7 +23,11 @@ import (
const (
// ErrCodeNotSupported code for NotSupported Errors.
ErrCodeNotSupported int = iota + 1
// ErrCodeNoPathDefined code for NoPathDefined Errors.
ErrCodeNoPathDefined
// ErrCodeFsInfoFailed code for FsInfoFailed Errors.
ErrCodeFsInfoFailed
)

View File

@ -34,7 +34,7 @@ type metricsStatFS struct {
path string
}
// NewMetricsStatfs creates a new metricsStatFS with the Volume path.
// NewMetricsStatFS creates a new metricsStatFS with the Volume path.
func NewMetricsStatFS(path string) MetricsProvider {
return &metricsStatFS{path}
}

View File

@ -44,7 +44,10 @@ import (
"k8s.io/kubernetes/pkg/volume/util/subpath"
)
// ProbeOperation represents a type of operation for probing volume plugins.
type ProbeOperation uint32
// ProbeEvent represents an event triggered during a volume plugin probe operation.
type ProbeEvent struct {
Plugin VolumePlugin // VolumePlugin that was added/updated/removed. if ProbeEvent.Op is 'ProbeRemove', Plugin should be nil
PluginName string
@ -52,17 +55,22 @@ type ProbeEvent struct {
}
const (
// Common parameter which can be specified in StorageClass to specify the desired FSType
// VolumeParameterFSType is a common parameter which can be specified in StorageClass to specify the desired FSType
// Provisioners SHOULD implement support for this if they are block device based
// Must be a filesystem type supported by the host operating system.
// Ex. "ext4", "xfs", "ntfs". Default value depends on the provisioner
VolumeParameterFSType = "fstype"
// ProbeAddOrUpdate represents an operation where a probe is added or updated.
ProbeAddOrUpdate ProbeOperation = 1 << iota
// ProbeRemove represents an operation to remove a probe.
// This operation is used to indicate that a previously added probe should be removed.
ProbeRemove
)
var ErrNoPluiginMatched = errors.New("no volume plugin matched")
// ErrNoPluginMatched is used to return when no volume plugin matches the requested type.
var ErrNoPluginMatched = errors.New("no volume plugin matched")
// VolumeOptions contains option information about a volume.
type VolumeOptions struct {
@ -108,6 +116,7 @@ type NodeResizeOptions struct {
OldSize resource.Quantity
}
// DynamicPluginProber is an interface that defines methods for probing dynamic volume plugins.
type DynamicPluginProber interface {
Init() error
@ -225,6 +234,7 @@ type AttachableVolumePlugin interface {
NewDetacher() (Detacher, error)
// CanAttach tests if provided volume spec is attachable
CanAttach(spec *Spec) (bool, error)
VerifyExhaustedResource(spec *Spec, nodeName types.NodeName)
}
// DeviceMountableVolumePlugin is an extended interface of VolumePlugin and is used
@ -628,9 +638,8 @@ func (pm *VolumePluginMgr) initProbedPlugin(probedPlugin VolumePlugin) error {
// specification. If no plugins can support or more than one plugin can
// support it, return error.
func (pm *VolumePluginMgr) FindPluginBySpec(spec *Spec) (VolumePlugin, error) {
pm.mutex.RLock()
defer pm.mutex.RUnlock()
pm.mutex.Lock()
defer pm.mutex.Unlock()
if spec == nil {
return nil, fmt.Errorf("could not find plugin because volume spec is nil")
}
@ -643,8 +652,8 @@ func (pm *VolumePluginMgr) FindPluginBySpec(spec *Spec) (VolumePlugin, error) {
matchedPluginNames = append(matchedPluginNames, v.GetPluginName())
}
}
pm.refreshProbedPlugins()
for _, plugin := range pm.probedPlugins {
if plugin.CanSupport(spec) {
match = plugin
@ -653,7 +662,7 @@ func (pm *VolumePluginMgr) FindPluginBySpec(spec *Spec) (VolumePlugin, error) {
}
if len(matchedPluginNames) == 0 {
return nil, ErrNoPluiginMatched
return nil, ErrNoPluginMatched
}
if len(matchedPluginNames) > 1 {
return nil, fmt.Errorf("multiple volume plugins matched: %s", strings.Join(matchedPluginNames, ","))
@ -664,14 +673,13 @@ func (pm *VolumePluginMgr) FindPluginBySpec(spec *Spec) (VolumePlugin, error) {
// FindPluginByName fetches a plugin by name. If no plugin is found, returns error.
func (pm *VolumePluginMgr) FindPluginByName(name string) (VolumePlugin, error) {
pm.mutex.RLock()
defer pm.mutex.RUnlock()
pm.mutex.Lock()
defer pm.mutex.Unlock()
var match VolumePlugin
if v, found := pm.plugins[name]; found {
match = v
}
pm.refreshProbedPlugins()
if plugin, found := pm.probedPlugins[name]; found {
if match != nil {
@ -698,6 +706,7 @@ func (pm *VolumePluginMgr) refreshProbedPlugins() {
// because the probe function can return a list of valid plugins
// even when an error is present we still must add the plugins
// or they will be skipped because each event only fires once
for _, event := range events {
if event.Op == ProbeAddOrUpdate {
if err := pm.initProbedPlugin(event.Plugin); err != nil {
@ -730,7 +739,7 @@ func (pm *VolumePluginMgr) FindPersistentPluginBySpec(spec *Spec) (PersistentVol
return nil, fmt.Errorf("no persistent volume plugin matched")
}
// FindPersistentPluginByName fetches a persistent volume plugin by name. If
// FindPersistentPluginByName fetches a recyclable persistent volume plugin by name. If
// no plugin is found, returns error.
func (pm *VolumePluginMgr) FindPersistentPluginByName(name string) (PersistentVolumePlugin, error) {
volumePlugin, err := pm.FindPluginByName(name)
@ -743,7 +752,7 @@ func (pm *VolumePluginMgr) FindPersistentPluginByName(name string) (PersistentVo
return nil, fmt.Errorf("no persistent volume plugin matched")
}
// FindRecyclablePluginByName fetches a persistent volume plugin by name. If
// FindRecyclablePluginBySpec fetches a recyclable persistent volume plugin by spec. If
// no plugin is found, returns error.
func (pm *VolumePluginMgr) FindRecyclablePluginBySpec(spec *Spec) (RecyclableVolumePlugin, error) {
volumePlugin, err := pm.FindPluginBySpec(spec)
@ -756,7 +765,7 @@ func (pm *VolumePluginMgr) FindRecyclablePluginBySpec(spec *Spec) (RecyclableVol
return nil, fmt.Errorf("no recyclable volume plugin matched")
}
// FindProvisionablePluginByName fetches a persistent volume plugin by name. If
// FindProvisionablePluginByName fetches a provisionable persistent volume plugin by name. If
// no plugin is found, returns error.
func (pm *VolumePluginMgr) FindProvisionablePluginByName(name string) (ProvisionableVolumePlugin, error) {
volumePlugin, err := pm.FindPluginByName(name)
@ -769,7 +778,7 @@ func (pm *VolumePluginMgr) FindProvisionablePluginByName(name string) (Provision
return nil, fmt.Errorf("no provisionable volume plugin matched")
}
// FindDeletablePluginBySpec fetches a persistent volume plugin by spec. If
// FindDeletablePluginBySpec fetches a provisionable persistent volume plugin by spec. If
// no plugin is found, returns error.
func (pm *VolumePluginMgr) FindDeletablePluginBySpec(spec *Spec) (DeletableVolumePlugin, error) {
volumePlugin, err := pm.FindPluginBySpec(spec)
@ -782,7 +791,7 @@ func (pm *VolumePluginMgr) FindDeletablePluginBySpec(spec *Spec) (DeletableVolum
return nil, fmt.Errorf("no deletable volume plugin matched")
}
// FindDeletablePluginByName fetches a persistent volume plugin by name. If
// FindDeletablePluginByName fetches a deleteable persistent volume plugin by name. If
// no plugin is found, returns error.
func (pm *VolumePluginMgr) FindDeletablePluginByName(name string) (DeletableVolumePlugin, error) {
volumePlugin, err := pm.FindPluginByName(name)
@ -829,7 +838,7 @@ func (pm *VolumePluginMgr) FindAttachablePluginByName(name string) (AttachableVo
return nil, nil
}
// FindDeviceMountablePluginBySpec fetches a persistent volume plugin by spec.
// FindDeviceMountablePluginBySpec fetches a devicemountable persistent volume plugin by spec.
func (pm *VolumePluginMgr) FindDeviceMountablePluginBySpec(spec *Spec) (DeviceMountableVolumePlugin, error) {
volumePlugin, err := pm.FindPluginBySpec(spec)
if err != nil {
@ -845,7 +854,7 @@ func (pm *VolumePluginMgr) FindDeviceMountablePluginBySpec(spec *Spec) (DeviceMo
return nil, nil
}
// FindDeviceMountablePluginByName fetches a devicemountable volume plugin by name.
// FindDeviceMountablePluginByName fetches a devicemountable persistent volume plugin by name.
func (pm *VolumePluginMgr) FindDeviceMountablePluginByName(name string) (DeviceMountableVolumePlugin, error) {
volumePlugin, err := pm.FindPluginByName(name)
if err != nil {
@ -857,7 +866,7 @@ func (pm *VolumePluginMgr) FindDeviceMountablePluginByName(name string) (DeviceM
return nil, nil
}
// FindExpandablePluginBySpec fetches a persistent volume plugin by spec.
// FindExpandablePluginBySpec fetches an expandable persistent volume plugin by spec.
func (pm *VolumePluginMgr) FindExpandablePluginBySpec(spec *Spec) (ExpandableVolumePlugin, error) {
volumePlugin, err := pm.FindPluginBySpec(spec)
if err != nil {
@ -867,7 +876,7 @@ func (pm *VolumePluginMgr) FindExpandablePluginBySpec(spec *Spec) (ExpandableVol
klog.V(4).InfoS("FindExpandablePluginBySpec -> returning noopExpandableVolumePluginInstance", "specName", spec.Name())
return &noopExpandableVolumePluginInstance{spec}, nil
}
if errors.Is(err, ErrNoPluiginMatched) {
if errors.Is(err, ErrNoPluginMatched) {
return nil, nil
}
klog.V(4).InfoS("FindExpandablePluginBySpec -> err", "specName", spec.Name(), "err", err)
@ -880,7 +889,7 @@ func (pm *VolumePluginMgr) FindExpandablePluginBySpec(spec *Spec) (ExpandableVol
return nil, nil
}
// FindExpandablePluginBySpec fetches a persistent volume plugin by name.
// FindExpandablePluginByName fetches an expandable persistent volume plugin by name.
func (pm *VolumePluginMgr) FindExpandablePluginByName(name string) (ExpandableVolumePlugin, error) {
volumePlugin, err := pm.FindPluginByName(name)
if err != nil {
@ -919,7 +928,7 @@ func (pm *VolumePluginMgr) FindMapperPluginByName(name string) (BlockVolumePlugi
return nil, nil
}
// FindNodeExpandablePluginBySpec fetches a persistent volume plugin by spec
// FindNodeExpandablePluginBySpec fetches a node expandable persistent volume plugin by spec
func (pm *VolumePluginMgr) FindNodeExpandablePluginBySpec(spec *Spec) (NodeExpandableVolumePlugin, error) {
volumePlugin, err := pm.FindPluginBySpec(spec)
if err != nil {
@ -931,7 +940,7 @@ func (pm *VolumePluginMgr) FindNodeExpandablePluginBySpec(spec *Spec) (NodeExpan
return nil, nil
}
// FindNodeExpandablePluginByName fetches a persistent volume plugin by name
// FindNodeExpandablePluginByName fetches a node expandable persistent volume plugin by name
func (pm *VolumePluginMgr) FindNodeExpandablePluginByName(name string) (NodeExpandableVolumePlugin, error) {
volumePlugin, err := pm.FindPluginByName(name)
if err != nil {
@ -945,6 +954,9 @@ func (pm *VolumePluginMgr) FindNodeExpandablePluginByName(name string) (NodeExpa
return nil, nil
}
// Run starts the volume plugin manager, initializing and running the necessary
// tasks for managing volume plugins. This method is typically called to begin
// the plugin management lifecycle.
func (pm *VolumePluginMgr) Run(stopCh <-chan struct{}) {
kletHost, ok := pm.Host.(KubeletVolumeHost)
if ok {
@ -1007,7 +1019,7 @@ func NewPersistentVolumeRecyclerPodTemplate() *v1.Pod {
return pod
}
// Check validity of recycle pod template
// ValidateRecyclerPodTemplate checks validity of recycle pod template
// List of checks:
// - at least one volume is defined in the recycle pod template
// If successful, returns nil

View File

@ -85,6 +85,11 @@ func diskUsage(currPath string, info os.FileInfo) (int64, error) {
return size, nil
}
// go1.23 behavior change: https://github.com/golang/go/issues/63703#issuecomment-2535941458
if info.Mode()&os.ModeIrregular != 0 {
return size, nil
}
size += info.Size()
if !info.IsDir() {

View File

@ -19,8 +19,6 @@ package hostutil
import (
"fmt"
"os"
"k8s.io/mount-utils"
)
// FileType enumerates the known set of possible file types.
@ -52,10 +50,6 @@ type HostUtils interface {
DeviceOpened(pathname string) (bool, error)
// PathIsDevice determines if a path is a device.
PathIsDevice(pathname string) (bool, error)
// GetDeviceNameFromMount finds the device name by checking the mount path
// to get the global mount path within its plugin directory.
// TODO: Remove this method once the rbd and vsphere plugins are removed from in-tree.
GetDeviceNameFromMount(mounter mount.Interface, mountPath, pluginMountDir string) (string, error)
// MakeRShared checks that given path is on a mount with 'rshared' mount
// propagation. If not, it bind-mounts the path as rshared.
MakeRShared(path string) error

View File

@ -66,7 +66,7 @@ func (hu *HostUtil) PathIsDevice(pathname string) (bool, error) {
return isDevice, err
}
// ExclusiveOpenFailsOnDevice is shared with NsEnterMounter
// ExclusiveOpenFailsOnDevice checks if block device in use by calling Open with O_EXCL flag.
func ExclusiveOpenFailsOnDevice(pathname string) (bool, error) {
var isDevice bool
finfo, err := os.Stat(pathname)
@ -154,8 +154,6 @@ func (hu *HostUtil) PathExists(pathname string) (bool, error) {
}
// EvalHostSymlinks returns the path name after evaluating symlinks.
// TODO once the nsenter implementation is removed, this method can be removed
// from the interface and filepath.EvalSymlinks used directly
func (hu *HostUtil) EvalHostSymlinks(pathname string) (string, error) {
return filepath.EvalSymlinks(pathname)
}
@ -280,8 +278,8 @@ func (hu *HostUtil) GetMode(pathname string) (os.FileMode, error) {
return GetModeLinux(pathname)
}
// GetOwnerLinux is shared between Linux and NsEnterMounter
// pathname must already be evaluated for symlinks
// pathname must already be evaluated for symlinks.
// GetOwnerLinux returns the integer ID for the user and group of the given path.
func GetOwnerLinux(pathname string) (int64, int64, error) {
info, err := os.Stat(pathname)
if err != nil {
@ -291,7 +289,7 @@ func GetOwnerLinux(pathname string) (int64, int64, error) {
return int64(stat.Uid), int64(stat.Gid), nil
}
// GetModeLinux is shared between Linux and NsEnterMounter
// GetModeLinux returns permissions of the pathname.
func GetModeLinux(pathname string) (os.FileMode, error) {
info, err := os.Stat(pathname)
if err != nil {

View File

@ -29,7 +29,6 @@ import (
"golang.org/x/sys/windows"
"k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/util/filesystem"
"k8s.io/mount-utils"
utilpath "k8s.io/utils/path"
)
@ -103,14 +102,6 @@ func isSystemCannotAccessErr(err error) bool {
func (hu *(HostUtil)) GetFileType(pathname string) (FileType, error) {
filetype, err := getFileType(pathname)
// os.Stat will return a 1920 error (windows.ERROR_CANT_ACCESS_FILE) if we use it on a Unix Socket
// on Windows. In this case, we need to use a different method to check if it's a Unix Socket.
if err == errUnknownFileType || isSystemCannotAccessErr(err) {
if isSocket, errSocket := filesystem.IsUnixDomainSocket(pathname); errSocket == nil && isSocket {
return FileTypeSocket, nil
}
}
return filetype, err
}

View File

@ -78,7 +78,7 @@ func (sp *subpath) PrepareSafeSubpath(subPath Subpath) (newHostPath string, clea
return newHostPath, cleanupAction, err
}
// This implementation is shared between Linux and NsEnter
// safeOpenSubPath opens subpath and returns its fd.
func safeOpenSubPath(mounter mount.Interface, subpath Subpath) (int, error) {
if !mount.PathWithinBase(subpath.Path, subpath.VolumePath) {
return -1, fmt.Errorf("subpath %q not within volume path %q", subpath.Path, subpath.VolumePath)
@ -92,11 +92,6 @@ func safeOpenSubPath(mounter mount.Interface, subpath Subpath) (int, error) {
// prepareSubpathTarget creates target for bind-mount of subpath. It returns
// "true" when the target already exists and something is mounted there.
// Given Subpath must have all paths with already resolved symlinks and with
// paths relevant to kubelet (when it runs in a container).
// This function is called also by NsEnterMounter. It works because
// /var/lib/kubelet is mounted from the host into the container with Kubelet as
// /var/lib/kubelet too.
func prepareSubpathTarget(mounter mount.Interface, subpath Subpath) (bool, string, error) {
// Early check for already bind-mounted subpath.
bindPathTarget := getSubpathBindTarget(subpath)
@ -237,7 +232,7 @@ func doBindSubPath(mounter mount.Interface, subpath Subpath) (hostPath string, e
return bindPathTarget, nil
}
// This implementation is shared between Linux and NsEnter
// doCleanSubPaths tears down the subpath bind mounts for a pod
func doCleanSubPaths(mounter mount.Interface, podDir string, volumeName string) error {
// scan /var/lib/kubelet/pods/<uid>/volume-subpaths/<volume>/*
subPathDir := filepath.Join(podDir, containerSubPathDirectoryName, volumeName)
@ -372,9 +367,7 @@ func removeEmptyDirs(baseDir, endDir string) error {
return nil
}
// This implementation is shared between Linux and NsEnterMounter. Both pathname
// and base must be either already resolved symlinks or thet will be resolved in
// kubelet's mount namespace (in case it runs containerized).
// doSafeMakeDir creates a directory at pathname, but only if it is within base.
func doSafeMakeDir(pathname string, base string, perm os.FileMode) error {
klog.V(4).Infof("Creating directory %q within base %q", pathname, base)
@ -523,7 +516,6 @@ func findExistingPrefix(base, pathname string) (string, []string, error) {
return pathname, []string{}, nil
}
// This implementation is shared between Linux and NsEnterMounter
// Open path and return its fd.
// Symlinks are disallowed (pathname must already resolve symlinks),
// and the path must be within the base directory.

View File

@ -24,7 +24,6 @@ import (
"os"
"k8s.io/mount-utils"
"k8s.io/utils/nsenter"
)
type subpath struct{}
@ -36,12 +35,6 @@ func New(mount.Interface) Interface {
return &subpath{}
}
// NewNSEnter is to satisfy the compiler for having NewSubpathNSEnter exist for all
// OS choices. however, NSEnter is only valid on Linux
func NewNSEnter(mounter mount.Interface, ne *nsenter.Nsenter, rootDir string) Interface {
return nil
}
func (sp *subpath) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) {
return subPath.Path, nil, errUnsupported
}

View File

@ -29,7 +29,6 @@ import (
"k8s.io/klog/v2"
"k8s.io/mount-utils"
"k8s.io/utils/nsenter"
)
// MaxPathLength is the maximum length of Windows path. Normally, it is 260, but if long path is enable,
@ -43,12 +42,6 @@ func New(mount.Interface) Interface {
return &subpath{}
}
// NewNSEnter is to satisfy the compiler for having NewSubpathNSEnter exist for all
// OS choices. however, NSEnter is only valid on Linux
func NewNSEnter(mounter mount.Interface, ne *nsenter.Nsenter, rootDir string) Interface {
return nil
}
// isDriveLetterPath returns true if the given path is empty or it ends with ":" or ":\" or ":\\"
func isDriveLetterorEmptyPath(path string) bool {
if path == "" || strings.HasSuffix(path, ":\\\\") || strings.HasSuffix(path, ":") || strings.HasSuffix(path, ":\\") {
@ -208,6 +201,12 @@ func lockAndCheckSubPathWithoutSymlink(volumePath, subPath string) ([]uintptr, e
break
}
// go1.23 behavior change: https://github.com/golang/go/issues/63703#issuecomment-2535941458
if stat.Mode()&os.ModeIrregular != 0 {
errorResult = fmt.Errorf("subpath %q is an unexpected irregular file after EvalSymlinks", currentFullPath)
break
}
if !mount.PathWithinBase(currentFullPath, volumePath) {
errorResult = fmt.Errorf("SubPath %q not within volume path %q", currentFullPath, volumePath)
break
@ -342,6 +341,10 @@ func doSafeMakeDir(pathname string, base string, perm os.FileMode) error {
if stat.Mode()&os.ModeSymlink != 0 {
return fmt.Errorf("subpath %q is an unexpected symlink after Mkdir", currentPath)
}
// go1.23 behavior change: https://github.com/golang/go/issues/63703#issuecomment-2535941458
if stat.Mode()&os.ModeIrregular != 0 {
return fmt.Errorf("subpath %q is an unexpected irregular file after Mkdir", currentPath)
}
}
return nil

View File

@ -17,12 +17,15 @@ limitations under the License.
package volume
import (
"sync/atomic"
"time"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
)
// Volume represents a directory used by pods or hosts on a node. All method
@ -130,6 +133,20 @@ type MounterArgs struct {
FSGroupChangePolicy *v1.PodFSGroupChangePolicy
DesiredSize *resource.Quantity
SELinuxLabel string
Recorder record.EventRecorder
}
type VolumeOwnership struct {
mounter Mounter
dir string
fsGroup *int64
fsGroupChangePolicy *v1.PodFSGroupChangePolicy
completionCallback func(volumetypes.CompleteFuncParam)
// for monitoring progress of permission change operation
pod *v1.Pod
fileCounter atomic.Int64
recorder record.EventRecorder
}
// Mounter interface provides methods to set up/mount the volume.

View File

@ -20,14 +20,19 @@ limitations under the License.
package volume
import (
"context"
"fmt"
"path/filepath"
"strings"
"syscall"
"os"
"time"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/record"
"k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/kubelet/events"
"k8s.io/kubernetes/pkg/volume/util/types"
)
@ -37,38 +42,110 @@ const (
execMask = os.FileMode(0110)
)
// SetVolumeOwnership modifies the given volume to be owned by
// fsGroup, and sets SetGid so that newly created files are owned by
// fsGroup. If fsGroup is nil nothing is done.
func SetVolumeOwnership(mounter Mounter, dir string, fsGroup *int64, fsGroupChangePolicy *v1.PodFSGroupChangePolicy, completeFunc func(types.CompleteFuncParam)) error {
if fsGroup == nil {
var (
// function that will be used for changing file permissions on linux
// mainly stored here as a variable so as it can replaced in tests
filePermissionChangeFunc = changeFilePermission
progressReportDuration = 60 * time.Second
firstEventReportDuration = 30 * time.Second
)
// NewVolumeOwnership returns an interface that can be used to recursively change volume permissions and ownership
func NewVolumeOwnership(mounter Mounter, dir string, fsGroup *int64, fsGroupChangePolicy *v1.PodFSGroupChangePolicy, completeFunc func(types.CompleteFuncParam)) *VolumeOwnership {
vo := &VolumeOwnership{
mounter: mounter,
dir: dir,
fsGroup: fsGroup,
fsGroupChangePolicy: fsGroupChangePolicy,
completionCallback: completeFunc,
}
vo.fileCounter.Store(0)
return vo
}
func (vo *VolumeOwnership) AddProgressNotifier(pod *v1.Pod, recorder record.EventRecorder) *VolumeOwnership {
vo.pod = pod
vo.recorder = recorder
return vo
}
func (vo *VolumeOwnership) ChangePermissions() error {
if vo.fsGroup == nil {
return nil
}
timer := time.AfterFunc(30*time.Second, func() {
klog.Warningf("Setting volume ownership for %s and fsGroup set. If the volume has a lot of files then setting volume ownership could be slow, see https://github.com/kubernetes/kubernetes/issues/69699", dir)
if skipPermissionChange(vo.mounter, vo.dir, vo.fsGroup, vo.fsGroupChangePolicy) {
klog.V(3).InfoS("Skipping permission and ownership change for volume", "path", vo.dir)
return nil
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
timer := time.AfterFunc(firstEventReportDuration, func() {
vo.initiateProgressMonitor(ctx)
})
defer timer.Stop()
if skipPermissionChange(mounter, dir, fsGroup, fsGroupChangePolicy) {
klog.V(3).InfoS("Skipping permission and ownership change for volume", "path", dir)
return nil
}
return vo.changePermissionsRecursively()
}
err := walkDeep(dir, func(path string, info os.FileInfo, err error) error {
func (vo *VolumeOwnership) initiateProgressMonitor(ctx context.Context) {
klog.Warningf("Setting volume ownership for %s and fsGroup set. If the volume has a lot of files then setting volume ownership could be slow, see https://github.com/kubernetes/kubernetes/issues/69699", vo.dir)
if vo.pod != nil {
go vo.monitorProgress(ctx)
}
}
func (vo *VolumeOwnership) changePermissionsRecursively() error {
err := walkDeep(vo.dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
return changeFilePermission(path, fsGroup, mounter.GetAttributes().ReadOnly, info)
vo.fileCounter.Add(1)
return filePermissionChangeFunc(path, vo.fsGroup, vo.mounter.GetAttributes().ReadOnly, info)
})
if completeFunc != nil {
completeFunc(types.CompleteFuncParam{
if vo.completionCallback != nil {
vo.completionCallback(types.CompleteFuncParam{
Err: &err,
})
}
return err
}
func (vo *VolumeOwnership) monitorProgress(ctx context.Context) {
dirName := getDirnameToReport(vo.dir, string(vo.pod.UID))
msg := fmt.Sprintf("Setting volume ownership for %s is taking longer than expected, consider using OnRootMismatch - https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#configure-volume-permission-and-ownership-change-policy-for-pods", dirName)
vo.recorder.Event(vo.pod, v1.EventTypeWarning, events.VolumePermissionChangeInProgress, msg)
ticker := time.NewTicker(progressReportDuration)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
vo.logWarning()
}
}
}
// report everything after podUID in dir string, including podUID
func getDirnameToReport(dir, podUID string) string {
podUIDIndex := strings.Index(dir, podUID)
if podUIDIndex == -1 {
return dir
}
return dir[podUIDIndex:]
}
func (vo *VolumeOwnership) logWarning() {
dirName := getDirnameToReport(vo.dir, string(vo.pod.UID))
msg := fmt.Sprintf("Setting volume ownership for %s, processed %d files.", dirName, vo.fileCounter.Load())
klog.Warning(msg)
vo.recorder.Event(vo.pod, v1.EventTypeWarning, events.VolumePermissionChangeInProgress, msg)
}
func changeFilePermission(filename string, fsGroup *int64, readonly bool, info os.FileInfo) error {
err := os.Lchown(filename, -1, int(*fsGroup))
if err != nil {

View File

@ -21,9 +21,19 @@ package volume
import (
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/record"
"k8s.io/kubernetes/pkg/volume/util/types"
)
func SetVolumeOwnership(mounter Mounter, dir string, fsGroup *int64, fsGroupChangePolicy *v1.PodFSGroupChangePolicy, completeFunc func(types.CompleteFuncParam)) error {
// NewVolumeOwnership returns an interface that can be used to recursively change volume permissions and ownership
func NewVolumeOwnership(mounter Mounter, dir string, fsGroup *int64, fsGroupChangePolicy *v1.PodFSGroupChangePolicy, completeFunc func(types.CompleteFuncParam)) *VolumeOwnership {
return nil
}
func (vo *VolumeOwnership) AddProgressNotifier(pod *v1.Pod, recorder record.EventRecorder) *VolumeOwnership {
return vo
}
func (vo *VolumeOwnership) ChangePermissions() error {
return nil
}