Skip to content

Commit 5b47f99

Browse files
committed
apiserver: sync with https server shutdown to flush existing connections
1 parent 8743a0e commit 5b47f99

File tree

7 files changed

+34
-19
lines changed

7 files changed

+34
-19
lines changed

cmd/cloud-controller-manager/app/controllermanager.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ func Run(c *cloudcontrollerconfig.CompletedConfig, stopCh <-chan struct{}) error
149149
if c.SecureServing != nil {
150150
unsecuredMux := genericcontrollermanager.NewBaseHandler(&c.ComponentConfig.Generic.Debugging, checks...)
151151
handler := genericcontrollermanager.BuildHandlerChain(unsecuredMux, &c.Authorization, &c.Authentication)
152-
if err := c.SecureServing.Serve(handler, 0, stopCh); err != nil {
152+
// TODO: handle stoppedCh returned by c.SecureServing.Serve
153+
if _, err := c.SecureServing.Serve(handler, 0, stopCh); err != nil {
153154
return err
154155
}
155156
}

cmd/kube-controller-manager/app/controllermanager.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ func Run(c *config.CompletedConfig, stopCh <-chan struct{}) error {
170170
if c.SecureServing != nil {
171171
unsecuredMux = genericcontrollermanager.NewBaseHandler(&c.ComponentConfig.Generic.Debugging, checks...)
172172
handler := genericcontrollermanager.BuildHandlerChain(unsecuredMux, &c.Authorization, &c.Authentication)
173-
if err := c.SecureServing.Serve(handler, 0, stopCh); err != nil {
173+
// TODO: handle stoppedCh returned by c.SecureServing.Serve
174+
if _, err := c.SecureServing.Serve(handler, 0, stopCh); err != nil {
174175
return err
175176
}
176177
}

cmd/kube-scheduler/app/server.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ func Run(cc schedulerserverconfig.CompletedConfig, stopCh <-chan struct{}) error
214214
}
215215
if cc.SecureServing != nil {
216216
handler := buildHandlerChain(newHealthzHandler(&cc.ComponentConfig, false, checks...), cc.Authentication.Authenticator, cc.Authorization.Authorizer)
217-
if err := cc.SecureServing.Serve(handler, 0, stopCh); err != nil {
217+
// TODO: handle stoppedCh returned by c.SecureServing.Serve
218+
if _, err := cc.SecureServing.Serve(handler, 0, stopCh); err != nil {
218219
// fail early for secure handlers, removing the old error loop from above
219220
return fmt.Errorf("failed to start healthz server: %v", err)
220221
}

staging/src/k8s.io/apiserver/pkg/server/deprecated_insecure_serving.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ func (s *DeprecatedInsecureServingInfo) Serve(handler http.Handler, shutdownTime
5050
} else {
5151
klog.Infof("Serving insecurely on %s", s.Listener.Addr())
5252
}
53-
return RunServer(insecureServer, s.Listener, shutdownTimeout, stopCh)
53+
_, err := RunServer(insecureServer, s.Listener, shutdownTimeout, stopCh)
54+
// NOTE: we do not handle stoppedCh returned by RunServer for graceful termination here
55+
return err
5456
}
5557

5658
func (s *DeprecatedInsecureServingInfo) NewLoopbackClientConfig() (*rest.Config, error) {

staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,11 @@ func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) error {
296296

297297
// Use an internal stop channel to allow cleanup of the listeners on error.
298298
internalStopCh := make(chan struct{})
299-
299+
var stoppedCh <-chan struct{}
300300
if s.SecureServingInfo != nil && s.Handler != nil {
301-
if err := s.SecureServingInfo.Serve(s.Handler, s.ShutdownTimeout, internalStopCh); err != nil {
301+
var err error
302+
stoppedCh, err = s.SecureServingInfo.Serve(s.Handler, s.ShutdownTimeout, internalStopCh)
303+
if err != nil {
302304
close(internalStopCh)
303305
return err
304306
}
@@ -310,6 +312,9 @@ func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) error {
310312
go func() {
311313
<-stopCh
312314
close(internalStopCh)
315+
if stoppedCh != nil {
316+
<-stoppedCh
317+
}
313318
s.HandlerChainWaitGroup.Wait()
314319
close(auditStopCh)
315320
}()

staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,9 +548,9 @@ func TestGracefulShutdown(t *testing.T) {
548548

549549
// get port
550550
serverPort := ln.Addr().(*net.TCPAddr).Port
551-
err = RunServer(insecureServer, ln, 10*time.Second, stopCh)
551+
stoppedCh, err := RunServer(insecureServer, ln, 10*time.Second, stopCh)
552552
if err != nil {
553-
t.Errorf("RunServer err: %v", err)
553+
t.Fatalf("RunServer err: %v", err)
554554
}
555555

556556
graceCh := make(chan struct{})
@@ -577,6 +577,7 @@ func TestGracefulShutdown(t *testing.T) {
577577

578578
// wait for wait group handler finish
579579
s.HandlerChainWaitGroup.Wait()
580+
<-stoppedCh
580581

581582
// check server all handlers finished.
582583
if !graceShutdown {

staging/src/k8s.io/apiserver/pkg/server/secure_serving.go

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ const (
3737
defaultKeepAlivePeriod = 3 * time.Minute
3838
)
3939

40-
// serveSecurely runs the secure http server. It fails only if certificates cannot
41-
// be loaded or the initial listen call fails. The actual server loop (stoppable by closing
42-
// stopCh) runs in a go routine, i.e. serveSecurely does not block.
43-
func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Duration, stopCh <-chan struct{}) error {
40+
// Serve runs the secure http server. It fails only if certificates cannot be loaded or the initial listen call fails.
41+
// The actual server loop (stoppable by closing stopCh) runs in a go routine, i.e. Serve does not block.
42+
// It returns a stoppedCh that is closed when all non-hijacked active requests have been processed.
43+
func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Duration, stopCh <-chan struct{}) (<-chan struct{}, error) {
4444
if s.Listener == nil {
45-
return fmt.Errorf("listener must not be nil")
45+
return nil, fmt.Errorf("listener must not be nil")
4646
}
4747

4848
secureServer := &http.Server{
@@ -110,29 +110,33 @@ func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Dur
110110

111111
// apply settings to the server
112112
if err := http2.ConfigureServer(secureServer, http2Options); err != nil {
113-
return fmt.Errorf("error configuring http2: %v", err)
113+
return nil, fmt.Errorf("error configuring http2: %v", err)
114114
}
115115

116116
klog.Infof("Serving securely on %s", secureServer.Addr)
117117
return RunServer(secureServer, s.Listener, shutdownTimeout, stopCh)
118118
}
119119

120120
// RunServer listens on the given port if listener is not given,
121-
// then spawns a go-routine continuously serving
122-
// until the stopCh is closed. This function does not block.
121+
// then spawns a go-routine continuously serving until the stopCh is closed.
122+
// It returns a stoppedCh that is closed when all non-hijacked active requests
123+
// have been processed.
124+
// This function does not block
123125
// TODO: make private when insecure serving is gone from the kube-apiserver
124126
func RunServer(
125127
server *http.Server,
126128
ln net.Listener,
127129
shutDownTimeout time.Duration,
128130
stopCh <-chan struct{},
129-
) error {
131+
) (<-chan struct{}, error) {
130132
if ln == nil {
131-
return fmt.Errorf("listener must not be nil")
133+
return nil, fmt.Errorf("listener must not be nil")
132134
}
133135

134136
// Shutdown server gracefully.
137+
stoppedCh := make(chan struct{})
135138
go func() {
139+
defer close(stoppedCh)
136140
<-stopCh
137141
ctx, cancel := context.WithTimeout(context.Background(), shutDownTimeout)
138142
server.Shutdown(ctx)
@@ -159,7 +163,7 @@ func RunServer(
159163
}
160164
}()
161165

162-
return nil
166+
return stoppedCh, nil
163167
}
164168

165169
type NamedTLSCert struct {

0 commit comments

Comments
 (0)