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

Commit

Permalink
change taint format and events (#7)
Browse files Browse the repository at this point in the history
* change taint format and events
  • Loading branch information
Joseph-Irving authored Mar 25, 2019
1 parent 7b84bfa commit cc00665
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 22 deletions.
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Nidhogg was built using [Kubebuilder](https://github.com/kubernetes-sigs/kubebui
## Usage

Nidhogg requires a json config file to tell it what Daemonsets to watch and what nodes to act on.
`nodeSelector` is a map of keys/values corresponding to node labels. `daemonsets` is an array of Daemonsets to watch, each containing two fields `name` and `namespace`. Nodes are tainted with taint that follows the format of `<daemonset-name>-not-ready:NoSchedule`.
`nodeSelector` is a map of keys/values corresponding to node labels. `daemonsets` is an array of Daemonsets to watch, each containing two fields `name` and `namespace`. Nodes are tainted with taint that follows the format of `nidhogg.uswitch.com/namespace.name:NoSchedule`.

Example:

Expand All @@ -27,7 +27,17 @@ Example:
}
```
This example will taint any nodes that have the label `node-role.kubernetes.io/node=""` if they do not have a running and ready pod from the `kiam` daemonset in the `kube-system` namespace.
It will add a taint of `kiam-not-ready:NoSchedule` until there is a ready kiam pod on the node.
It will add a taint of `nidhogg.uswitch.com/kube-system.kiam:NoSchedule` until there is a ready kiam pod on the node.

If you want pods to be able to run on the nidhogg tainted nodes you can add a toleration:

```yaml
spec:
tolerations:
- key: nidhogg.uswitch.com/kube-system.kiam
operator: "Exists"
effect: NoSchedule
```
## Deploying
Docker images can be found at https://quay.io/uswitch/nidhogg
Expand Down
61 changes: 41 additions & 20 deletions pkg/nidhogg/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
)

const taintKey = "nidhogg.uswitch.com"

// Handler performs the main business logic of the Wave controller
type Handler struct {
client.Client
Expand All @@ -33,6 +35,11 @@ type Daemonset struct {
Namespace string `json:"namespace"`
}

type taintChanges struct {
taintsAdded []string
taintsRemoved []string
}

// NewHandler constructs a new instance of Handler
func NewHandler(c client.Client, r record.EventRecorder, conf HandlerConfig) *Handler {
return &Handler{Client: c, recorder: r, config: conf}
Expand All @@ -49,34 +56,19 @@ func (h *Handler) HandleNode(instance *corev1.Node) (reconcile.Result, error) {
return reconcile.Result{}, nil
}

copy := instance.DeepCopy()

for _, daemonset := range h.config.Daemonsets {
taintName := daemonset.Name + "-not-ready"
// Get Pod for node
pod, err := h.getDaemonsetPod(instance.Name, daemonset)
if err != nil {
return reconcile.Result{}, fmt.Errorf("error fetching pods: %v", err)
}

if pod == nil || podNotReady(pod) {
if !taintPresent(copy, taintName) {
copy.Spec.Taints = addTaint(copy.Spec.Taints, taintName)
}
} else {
copy.Spec.Taints = removeTaint(copy.Spec.Taints, taintName)
}

copy, taintChanges, err := h.caclulateTaints(instance)
if err != nil {
return reconcile.Result{}, fmt.Errorf("error caluclating taints for node: %v", err)
}

if !reflect.DeepEqual(copy, instance) {
instance = copy
log.Info("Updating Node taints", "instance", instance.Name, "taints", instance.Spec.Taints)
log.Info("Updating Node taints", "instance", instance.Name, "taints added", taintChanges.taintsAdded, "taints removed", taintChanges.taintsRemoved)
err := h.Update(context.TODO(), instance)
// 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 updated to %s", copy.Spec.Taints)
h.recorder.Eventf(copy, corev1.EventTypeNormal, "TaintsChanged", "Taints added: %s, Taints removed: %s", taintChanges.taintsAdded, taintChanges.taintsRemoved)
if err != nil {
return reconcile.Result{}, err
}
Expand All @@ -85,6 +77,35 @@ func (h *Handler) HandleNode(instance *corev1.Node) (reconcile.Result, error) {
return reconcile.Result{}, nil
}

func (h *Handler) caclulateTaints(instance *corev1.Node) (*corev1.Node, taintChanges, error) {

copy := instance.DeepCopy()

var changes taintChanges

for _, daemonset := range h.config.Daemonsets {

taint := fmt.Sprintf("%s/%s.%s", taintKey, daemonset.Namespace, daemonset.Name)
// Get Pod for node
pod, err := h.getDaemonsetPod(instance.Name, daemonset)
if err != nil {
return nil, taintChanges{}, fmt.Errorf("error fetching pods: %v", err)
}

if pod == nil || podNotReady(pod) {
if !taintPresent(copy, taint) {
copy.Spec.Taints = addTaint(copy.Spec.Taints, taint)
changes.taintsAdded = append(changes.taintsAdded, taint)
}
} else if taintPresent(copy, taint) {
copy.Spec.Taints = removeTaint(copy.Spec.Taints, taint)
changes.taintsRemoved = append(changes.taintsRemoved, taint)
}

}
return copy, changes, nil
}

func (h *Handler) getDaemonsetPod(nodeName string, ds Daemonset) (*corev1.Pod, error) {
opts := client.InNamespace(ds.Namespace)
pods := &corev1.PodList{}
Expand Down

0 comments on commit cc00665

Please sign in to comment.