mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-08 03:33:56 +00:00
Cleanup rest storage resources on shutdown
This commit is contained in:
parent
65178fec72
commit
0527a0dd45
@ -159,7 +159,7 @@ func Run(completeOptions completedServerRunOptions, stopCh <-chan struct{}) erro
|
|||||||
|
|
||||||
klog.InfoS("Golang settings", "GOGC", os.Getenv("GOGC"), "GOMAXPROCS", os.Getenv("GOMAXPROCS"), "GOTRACEBACK", os.Getenv("GOTRACEBACK"))
|
klog.InfoS("Golang settings", "GOGC", os.Getenv("GOGC"), "GOMAXPROCS", os.Getenv("GOMAXPROCS"), "GOTRACEBACK", os.Getenv("GOTRACEBACK"))
|
||||||
|
|
||||||
server, err := CreateServerChain(completeOptions, stopCh)
|
server, err := CreateServerChain(completeOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -173,7 +173,7 @@ func Run(completeOptions completedServerRunOptions, stopCh <-chan struct{}) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateServerChain creates the apiservers connected via delegation.
|
// CreateServerChain creates the apiservers connected via delegation.
|
||||||
func CreateServerChain(completedOptions completedServerRunOptions, stopCh <-chan struct{}) (*aggregatorapiserver.APIAggregator, error) {
|
func CreateServerChain(completedOptions completedServerRunOptions) (*aggregatorapiserver.APIAggregator, error) {
|
||||||
kubeAPIServerConfig, serviceResolver, pluginInitializer, err := CreateKubeAPIServerConfig(completedOptions)
|
kubeAPIServerConfig, serviceResolver, pluginInitializer, err := CreateKubeAPIServerConfig(completedOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -213,7 +213,7 @@ func StartTestServer(t Logger, instanceOptions *TestServerInstanceOptions, custo
|
|||||||
|
|
||||||
t.Logf("runtime-config=%v", completedOptions.APIEnablement.RuntimeConfig)
|
t.Logf("runtime-config=%v", completedOptions.APIEnablement.RuntimeConfig)
|
||||||
t.Logf("Starting kube-apiserver on port %d...", s.SecureServing.BindPort)
|
t.Logf("Starting kube-apiserver on port %d...", s.SecureServing.BindPort)
|
||||||
server, err := app.CreateServerChain(completedOptions, stopCh)
|
server, err := app.CreateServerChain(completedOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, fmt.Errorf("failed to create server chain: %v", err)
|
return result, fmt.Errorf("failed to create server chain: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -70,9 +70,12 @@ func StorageWithCacher() generic.StorageDecorator {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, func() {}, err
|
return nil, func() {}, err
|
||||||
}
|
}
|
||||||
|
var once sync.Once
|
||||||
destroyFunc := func() {
|
destroyFunc := func() {
|
||||||
|
once.Do(func() {
|
||||||
cacher.Stop()
|
cacher.Stop()
|
||||||
d()
|
d()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : Remove RegisterStorageCleanup below when PR
|
// TODO : Remove RegisterStorageCleanup below when PR
|
||||||
|
@ -217,7 +217,10 @@ type Store struct {
|
|||||||
// If the StorageVersioner is nil, apiserver will leave the
|
// If the StorageVersioner is nil, apiserver will leave the
|
||||||
// storageVersionHash as empty in the discovery document.
|
// storageVersionHash as empty in the discovery document.
|
||||||
StorageVersioner runtime.GroupVersioner
|
StorageVersioner runtime.GroupVersioner
|
||||||
// Called to cleanup clients used by the underlying Storage; optional.
|
|
||||||
|
// DestroyFunc cleans up clients used by the underlying Storage; optional.
|
||||||
|
// If set, DestroyFunc has to be implemented in thread-safe way and
|
||||||
|
// be prepared for being called more than once.
|
||||||
DestroyFunc func()
|
DestroyFunc func()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,6 +282,13 @@ func (e *Store) New() runtime.Object {
|
|||||||
return e.NewFunc()
|
return e.NewFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destroy cleans up its resources on shutdown.
|
||||||
|
func (e *Store) Destroy() {
|
||||||
|
if e.DestroyFunc != nil {
|
||||||
|
e.DestroyFunc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewList implements rest.Lister.
|
// NewList implements rest.Lister.
|
||||||
func (e *Store) NewList() runtime.Object {
|
func (e *Store) NewList() runtime.Object {
|
||||||
return e.NewListFunc()
|
return e.NewListFunc()
|
||||||
@ -1433,11 +1443,14 @@ func (e *Store) CompleteWithOptions(options *generic.StoreOptions) error {
|
|||||||
if opts.CountMetricPollPeriod > 0 {
|
if opts.CountMetricPollPeriod > 0 {
|
||||||
stopFunc := e.startObservingCount(opts.CountMetricPollPeriod, opts.StorageObjectCountTracker)
|
stopFunc := e.startObservingCount(opts.CountMetricPollPeriod, opts.StorageObjectCountTracker)
|
||||||
previousDestroy := e.DestroyFunc
|
previousDestroy := e.DestroyFunc
|
||||||
|
var once sync.Once
|
||||||
e.DestroyFunc = func() {
|
e.DestroyFunc = func() {
|
||||||
|
once.Do(func() {
|
||||||
stopFunc()
|
stopFunc()
|
||||||
if previousDestroy != nil {
|
if previousDestroy != nil {
|
||||||
previousDestroy()
|
previousDestroy()
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,6 +89,16 @@ type APIGroupInfo struct {
|
|||||||
StaticOpenAPISpec *spec.Swagger
|
StaticOpenAPISpec *spec.Swagger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *APIGroupInfo) destroyStorage() {
|
||||||
|
for _, stores := range a.VersionedResourcesStorageMap {
|
||||||
|
for _, store := range stores {
|
||||||
|
// TODO(wojtek-t): Uncomment once all storage support it.
|
||||||
|
klog.Errorf("Destroying storage: %v", store)
|
||||||
|
// store.Destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GenericAPIServer contains state for a Kubernetes cluster api server.
|
// GenericAPIServer contains state for a Kubernetes cluster api server.
|
||||||
type GenericAPIServer struct {
|
type GenericAPIServer struct {
|
||||||
// discoveryAddresses is used to build cluster IPs for discovery.
|
// discoveryAddresses is used to build cluster IPs for discovery.
|
||||||
@ -222,6 +232,9 @@ type GenericAPIServer struct {
|
|||||||
// lifecycleSignals provides access to the various signals that happen during the life cycle of the apiserver.
|
// lifecycleSignals provides access to the various signals that happen during the life cycle of the apiserver.
|
||||||
lifecycleSignals lifecycleSignals
|
lifecycleSignals lifecycleSignals
|
||||||
|
|
||||||
|
// destroyFns contains a list of functions that should be called on shutdown to clean up resources.
|
||||||
|
destroyFns []func()
|
||||||
|
|
||||||
// muxAndDiscoveryCompleteSignals holds signals that indicate all known HTTP paths have been registered.
|
// muxAndDiscoveryCompleteSignals holds signals that indicate all known HTTP paths have been registered.
|
||||||
// it exists primarily to avoid returning a 404 response when a resource actually exists but we haven't installed the path to a handler.
|
// it exists primarily to avoid returning a 404 response when a resource actually exists but we haven't installed the path to a handler.
|
||||||
// it is exposed for easier composition of the individual servers.
|
// it is exposed for easier composition of the individual servers.
|
||||||
@ -264,6 +277,11 @@ type DelegationTarget interface {
|
|||||||
|
|
||||||
// MuxAndDiscoveryCompleteSignals exposes registered signals that indicate if all known HTTP paths have been installed.
|
// MuxAndDiscoveryCompleteSignals exposes registered signals that indicate if all known HTTP paths have been installed.
|
||||||
MuxAndDiscoveryCompleteSignals() map[string]<-chan struct{}
|
MuxAndDiscoveryCompleteSignals() map[string]<-chan struct{}
|
||||||
|
|
||||||
|
// Destroy cleans up its resources on shutdown.
|
||||||
|
// Destroy has to be implemented in thread-safe way and be prepared
|
||||||
|
// for being called more than once.
|
||||||
|
Destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *GenericAPIServer) UnprotectedHandler() http.Handler {
|
func (s *GenericAPIServer) UnprotectedHandler() http.Handler {
|
||||||
@ -301,6 +319,18 @@ func (s *GenericAPIServer) MuxAndDiscoveryCompleteSignals() map[string]<-chan st
|
|||||||
return s.muxAndDiscoveryCompleteSignals
|
return s.muxAndDiscoveryCompleteSignals
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destroy cleans up all its and its delegation target resources on shutdown.
|
||||||
|
// It starts with destroying its own resources and later proceeds with
|
||||||
|
// its delegation target.
|
||||||
|
func (s *GenericAPIServer) Destroy() {
|
||||||
|
for _, destroyFn := range s.destroyFns {
|
||||||
|
destroyFn()
|
||||||
|
}
|
||||||
|
if s.delegationTarget != nil {
|
||||||
|
s.delegationTarget.Destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type emptyDelegate struct {
|
type emptyDelegate struct {
|
||||||
// handler is called at the end of the delegation chain
|
// handler is called at the end of the delegation chain
|
||||||
// when a request has been made against an unregistered HTTP path the individual servers will simply pass it through until it reaches the handler.
|
// when a request has been made against an unregistered HTTP path the individual servers will simply pass it through until it reaches the handler.
|
||||||
@ -340,6 +370,8 @@ func (s emptyDelegate) PrepareRun() preparedGenericAPIServer {
|
|||||||
func (s emptyDelegate) MuxAndDiscoveryCompleteSignals() map[string]<-chan struct{} {
|
func (s emptyDelegate) MuxAndDiscoveryCompleteSignals() map[string]<-chan struct{} {
|
||||||
return map[string]<-chan struct{}{}
|
return map[string]<-chan struct{}{}
|
||||||
}
|
}
|
||||||
|
func (s emptyDelegate) Destroy() {
|
||||||
|
}
|
||||||
|
|
||||||
// preparedGenericAPIServer is a private wrapper that enforces a call of PrepareRun() before Run can be invoked.
|
// preparedGenericAPIServer is a private wrapper that enforces a call of PrepareRun() before Run can be invoked.
|
||||||
type preparedGenericAPIServer struct {
|
type preparedGenericAPIServer struct {
|
||||||
@ -395,6 +427,9 @@ func (s preparedGenericAPIServer) Run(stopCh <-chan struct{}) error {
|
|||||||
delayedStopCh := s.lifecycleSignals.AfterShutdownDelayDuration
|
delayedStopCh := s.lifecycleSignals.AfterShutdownDelayDuration
|
||||||
shutdownInitiatedCh := s.lifecycleSignals.ShutdownInitiated
|
shutdownInitiatedCh := s.lifecycleSignals.ShutdownInitiated
|
||||||
|
|
||||||
|
// Clean up resources on shutdown.
|
||||||
|
defer s.Destroy()
|
||||||
|
|
||||||
// spawn a new goroutine for closing the MuxAndDiscoveryComplete signal
|
// spawn a new goroutine for closing the MuxAndDiscoveryComplete signal
|
||||||
// registration happens during construction of the generic api server
|
// registration happens during construction of the generic api server
|
||||||
// the last server in the chain aggregates signals from the previous instances
|
// the last server in the chain aggregates signals from the previous instances
|
||||||
@ -584,6 +619,8 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
|
|||||||
resourceInfos = append(resourceInfos, r...)
|
resourceInfos = append(resourceInfos, r...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.destroyFns = append(s.destroyFns, apiGroupInfo.destroyStorage)
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.StorageVersionAPI) &&
|
if utilfeature.DefaultFeatureGate.Enabled(features.StorageVersionAPI) &&
|
||||||
utilfeature.DefaultFeatureGate.Enabled(features.APIServerIdentity) {
|
utilfeature.DefaultFeatureGate.Enabled(features.APIServerIdentity) {
|
||||||
// API installation happens before we start listening on the handlers,
|
// API installation happens before we start listening on the handlers,
|
||||||
@ -595,6 +632,9 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InstallLegacyAPIGroup exposes the given legacy api group in the API.
|
||||||
|
// The <apiGroupInfo> passed into this function shouldn't be used elsewhere as the
|
||||||
|
// underlying storage will be destroyed on this servers shutdown.
|
||||||
func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo *APIGroupInfo) error {
|
func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo *APIGroupInfo) error {
|
||||||
if !s.legacyAPIGroupPrefixes.Has(apiPrefix) {
|
if !s.legacyAPIGroupPrefixes.Has(apiPrefix) {
|
||||||
return fmt.Errorf("%q is not in the allowed legacy API prefixes: %v", apiPrefix, s.legacyAPIGroupPrefixes.List())
|
return fmt.Errorf("%q is not in the allowed legacy API prefixes: %v", apiPrefix, s.legacyAPIGroupPrefixes.List())
|
||||||
@ -616,7 +656,9 @@ func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exposes given api groups in the API.
|
// InstallAPIGroups exposes given api groups in the API.
|
||||||
|
// The <apiGroupInfos> passed into this function shouldn't be used elsewhere as the
|
||||||
|
// underlying storage will be destroyed on this servers shutdown.
|
||||||
func (s *GenericAPIServer) InstallAPIGroups(apiGroupInfos ...*APIGroupInfo) error {
|
func (s *GenericAPIServer) InstallAPIGroups(apiGroupInfos ...*APIGroupInfo) error {
|
||||||
for _, apiGroupInfo := range apiGroupInfos {
|
for _, apiGroupInfo := range apiGroupInfos {
|
||||||
// Do not register empty group or empty version. Doing so claims /apis/ for the wrong entity to be returned.
|
// Do not register empty group or empty version. Doing so claims /apis/ for the wrong entity to be returned.
|
||||||
@ -669,7 +711,9 @@ func (s *GenericAPIServer) InstallAPIGroups(apiGroupInfos ...*APIGroupInfo) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exposes the given api group in the API.
|
// InstallAPIGroup exposes the given api group in the API.
|
||||||
|
// The <apiGroupInfo> passed into this function shouldn't be used elsewhere as the
|
||||||
|
// underlying storage will be destroyed on this servers shutdown.
|
||||||
func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error {
|
func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error {
|
||||||
return s.InstallAPIGroups(apiGroupInfo)
|
return s.InstallAPIGroups(apiGroupInfo)
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ func StartRealAPIServerOrDie(t *testing.T, configFuncs ...func(*options.ServerRu
|
|||||||
|
|
||||||
stopCh := make(chan struct{})
|
stopCh := make(chan struct{})
|
||||||
|
|
||||||
kubeAPIServer, err := app.CreateServerChain(completedOptions, stopCh)
|
kubeAPIServer, err := app.CreateServerChain(completedOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user