Skip to content

Commit c73aeaf

Browse files
authored
Merge pull request kubernetes#128234 from aroradaman/kube-proxy-multi-listen
kube-proxy: use netutils.MultiListen for healthz and metrics server
2 parents d7e5ff8 + 0aa9dc8 commit c73aeaf

File tree

5 files changed

+51
-34
lines changed

5 files changed

+51
-34
lines changed

cmd/kube-proxy/app/server.go

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ func serveHealthz(ctx context.Context, hz *healthcheck.ProxierHealthServer, errC
419419
}
420420

421421
fn := func() {
422-
err := hz.Run()
422+
err := hz.Run(ctx)
423423
if err != nil {
424424
logger.Error(err, "Healthz server failed")
425425
if errCh != nil {
@@ -435,7 +435,7 @@ func serveHealthz(ctx context.Context, hz *healthcheck.ProxierHealthServer, errC
435435
go wait.Until(fn, 5*time.Second, ctx.Done())
436436
}
437437

438-
func serveMetrics(bindAddress string, proxyMode kubeproxyconfig.ProxyMode, enableProfiling bool, errCh chan error) {
438+
func serveMetrics(ctx context.Context, bindAddress string, proxyMode kubeproxyconfig.ProxyMode, enableProfiling bool, errCh chan error) {
439439
if len(bindAddress) == 0 {
440440
return
441441
}
@@ -460,17 +460,31 @@ func serveMetrics(bindAddress string, proxyMode kubeproxyconfig.ProxyMode, enabl
460460
configz.InstallHandler(proxyMux)
461461

462462
fn := func() {
463-
err := http.ListenAndServe(bindAddress, proxyMux)
464-
if err != nil {
465-
err = fmt.Errorf("starting metrics server failed: %w", err)
466-
utilruntime.HandleError(err)
467-
if errCh != nil {
468-
errCh <- err
469-
// if in hardfail mode, never retry again
470-
blockCh := make(chan error)
471-
<-blockCh
463+
var err error
464+
defer func() {
465+
if err != nil {
466+
err = fmt.Errorf("starting metrics server failed: %w", err)
467+
utilruntime.HandleError(err)
468+
if errCh != nil {
469+
errCh <- err
470+
// if in hardfail mode, never retry again
471+
blockCh := make(chan error)
472+
<-blockCh
473+
}
472474
}
475+
}()
476+
477+
listener, err := netutils.MultiListen(ctx, "tcp", bindAddress)
478+
if err != nil {
479+
return
480+
}
481+
482+
server := &http.Server{Handler: proxyMux}
483+
err = server.Serve(listener)
484+
if err != nil {
485+
return
473486
}
487+
474488
}
475489
go wait.Until(fn, 5*time.Second, wait.NeverStop)
476490
}
@@ -512,7 +526,7 @@ func (s *ProxyServer) Run(ctx context.Context) error {
512526
serveHealthz(ctx, s.HealthzServer, healthzErrCh)
513527

514528
// Start up a metrics server if requested
515-
serveMetrics(s.Config.MetricsBindAddress, s.Config.Mode, s.Config.EnableProfiling, metricsErrCh)
529+
serveMetrics(ctx, s.Config.MetricsBindAddress, s.Config.Mode, s.Config.EnableProfiling, metricsErrCh)
516530

517531
noProxyName, err := labels.NewRequirement(apis.LabelServiceProxyName, selection.DoesNotExist, nil)
518532
if err != nil {

pkg/proxy/healthcheck/common.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,25 @@ limitations under the License.
1717
package healthcheck
1818

1919
import (
20+
"context"
2021
"net"
2122
"net/http"
23+
24+
netutils "k8s.io/utils/net"
2225
)
2326

2427
// listener allows for testing of ServiceHealthServer and ProxierHealthServer.
2528
type listener interface {
26-
// Listen is very much like net.Listen, except the first arg (network) is
29+
// Listen is very much like netutils.MultiListen, except the second arg (network) is
2730
// fixed to be "tcp".
28-
Listen(addr string) (net.Listener, error)
31+
Listen(ctx context.Context, addrs ...string) (net.Listener, error)
2932
}
3033

3134
// httpServerFactory allows for testing of ServiceHealthServer and ProxierHealthServer.
3235
type httpServerFactory interface {
3336
// New creates an instance of a type satisfying HTTPServer. This is
3437
// designed to include http.Server.
35-
New(addr string, handler http.Handler) httpServer
38+
New(handler http.Handler) httpServer
3639
}
3740

3841
// httpServer allows for testing of ServiceHealthServer and ProxierHealthServer.
@@ -45,18 +48,17 @@ type httpServer interface {
4548
// Implement listener in terms of net.Listen.
4649
type stdNetListener struct{}
4750

48-
func (stdNetListener) Listen(addr string) (net.Listener, error) {
49-
return net.Listen("tcp", addr)
51+
func (stdNetListener) Listen(ctx context.Context, addrs ...string) (net.Listener, error) {
52+
return netutils.MultiListen(ctx, "tcp", addrs...)
5053
}
5154

5255
var _ listener = stdNetListener{}
5356

5457
// Implement httpServerFactory in terms of http.Server.
5558
type stdHTTPServerFactory struct{}
5659

57-
func (stdHTTPServerFactory) New(addr string, handler http.Handler) httpServer {
60+
func (stdHTTPServerFactory) New(handler http.Handler) httpServer {
5861
return &http.Server{
59-
Addr: addr,
6062
Handler: handler,
6163
}
6264
}

pkg/proxy/healthcheck/healthcheck_test.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package healthcheck
1818

1919
import (
20+
"context"
2021
"encoding/json"
2122
"net"
2223
"net/http"
@@ -54,17 +55,17 @@ func (fake *fakeListener) hasPort(addr string) bool {
5455
return fake.openPorts.Has(addr)
5556
}
5657

57-
func (fake *fakeListener) Listen(addr string) (net.Listener, error) {
58-
fake.openPorts.Insert(addr)
58+
func (fake *fakeListener) Listen(_ context.Context, addrs ...string) (net.Listener, error) {
59+
fake.openPorts.Insert(addrs...)
5960
return &fakeNetListener{
6061
parent: fake,
61-
addr: addr,
62+
addrs: addrs,
6263
}, nil
6364
}
6465

6566
type fakeNetListener struct {
6667
parent *fakeListener
67-
addr string
68+
addrs []string
6869
}
6970

7071
type fakeAddr struct {
@@ -82,7 +83,7 @@ func (fake *fakeNetListener) Accept() (net.Conn, error) {
8283
}
8384

8485
func (fake *fakeNetListener) Close() error {
85-
fake.parent.openPorts.Delete(fake.addr)
86+
fake.parent.openPorts.Delete(fake.addrs...)
8687
return nil
8788
}
8889

@@ -97,15 +98,13 @@ func newFakeHTTPServerFactory() *fakeHTTPServerFactory {
9798
return &fakeHTTPServerFactory{}
9899
}
99100

100-
func (fake *fakeHTTPServerFactory) New(addr string, handler http.Handler) httpServer {
101+
func (fake *fakeHTTPServerFactory) New(handler http.Handler) httpServer {
101102
return &fakeHTTPServer{
102-
addr: addr,
103103
handler: handler,
104104
}
105105
}
106106

107107
type fakeHTTPServer struct {
108-
addr string
109108
handler http.Handler
110109
}
111110

@@ -471,7 +470,7 @@ func TestHealthzServer(t *testing.T) {
471470
fakeClock := testingclock.NewFakeClock(time.Now())
472471

473472
hs := newProxierHealthServer(listener, httpFactory, fakeClock, "127.0.0.1:10256", 10*time.Second)
474-
server := hs.httpFactory.New(hs.addr, healthzHandler{hs: hs})
473+
server := hs.httpFactory.New(healthzHandler{hs: hs})
475474

476475
hsTest := &serverTest{
477476
server: server,
@@ -506,7 +505,7 @@ func TestLivezServer(t *testing.T) {
506505
fakeClock := testingclock.NewFakeClock(time.Now())
507506

508507
hs := newProxierHealthServer(listener, httpFactory, fakeClock, "127.0.0.1:10256", 10*time.Second)
509-
server := hs.httpFactory.New(hs.addr, livezHandler{hs: hs})
508+
server := hs.httpFactory.New(livezHandler{hs: hs})
510509

511510
hsTest := &serverTest{
512511
server: server,

pkg/proxy/healthcheck/proxier_health.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package healthcheck
1818

1919
import (
20+
"context"
2021
"fmt"
2122
"net/http"
2223
"sync"
@@ -162,13 +163,13 @@ func (hs *ProxierHealthServer) NodeEligible() bool {
162163
}
163164

164165
// Run starts the healthz HTTP server and blocks until it exits.
165-
func (hs *ProxierHealthServer) Run() error {
166+
func (hs *ProxierHealthServer) Run(ctx context.Context) error {
166167
serveMux := http.NewServeMux()
167168
serveMux.Handle("/healthz", healthzHandler{hs: hs})
168169
serveMux.Handle("/livez", livezHandler{hs: hs})
169-
server := hs.httpFactory.New(hs.addr, serveMux)
170+
server := hs.httpFactory.New(serveMux)
170171

171-
listener, err := hs.listener.Listen(hs.addr)
172+
listener, err := hs.listener.Listen(ctx, hs.addr)
172173
if err != nil {
173174
return fmt.Errorf("failed to start proxier healthz on %s: %v", hs.addr, err)
174175
}

pkg/proxy/healthcheck/service_health.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package healthcheck
1818

1919
import (
20+
"context"
2021
"fmt"
2122
"net"
2223
"net/http"
@@ -170,9 +171,9 @@ func (hcI *hcInstance) listenAndServeAll(hcs *server) error {
170171
for _, ip := range hcs.nodeIPs {
171172
addr := net.JoinHostPort(ip.String(), fmt.Sprint(hcI.port))
172173
// create http server
173-
httpSrv := hcs.httpFactory.New(addr, hcHandler{name: hcI.nsn, hcs: hcs})
174+
httpSrv := hcs.httpFactory.New(hcHandler{name: hcI.nsn, hcs: hcs})
174175
// start listener
175-
listener, err = hcs.listener.Listen(addr)
176+
listener, err = hcs.listener.Listen(context.TODO(), addr)
176177
if err != nil {
177178
// must close whatever have been previously opened
178179
// to allow a retry/or port ownership change as needed

0 commit comments

Comments
 (0)