Skip to content

josecastillolema/baseline-operator

Repository files navigation

GitHub GitHub language count GitHub top language Go Report Card Docker Image CI

baseline-operator

The baseline-operator provides a way to run stress-ng workloads on Kubernetes in various deployment configurations.

It is intended to create an artificial baseline load in a Kubernetes cluster in order to be able to run other Kubernetes tests in more realistic conditions (performance, cluster upgrade, etc.).

Use

Create a baseline CRD, i.e.:

apiVersion: perf.baseline.io/v1
kind: Baseline
metadata:
  name: baseline-sample
spec:
  cpu: 1                                             # Cores
  mem: 1G                                            # Size of the virtual memory. Can be defined as a % of the available memory
  io: 1                                              # Workers continuously calling sync to commit buffer cache to disk
  sock: 1                                            # Workers exercising socket I/O networking
  custom: "--timer 1"                                # Other custom params
  # image: quay.io/cloud-bulldozer/stressng          # Custom image
  # hostNetwork: true                                # Directly use host network
  # nodeSelector:                                    # Filter nodes with labels
  #   stress: "true"
  # tolerations:                                     # Use the control plane nodes
  # - key: node-role.kubernetes.io/control-plane
  #   operator: Exists
  #   effect: NoSchedule
  # - key: node-role.kubernetes.io/master
  #   operator: Exists
  #   effect: NoSchedule
$ kubectl apply -f config/samples/perf_v1_baseline.yaml
baseline.perf.baseline.io/baseline-sample configured

$ kubectl get baseline
NAME              COMMAND                                                                                AGE
baseline-sample   stress-ng -t 0 --cpu 1 --vm 1 --vm-bytes 1G --io 1 --sock 1 --sock-if eth0 --timer 1   3s

Check for the DaemonSet:

$ kubectl get daemonset
NAME              DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
baseline-sample   1         1         1       1            1           <none>          1m

Check for the Pods:

$ kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
baseline-sample-nnq5b   1/1     Running   0          1m

$ kubectl logs baseline-sample-nnq5b 
stress-ng: info:  [1] setting to a 0 second run per stressor
stress-ng: info:  [1] dispatching hogs: 1 cpu, 1 vm, 1 io, 1 sock, 1 timer

Updating the CRD

Update or remove parameters from the CRD:

$ kubectl patch baseline baseline-sample --type merge -p '{"spec":{"cpu":2}}'
baseline.perf.baseline.io/baseline-sample patched

$ kubectl get po
NAME                    READY   STATUS              RESTARTS   AGE
baseline-sample-nnq5b   1/1     Terminating         0          5m
baseline-sample-xvxc9   0/1     ContainerCreating   0          1s

$ kubectl logs baseline-sample-xvxc9
stress-ng: info:  [1] setting to a 0 second run per stressor
stress-ng: info:  [1] dispatching hogs: 2 cpu, 1 vm, 1 io, 1 sock, 1 timer

Some updates (like the above) that get translated into a new command cause the DaemonSet to be recreated.

Check for the CRD events:

$ kubectl describe baseline baseline-sample
...
Events:
  Type    Reason     Age    From      Message
  ----    ------     ----   ----      -------
  Normal  Created    5m20s  Baseline  Created daemonset default/baseline-sample
  Normal  Recreated  4s     Baseline  Rereated daemonset default/baseline-sample

Other fields of the CRD can be updated without the need of a DaemonSet recreation, like i.e.: image, hostNetwork, nodeSelector and tolerations:

$ kubectl patch baseline baseline-sample --type merge -p '{"spec":{"nodeSelector":{"stress":"true"}}}'
baseline.perf.baseline.io/baseline-sample patched

$ kubects get daemonset
NAME              DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
baseline-sample   0         0         0       0            0           stress=true     3m9s

$ kubectl describe baseline baseline-sample
...
Events:
  Type    Reason     Age    From      Message
  ----    ------     ----   ----      -------
  Normal  Created    6m20s  Baseline  Created daemonset default/baseline-sample
  Normal  Recreated  1m10s  Baseline  Rereated daemonset default/baseline-sample
  Normal  Updated    7s     Baseline  Updated daemonset default/baseline-sample

Node placement

If you specify node selector(s), then the DaemonSet controller will create Pods on nodes which match that node selector(s):

apiVersion: perf.baseline.io/v1
kind: Baseline
metadata:
  name: baseline-sample
spec:
  cpu: 1
  nodeSelector:
    stress: "true"
$ kubectl get daemonset
NAME              DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
baseline-sample   1         1         1       1            1           stress=true     1m

By default, DaemonSet Pods only run in worker nodes. If you want to run stress-ng loads in control plane nodes you can use tolerations:

apiVersion: perf.baseline.io/v1
kind: Baseline
metadata:
  name: baseline-sample
spec:
  cpu: 1			            
  tolerations:
  # these tolerations are to have the daemonset runnable on control plane nodes
  # remove them if your control plane nodes should not run pods
  - key: node-role.kubernetes.io/control-plane
    operator: Exists
    effect: NoSchedule
  - key: node-role.kubernetes.io/master
    operator: Exists
    effect: NoSchedule

Custom image

It is possible to select a custom image for stress-ng using the image property:

apiVersion: perf.baseline.io/v1
kind: Baseline
metadata:
  name: baseline-sample
spec:
  cpu: 1
  image: quay.io/cloud-bulldozer/stressng

If not defined, defaults to quay.io/jcastillolema/stressng:0.14.01. For network workloads is important for stress-ng version to be >= 0.14.01, which allows to choose the network interface via --sock-if, sockmany-if, --udp-if and udp-flood-if. The default image was compiled through this Dockerfile:

FROM quay.io/centos/centos:stream8

WORKDIR /root
RUN yum install -y libaio-devel libattr-devel libcap-devel libgcrypt-devel libjpeg-devel keyutils-libs-devel lksctp-tools-devel libatomic zlib-devel cmake gcc
RUN curl -L https://github.com/ColinIanKing/stress-ng/archive/refs/tags/V0.14.01.tar.gz -o V0.14.01.tar.gz && tar -xzvf V0.14.01.tar.gz -C /root --strip-components=1
RUN make clean && make && mv stress-ng /usr/local/bin

Installation

$ git clone https://github.com/josecastillolema/baseline-operator
$ cd baseline-operator
$ make deploy