diff --git a/cmd/tiller/probes.go b/cmd/tiller/probes.go new file mode 100644 index 000000000..fcbb20665 --- /dev/null +++ b/cmd/tiller/probes.go @@ -0,0 +1,20 @@ +package main + +import ( + "net/http" +) + +func readinessProbe(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) +} + +func livenessProbe(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) +} + +func newProbesMux() *http.ServeMux { + mux := http.NewServeMux() + mux.HandleFunc("/readiness", readinessProbe) + mux.HandleFunc("/liveness", livenessProbe) + return mux +} diff --git a/cmd/tiller/probes_test.go b/cmd/tiller/probes_test.go new file mode 100644 index 000000000..5b625fcc4 --- /dev/null +++ b/cmd/tiller/probes_test.go @@ -0,0 +1,28 @@ +package main + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestProbesServer(t *testing.T) { + mux := newProbesMux() + srv := httptest.NewServer(mux) + defer srv.Close() + resp, err := http.Get(srv.URL + "/readiness") + if err != nil { + t.Fatalf("GET /readiness returned an error (%s)", err) + } + if resp.StatusCode != http.StatusOK { + t.Fatalf("GET /readiness returned status code %d, expected %d", resp.StatusCode, http.StatusOK) + } + + resp, err = http.Get(srv.URL + "/liveness") + if err != nil { + t.Fatalf("GET /liveness returned an error (%s)", err) + } + if resp.StatusCode != http.StatusOK { + t.Fatalf("GET /liveness returned status code %d, expected %d", resp.StatusCode, http.StatusOK) + } +} diff --git a/cmd/tiller/tiller.go b/cmd/tiller/tiller.go index aba7561ea..f1b209a10 100644 --- a/cmd/tiller/tiller.go +++ b/cmd/tiller/tiller.go @@ -3,6 +3,7 @@ package main import ( "fmt" "net" + "net/http" "os" "github.com/kubernetes/helm/cmd/tiller/environment" @@ -21,6 +22,7 @@ var rootServer = grpc.NewServer() var env = environment.New() var addr = ":44134" +var probe = ":44135" var namespace = "" const globalUsage = `The Kubernetes Helm server. @@ -53,10 +55,29 @@ func start(c *cobra.Command, args []string) { } fmt.Printf("Tiller is running on %s\n", addr) + fmt.Printf("Tiller probes server is running on %s\n", probe) - if err := rootServer.Serve(lstn); err != nil { + srvErrCh := make(chan error) + probeErrCh := make(chan error) + go func() { + if err := rootServer.Serve(lstn); err != nil { + srvErrCh <- err + } + }() + + go func() { + mux := newProbesMux() + if err := http.ListenAndServe(addr, mux); err != nil { + probeErrCh <- err + } + }() + + select { + case err := <-srvErrCh: fmt.Fprintf(os.Stderr, "Server died: %s\n", err) os.Exit(1) + case err := <-probeErrCh: + fmt.Fprintf(os.Stderr, "Probes server died: %s\n", err) } } diff --git a/pkg/client/install.go b/pkg/client/install.go index 1131ba631..35fd42f21 100644 --- a/pkg/client/install.go +++ b/pkg/client/install.go @@ -108,4 +108,16 @@ spec: - containerPort: 44134 name: tiller imagePullPolicy: Always + livenessProbe: + httpGet: + path: /liveness + port: 44135 + initialDelaySeconds: 1 + timeoutSeconds: 1 + readinessProbe: + httpGet: + path: /readiness + port: 44135 + initialDelaySeconds: 1 + timeoutSeconds: 1 `