Skip to content

Commit 1bdec27

Browse files
committed
Monitor node status
For now, only using Kubernets provided conditions (OutOfDisk, MemoryPressure, DiskPressure, NetworkUnavailable). We don't check (yet) for kube-state-metrics.
1 parent 4fb8f99 commit 1bdec27

File tree

9 files changed

+112
-13
lines changed

9 files changed

+112
-13
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ tools:
66
which glide || go get -u github.com/Masterminds/glide
77

88
lint:
9-
gometalinter -j 1 --vendor --disable-all \
10-
--enable=errcheck \
9+
gometalinter --concurrency=1 --deadline=120s --vendor --disable-all \
1110
--enable=vet \
1211
--enable=vetshadow \
12+
--enable=errcheck \
1313
--enable=structcheck \
1414
--enable=aligncheck \
1515
--enable=deadcode \

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ kube-alert monitors:
66
* Pod failures (unschedulables, error pulling images, crashloop backoff, etc.)
77
* Pods restarts
88
* Cluster's components status (issues with etcd, scheduler, or controller-manager daemons)
9+
* Nodes status (out-of-disk, memory pressure, network unavailable, ...)
910

1011
Support alerting to Datadog and to logs (ie. syslog).
1112

pkg/controllers/cs/cs.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ func (c *CsController) HandlerName() string {
2222
}
2323

2424
func (c *CsController) Init(conf *config.AlertConfig, handler handlers.Handler) controllers.Controller {
25-
c.CommonController = controllers.CommonController{}
26-
c.Conf = conf
27-
c.Handler = handler
25+
c.CommonController = controllers.CommonController{
26+
Conf: conf,
27+
Handler: handler,
28+
Name: "componentstatus",
29+
}
2830

2931
client := c.Conf.ClientSet
30-
c.Name = "componentstatus"
3132
c.ObjType = &v1.ComponentStatus{}
3233
c.ListWatch = &cache.ListWatch{
3334
ListFunc: func(options meta_v1.ListOptions) (runtime.Object, error) {

pkg/controllers/node/node.go

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package node
2+
3+
import (
4+
"github.com/bpineau/kube-alert/config"
5+
"github.com/bpineau/kube-alert/pkg/controllers"
6+
"github.com/bpineau/kube-alert/pkg/handlers"
7+
8+
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
"k8s.io/apimachinery/pkg/runtime"
10+
"k8s.io/apimachinery/pkg/watch"
11+
"k8s.io/client-go/pkg/api/v1"
12+
"k8s.io/client-go/tools/cache"
13+
)
14+
15+
type NodeController struct {
16+
// https://golang.org/doc/effective_go.html#embedding
17+
controllers.CommonController
18+
}
19+
20+
func (c *NodeController) HandlerName() string {
21+
return "node"
22+
}
23+
24+
func (c *NodeController) Init(conf *config.AlertConfig, handler handlers.Handler) controllers.Controller {
25+
c.CommonController = controllers.CommonController{
26+
Conf: conf,
27+
Handler: handler,
28+
Name: "node",
29+
}
30+
31+
client := c.Conf.ClientSet
32+
c.ObjType = &v1.Node{}
33+
c.ListWatch = &cache.ListWatch{
34+
ListFunc: func(options meta_v1.ListOptions) (runtime.Object, error) {
35+
return client.CoreV1().Nodes().List(options)
36+
},
37+
WatchFunc: func(options meta_v1.ListOptions) (watch.Interface, error) {
38+
return client.CoreV1().Nodes().Watch(options)
39+
},
40+
}
41+
42+
return c
43+
}

pkg/controllers/pod/pod.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ func (c *PodController) HandlerName() string {
2222
}
2323

2424
func (c *PodController) Init(conf *config.AlertConfig, handler handlers.Handler) controllers.Controller {
25-
c.CommonController = controllers.CommonController{}
26-
c.Conf = conf
27-
c.Handler = handler
25+
c.CommonController = controllers.CommonController{
26+
Conf: conf,
27+
Handler: handler,
28+
Name: "pod",
29+
}
2830

2931
client := c.Conf.ClientSet
30-
c.Name = "pod"
3132
c.ObjType = &v1.Pod{}
3233
c.ListWatch = &cache.ListWatch{
3334
ListFunc: func(options meta_v1.ListOptions) (runtime.Object, error) {

pkg/handlers/cs/cs.go

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ func (h *CsHandler) Init(c *config.AlertConfig) error {
2020
func (h *CsHandler) ObjectCreated(obj interface{}) (bool, string) {
2121
cs, _ := obj.(*v1.ComponentStatus)
2222

23+
if cs == nil || cs.Conditions == nil {
24+
return true, ""
25+
}
26+
2327
for _, c := range cs.Conditions {
2428
if c.Type != "Healthy" {
2529
continue

pkg/handlers/handlers.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package handlers
33
import (
44
"github.com/bpineau/kube-alert/config"
55
"github.com/bpineau/kube-alert/pkg/handlers/cs"
6+
"github.com/bpineau/kube-alert/pkg/handlers/node"
67
"github.com/bpineau/kube-alert/pkg/handlers/pod"
78
)
89

@@ -13,6 +14,7 @@ type Handler interface {
1314
}
1415

1516
var Handlers = map[string]Handler{
16-
"pod": &pod.PodHandler{},
17-
"cs": &cs.CsHandler{},
17+
"cs": &cs.CsHandler{},
18+
"pod": &pod.PodHandler{},
19+
"node": &node.NodeHandler{},
1820
}

pkg/handlers/node/node.go

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package node
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/bpineau/kube-alert/config"
7+
"k8s.io/client-go/pkg/api/v1"
8+
)
9+
10+
type NodeHandler struct {
11+
conf *config.AlertConfig
12+
}
13+
14+
var knownBadConditions = map[string]bool{
15+
"OutOfDisk": true,
16+
"MemoryPressure": true,
17+
"DiskPressure": true,
18+
"NetworkUnavailable": true,
19+
}
20+
21+
func (n *NodeHandler) Init(c *config.AlertConfig) error {
22+
c.Logger.Info("node handler initialized")
23+
n.conf = c
24+
return nil
25+
}
26+
27+
func (n *NodeHandler) ObjectCreated(obj interface{}) (bool, string) {
28+
node, _ := obj.(*v1.Node)
29+
30+
for _, c := range node.Status.Conditions {
31+
if c.Status == "False" {
32+
continue
33+
}
34+
35+
if knownBadConditions[string(c.Type)] {
36+
return false, fmt.Sprintf("Node %s is unhealthy: %s", node.Name, c.Message)
37+
}
38+
}
39+
40+
return true, ""
41+
}
42+
43+
func (n *NodeHandler) ObjectDeleted(obj interface{}) (bool, string) {
44+
return true, ""
45+
}

pkg/run/run.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@ import (
88
"github.com/bpineau/kube-alert/config"
99
"github.com/bpineau/kube-alert/pkg/controllers"
1010
"github.com/bpineau/kube-alert/pkg/controllers/cs"
11+
"github.com/bpineau/kube-alert/pkg/controllers/node"
1112
"github.com/bpineau/kube-alert/pkg/controllers/pod"
1213
"github.com/bpineau/kube-alert/pkg/handlers"
1314
"github.com/bpineau/kube-alert/pkg/health"
1415
)
1516

1617
var Controllers = []controllers.Controller{
17-
&pod.PodController{},
1818
&cs.CsController{},
19+
&pod.PodController{},
20+
&node.NodeController{},
1921
}
2022

2123
func Run(config *config.AlertConfig) {

0 commit comments

Comments
 (0)