Skip to content
This repository has been archived by the owner on Mar 5, 2024. It is now read-only.

Commit

Permalink
handler: add annotation when the node is taintless, first time seen r…
Browse files Browse the repository at this point in the history
…eady (#12)
  • Loading branch information
JulienBalestra authored and Joseph-Irving committed Dec 17, 2019
1 parent 90529bc commit 6c901b9
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 5 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Nidhogg is a controller that taints nodes based on whether a Pod from a specific

Sometimes you have a Daemonset that is so important that you don't want other pods to run on your node until that Daemonset is up and running on the node. Nidhogg solves this problem by tainting the node until your Daemonset pod is ready, preventing pods that don't tolerate the taint from scheduling there.

Nidhogg annotate the node when all the required taints are removed: `nidhogg.uswitch.com/first-time-ready: 2006-01-02T15:04:05Z`

Nidhogg was built using [Kubebuilder](https://github.com/kubernetes-sigs/kubebuilder)

## Usage
Expand Down
33 changes: 28 additions & 5 deletions pkg/nidhogg/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"reflect"
"strings"
"time"

"github.com/prometheus/client_golang/prometheus"
corev1 "k8s.io/api/core/v1"
Expand All @@ -18,9 +19,10 @@ import (
)

const (
taintKey = "nidhogg.uswitch.com"
taintOperationAdded = "added"
taintOperationRemoved = "removed"
taintKey = "nidhogg.uswitch.com"
taintOperationAdded = "added"
taintOperationRemoved = "removed"
annotationFirstTimeReady = taintKey + "/first-time-ready"
)

var (
Expand Down Expand Up @@ -96,9 +98,30 @@ func (h *Handler) HandleNode(instance *corev1.Node) (reconcile.Result, error) {
return reconcile.Result{}, fmt.Errorf("error caluclating taints for node: %v", err)
}

taintLess := true
for _, taint := range copy.Spec.Taints {
if strings.HasPrefix(taint.Key, taintKey) {
taintLess = false
}
}

var firstTimeReady string
if taintLess {
firstTimeReady = time.Now().Format("2006-01-02T15:04:05Z")
if copy.Annotations == nil {
copy.Annotations = map[string]string{
annotationFirstTimeReady: firstTimeReady,
}
} else if _, ok := copy.Annotations[annotationFirstTimeReady]; !ok {
copy.Annotations[annotationFirstTimeReady] = firstTimeReady
} else {
firstTimeReady = copy.Annotations[annotationFirstTimeReady]
}
}

if !reflect.DeepEqual(copy, instance) {
instance = copy
log.Info("Updating Node taints", "instance", instance.Name, "taints added", taintChanges.taintsAdded, "taints removed", taintChanges.taintsRemoved)
log.Info("Updating Node taints", "instance", instance.Name, "taints added", taintChanges.taintsAdded, "taints removed", taintChanges.taintsRemoved, "taintLess", taintLess, "firstTimeReady", firstTimeReady)
err := h.Update(context.TODO(), instance)
if err != nil {
taintOperationErrors.WithLabelValues("nodeUpdate").Inc()
Expand All @@ -114,7 +137,7 @@ func (h *Handler) HandleNode(instance *corev1.Node) (reconcile.Result, error) {
// this is a hack to make the event work on a non-namespaced object
copy.UID = types.UID(copy.Name)

h.recorder.Eventf(copy, corev1.EventTypeNormal, "TaintsChanged", "Taints added: %s, Taints removed: %s", taintChanges.taintsAdded, taintChanges.taintsRemoved)
h.recorder.Eventf(copy, corev1.EventTypeNormal, "TaintsChanged", "Taints added: %s, Taints removed: %s, TaintLess: %v, FirstTimeReady: %q", taintChanges.taintsAdded, taintChanges.taintsRemoved, taintLess, firstTimeReady)
}

return reconcile.Result{}, nil
Expand Down

0 comments on commit 6c901b9

Please sign in to comment.