github.com/cilium/cilium@v1.16.2/operator/api/health.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package api 5 6 import ( 7 "errors" 8 9 "github.com/cilium/hive/cell" 10 "github.com/go-openapi/runtime/middleware" 11 "github.com/sirupsen/logrus" 12 "k8s.io/client-go/discovery" 13 14 "github.com/cilium/cilium/api/v1/operator/server/restapi/operator" 15 k8sClient "github.com/cilium/cilium/pkg/k8s/client" 16 "github.com/cilium/cilium/pkg/kvstore" 17 ) 18 19 type kvstoreEnabledFunc func() bool 20 type isOperatorLeadingFunc func() bool 21 22 func HealthHandlerCell( 23 kvstoreEnabled kvstoreEnabledFunc, 24 isOperatorLeading isOperatorLeadingFunc, 25 ) cell.Cell { 26 return cell.Module( 27 "health-handler", 28 "Operator health HTTP handler", 29 30 cell.Provide(func( 31 clientset k8sClient.Clientset, 32 logger logrus.FieldLogger, 33 ) operator.GetHealthzHandler { 34 if !clientset.IsEnabled() { 35 return &healthHandler{ 36 enabled: false, 37 } 38 } 39 40 return &healthHandler{ 41 enabled: true, 42 isOperatorLeading: isOperatorLeading, 43 kvstoreEnabled: kvstoreEnabled, 44 discovery: clientset.Discovery(), 45 log: logger, 46 } 47 }), 48 ) 49 } 50 51 type healthHandler struct { 52 enabled bool 53 isOperatorLeading isOperatorLeadingFunc 54 kvstoreEnabled kvstoreEnabledFunc 55 discovery discovery.DiscoveryInterface 56 log logrus.FieldLogger 57 } 58 59 func (h *healthHandler) Handle(params operator.GetHealthzParams) middleware.Responder { 60 if !h.enabled { 61 return operator.NewGetHealthzNotImplemented() 62 } 63 64 if err := h.checkStatus(); err != nil { 65 h.log.WithError(err).Warn("Health check status") 66 return operator.NewGetHealthzInternalServerError().WithPayload(err.Error()) 67 } 68 69 return operator.NewGetHealthzOK().WithPayload("ok") 70 } 71 72 // checkStatus verifies the connection status to the kvstore and the 73 // k8s apiserver and returns an error if any of them is unhealthy 74 func (h *healthHandler) checkStatus() error { 75 // We check if we are the leader here because only the leader has 76 // access to the kvstore client. Otherwise, the kvstore client check 77 // will block. It is safe for a non-leader to skip this check, as the 78 // it is the leader's responsibility to report the status of the 79 // kvstore client. 80 if h.isOperatorLeading() && h.kvstoreEnabled() { 81 client := kvstore.Client() 82 if client == nil { 83 return errors.New("kvstore client not configured") 84 } 85 if _, err := client.Status(); err != nil { 86 return err 87 } 88 } 89 _, err := h.discovery.ServerVersion() 90 return err 91 }