Skip to content

josecastillolema/baseline-operator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

82 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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

About

Run stress-ng workloads on Kubernetes

Topics

Resources

License

Stars

Watchers

Forks

Contributors