Addressed comments.

This commit is contained in:
Brendan Burns 2014-07-15 11:39:19 -07:00
parent 62dfc74606
commit c5db874090
7 changed files with 55 additions and 37 deletions

18
pkg/health/doc.go Normal file
View File

@ -0,0 +1,18 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package health contains utilities for health checking, as well as health status information.
package health

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package util package health
import ( import (
"net/http" "net/http"
@ -22,30 +22,30 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
) )
type HealthCheckStatus int type Status int
const ( const (
CheckHealthy HealthCheckStatus = 0 Healthy Status = iota
CheckUnhealthy HealthCheckStatus = 1 Unhealthy
CheckUnknown HealthCheckStatus = 2 Unknown
) )
type HTTPGetInterface interface { type HTTPGetInterface interface {
Get(url string) (*http.Response, error) Get(url string) (*http.Response, error)
} }
func IsHealthy(url string, client HTTPGetInterface) (HealthCheckStatus, error) { func Check(url string, client HTTPGetInterface) (Status, error) {
res, err := client.Get(url) res, err := client.Get(url)
if res.Body != nil { if res.Body != nil {
defer res.Body.Close() defer res.Body.Close()
} }
if err != nil { if err != nil {
return CheckUnknown, err return Unknown, err
} }
if res.StatusCode >= http.StatusOK && res.StatusCode < http.StatusBadRequest { if res.StatusCode >= http.StatusOK && res.StatusCode < http.StatusBadRequest {
return CheckHealthy, nil return Healthy, nil
} else { } else {
glog.V(1).Infof("Health check failed for %s, Response: %v", url, *res) glog.V(1).Infof("Health check failed for %s, Response: %v", url, *res)
return CheckUnhealthy, nil return Unhealthy, nil
} }
} }

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package kubelet package health
import ( import (
"fmt" "fmt"
@ -22,12 +22,11 @@ import (
"strconv" "strconv"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/golang/glog" "github.com/golang/glog"
) )
type HealthChecker interface { type HealthChecker interface {
HealthCheck(container api.Container) (util.HealthCheckStatus, error) HealthCheck(container api.Container) (Status, error)
} }
// MakeHealthChecker creates a new HealthChecker. // MakeHealthChecker creates a new HealthChecker.
@ -46,18 +45,18 @@ type MuxHealthChecker struct {
checkers map[string]HealthChecker checkers map[string]HealthChecker
} }
func (m *MuxHealthChecker) HealthCheck(container api.Container) (util.HealthCheckStatus, error) { func (m *MuxHealthChecker) HealthCheck(container api.Container) (Status, error) {
checker, ok := m.checkers[container.LivenessProbe.Type] checker, ok := m.checkers[container.LivenessProbe.Type]
if !ok || checker == nil { if !ok || checker == nil {
glog.Warningf("Failed to find health checker for %s %s", container.Name, container.LivenessProbe.Type) glog.Warningf("Failed to find health checker for %s %s", container.Name, container.LivenessProbe.Type)
return util.CheckUnknown, nil return Unknown, nil
} }
return checker.HealthCheck(container) return checker.HealthCheck(container)
} }
// HTTPHealthChecker is an implementation of HealthChecker which checks container health by sending HTTP Get requests. // HTTPHealthChecker is an implementation of HealthChecker which checks container health by sending HTTP Get requests.
type HTTPHealthChecker struct { type HTTPHealthChecker struct {
client util.HTTPGetInterface client HTTPGetInterface
} }
func (h *HTTPHealthChecker) findPort(container api.Container, portName string) int64 { func (h *HTTPHealthChecker) findPort(container api.Container, portName string) int64 {
@ -70,17 +69,17 @@ func (h *HTTPHealthChecker) findPort(container api.Container, portName string) i
return -1 return -1
} }
func (h *HTTPHealthChecker) HealthCheck(container api.Container) (util.HealthCheckStatus, error) { func (h *HTTPHealthChecker) HealthCheck(container api.Container) (Status, error) {
params := container.LivenessProbe.HTTPGet params := container.LivenessProbe.HTTPGet
if params == nil { if params == nil {
return util.CheckUnknown, fmt.Errorf("Error, no HTTP parameters specified: %v", container) return Unknown, fmt.Errorf("Error, no HTTP parameters specified: %v", container)
} }
port := h.findPort(container, params.Port) port := h.findPort(container, params.Port)
if port == -1 { if port == -1 {
var err error var err error
port, err = strconv.ParseInt(params.Port, 10, 0) port, err = strconv.ParseInt(params.Port, 10, 0)
if err != nil { if err != nil {
return util.CheckUnknown, err return Unknown, err
} }
} }
var host string var host string
@ -90,5 +89,5 @@ func (h *HTTPHealthChecker) HealthCheck(container api.Container) (util.HealthChe
host = "localhost" host = "localhost"
} }
url := fmt.Sprintf("http://%s:%d%s", host, port, params.Path) url := fmt.Sprintf("http://%s:%d%s", host, port, params.Path)
return util.IsHealthy(url, h.client) return Check(url, h.client)
} }

View File

@ -14,14 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package kubelet package health
import ( import (
"net/http" "net/http"
"testing" "testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
) )
type fakeHTTPClient struct { type fakeHTTPClient struct {
@ -57,7 +56,7 @@ func TestHttpHealth(t *testing.T) {
} }
ok, err := check.HealthCheck(container) ok, err := check.HealthCheck(container)
if ok != util.CheckHealthy { if ok != Healthy {
t.Error("Unexpected unhealthy") t.Error("Unexpected unhealthy")
} }
if err != nil { if err != nil {

View File

@ -34,6 +34,7 @@ import (
"time" "time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/health"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/healthz" _ "github.com/GoogleCloudPlatform/kubernetes/pkg/healthz"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
@ -94,7 +95,7 @@ type Kubelet struct {
SyncFrequency time.Duration SyncFrequency time.Duration
HTTPCheckFrequency time.Duration HTTPCheckFrequency time.Duration
pullLock sync.Mutex pullLock sync.Mutex
HealthChecker HealthChecker HealthChecker health.HealthChecker
} }
type manifestUpdate struct { type manifestUpdate struct {
@ -159,7 +160,7 @@ func (kl *Kubelet) RunKubelet(dockerEndpoint, configPath, manifestURL, etcdServe
} }
go util.Forever(func() { s.ListenAndServe() }, 0) go util.Forever(func() { s.ListenAndServe() }, 0)
} }
kl.HealthChecker = MakeHealthChecker() kl.HealthChecker = health.MakeHealthChecker()
kl.syncLoop(updateChannel, kl) kl.syncLoop(updateChannel, kl)
} }
@ -736,7 +737,7 @@ func (kl *Kubelet) syncManifest(manifest *api.ContainerManifest, keepChannel cha
glog.V(1).Infof("health check errored: %v", err) glog.V(1).Infof("health check errored: %v", err)
continue continue
} }
if healthy != util.CheckHealthy { if healthy != health.Healthy {
glog.V(1).Infof("manifest %s container %s is unhealthy.", manifest.ID, container.Name) glog.V(1).Infof("manifest %s container %s is unhealthy.", manifest.ID, container.Name)
if err != nil { if err != nil {
glog.V(1).Infof("Failed to get container info %v, for %s", err, containerID) glog.V(1).Infof("Failed to get container info %v, for %s", err, containerID)
@ -993,16 +994,16 @@ func (kl *Kubelet) GetMachineStats() (*api.ContainerStats, error) {
return kl.statsFromContainerPath("/") return kl.statsFromContainerPath("/")
} }
func (kl *Kubelet) healthy(container api.Container, dockerContainer *docker.APIContainers) (util.HealthCheckStatus, error) { func (kl *Kubelet) healthy(container api.Container, dockerContainer *docker.APIContainers) (health.Status, error) {
// Give the container 60 seconds to start up. // Give the container 60 seconds to start up.
if container.LivenessProbe == nil { if container.LivenessProbe == nil {
return util.CheckHealthy, nil return health.Healthy, nil
} }
if time.Now().Unix()-dockerContainer.Created < container.LivenessProbe.InitialDelaySeconds { if time.Now().Unix()-dockerContainer.Created < container.LivenessProbe.InitialDelaySeconds {
return util.CheckHealthy, nil return health.Healthy, nil
} }
if kl.HealthChecker == nil { if kl.HealthChecker == nil {
return util.CheckHealthy, nil return health.Healthy, nil
} }
return kl.HealthChecker.HealthCheck(container) return kl.HealthChecker.HealthCheck(container)
} }

View File

@ -26,6 +26,7 @@ import (
"testing" "testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/health"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd" "github.com/coreos/go-etcd/etcd"
@ -424,8 +425,8 @@ func TestSyncManifestsDeletes(t *testing.T) {
type FalseHealthChecker struct{} type FalseHealthChecker struct{}
func (f *FalseHealthChecker) HealthCheck(container api.Container) (util.HealthCheckStatus, error) { func (f *FalseHealthChecker) HealthCheck(container api.Container) (health.Status, error) {
return util.CheckUnhealthy, nil return health.Unhealthy, nil
} }
func TestSyncManifestsUnhealthy(t *testing.T) { func TestSyncManifestsUnhealthy(t *testing.T) {

View File

@ -20,12 +20,12 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/health"
) )
type HealthyMinionRegistry struct { type HealthyMinionRegistry struct {
delegate MinionRegistry delegate MinionRegistry
client util.HTTPGetInterface client health.HTTPGetInterface
port int port int
} }
@ -48,11 +48,11 @@ func (h *HealthyMinionRegistry) List() (currentMinions []string, err error) {
return result, err return result, err
} }
for _, minion := range list { for _, minion := range list {
status, err := util.IsHealthy(h.makeMinionURL(minion), h.client) status, err := health.Check(h.makeMinionURL(minion), h.client)
if err != nil { if err != nil {
return result, err return result, err
} }
if status == util.CheckHealthy { if status == health.Healthy {
result = append(result, minion) result = append(result, minion)
} }
} }
@ -75,11 +75,11 @@ func (h *HealthyMinionRegistry) Contains(minion string) (bool, error) {
if !contains { if !contains {
return false, nil return false, nil
} }
status, err := util.IsHealthy(h.makeMinionURL(minion), h.client) status, err := health.Check(h.makeMinionURL(minion), h.client)
if err != nil { if err != nil {
return false, err return false, err
} }
if status == util.CheckUnhealthy { if status == health.Unhealthy {
return false, nil return false, nil
} }
return true, nil return true, nil