rebase: bump the k8s-dependencies group in /e2e with 3 updates

Bumps the k8s-dependencies group in /e2e with 3 updates: [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery), [k8s.io/cloud-provider](https://github.com/kubernetes/cloud-provider) and [k8s.io/pod-security-admission](https://github.com/kubernetes/pod-security-admission).


Updates `k8s.io/apimachinery` from 0.32.3 to 0.33.0
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.32.3...v0.33.0)

Updates `k8s.io/cloud-provider` from 0.32.3 to 0.33.0
- [Commits](https://github.com/kubernetes/cloud-provider/compare/v0.32.3...v0.33.0)

Updates `k8s.io/pod-security-admission` from 0.32.3 to 0.33.0
- [Commits](https://github.com/kubernetes/pod-security-admission/compare/v0.32.3...v0.33.0)

---
updated-dependencies:
- dependency-name: k8s.io/apimachinery
  dependency-version: 0.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: k8s-dependencies
- dependency-name: k8s.io/cloud-provider
  dependency-version: 0.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: k8s-dependencies
- dependency-name: k8s.io/pod-security-admission
  dependency-version: 0.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: k8s-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2025-05-06 11:20:01 +00:00
committed by mergify[bot]
parent d52dc2c4ba
commit dd77e72800
359 changed files with 11145 additions and 18557 deletions

View File

@ -73,12 +73,12 @@ import (
flowcontrolrequest "k8s.io/apiserver/pkg/util/flowcontrol/request"
"k8s.io/client-go/informers"
restclient "k8s.io/client-go/rest"
basecompatibility "k8s.io/component-base/compatibility"
"k8s.io/component-base/featuregate"
"k8s.io/component-base/logs"
"k8s.io/component-base/metrics/features"
"k8s.io/component-base/metrics/prometheus/slis"
"k8s.io/component-base/tracing"
utilversion "k8s.io/component-base/version"
"k8s.io/component-base/zpages/flagz"
"k8s.io/klog/v2"
openapicommon "k8s.io/kube-openapi/pkg/common"
@ -153,7 +153,17 @@ type Config struct {
// EffectiveVersion determines which apis and features are available
// based on when the api/feature lifecyle.
EffectiveVersion utilversion.EffectiveVersion
EffectiveVersion basecompatibility.EffectiveVersion
// EmulationForwardCompatible is an option to implicitly enable all APIs which are introduced after the emulation version and
// have higher priority than APIs of the same group resource enabled at the emulation version.
// If true, all APIs that have higher priority than the APIs(beta+) of the same group resource enabled at the emulation version will be installed.
// This is needed when a controller implementation migrates to newer API versions, for the binary version, and also uses the newer API versions even when emulation version is set.
// Not applicable to alpha APIs.
EmulationForwardCompatible bool
// RuntimeConfigEmulationForwardCompatible is an option to explicitly enable specific APIs introduced after the emulation version through the runtime-config.
// If true, APIs identified by group/version that are enabled in the --runtime-config flag will be installed even if it is introduced after the emulation version. --runtime-config flag values that identify multiple APIs, such as api/all,api/ga,api/beta, are not influenced by this flag and will only enable APIs available at the current emulation version.
// If false, error would be thrown if any GroupVersion or GroupVersionResource explicitly enabled in the --runtime-config flag is introduced after the emulation version.
RuntimeConfigEmulationForwardCompatible bool
// FeatureGate is a way to plumb feature gate through if you have them.
FeatureGate featuregate.FeatureGate
// AuditBackend is where audit events are sent to.
@ -839,20 +849,20 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G
StorageReadinessHook: NewStorageReadinessHook(c.StorageInitializationTimeout),
StorageVersionManager: c.StorageVersionManager,
EffectiveVersion: c.EffectiveVersion,
FeatureGate: c.FeatureGate,
EffectiveVersion: c.EffectiveVersion,
EmulationForwardCompatible: c.EmulationForwardCompatible,
RuntimeConfigEmulationForwardCompatible: c.RuntimeConfigEmulationForwardCompatible,
FeatureGate: c.FeatureGate,
muxAndDiscoveryCompleteSignals: map[string]<-chan struct{}{},
}
if c.FeatureGate.Enabled(genericfeatures.AggregatedDiscoveryEndpoint) {
manager := c.AggregatedDiscoveryGroupManager
if manager == nil {
manager = discoveryendpoint.NewResourceManager("apis")
}
s.AggregatedDiscoveryGroupManager = manager
s.AggregatedLegacyDiscoveryGroupManager = discoveryendpoint.NewResourceManager("api")
manager := c.AggregatedDiscoveryGroupManager
if manager == nil {
manager = discoveryendpoint.NewResourceManager("apis")
}
s.AggregatedDiscoveryGroupManager = manager
s.AggregatedLegacyDiscoveryGroupManager = discoveryendpoint.NewResourceManager("api")
for {
if c.JSONPatchMaxCopyBytes <= 0 {
break
@ -1030,6 +1040,11 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
failedHandler := genericapifilters.Unauthorized(c.Serializer)
failedHandler = genericapifilters.WithFailedAuthenticationAudit(failedHandler, c.AuditBackend, c.AuditPolicyRuleEvaluator)
// WithTracing comes after authentication so we can allow authenticated
// clients to influence sampling.
if c.FeatureGate.Enabled(genericfeatures.APIServerTracing) {
handler = genericapifilters.WithTracing(handler, c.TracerProvider)
}
failedHandler = filterlatency.TrackCompleted(failedHandler)
handler = filterlatency.TrackCompleted(handler)
handler = genericapifilters.WithAuthentication(handler, c.Authentication.Authenticator, failedHandler, c.Authentication.APIAudiences, c.Authentication.RequestHeaderConfig)
@ -1060,9 +1075,6 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
handler = genericfilters.WithRetryAfter(handler, c.lifecycleSignals.NotAcceptingNewRequest.Signaled())
}
handler = genericfilters.WithHTTPLogging(handler)
if c.FeatureGate.Enabled(genericfeatures.APIServerTracing) {
handler = genericapifilters.WithTracing(handler, c.TracerProvider)
}
handler = genericapifilters.WithLatencyTrackers(handler)
// WithRoutine will execute future handlers in a separate goroutine and serving
// handler in current goroutine to minimize the stack memory usage. It must be
@ -1108,15 +1120,11 @@ func installAPI(name string, s *GenericAPIServer, c *Config) {
}
}
routes.Version{Version: c.EffectiveVersion.BinaryVersion().Info()}.Install(s.Handler.GoRestfulContainer)
routes.Version{Version: c.EffectiveVersion.Info()}.Install(s.Handler.GoRestfulContainer)
if c.EnableDiscovery {
if c.FeatureGate.Enabled(genericfeatures.AggregatedDiscoveryEndpoint) {
wrapped := discoveryendpoint.WrapAggregatedDiscoveryToHandler(s.DiscoveryGroupManager, s.AggregatedDiscoveryGroupManager)
s.Handler.GoRestfulContainer.Add(wrapped.GenerateWebService("/apis", metav1.APIGroupList{}))
} else {
s.Handler.GoRestfulContainer.Add(s.DiscoveryGroupManager.WebService())
}
wrapped := discoveryendpoint.WrapAggregatedDiscoveryToHandler(s.DiscoveryGroupManager, s.AggregatedDiscoveryGroupManager)
s.Handler.GoRestfulContainer.Add(wrapped.GenerateWebService("/apis", metav1.APIGroupList{}))
}
if c.FlowControl != nil {
c.FlowControl.Install(s.Handler.NonGoRestfulMux)

View File

@ -19,6 +19,8 @@ package server
import (
"fmt"
"os"
"regexp"
"sort"
"strconv"
"strings"
@ -27,16 +29,26 @@ import (
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/sets"
apimachineryversion "k8s.io/apimachinery/pkg/util/version"
"k8s.io/apimachinery/pkg/version"
"k8s.io/apiserver/pkg/registry/rest"
serverstorage "k8s.io/apiserver/pkg/server/storage"
"k8s.io/klog/v2"
)
var alphaPattern = regexp.MustCompile(`^v\d+alpha\d+$`)
// resourceExpirationEvaluator holds info for deciding if a particular rest.Storage needs to excluded from the API
type resourceExpirationEvaluator struct {
currentVersion *apimachineryversion.Version
isAlpha bool
currentVersion *apimachineryversion.Version
emulationForwardCompatible bool
runtimeConfigEmulationForwardCompatible bool
isAlpha bool
// Special flag checking for the existence of alpha.0
// alpha.0 is a special case where everything merged to master is auto propagated to the release-1.n branch
isAlphaZero bool
// This is usually set for testing for which tests need to be removed. This prevent insta-failing CI.
// Set KUBE_APISERVER_STRICT_REMOVED_API_HANDLING_IN_ALPHA to see what will be removed when we tag beta
// This flag only takes effect during alpha but not alphaZero.
strictRemovedHandlingInAlpha bool
// This is usually set by a cluster-admin looking for a short-term escape hatch after something bad happened.
// This should be made a flag before merge
@ -46,24 +58,51 @@ type resourceExpirationEvaluator struct {
// ResourceExpirationEvaluator indicates whether or not a resource should be served.
type ResourceExpirationEvaluator interface {
// RemoveDeletedKinds inspects the storage map and modifies it in place by removing storage for kinds that have been deleted.
// RemoveUnavailableKinds inspects the storage map and modifies it in place by removing storage for kinds that have been deleted or are introduced after the current version.
// versionedResourcesStorageMap mirrors the field on APIGroupInfo, it's a map from version to resource to the storage.
RemoveDeletedKinds(groupName string, versioner runtime.ObjectVersioner, versionedResourcesStorageMap map[string]map[string]rest.Storage)
RemoveUnavailableKinds(groupName string, versioner runtime.ObjectVersioner, versionedResourcesStorageMap map[string]map[string]rest.Storage, apiResourceConfigSource serverstorage.APIResourceConfigSource) error
// ShouldServeForVersion returns true if a particular version cut off is after the current version
ShouldServeForVersion(majorRemoved, minorRemoved int) bool
}
type ResourceExpirationEvaluatorOptions struct {
// CurrentVersion is the current version of the apiserver.
CurrentVersion *apimachineryversion.Version
// Prerelease holds an optional prerelease portion of the version.
// This is used to determine if the current binary is an alpha.
Prerelease string
// EmulationForwardCompatible indicates whether the apiserver should serve resources that are introduced after the current version,
// when resources of the same group and resource name but with lower priority are served.
// Not applicable to alpha APIs.
EmulationForwardCompatible bool
// RuntimeConfigEmulationForwardCompatible indicates whether the apiserver should serve resources that are introduced after the current version,
// when the resource is explicitly enabled in runtime-config.
RuntimeConfigEmulationForwardCompatible bool
}
func NewResourceExpirationEvaluator(currentVersion *apimachineryversion.Version) (ResourceExpirationEvaluator, error) {
opts := ResourceExpirationEvaluatorOptions{
CurrentVersion: apimachineryversion.MajorMinor(currentVersion.Major(), currentVersion.Minor()),
Prerelease: currentVersion.PreRelease(),
}
return NewResourceExpirationEvaluatorFromOptions(opts)
}
func NewResourceExpirationEvaluatorFromOptions(opts ResourceExpirationEvaluatorOptions) (ResourceExpirationEvaluator, error) {
currentVersion := opts.CurrentVersion
if currentVersion == nil {
return nil, fmt.Errorf("empty NewResourceExpirationEvaluator currentVersion")
}
klog.V(1).Infof("NewResourceExpirationEvaluator with currentVersion: %s.", currentVersion)
ret := &resourceExpirationEvaluator{
strictRemovedHandlingInAlpha: false,
strictRemovedHandlingInAlpha: false,
emulationForwardCompatible: opts.EmulationForwardCompatible,
runtimeConfigEmulationForwardCompatible: opts.RuntimeConfigEmulationForwardCompatible,
}
// Only keeps the major and minor versions from input version.
ret.currentVersion = apimachineryversion.MajorMinor(currentVersion.Major(), currentVersion.Minor())
ret.isAlpha = strings.Contains(currentVersion.PreRelease(), "alpha")
ret.isAlpha = strings.Contains(opts.Prerelease, "alpha")
ret.isAlphaZero = strings.Contains(opts.Prerelease, "alpha.0")
if envString, ok := os.LookupEnv("KUBE_APISERVER_STRICT_REMOVED_API_HANDLING_IN_ALPHA"); !ok {
// do nothing
@ -84,7 +123,8 @@ func NewResourceExpirationEvaluator(currentVersion *apimachineryversion.Version)
return ret, nil
}
func (e *resourceExpirationEvaluator) shouldServe(gv schema.GroupVersion, versioner runtime.ObjectVersioner, resourceServingInfo rest.Storage) bool {
// isNotRemoved checks if a resource is removed due to the APILifecycleRemoved information.
func (e *resourceExpirationEvaluator) isNotRemoved(gv schema.GroupVersion, versioner runtime.ObjectVersioner, resourceServingInfo rest.Storage) bool {
internalPtr := resourceServingInfo.New()
target := gv
@ -99,15 +139,6 @@ func (e *resourceExpirationEvaluator) shouldServe(gv schema.GroupVersion, versio
return false
}
introduced, ok := versionedPtr.(introducedInterface)
if ok {
majorIntroduced, minorIntroduced := introduced.APILifecycleIntroduced()
verIntroduced := apimachineryversion.MajorMinor(uint(majorIntroduced), uint(minorIntroduced))
if e.currentVersion.LessThan(verIntroduced) {
return false
}
}
removed, ok := versionedPtr.(removedInterface)
if !ok {
return true
@ -127,7 +158,7 @@ func (e *resourceExpirationEvaluator) ShouldServeForVersion(majorRemoved, minorR
// at this point major and minor are equal, so this API should be removed when the current release GAs.
// If this is an alpha tag, don't remove by default, but allow the option.
// If the cluster-admin has requested serving one more release, allow it.
if e.isAlpha && e.strictRemovedHandlingInAlpha { // don't serve in alpha if we want strict handling
if e.isAlpha && !e.isAlphaZero && e.strictRemovedHandlingInAlpha { // don't serve in alpha.1+ if we want strict handling
return false
}
if e.isAlpha { // alphas are allowed to continue serving expired betas while we clean up the test
@ -150,13 +181,13 @@ type introducedInterface interface {
// removeDeletedKinds inspects the storage map and modifies it in place by removing storage for kinds that have been deleted.
// versionedResourcesStorageMap mirrors the field on APIGroupInfo, it's a map from version to resource to the storage.
func (e *resourceExpirationEvaluator) RemoveDeletedKinds(groupName string, versioner runtime.ObjectVersioner, versionedResourcesStorageMap map[string]map[string]rest.Storage) {
func (e *resourceExpirationEvaluator) removeDeletedKinds(groupName string, versioner runtime.ObjectVersioner, versionedResourcesStorageMap map[string]map[string]rest.Storage) {
versionsToRemove := sets.NewString()
for apiVersion := range sets.StringKeySet(versionedResourcesStorageMap) {
versionToResource := versionedResourcesStorageMap[apiVersion]
resourcesToRemove := sets.NewString()
for resourceName, resourceServingInfo := range versionToResource {
if !e.shouldServe(schema.GroupVersion{Group: groupName, Version: apiVersion}, versioner, resourceServingInfo) {
if !e.isNotRemoved(schema.GroupVersion{Group: groupName, Version: apiVersion}, versioner, resourceServingInfo) {
resourcesToRemove.Insert(resourceName)
}
}
@ -184,6 +215,126 @@ func (e *resourceExpirationEvaluator) RemoveDeletedKinds(groupName string, versi
}
}
func (e *resourceExpirationEvaluator) RemoveUnavailableKinds(groupName string, versioner runtime.ObjectVersioner, versionedResourcesStorageMap map[string]map[string]rest.Storage, apiResourceConfigSource serverstorage.APIResourceConfigSource) error {
e.removeDeletedKinds(groupName, versioner, versionedResourcesStorageMap)
return e.removeUnintroducedKinds(groupName, versioner, versionedResourcesStorageMap, apiResourceConfigSource)
}
// removeUnintroducedKinds inspects the storage map and modifies it in place by removing storage for kinds that are introduced after the current version.
// versionedResourcesStorageMap mirrors the field on APIGroupInfo, it's a map from version to resource to the storage.
func (e *resourceExpirationEvaluator) removeUnintroducedKinds(groupName string, versioner runtime.ObjectVersioner, versionedResourcesStorageMap map[string]map[string]rest.Storage, apiResourceConfigSource serverstorage.APIResourceConfigSource) error {
versionsToRemove := sets.NewString()
prioritizedVersions := versioner.PrioritizedVersionsForGroup(groupName)
sort.Slice(prioritizedVersions, func(i, j int) bool {
return version.CompareKubeAwareVersionStrings(prioritizedVersions[i].Version, prioritizedVersions[j].Version) > 0
})
enabledResources := sets.NewString()
// iterate from the end to the front, so that we remove the lower priority versions first.
for i := len(prioritizedVersions) - 1; i >= 0; i-- {
apiVersion := prioritizedVersions[i].Version
versionToResource := versionedResourcesStorageMap[apiVersion]
if len(versionToResource) == 0 {
continue
}
resourcesToRemove := sets.NewString()
for resourceName, resourceServingInfo := range versionToResource {
// we check the resource enablement from low priority to high priority.
// If the same resource with a different version that we have checked so far is already enabled, that means some resource with the same resourceName and a lower priority version has been enabled.
// Then emulation forward compatibility for the version being checked now is made based on this information.
lowerPriorityEnabled := enabledResources.Has(resourceName)
shouldKeep, err := e.shouldServeBasedOnVersionIntroduced(schema.GroupVersionResource{Group: groupName, Version: apiVersion, Resource: resourceName},
versioner, resourceServingInfo, apiResourceConfigSource, lowerPriorityEnabled)
if err != nil {
return err
}
if !shouldKeep {
resourcesToRemove.Insert(resourceName)
} else if !alphaPattern.MatchString(apiVersion) {
// enabledResources is passed onto the next iteration to check the enablement of higher priority resources for emulation forward compatibility.
// But enablement alpha apis do not affect the enablement of other versions because emulation forward compatibility is not applicable to alpha apis.
enabledResources.Insert(resourceName)
}
}
for resourceName := range versionedResourcesStorageMap[apiVersion] {
if !shouldRemoveResourceAndSubresources(resourcesToRemove, resourceName) {
continue
}
klog.V(1).Infof("Removing resource %v.%v.%v because it is introduced after the current version %s per APILifecycle.", resourceName, apiVersion, groupName, e.currentVersion.String())
storage := versionToResource[resourceName]
storage.Destroy()
delete(versionToResource, resourceName)
}
versionedResourcesStorageMap[apiVersion] = versionToResource
if len(versionedResourcesStorageMap[apiVersion]) == 0 {
versionsToRemove.Insert(apiVersion)
}
}
for _, apiVersion := range versionsToRemove.List() {
gv := schema.GroupVersion{Group: groupName, Version: apiVersion}
if apiResourceConfigSource != nil && apiResourceConfigSource.VersionExplicitlyEnabled(gv) {
return fmt.Errorf(
"cannot enable version %s in runtime-config because all the resources have been introduced after the current version %s. Consider setting --runtime-config-emulation-forward-compatible=true",
gv, e.currentVersion)
}
klog.V(1).Infof("Removing version %v.%v because it is introduced after the current version %s and because it has no resources per APILifecycle.", apiVersion, groupName, e.currentVersion.String())
delete(versionedResourcesStorageMap, apiVersion)
}
return nil
}
func (e *resourceExpirationEvaluator) shouldServeBasedOnVersionIntroduced(gvr schema.GroupVersionResource, versioner runtime.ObjectVersioner, resourceServingInfo rest.Storage,
apiResourceConfigSource serverstorage.APIResourceConfigSource, lowerPriorityEnabled bool) (bool, error) {
verIntroduced := apimachineryversion.MajorMinor(0, 0)
internalPtr := resourceServingInfo.New()
target := gvr.GroupVersion()
// honor storage that overrides group version (used for things like scale subresources)
if versionProvider, ok := resourceServingInfo.(rest.GroupVersionKindProvider); ok {
target = versionProvider.GroupVersionKind(target).GroupVersion()
}
versionedPtr, err := versioner.ConvertToVersion(internalPtr, target)
if err != nil {
utilruntime.HandleError(err)
return false, err
}
introduced, ok := versionedPtr.(introducedInterface)
if ok {
majorIntroduced, minorIntroduced := introduced.APILifecycleIntroduced()
verIntroduced = apimachineryversion.MajorMinor(uint(majorIntroduced), uint(minorIntroduced))
}
// should serve resource introduced at or before the current version.
if e.currentVersion.AtLeast(verIntroduced) {
return true, nil
}
// the rest of the function is to determine if a resource introduced after current version should be served. (only applicable in emulation mode.)
// if a lower priority version of the resource has been enabled, the same resource with higher priority
// should also be enabled if emulationForwardCompatible = true.
if e.emulationForwardCompatible && lowerPriorityEnabled {
return true, nil
}
if apiResourceConfigSource == nil {
return false, nil
}
// could explicitly enable future resources in runtime-config forward compatible mode.
if e.runtimeConfigEmulationForwardCompatible && (apiResourceConfigSource.ResourceExplicitlyEnabled(gvr) || apiResourceConfigSource.VersionExplicitlyEnabled(gvr.GroupVersion())) {
return true, nil
}
// return error if a future resource is explicit enabled in runtime-config but runtimeConfigEmulationForwardCompatible is false.
if apiResourceConfigSource.ResourceExplicitlyEnabled(gvr) {
return false, fmt.Errorf("cannot enable resource %s in runtime-config because it is introduced at %s after the current version %s. Consider setting --runtime-config-emulation-forward-compatible=true",
gvr, verIntroduced, e.currentVersion)
}
return false, nil
}
func shouldRemoveResourceAndSubresources(resourcesToRemove sets.String, resourceName string) bool {
for _, resourceToRemove := range resourcesToRemove.List() {
if resourceName == resourceToRemove {

View File

@ -15,4 +15,4 @@ limitations under the License.
*/
// Package server contains the plumbing to create kubernetes-like API server command.
package server // import "k8s.io/apiserver/pkg/server"
package server

View File

@ -16,4 +16,4 @@ limitations under the License.
// Package filters contains all the http handler chain filters which
// are not api related.
package filters // import "k8s.io/apiserver/pkg/server/filters"
package filters

View File

@ -52,8 +52,8 @@ var waitingMark = &requestWatermark{
phase: epmetrics.WaitingPhase,
}
var atomicMutatingExecuting, atomicReadOnlyExecuting int32
var atomicMutatingWaiting, atomicReadOnlyWaiting int32
var atomicMutatingExecuting, atomicReadOnlyExecuting atomic.Int32
var atomicMutatingWaiting, atomicReadOnlyWaiting atomic.Int32
// newInitializationSignal is defined for testing purposes.
var newInitializationSignal = utilflowcontrol.NewInitializationSignal
@ -143,16 +143,16 @@ func (h *priorityAndFairnessHandler) Handle(w http.ResponseWriter, r *http.Reque
isMutatingRequest := !nonMutatingRequestVerbs.Has(requestInfo.Verb)
noteExecutingDelta := func(delta int32) {
if isMutatingRequest {
watermark.recordMutating(int(atomic.AddInt32(&atomicMutatingExecuting, delta)))
watermark.recordMutating(int(atomicMutatingExecuting.Add(delta)))
} else {
watermark.recordReadOnly(int(atomic.AddInt32(&atomicReadOnlyExecuting, delta)))
watermark.recordReadOnly(int(atomicReadOnlyExecuting.Add(delta)))
}
}
noteWaitingDelta := func(delta int32) {
if isMutatingRequest {
waitingMark.recordMutating(int(atomic.AddInt32(&atomicMutatingWaiting, delta)))
waitingMark.recordMutating(int(atomicMutatingWaiting.Add(delta)))
} else {
waitingMark.recordReadOnly(int(atomic.AddInt32(&atomicReadOnlyWaiting, delta)))
waitingMark.recordReadOnly(int(atomicReadOnlyWaiting.Add(delta)))
}
}
queueNote := func(inQueue bool) {

View File

@ -54,8 +54,8 @@ import (
"k8s.io/apiserver/pkg/storageversion"
utilfeature "k8s.io/apiserver/pkg/util/feature"
restclient "k8s.io/client-go/rest"
basecompatibility "k8s.io/component-base/compatibility"
"k8s.io/component-base/featuregate"
utilversion "k8s.io/component-base/version"
"k8s.io/klog/v2"
openapibuilder3 "k8s.io/kube-openapi/pkg/builder3"
openapicommon "k8s.io/kube-openapi/pkg/common"
@ -244,7 +244,18 @@ type GenericAPIServer struct {
// EffectiveVersion determines which apis and features are available
// based on when the api/feature lifecyle.
EffectiveVersion utilversion.EffectiveVersion
EffectiveVersion basecompatibility.EffectiveVersion
// EmulationForwardCompatible is an option to implicitly enable all APIs which are introduced after the emulation version and
// have higher priority than APIs of the same group resource enabled at the emulation version.
// If true, all APIs that have higher priority than the APIs(beta+) of the same group resource enabled at the emulation version will be installed.
// This is needed when a controller implementation migrates to newer API versions, for the binary version, and also uses the newer API versions even when emulation version is set.
// Not applicable to alpha APIs.
EmulationForwardCompatible bool
// RuntimeConfigEmulationForwardCompatible is an option to explicitly enable specific APIs introduced after the emulation version through the runtime-config.
// If true, APIs identified by group/version that are enabled in the --runtime-config flag will be installed even if it is introduced after the emulation version. --runtime-config flag values that identify multiple APIs, such as api/all,api/ga,api/beta, are not influenced by this flag and will only enable APIs available at the current emulation version.
// If false, error would be thrown if any GroupVersion or GroupVersionResource explicitly enabled in the --runtime-config flag is introduced after the emulation version.
RuntimeConfigEmulationForwardCompatible bool
// FeatureGate is a way to plumb feature gate through if you have them.
FeatureGate featuregate.FeatureGate
@ -785,28 +796,26 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
}
resourceInfos = append(resourceInfos, r...)
if s.FeatureGate.Enabled(features.AggregatedDiscoveryEndpoint) {
// Aggregated discovery only aggregates resources under /apis
if apiPrefix == APIGroupPrefix {
s.AggregatedDiscoveryGroupManager.AddGroupVersion(
groupVersion.Group,
apidiscoveryv2.APIVersionDiscovery{
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
Version: groupVersion.Version,
Resources: discoveryAPIResources,
},
)
} else {
// There is only one group version for legacy resources, priority can be defaulted to 0.
s.AggregatedLegacyDiscoveryGroupManager.AddGroupVersion(
groupVersion.Group,
apidiscoveryv2.APIVersionDiscovery{
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
Version: groupVersion.Version,
Resources: discoveryAPIResources,
},
)
}
// Aggregated discovery only aggregates resources under /apis
if apiPrefix == APIGroupPrefix {
s.AggregatedDiscoveryGroupManager.AddGroupVersion(
groupVersion.Group,
apidiscoveryv2.APIVersionDiscovery{
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
Version: groupVersion.Version,
Resources: discoveryAPIResources,
},
)
} else {
// There is only one group version for legacy resources, priority can be defaulted to 0.
s.AggregatedLegacyDiscoveryGroupManager.AddGroupVersion(
groupVersion.Group,
apidiscoveryv2.APIVersionDiscovery{
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
Version: groupVersion.Version,
Resources: discoveryAPIResources,
},
)
}
}
@ -844,12 +853,8 @@ func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo
// Install the version handler.
// Add a handler at /<apiPrefix> to enumerate the supported api versions.
legacyRootAPIHandler := discovery.NewLegacyRootAPIHandler(s.discoveryAddresses, s.Serializer, apiPrefix)
if s.FeatureGate.Enabled(features.AggregatedDiscoveryEndpoint) {
wrapped := discoveryendpoint.WrapAggregatedDiscoveryToHandler(legacyRootAPIHandler, s.AggregatedLegacyDiscoveryGroupManager)
s.Handler.GoRestfulContainer.Add(wrapped.GenerateWebService("/api", metav1.APIVersions{}))
} else {
s.Handler.GoRestfulContainer.Add(legacyRootAPIHandler.WebService())
}
wrapped := discoveryendpoint.WrapAggregatedDiscoveryToHandler(legacyRootAPIHandler, s.AggregatedLegacyDiscoveryGroupManager)
s.Handler.GoRestfulContainer.Add(wrapped.GenerateWebService("/api", metav1.APIVersions{}))
s.registerStorageReadinessCheck("", apiGroupInfo)
return nil
@ -991,8 +996,18 @@ func (s *GenericAPIServer) newAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupV
// NewDefaultAPIGroupInfo returns an APIGroupInfo stubbed with "normal" values
// exposed for easier composition from other packages
func NewDefaultAPIGroupInfo(group string, scheme *runtime.Scheme, parameterCodec runtime.ParameterCodec, codecs serializer.CodecFactory) APIGroupInfo {
opts := []serializer.CodecFactoryOptionsMutator{}
if utilfeature.DefaultFeatureGate.Enabled(features.CBORServingAndStorage) {
codecs = serializer.NewCodecFactory(scheme, serializer.WithSerializer(cbor.NewSerializerInfo))
opts = append(opts, serializer.WithSerializer(cbor.NewSerializerInfo))
}
if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToJSON) {
opts = append(opts, serializer.WithStreamingCollectionEncodingToJSON())
}
if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToProtobuf) {
opts = append(opts, serializer.WithStreamingCollectionEncodingToProtobuf())
}
if len(opts) != 0 {
codecs = serializer.NewCodecFactory(scheme, opts...)
}
return APIGroupInfo{
PrioritizedVersions: scheme.PrioritizedVersionsForGroup(group),

View File

@ -19,4 +19,4 @@ limitations under the License.
//
// import "k8s.io/apiserver/pkg/server/healthz"
// healthz.InstallHandler(mux)
package healthz // import "k8s.io/apiserver/pkg/server/healthz"
package healthz

View File

@ -16,4 +16,4 @@ limitations under the License.
// Package httplog contains a helper object and functions to maintain a log
// along with an http response.
package httplog // import "k8s.io/apiserver/pkg/server/httplog"
package httplog

View File

@ -15,4 +15,4 @@ limitations under the License.
*/
// Package mux contains abstractions for http multiplexing of APIs.
package mux // import "k8s.io/apiserver/pkg/server/mux"
package mux

View File

@ -95,6 +95,14 @@ func (s *APIEnablementOptions) ApplyTo(c *server.Config, defaultResourceConfig *
}
mergedResourceConfig, err := resourceconfig.MergeAPIResourceConfigs(defaultResourceConfig, s.RuntimeConfig, registry)
if err != nil {
return err
}
// apply emulation forward compatibility to the api enablement if applicable.
if c.EmulationForwardCompatible {
mergedResourceConfig, err = resourceconfig.EmulationForwardCompatibleResourceConfig(mergedResourceConfig, s.RuntimeConfig, registry)
}
c.MergedResourceConfig = mergedResourceConfig
return err

View File

@ -18,4 +18,4 @@ limitations under the License.
// server. It takes a minimal set of dependencies and does not reference
// implementations, in order to ensure it may be reused by multiple components
// (such as CLI commands that wish to generate or validate config).
package options // import "k8s.io/apiserver/pkg/server/options"
package options

View File

@ -27,9 +27,9 @@ import (
"k8s.io/apimachinery/pkg/util/errors"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/server"
"k8s.io/apiserver/pkg/util/compatibility"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/component-base/featuregate"
utilversion "k8s.io/component-base/version"
basecompatibility "k8s.io/component-base/compatibility"
"github.com/spf13/pflag"
)
@ -95,22 +95,32 @@ type ServerRunOptions struct {
ShutdownWatchTerminationGracePeriod time.Duration
// ComponentGlobalsRegistry is the registry where the effective versions and feature gates for all components are stored.
ComponentGlobalsRegistry featuregate.ComponentGlobalsRegistry
ComponentGlobalsRegistry basecompatibility.ComponentGlobalsRegistry
// ComponentName is name under which the server's global variabled are registered in the ComponentGlobalsRegistry.
ComponentName string
// EmulationForwardCompatible is an option to implicitly enable all APIs which are introduced after the emulation version and
// have higher priority than APIs of the same group resource enabled at the emulation version.
// If true, all APIs that have higher priority than the APIs(beta+) of the same group resource enabled at the emulation version will be installed.
// This is needed when a controller implementation migrates to newer API versions, for the binary version, and also uses the newer API versions even when emulation version is set.
// Not applicable to alpha APIs.
EmulationForwardCompatible bool
// RuntimeConfigEmulationForwardCompatible is an option to explicitly enable specific APIs introduced after the emulation version through the runtime-config.
// If true, APIs identified by group/version that are enabled in the --runtime-config flag will be installed even if it is introduced after the emulation version. --runtime-config flag values that identify multiple APIs, such as api/all,api/ga,api/beta, are not influenced by this flag and will only enable APIs available at the current emulation version.
// If false, error would be thrown if any GroupVersion or GroupVersionResource explicitly enabled in the --runtime-config flag is introduced after the emulation version.
RuntimeConfigEmulationForwardCompatible bool
}
func NewServerRunOptions() *ServerRunOptions {
if featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent) == nil {
if compatibility.DefaultComponentGlobalsRegistry.EffectiveVersionFor(basecompatibility.DefaultKubeComponent) == nil {
featureGate := utilfeature.DefaultMutableFeatureGate
effectiveVersion := utilversion.DefaultKubeEffectiveVersion()
utilruntime.Must(featuregate.DefaultComponentGlobalsRegistry.Register(featuregate.DefaultKubeComponent, effectiveVersion, featureGate))
effectiveVersion := compatibility.DefaultBuildEffectiveVersion()
utilruntime.Must(compatibility.DefaultComponentGlobalsRegistry.Register(basecompatibility.DefaultKubeComponent, effectiveVersion, featureGate))
}
return NewServerRunOptionsForComponent(featuregate.DefaultKubeComponent, featuregate.DefaultComponentGlobalsRegistry)
return NewServerRunOptionsForComponent(basecompatibility.DefaultKubeComponent, compatibility.DefaultComponentGlobalsRegistry)
}
func NewServerRunOptionsForComponent(componentName string, componentGlobalsRegistry featuregate.ComponentGlobalsRegistry) *ServerRunOptions {
func NewServerRunOptionsForComponent(componentName string, componentGlobalsRegistry basecompatibility.ComponentGlobalsRegistry) *ServerRunOptions {
defaults := server.NewConfig(serializer.CodecFactory{})
return &ServerRunOptions{
MaxRequestsInFlight: defaults.MaxRequestsInFlight,
@ -152,6 +162,8 @@ func (s *ServerRunOptions) ApplyTo(c *server.Config) error {
c.ShutdownWatchTerminationGracePeriod = s.ShutdownWatchTerminationGracePeriod
c.EffectiveVersion = s.ComponentGlobalsRegistry.EffectiveVersionFor(s.ComponentName)
c.FeatureGate = s.ComponentGlobalsRegistry.FeatureGateFor(s.ComponentName)
c.EmulationForwardCompatible = s.EmulationForwardCompatible
c.RuntimeConfigEmulationForwardCompatible = s.RuntimeConfigEmulationForwardCompatible
return nil
}
@ -231,6 +243,17 @@ func (s *ServerRunOptions) Validate() []error {
if errs := s.ComponentGlobalsRegistry.Validate(); len(errs) != 0 {
errors = append(errors, errs...)
}
effectiveVersion := s.ComponentGlobalsRegistry.EffectiveVersionFor(s.ComponentName)
if effectiveVersion == nil {
return errors
}
notEmulationMode := effectiveVersion.BinaryVersion().WithPatch(0).EqualTo(effectiveVersion.EmulationVersion())
if notEmulationMode && s.EmulationForwardCompatible {
errors = append(errors, fmt.Errorf("ServerRunOptions.EmulationForwardCompatible cannot be set to true if the emulation version is the same as the binary version"))
}
if notEmulationMode && s.RuntimeConfigEmulationForwardCompatible {
errors = append(errors, fmt.Errorf("ServerRunOptions.RuntimeConfigEmulationForwardCompatible cannot be set to true if the emulation version is the same as the binary version"))
}
return errors
}
@ -376,6 +399,13 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
"for active watch request(s) to drain during the graceful server shutdown window.")
s.ComponentGlobalsRegistry.AddFlags(fs)
fs.BoolVar(&s.EmulationForwardCompatible, "emulation-forward-compatible", s.EmulationForwardCompatible, ""+
"If true, for any beta+ APIs enabled by default or by --runtime-config at the emulation version, their future versions with higher priority/stability will be auto enabled even if they introduced after the emulation version. "+
"Can only be set to true if the emulation version is lower than the binary version.")
fs.BoolVar(&s.RuntimeConfigEmulationForwardCompatible, "runtime-config-emulation-forward-compatible", s.RuntimeConfigEmulationForwardCompatible, ""+
"If true, APIs identified by group/version that are enabled in the --runtime-config flag will be installed even if it is introduced after the emulation version. "+
"If false, server would fail to start if any APIs identified by group/version that are enabled in the --runtime-config flag are introduced after the emulation version. "+
"Can only be set to true if the emulation version is lower than the binary version.")
}
// Complete fills missing fields with defaults.

View File

@ -18,6 +18,7 @@ package options
import (
"fmt"
"time"
"github.com/google/uuid"
@ -49,9 +50,18 @@ func (s *SecureServingOptionsWithLoopback) ApplyTo(secureServingInfo **server.Se
return nil
}
// Set a validity period of approximately 3 years for the loopback certificate
// to avoid kube-apiserver disruptions due to certificate expiration.
// When this certificate expires, restarting kube-apiserver will automatically
// regenerate a new certificate with fresh validity dates.
maxAge := (3*365 + 1) * 24 * time.Hour
// create self-signed cert+key with the fake server.LoopbackClientServerNameOverride and
// let the server return it when the loopback client connects.
certPem, keyPem, err := certutil.GenerateSelfSignedCertKey(server.LoopbackClientServerNameOverride, nil, nil)
certPem, keyPem, err := certutil.GenerateSelfSignedCertKeyWithOptions(certutil.SelfSignedCertKeyOptions{
Host: server.LoopbackClientServerNameOverride,
MaxAge: maxAge,
})
if err != nil {
return fmt.Errorf("failed to generate self-signed certificate for loopback connection: %v", err)
}

View File

@ -15,4 +15,4 @@ limitations under the License.
*/
// Package resourceconfig contains the resource config related helper functions.
package resourceconfig // import "k8s.io/apiserver/pkg/server/resourceconfig"
package resourceconfig

View File

@ -19,11 +19,13 @@ package resourceconfig
import (
"fmt"
"regexp"
"sort"
"strconv"
"strings"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/version"
serverstore "k8s.io/apiserver/pkg/server/storage"
cliflag "k8s.io/component-base/cli/flag"
)
@ -36,6 +38,8 @@ type GroupVersionRegistry interface {
IsVersionRegistered(v schema.GroupVersion) bool
// PrioritizedVersionsAllGroups returns all registered group versions.
PrioritizedVersionsAllGroups() []schema.GroupVersion
// PrioritizedVersionsForGroup returns versions for a single group in priority order
PrioritizedVersionsForGroup(group string) []schema.GroupVersion
}
// MergeResourceEncodingConfigs merges the given defaultResourceConfig with specific GroupVersionResource overrides.
@ -100,7 +104,17 @@ func MergeAPIResourceConfigs(
}
}
}
if err := applyVersionAndResourcePreferences(resourceConfig, overrides, registry); err != nil {
return nil, err
}
return resourceConfig, nil
}
func applyVersionAndResourcePreferences(
resourceConfig *serverstore.ResourceConfig,
overrides cliflag.ConfigurationMap,
registry GroupVersionRegistry,
) error {
type versionEnablementPreference struct {
key string
enabled bool
@ -130,7 +144,7 @@ func MergeAPIResourceConfigs(
groupVersionString := tokens[0] + "/" + tokens[1]
groupVersion, err := schema.ParseGroupVersion(groupVersionString)
if err != nil {
return nil, fmt.Errorf("invalid key %s", key)
return fmt.Errorf("invalid key %s", key)
}
// Exclude group not registered into the registry.
@ -140,11 +154,11 @@ func MergeAPIResourceConfigs(
// Verify that the groupVersion is registered into registry.
if !registry.IsVersionRegistered(groupVersion) {
return nil, fmt.Errorf("group version %s that has not been registered", groupVersion.String())
return fmt.Errorf("group version %s that has not been registered", groupVersion.String())
}
enabled, err := getRuntimeConfigValue(overrides, key, false)
if err != nil {
return nil, err
return err
}
switch len(tokens) {
@ -156,7 +170,7 @@ func MergeAPIResourceConfigs(
})
case 3:
if strings.ToLower(tokens[2]) != tokens[2] {
return nil, fmt.Errorf("invalid key %v: group/version/resource and resource is always lowercase plural, not %q", key, tokens[2])
return fmt.Errorf("invalid key %v: group/version/resource and resource is always lowercase plural, not %q", key, tokens[2])
}
resourcePreferences = append(resourcePreferences, resourceEnablementPreference{
key: key,
@ -170,11 +184,11 @@ func MergeAPIResourceConfigs(
for _, versionPreference := range versionPreferences {
if versionPreference.enabled {
// enable the groupVersion for "group/version=true"
resourceConfig.EnableVersions(versionPreference.groupVersion)
resourceConfig.ExplicitlyEnableVersions(versionPreference.groupVersion)
} else {
// disable the groupVersion only for "group/version=false"
resourceConfig.DisableVersions(versionPreference.groupVersion)
resourceConfig.ExplicitlyDisableVersions(versionPreference.groupVersion)
}
}
@ -182,13 +196,12 @@ func MergeAPIResourceConfigs(
for _, resourcePreference := range resourcePreferences {
if resourcePreference.enabled {
// enable the resource for "group/version/resource=true"
resourceConfig.EnableResources(resourcePreference.groupVersionResource)
resourceConfig.ExplicitlyEnableResources(resourcePreference.groupVersionResource)
} else {
resourceConfig.DisableResources(resourcePreference.groupVersionResource)
resourceConfig.ExplicitlyDisableResources(resourcePreference.groupVersionResource)
}
}
return resourceConfig, nil
return nil
}
func getRuntimeConfigValue(overrides cliflag.ConfigurationMap, apiKey string, defaultValue bool) (bool, error) {
@ -227,3 +240,61 @@ func ParseGroups(resourceConfig cliflag.ConfigurationMap) ([]string, error) {
return groups, nil
}
// EmulationForwardCompatibleResourceConfig creates a new ResourceConfig that besides all the enabled resources in resourceConfig,
// enables all higher priority versions of enabled resources, excluding alpha versions.
// This is useful for ensuring forward compatibility when a new version of an API is introduced.
func EmulationForwardCompatibleResourceConfig(
resourceConfig *serverstore.ResourceConfig,
resourceConfigOverrides cliflag.ConfigurationMap,
registry GroupVersionRegistry,
) (*serverstore.ResourceConfig, error) {
ret := serverstore.NewResourceConfig()
for gv, enabled := range resourceConfig.GroupVersionConfigs {
ret.GroupVersionConfigs[gv] = enabled
if !enabled {
continue
}
// emulation forward compatibility is not applicable to alpha apis.
if alphaPattern.MatchString(gv.Version) {
continue
}
// if a gv is enabled, all the versions with higher priority (all the versions before gv in PrioritizedVersionsForGroup) are also implicitly enabled for emulation forward compatibility.
prioritizedVersions := registry.PrioritizedVersionsForGroup(gv.Group)
sort.Slice(prioritizedVersions, func(i, j int) bool {
return version.CompareKubeAwareVersionStrings(prioritizedVersions[i].Version, prioritizedVersions[j].Version) > 0
})
for _, pgv := range prioritizedVersions {
if pgv.Version == gv.Version {
break
}
ret.EnableVersions(pgv)
}
}
for gvr, enabled := range resourceConfig.ResourceConfigs {
ret.ResourceConfigs[gvr] = enabled
if !enabled {
continue
}
// emulation forward compatibility is not applicable to alpha apis.
if alphaPattern.MatchString(gvr.Version) {
continue
}
// if a gvr is enabled, all the versions with the same resource name and higher priority (all the versions before gv in PrioritizedVersionsForGroup) are also implicitly enabled for emulation forward compatibility.
prioritizedVersions := registry.PrioritizedVersionsForGroup(gvr.Group)
sort.Slice(prioritizedVersions, func(i, j int) bool {
return version.CompareKubeAwareVersionStrings(prioritizedVersions[i].Version, prioritizedVersions[j].Version) > 0
})
for _, pgv := range prioritizedVersions {
if pgv.Version == gvr.Version {
break
}
ret.EnableResources(pgv.WithResource(gvr.Resource))
}
}
// need to reapply the version preferences if there is an override of a higher priority version.
if err := applyVersionAndResourcePreferences(ret, resourceConfigOverrides, registry); err != nil {
return nil, err
}
return ret, nil
}

View File

@ -15,4 +15,4 @@ limitations under the License.
*/
// Package routes holds a collection of optional genericapiserver http handlers.
package routes // import "k8s.io/apiserver/pkg/server/routes"
package routes

View File

@ -39,10 +39,10 @@ func (v Version) Install(c *restful.Container) {
// Set up a service to return the git code version.
versionWS := new(restful.WebService)
versionWS.Path("/version")
versionWS.Doc("git code version from which this is built")
versionWS.Doc("get the version information for this server.")
versionWS.Route(
versionWS.GET("/").To(v.handleVersion).
Doc("get the code version").
Doc("get the version information for this server").
Operation("getCodeVersion").
Produces(restful.MIME_JSON).
Consumes(restful.MIME_JSON).

View File

@ -172,33 +172,31 @@ func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Dur
ReadHeaderTimeout: 32 * time.Second, // just shy of requestTimeoutUpperBound
}
// At least 99% of serialized resources in surveyed clusters were smaller than 256kb.
// This should be big enough to accommodate most API POST requests in a single frame,
// and small enough to allow a per connection buffer of this size multiplied by `MaxConcurrentStreams`.
const resourceBody99Percentile = 256 * 1024
http2Options := &http2.Server{
IdleTimeout: 90 * time.Second, // matches http.DefaultTransport keep-alive timeout
}
// shrink the per-stream buffer and max framesize from the 1MB default while still accommodating most API POST requests in a single frame
http2Options.MaxUploadBufferPerStream = resourceBody99Percentile
http2Options.MaxReadFrameSize = resourceBody99Percentile
// use the overridden concurrent streams setting or make the default of 250 explicit so we can size MaxUploadBufferPerConnection appropriately
if s.HTTP2MaxStreamsPerConnection > 0 {
http2Options.MaxConcurrentStreams = uint32(s.HTTP2MaxStreamsPerConnection)
} else {
// match http2.initialMaxConcurrentStreams used by clients
// this makes it so that a malicious client can only open 400 streams before we forcibly close the connection
// https://github.com/golang/net/commit/b225e7ca6dde1ef5a5ae5ce922861bda011cfabd
http2Options.MaxConcurrentStreams = 100
}
// increase the connection buffer size from the 1MB default to handle the specified number of concurrent streams
http2Options.MaxUploadBufferPerConnection = http2Options.MaxUploadBufferPerStream * int32(http2Options.MaxConcurrentStreams)
if !s.DisableHTTP2 {
// At least 99% of serialized resources in surveyed clusters were smaller than 256kb.
// This should be big enough to accommodate most API POST requests in a single frame,
// and small enough to allow a per connection buffer of this size multiplied by `MaxConcurrentStreams`.
const resourceBody99Percentile = 256 * 1024
http2Options := &http2.Server{
IdleTimeout: 90 * time.Second, // matches http.DefaultTransport keep-alive timeout
// shrink the per-stream buffer and max framesize from the 1MB default while still accommodating most API POST requests in a single frame
MaxUploadBufferPerStream: resourceBody99Percentile,
MaxReadFrameSize: resourceBody99Percentile,
}
// use the overridden concurrent streams setting or make the default of 250 explicit so we can size MaxUploadBufferPerConnection appropriately
if s.HTTP2MaxStreamsPerConnection > 0 {
http2Options.MaxConcurrentStreams = uint32(s.HTTP2MaxStreamsPerConnection)
} else {
// match http2.initialMaxConcurrentStreams used by clients
// this makes it so that a malicious client can only open 400 streams before we forcibly close the connection
// https://github.com/golang/net/commit/b225e7ca6dde1ef5a5ae5ce922861bda011cfabd
http2Options.MaxConcurrentStreams = 100
}
// increase the connection buffer size from the 1MB default to handle the specified number of concurrent streams
http2Options.MaxUploadBufferPerConnection = http2Options.MaxUploadBufferPerStream * int32(http2Options.MaxConcurrentStreams)
// apply settings to the server
if err := http2.ConfigureServer(secureServer, http2Options); err != nil {
return nil, nil, fmt.Errorf("error configuring http2: %v", err)
@ -236,8 +234,11 @@ func RunServer(
defer close(serverShutdownCh)
<-stopCh
ctx, cancel := context.WithTimeout(context.Background(), shutDownTimeout)
server.Shutdown(ctx)
cancel()
defer cancel()
err := server.Shutdown(ctx)
if err != nil {
klog.Errorf("Failed to shutdown server: %v", err)
}
}()
go func() {

View File

@ -15,4 +15,4 @@ limitations under the License.
*/
// Package storage contains the plumbing to setup the etcd storage of the apiserver.
package storage // import "k8s.io/apiserver/pkg/server/storage"
package storage

View File

@ -24,17 +24,26 @@ import (
type APIResourceConfigSource interface {
ResourceEnabled(resource schema.GroupVersionResource) bool
AnyResourceForGroupEnabled(group string) bool
ResourceExplicitlyEnabled(resource schema.GroupVersionResource) bool
VersionExplicitlyEnabled(version schema.GroupVersion) bool
}
var _ APIResourceConfigSource = &ResourceConfig{}
type ResourceConfig struct {
GroupVersionConfigs map[schema.GroupVersion]bool
ResourceConfigs map[schema.GroupVersionResource]bool
GroupVersionConfigs map[schema.GroupVersion]bool
ResourceConfigs map[schema.GroupVersionResource]bool
ExplicitGroupVersionConfigs map[schema.GroupVersion]bool
ExplicitResourceConfigs map[schema.GroupVersionResource]bool
}
func NewResourceConfig() *ResourceConfig {
return &ResourceConfig{GroupVersionConfigs: map[schema.GroupVersion]bool{}, ResourceConfigs: map[schema.GroupVersionResource]bool{}}
return &ResourceConfig{
GroupVersionConfigs: map[schema.GroupVersion]bool{},
ResourceConfigs: map[schema.GroupVersionResource]bool{},
ExplicitGroupVersionConfigs: map[schema.GroupVersion]bool{},
ExplicitResourceConfigs: map[schema.GroupVersionResource]bool{},
}
}
// DisableMatchingVersions disables all group/versions for which the matcher function returns true.
@ -77,6 +86,7 @@ func (o *ResourceConfig) removeMatchingResourcePreferences(matcher func(gvr sche
}
for _, k := range keysToRemove {
delete(o.ResourceConfigs, k)
delete(o.ExplicitResourceConfigs, k)
}
}
@ -91,6 +101,13 @@ func (o *ResourceConfig) DisableVersions(versions ...schema.GroupVersion) {
}
}
func (o *ResourceConfig) ExplicitlyDisableVersions(versions ...schema.GroupVersion) {
for _, version := range versions {
o.ExplicitGroupVersionConfigs[version] = false
}
o.DisableVersions(versions...)
}
// EnableVersions enables all resources in a given groupVersion.
// This will remove any preferences previously set on individual resources.
func (o *ResourceConfig) EnableVersions(versions ...schema.GroupVersion) {
@ -103,10 +120,16 @@ func (o *ResourceConfig) EnableVersions(versions ...schema.GroupVersion) {
}
func (o *ResourceConfig) ExplicitlyEnableVersions(versions ...schema.GroupVersion) {
for _, version := range versions {
o.ExplicitGroupVersionConfigs[version] = true
}
o.EnableVersions(versions...)
}
// TODO this must be removed and we enable/disable individual resources.
func (o *ResourceConfig) versionEnabled(version schema.GroupVersion) bool {
enabled, _ := o.GroupVersionConfigs[version]
return enabled
return o.GroupVersionConfigs[version]
}
func (o *ResourceConfig) DisableResources(resources ...schema.GroupVersionResource) {
@ -115,12 +138,26 @@ func (o *ResourceConfig) DisableResources(resources ...schema.GroupVersionResour
}
}
func (o *ResourceConfig) ExplicitlyDisableResources(resources ...schema.GroupVersionResource) {
for _, resource := range resources {
o.ExplicitResourceConfigs[resource] = false
}
o.DisableResources(resources...)
}
func (o *ResourceConfig) EnableResources(resources ...schema.GroupVersionResource) {
for _, resource := range resources {
o.ResourceConfigs[resource] = true
}
}
func (o *ResourceConfig) ExplicitlyEnableResources(resources ...schema.GroupVersionResource) {
for _, resource := range resources {
o.ExplicitResourceConfigs[resource] = true
}
o.EnableResources(resources...)
}
func (o *ResourceConfig) ResourceEnabled(resource schema.GroupVersionResource) bool {
// if a resource is explicitly set, that takes priority over the preference of the version.
resourceEnabled, explicitlySet := o.ResourceConfigs[resource]
@ -151,3 +188,19 @@ func (o *ResourceConfig) AnyResourceForGroupEnabled(group string) bool {
return false
}
func (o *ResourceConfig) ResourceExplicitlyEnabled(resource schema.GroupVersionResource) bool {
resourceEnabled, explicitlySet := o.ExplicitResourceConfigs[resource]
if explicitlySet {
return resourceEnabled
}
return false
}
func (o *ResourceConfig) VersionExplicitlyEnabled(version schema.GroupVersion) bool {
versionEnabled, explicitlySet := o.ExplicitGroupVersionConfigs[version]
if explicitlySet {
return versionEnabled
}
return false
}

View File

@ -22,7 +22,8 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
apimachineryversion "k8s.io/apimachinery/pkg/util/version"
version "k8s.io/component-base/version"
"k8s.io/apiserver/pkg/util/compatibility"
basecompatibility "k8s.io/component-base/compatibility"
)
type ResourceEncodingConfig interface {
@ -43,7 +44,7 @@ type DefaultResourceEncodingConfig struct {
// resources records the overriding encoding configs for individual resources.
resources map[schema.GroupResource]*OverridingResourceEncoding
scheme *runtime.Scheme
effectiveVersion version.EffectiveVersion
effectiveVersion basecompatibility.EffectiveVersion
}
type OverridingResourceEncoding struct {
@ -54,7 +55,11 @@ type OverridingResourceEncoding struct {
var _ ResourceEncodingConfig = &DefaultResourceEncodingConfig{}
func NewDefaultResourceEncodingConfig(scheme *runtime.Scheme) *DefaultResourceEncodingConfig {
return &DefaultResourceEncodingConfig{resources: map[schema.GroupResource]*OverridingResourceEncoding{}, scheme: scheme, effectiveVersion: version.DefaultKubeEffectiveVersion()}
return NewDefaultResourceEncodingConfigForEffectiveVersion(scheme, compatibility.DefaultComponentGlobalsRegistry.EffectiveVersionFor(basecompatibility.DefaultKubeComponent))
}
func NewDefaultResourceEncodingConfigForEffectiveVersion(scheme *runtime.Scheme, effectiveVersion basecompatibility.EffectiveVersion) *DefaultResourceEncodingConfig {
return &DefaultResourceEncodingConfig{resources: map[schema.GroupResource]*OverridingResourceEncoding{}, scheme: scheme, effectiveVersion: effectiveVersion}
}
func (o *DefaultResourceEncodingConfig) SetResourceEncoding(resourceBeingStored schema.GroupResource, externalEncodingVersion, internalVersion schema.GroupVersion) {
@ -64,7 +69,7 @@ func (o *DefaultResourceEncodingConfig) SetResourceEncoding(resourceBeingStored
}
}
func (o *DefaultResourceEncodingConfig) SetEffectiveVersion(effectiveVersion version.EffectiveVersion) {
func (o *DefaultResourceEncodingConfig) SetEffectiveVersion(effectiveVersion basecompatibility.EffectiveVersion) {
o.effectiveVersion = effectiveVersion
}
@ -121,7 +126,7 @@ type replacementInterface interface {
APILifecycleReplacement() schema.GroupVersionKind
}
func emulatedStorageVersion(binaryVersionOfResource schema.GroupVersion, example runtime.Object, effectiveVersion version.EffectiveVersion, scheme *runtime.Scheme) (schema.GroupVersion, error) {
func emulatedStorageVersion(binaryVersionOfResource schema.GroupVersion, example runtime.Object, effectiveVersion basecompatibility.EffectiveVersion, scheme *runtime.Scheme) (schema.GroupVersion, error) {
if example == nil || effectiveVersion == nil {
return binaryVersionOfResource, nil
}
@ -172,7 +177,7 @@ func emulatedStorageVersion(binaryVersionOfResource schema.GroupVersion, example
}
// If it was introduced after current compatibility version, don't use it
// skip the introduced check for test when currentVersion is 0.0 to test all apis
// skip the introduced check for test when current compatibility version is 0.0 to test all apis
if introduced, hasIntroduced := exampleOfGVK.(introducedInterface); hasIntroduced && (compatibilityVersion.Major() > 0 || compatibilityVersion.Minor() > 0) {
// Skip versions that have a replacement.