Skip to content

Commit 2927f6a

Browse files
committed
livenessprobe should only connect on startup & only probe on each health check
1 parent 62d39be commit 2927f6a

File tree

3 files changed

+67
-153
lines changed

3 files changed

+67
-153
lines changed

cmd/livenessprobe_test.go

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ limitations under the License.
1717
package main
1818

1919
import (
20-
"context"
20+
"net/http"
21+
"net/http/httptest"
2122
"testing"
22-
"time"
2323

2424
csi "github.com/container-storage-interface/spec/lib/go/csi"
2525
"github.com/golang/mock/gomock"
26+
connlib "github.com/kubernetes-csi/csi-lib-utils/connection"
2627
"github.com/kubernetes-csi/csi-test/driver"
27-
"github.com/kubernetes-csi/livenessprobe/pkg/connection"
28+
"google.golang.org/grpc"
2829
)
2930

3031
const (
@@ -37,7 +38,7 @@ func createMockServer(t *testing.T) (
3738
*driver.MockIdentityServer,
3839
*driver.MockControllerServer,
3940
*driver.MockNodeServer,
40-
connection.CSIConnection,
41+
*grpc.ClientConn,
4142
error) {
4243
// Start the mock server
4344
mockController := gomock.NewController(t)
@@ -53,7 +54,7 @@ func createMockServer(t *testing.T) (
5354

5455
// Create a client connection to it
5556
addr := drv.Address()
56-
csiConn, err := connection.NewConnection(addr)
57+
csiConn, err := connlib.Connect(addr)
5758
if err != nil {
5859
return nil, nil, nil, nil, nil, nil, err
5960
}
@@ -72,20 +73,28 @@ func TestProbe(t *testing.T) {
7273

7374
var injectedErr error
7475

75-
// Setting up expected calls' responses
76-
inPlugin := &csi.GetPluginInfoRequest{}
77-
outPlugin := &csi.GetPluginInfoResponse{
78-
Name: "foo/bar",
79-
}
80-
idServer.EXPECT().GetPluginInfo(gomock.Any(), inPlugin).Return(outPlugin, injectedErr).Times(1)
81-
8276
inProbe := &csi.ProbeRequest{}
8377
outProbe := &csi.ProbeResponse{}
8478
idServer.EXPECT().Probe(gomock.Any(), inProbe).Return(outProbe, injectedErr).Times(1)
85-
// Calling Probing function
86-
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
87-
defer cancel()
88-
if err := runProbe(ctx, csiConn); err != nil {
89-
t.Fatalf("failed to run probe with error: %+v", err)
79+
80+
hp := &healthProbe{
81+
conn: csiConn,
82+
driverName: driverName,
83+
}
84+
85+
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
86+
if req.URL.String() == "/healthz" {
87+
hp.checkProbe(rw, req)
88+
}
89+
}))
90+
defer server.Close()
91+
92+
httpreq, err := http.NewRequest("GET", server.URL+"/healthz", nil)
93+
if err != nil {
94+
t.Fatalf("failed to build test request for health check: %v", err)
95+
}
96+
_, err = http.DefaultClient.Do(httpreq)
97+
if err != nil {
98+
t.Errorf("failed to check probe: %v", err)
9099
}
91100
}

cmd/main.go

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,62 +25,47 @@ import (
2525

2626
"k8s.io/klog"
2727

28-
"github.com/kubernetes-csi/livenessprobe/pkg/connection"
29-
)
30-
31-
const (
32-
// Default timeout of short CSI calls like GetPluginInfo
33-
csiTimeout = time.Second
28+
connlib "github.com/kubernetes-csi/csi-lib-utils/connection"
29+
"google.golang.org/grpc"
3430
)
3531

3632
// Command line flags
3733
var (
3834
// kubeconfig = flag.String("kubeconfig", "", "Absolute path to the kubeconfig file. Required only when running out of cluster.")
3935
connectionTimeout = flag.Duration("connection-timeout", 0, "The --connection-timeout flag is deprecated")
36+
probeTimeout = flag.Duration("probe-timeout", time.Second, "Probe timeout in seconds")
4037
csiAddress = flag.String("csi-address", "/run/csi/socket", "Address of the CSI driver socket.")
4138
healthzPort = flag.String("health-port", "9808", "TCP ports for listening healthz requests")
4239
)
4340

44-
func runProbe(ctx context.Context, csiConn connection.CSIConnection) error {
45-
// Get CSI driver name.
46-
klog.Infof("Calling CSI driver to discover driver name.")
47-
csiDriverName, err := csiConn.GetDriverName(ctx)
48-
if err != nil {
49-
return err
50-
}
51-
klog.Infof("CSI driver name: %q", csiDriverName)
52-
// Sending Probe request
53-
klog.Infof("Sending probe request to CSI driver.")
54-
err = csiConn.LivenessProbe(ctx)
55-
return err
41+
type healthProbe struct {
42+
conn *grpc.ClientConn
43+
driverName string
5644
}
5745

58-
func getCSIConnection() (connection.CSIConnection, error) {
59-
klog.Infof("Attempting to open a gRPC connection with: %s", *csiAddress)
60-
return connection.NewConnection(*csiAddress)
61-
}
46+
func (h *healthProbe) checkProbe(w http.ResponseWriter, req *http.Request) {
47+
ctx, cancel := context.WithTimeout(req.Context(), *probeTimeout)
48+
defer cancel()
6249

63-
func checkHealth(w http.ResponseWriter, req *http.Request) {
64-
klog.Infof("Request: %s from: %s\n", req.URL.Path, req.RemoteAddr)
65-
csiConn, err := getCSIConnection()
50+
klog.Infof("Sending probe request to CSI driver %q", h.driverName)
51+
ready, err := connlib.Probe(ctx, h.conn)
6652
if err != nil {
6753
w.WriteHeader(http.StatusInternalServerError)
6854
w.Write([]byte(err.Error()))
69-
klog.Errorf("Failed to get connection to CSI with error: %v.", err)
55+
klog.Errorf("health check failed: %v", err)
7056
return
7157
}
72-
defer csiConn.Close()
73-
ctx, cancel := context.WithCancel(context.Background())
74-
defer cancel()
75-
if err := runProbe(ctx, csiConn); err != nil {
58+
59+
if !ready {
7660
w.WriteHeader(http.StatusInternalServerError)
7761
w.Write([]byte(err.Error()))
78-
klog.Errorf("Health check failed with: %v.", err)
79-
} else {
80-
w.WriteHeader(http.StatusOK)
81-
w.Write([]byte(`ok`))
82-
klog.Infof("Health check succeeded.")
62+
klog.Error("driver responded but is not ready")
63+
return
8364
}
65+
66+
w.WriteHeader(http.StatusOK)
67+
w.Write([]byte(`ok`))
68+
klog.Infof("Health check succeeded")
8469
}
8570

8671
func main() {
@@ -92,10 +77,29 @@ func main() {
9277
klog.Warning("--connection-timeout is deprecated and will have no effect")
9378
}
9479

80+
csiConn, err := connlib.Connect(*csiAddress)
81+
if err != nil {
82+
// connlib should retry forever so a returned error should mean
83+
// the grpc client is misconfigured rather than an error on the network
84+
klog.Fatalf("failed to establish connection to CSI driver: %v", err)
85+
}
86+
87+
klog.Infof("calling CSI driver to discover driver name")
88+
csiDriverName, err := connlib.GetDriverName(context.Background(), csiConn)
89+
if err != nil {
90+
klog.Fatalf("failed to get CSI driver name: %v", err)
91+
}
92+
klog.Infof("CSI driver name: %q", csiDriverName)
93+
94+
hp := &healthProbe{
95+
conn: csiConn,
96+
driverName: csiDriverName,
97+
}
98+
9599
addr := net.JoinHostPort("0.0.0.0", *healthzPort)
96-
http.HandleFunc("/healthz", checkHealth)
100+
http.HandleFunc("/healthz", hp.checkProbe)
97101
klog.Infof("Serving requests to /healthz on: %s", addr)
98-
err := http.ListenAndServe(addr, nil)
102+
err = http.ListenAndServe(addr, nil)
99103
if err != nil {
100104
klog.Fatalf("failed to start http server with error: %v", err)
101105
}

pkg/connection/connection.go

Lines changed: 0 additions & 99 deletions
This file was deleted.

0 commit comments

Comments
 (0)