Skip to content

Commit

Permalink
feat: implement apisix healthz check (#770)
Browse files Browse the repository at this point in the history
  • Loading branch information
mayocream committed Dec 14, 2021
1 parent 4a6509c commit 6110bf5
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 1 deletion.
42 changes: 42 additions & 0 deletions pkg/api/router/apisix_healthz.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 router

import (
"net/http"

"github.com/gin-gonic/gin"
)

// MountWebhooks mounts apisix healthz route.
func MountApisixHealthz(r *gin.Engine, state *HealthState) {
r.GET("/apisix/healthz", apisixHealthz(state))
}

func apisixHealthz(state *HealthState) gin.HandlerFunc {
return func(c *gin.Context) {
state.RLock()
err := state.Err
state.RUnlock()

if err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError,
healthzResponse{Status: err.Error()})
return
}
c.AbortWithStatusJSON(http.StatusOK, healthzResponse{Status: "ok"})
}
}
1 change: 0 additions & 1 deletion pkg/api/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ type healthzResponse struct {

func mountHealthz(r *gin.Engine) {
r.GET("/healthz", healthz)
r.GET("/apisix/healthz", healthz)
}

func healthz(c *gin.Context) {
Expand Down
16 changes: 16 additions & 0 deletions pkg/api/router/router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ func TestHealthz(t *testing.T) {
assert.Equal(t, healthzResponse{Status: "ok"}, resp)
}

func TestApisixHealthz(t *testing.T) {
w := httptest.NewRecorder()
c, r := gin.CreateTestContext(w)
var state HealthState
MountApisixHealthz(r, &state)
apisixHealthz(&state)(c)

assert.Equal(t, w.Code, http.StatusOK)

var resp healthzResponse
dec := json.NewDecoder(w.Body)
assert.Nil(t, dec.Decode(&resp))

assert.Equal(t, resp, healthzResponse{Status: "ok"})
}

func TestMetrics(t *testing.T) {
w := httptest.NewRecorder()
c, r := gin.CreateTestContext(w)
Expand Down
25 changes: 25 additions & 0 deletions pkg/api/router/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 router

import "sync"

// HealthState stores healthcheck err of APISIX
type HealthState struct {
sync.RWMutex

Err error
}
4 changes: 4 additions & 0 deletions pkg/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (

// Server represents the API Server in ingress-apisix-controller.
type Server struct {
HealthState *apirouter.HealthState
httpServer *gin.Engine
admissionServer *http.Server
httpListener net.Listener
Expand All @@ -53,9 +54,12 @@ func NewServer(cfg *config.Config) (*Server, error) {
apirouter.Mount(httpServer)

srv := &Server{
HealthState: new(apirouter.HealthState),
httpServer: httpServer,
httpListener: httpListener,
}
apirouter.MountApisixHealthz(httpServer, srv.HealthState)

if cfg.EnableProfiling {
srv.pprofMu = new(http.ServeMux)
srv.pprofMu.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
Expand Down
4 changes: 4 additions & 0 deletions pkg/ingress/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,10 @@ func (c *Controller) checkClusterHealth(ctx context.Context, cancelFunc context.
if err != nil {
// Finally failed health check, then give up leader.
log.Warnf("failed to check health for default cluster: %s, give up leader", err)
c.apiServer.HealthState.Lock()
defer c.apiServer.HealthState.Unlock()

c.apiServer.HealthState.Err = err
return
}
log.Debugf("success check health for default cluster")
Expand Down

0 comments on commit 6110bf5

Please sign in to comment.