Skip to content
Snippets Groups Projects
Commit e71cc3e5 authored by Sören Henning's avatar Sören Henning
Browse files

Merge branch 'make-patcher-params-flexibal' into 'theodolite-kotlin'

Make patcher parameters flexible

See merge request !148
parents 2cbbeea0 8d1954db
No related branches found
No related tags found
4 merge requests!159Re-implementation of Theodolite with Kotlin/Quarkus,!157Update Graal Image in CI pipeline,!148Make patcher parameters flexible,!83WIP: Re-implementation of Theodolite with Kotlin/Quarkus
Pipeline #3657 passed
Showing
with 190 additions and 144 deletions
......@@ -55,12 +55,12 @@ spec:
resource:
type: string
default: ""
container:
type: string
default: ""
variableName:
type: string
default: ""
config:
type: object
additionalProperties: true
x-kubernetes-map-type: "granular"
default:
"": ""
loadTypes:
type: array
minItems: 1
......@@ -81,12 +81,12 @@ spec:
resource:
type: string
default: ""
container:
type: string
default: ""
variableName:
type: string
default: ""
config:
type: object
additionalProperties: true
x-kubernetes-map-type: "granular"
default:
"": ""
kafkaConfig:
type: object
properties:
......
{{- if .Values.executionCRD.create -}}
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
......@@ -96,12 +95,12 @@ spec:
resource:
type: string
default: ""
container:
type: string
default: ""
variableName:
type: string
default: ""
config:
type: object
additionalProperties: true
x-kubernetes-map-type: "granular"
default:
"": ""
value:
type: string
status:
......@@ -127,6 +126,4 @@ spec:
jsonPath: .metadata.creationTimestamp
subresources:
status: {}
scope: Namespaced
status: {}
{{- end }}
\ No newline at end of file
scope: Namespaced
\ No newline at end of file
......@@ -19,14 +19,16 @@ resourceTypes:
patchers:
- type: String
resources: String
<Patcher Arguments> ...
properties:
<Patcher Arguments> ...
...
loadTypes:
- typeName: String
patchers:
- type: String
resources: String
<Patcher Arguments> ...
properties:
<Patcher Arguments> ...
...
kafkaConfig:
bootstrapServer: String
......@@ -49,7 +51,7 @@ The properties have the following definitions:
* **patchers**: List of [patchers](#Patchers) used to scale this resource type. Each patcher has the following structure:
* **type**: Type of the [patcher](#Patchers). The concrete types can be looked up in the list of [patchers](#Patchers).
* **resources**: Specifies the Kubernetes resource to be patched.
* **Patcher Arguments**: (Optional) Patcher specific additional arguments.
* **properties**: *Patcher Arguments*: (Optional) Patcher specific additional arguments.
* **loadTypes**: A list of load types that can be scaled for this *benchmark*. For each load type the concrete values are defined in the *execution* object. Each load type has the following structure:
* **typeName**: Name of the load type.
* **patchers**: List of patchers used to scale * **resourceTypes**: A list of resource types that can be scaled for this *benchmark*. For each resource type the concrete values are defined in the *execution* resource object.Each resource type has the following structure:
......@@ -57,7 +59,7 @@ The properties have the following definitions:
* **patchers**: List of patchers used to scale this resource type. Each patcher has the following structure:
* **type**: Type of the Patcher. The concrete types can be looked up in the list of patchers.
* **resources**: Specifies the Kubernetes resource to be patched.
* **Patcher Arguments**: (Optional) Patcher specific additional arguments.
* **properties**: *Patcher Arguments*: (Optional) Patcher specific additional arguments as Map<String, String>.
* **kafkaConfig**: Contains the Kafka configuration.
* **bootstrapServers**: The bootstrap servers connection string.
* **topics**: List of topics to be created for each [experiment](#Experiment). Alternative theodolite offers the possibility to remove certain topics after each experiment.
......@@ -105,7 +107,8 @@ configurationOverrides:
- patcher:
type: String
resource: String
<Patcher Arguments> ...
properties:
<Patcher Arguments> ...
...
```
......@@ -136,7 +139,7 @@ The properties have the following definitions:
* **patcher**: Patcher used to patch a resource. Each patcher has the following structure:
* **type**: Type of the Patcher. The concrete types can be looked up in the list of patchers.
* **resources**: Specifies the Kubernetes resource to be patched.
* **Patcher Arguments**: (Optional) Patcher specific additional arguments.
* **properties**: *Patcher Arguments*: (Optional) Patcher specific additional arguments.
## Patchers
......@@ -159,19 +162,22 @@ The properties have the following definitions:
* **EnvVarPatcher**: Allows to modify the value of an environment variable for a container in a kubernetes deployment.
* **type**: "EnvVarPatcher"
* **resource**: "uc1-load-generator-deployment.yaml"
* **container**: "workload-generator"
* **variableName**: "NUM_SENSORS"
* **properties**:
* container: "workload-generator"
* variableName: "NUM_SENSORS"
* **NodeSelectorPatcher**: Changes the node selection field in kubernetes resources.
* **type**: "NodeSelectorPatcher"
* **resource**: "uc1-load-generator-deployment.yaml"
* **variableName**: "env"
* **properties**:
* variableName: "env"
* **value**: "prod"
* **ResourceLimitPatcher**: Changes the resource limit for a kubernetes resource.
* **resource**: "uc1-kstreams-deployment.yaml"
* **container**: "uc-application"
* **variableName**: "cpu" or "memory"
* **properties**:
* container: "uc-application"
* variableName: "cpu" or "memory"
* **value**:"1000m" or "2Gi"
* **SchedulerNamePatcher**: Changes the sheduler for kubernetes resources.
......@@ -182,7 +188,8 @@ The properties have the following definitions:
* **ImagePatcher**: Changes the image of a kubernetes resource. Currently not fully implemented.
* **type**: "ImagePatcher"
* **resource**: "uc1-kstreams-deployment.yaml"
* **container**: "uc-application"
* **properties**:
* container: "uc-application"
* **value**: "dockerhubrepo/imagename"
......
......@@ -17,10 +17,13 @@ loadTypes:
patchers:
- type: "EnvVarPatcher"
resource: "uc1-load-generator-deployment.yaml"
container: "workload-generator"
variableName: "NUM_SENSORS"
properties:
variableName: "NUM_SENSORS"
container: "workload-generator"
- type: "NumSensorsLoadGeneratorReplicaPatcher"
resource: "uc1-load-generator-deployment.yaml"
properties:
loadGenMaxRecords: "15000"
kafkaConfig:
bootstrapServer: "localhost:31290"
topics:
......
......@@ -20,29 +20,33 @@ execution:
loadGenerationDelay: 30 # in seconds, optional field, default is 0 seconds
restrictions:
- "LowerBound"
configOverrides: []
# - patcher:
# type: "NodeSelectorPatcher"
# resource: "uc1-load-generator-deployment.yaml"
# variableName: "env"
# value: "prod"
# - patcher:
# type: "NodeSelectorPatcher"
# resource: "uc1-kstreams-deployment.yaml"
# variableName: "env"
# value: "prod"
# - patcher:
# type: "ResourceLimitPatcher"
# resource: "uc1-kstreams-deployment.yaml"
# container: "uc-application"
# variableName: "cpu"
# value: "1000m"
# - patcher:
# type: "ResourceLimitPatcher"
# resource: "uc1-kstreams-deployment.yaml"
# container: "uc-application"
# variableName: "memory"
# value: "2Gi"
configOverrides:
- patcher:
type: "NodeSelectorPatcher"
resource: "uc1-load-generator-deployment.yaml"
properties:
variableName: "env"
value: "prod"
- patcher:
type: "NodeSelectorPatcher"
resource: "uc1-kstreams-deployment.yaml"
properties:
variableName: "env"
value: "prod"
- patcher:
type: "ResourceLimitPatcher"
resource: "uc1-kstreams-deployment.yaml"
properties:
container: "uc-application"
limitedResource: "cpu"
value: "1000m"
- patcher:
type: "ResourceLimitPatcher"
resource: "uc1-kstreams-deployment.yaml"
properties:
container: "uc-application"
limitedResource: "memory"
value: "2Gi"
# - patcher:
# type: "SchedulerNamePatcher"
# resource: "uc1-kstreams-deployment.yaml"
......
......@@ -17,14 +17,17 @@ spec:
- type: "ReplicaPatcher"
resource: "uc1-kstreams-deployment.yaml"
loadTypes:
- typeName: "NumSensors"
patchers:
- type: "EnvVarPatcher"
resource: "uc1-load-generator-deployment.yaml"
container: "workload-generator"
variableName: "NUM_SENSORS"
- type: "NumSensorsLoadGeneratorReplicaPatcher"
resource: "uc1-load-generator-deployment.yaml"
- typeName: "NumSensors"
patchers:
- type: "EnvVarPatcher"
resource: "uc1-load-generator-deployment.yaml"
properties:
variableName: "NUM_SENSORS"
container: "workload-generator"
- type: "NumSensorsLoadGeneratorReplicaPatcher"
resource: "uc1-load-generator-deployment.yaml"
properties:
loadGenMaxRecords: "15000"
kafkaConfig:
bootstrapServer: "theodolite-cp-kafka:9092"
topics:
......
......@@ -21,33 +21,37 @@ spec:
strategy: "LinearSearch"
duration: 300 # in seconds
repetitions: 1
delay: 30 # in seconds
loadGenerationDelay: 30 # in seconds
restrictions:
- "LowerBound"
configOverrides: []
# - patcher:
# type: "NodeSelectorPatcher"
# resource: "uc1-load-generator-deployment.yaml"
# variableName: "env"
# value: "prod"
# - patcher:
# type: "NodeSelectorPatcher"
# resource: "uc1-kstreams-deployment.yaml"
# variableName: "env"
# value: "prod"
# - patcher:
# type: "ResourceLimitPatcher"
# resource: "uc1-kstreams-deployment.yaml"
# container: "uc-application"
# variableName: "cpu"
# value: "1000m"
# - patcher:
# type: "ResourceLimitPatcher"
# resource: "uc1-kstreams-deployment.yaml"
# container: "uc-application"
# variableName: "memory"
# value: "2Gi"
# - patcher:
# type: "SchedulerNamePatcher"
# resource: "uc1-kstreams-deployment.yaml"
# value: "random-scheduler"
configOverrides:
# - patcher:
# type: "NodeSelectorPatcher"
# resource: "uc1-load-generator-deployment.yaml"
# properties:
# variableName: "env"
# value: "prod"
# - patcher:
# type: "NodeSelectorPatcher"
# resource: "uc1-kstreams-deployment.yaml"
# properties:
# variableName: "env"
# value: "prod"
# - patcher:
# type: "ResourceLimitPatcher"
# resource: "uc1-kstreams-deployment.yaml"
# properties:
# container: "uc-application"
# limitedResource: "cpu"
# value: "1000m"
# - patcher:
# type: "ResourceLimitPatcher"
# resource: "uc1-kstreams-deployment.yaml"
# properties:
# container: "uc-application"
# limitedResource: "memory"
# value: "2Gi"
# - patcher:
# type: "SchedulerNamePatcher"
# resource: "uc1-kstreams-deployment.yaml"
# value: "random-scheduler"
......@@ -183,7 +183,7 @@ class TheodoliteController(
val configurationOverride = ConfigurationOverride()
configurationOverride.patcher = PatcherDefinition()
configurationOverride.patcher.type = "LabelPatcher"
configurationOverride.patcher.variableName = labelName
configurationOverride.patcher.properties = mutableMapOf("variableName" to labelName)
configurationOverride.patcher.resource = it
configurationOverride.value = labelValue
additionalConfigOverrides.add(configurationOverride)
......
......@@ -20,7 +20,5 @@ import io.fabric8.kubernetes.api.model.KubernetesResource
*
*/
abstract class AbstractPatcher(
k8sResource: KubernetesResource,
container: String? = null,
variableName: String? = null
k8sResource: KubernetesResource
) : Patcher
......@@ -16,7 +16,7 @@ class EnvVarPatcher(
private val k8sResource: KubernetesResource,
private val container: String,
private val variableName: String
) : AbstractPatcher(k8sResource, container, variableName) {
) : AbstractPatcher(k8sResource) {
override fun <String> patch(value: String) {
if (k8sResource is Deployment) {
......
......@@ -11,7 +11,7 @@ import io.fabric8.kubernetes.api.model.apps.StatefulSet
* @param container Container to be patched.
*/
class ImagePatcher(private val k8sResource: KubernetesResource, private val container: String) :
AbstractPatcher(k8sResource, container) {
AbstractPatcher(k8sResource) {
override fun <String> patch(imagePath: String) {
if (k8sResource is Deployment) {
......
......@@ -8,10 +8,9 @@ import io.fabric8.kubernetes.api.model.apps.StatefulSet
import io.fabric8.kubernetes.client.CustomResource
class LabelPatcher(private val k8sResource: KubernetesResource, val variableName: String) :
AbstractPatcher(k8sResource, variableName) {
AbstractPatcher(k8sResource) {
override fun <String> patch(labelValue: String) {
println("call patcher for resource $k8sResource !")
if(labelValue is kotlin.String){
when(k8sResource){
is Deployment -> {
......
......@@ -10,7 +10,7 @@ import io.fabric8.kubernetes.api.model.apps.Deployment
* @param variableName The `label-key` of the node for which the `label-value` is to be patched.
*/
class NodeSelectorPatcher(private val k8sResource: KubernetesResource, private val variableName: String) :
AbstractPatcher(k8sResource, variableName) {
AbstractPatcher(k8sResource) {
override fun <String> patch(value: String) {
if (k8sResource is Deployment) {
k8sResource.spec.template.spec.nodeSelector = mapOf(variableName to value as kotlin.String)
......
......@@ -4,16 +4,17 @@ import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.api.model.apps.Deployment
import kotlin.math.pow
private const val NUM_SENSORS = 4.0
private const val LOAD_GEN_MAX_RECORDS = 150000
class NumNestedGroupsLoadGeneratorReplicaPatcher(private val k8sResource: KubernetesResource) :
class NumNestedGroupsLoadGeneratorReplicaPatcher(
private val k8sResource: KubernetesResource,
private val numSensors: String,
private val loadGenMaxRecords: String
) :
AbstractPatcher(k8sResource) {
override fun <String> patch(value: String) {
if (k8sResource is Deployment) {
if (value is kotlin.String) {
val approxNumSensors = NUM_SENSORS.pow(Integer.parseInt(value).toDouble())
val loadGenInstances = (approxNumSensors + LOAD_GEN_MAX_RECORDS - 1) / LOAD_GEN_MAX_RECORDS
val approxNumSensors = numSensors.toDouble().pow(Integer.parseInt(value).toDouble())
val loadGenInstances = (approxNumSensors + loadGenMaxRecords.toDouble() - 1) / loadGenMaxRecords.toDouble()
this.k8sResource.spec.replicas = loadGenInstances.toInt()
}
}
......
......@@ -3,14 +3,16 @@ package theodolite.patcher
import io.fabric8.kubernetes.api.model.KubernetesResource
import io.fabric8.kubernetes.api.model.apps.Deployment
private const val LOAD_GEN_MAX_RECORDS = 150000
class NumSensorsLoadGeneratorReplicaPatcher(private val k8sResource: KubernetesResource) :
class NumSensorsLoadGeneratorReplicaPatcher(
private val k8sResource: KubernetesResource,
private val loadGenMaxRecords: String
) :
AbstractPatcher(k8sResource) {
override fun <String> patch(value: String) {
if (k8sResource is Deployment) {
if (value is kotlin.String) {
val loadGenInstances = (Integer.parseInt(value) + LOAD_GEN_MAX_RECORDS - 1) / LOAD_GEN_MAX_RECORDS
val loadGenInstances = (Integer.parseInt(value) + loadGenMaxRecords.toInt() - 1) / loadGenMaxRecords.toInt()
this.k8sResource.spec.replicas = loadGenInstances
}
}
......
......@@ -2,6 +2,7 @@ package theodolite.patcher
import io.fabric8.kubernetes.api.model.KubernetesResource
import theodolite.util.DeploymentFailedException
import theodolite.util.InvalidPatcherConfigurationException
import theodolite.util.PatcherDefinition
/**
......@@ -28,28 +29,56 @@ class PatcherFactory {
k8sResources: List<Pair<String, KubernetesResource>>
): Patcher {
val resource =
k8sResources.filter { it.first == patcherDefinition.resource }.map { resource -> resource.second }.firstOrNull()
k8sResources.filter { it.first == patcherDefinition.resource }
.map { resource -> resource.second }
.firstOrNull()
?: throw DeploymentFailedException("Could not find resource ${patcherDefinition.resource}")
return when (patcherDefinition.type) {
"ReplicaPatcher" -> ReplicaPatcher(resource)
"NumNestedGroupsLoadGeneratorReplicaPatcher" -> NumNestedGroupsLoadGeneratorReplicaPatcher(resource)
"NumSensorsLoadGeneratorReplicaPatcher" -> NumSensorsLoadGeneratorReplicaPatcher(resource)
"EnvVarPatcher" -> EnvVarPatcher(resource, patcherDefinition.container, patcherDefinition.variableName)
"NodeSelectorPatcher" -> NodeSelectorPatcher(resource, patcherDefinition.variableName)
"ResourceLimitPatcher" -> ResourceLimitPatcher(
resource,
patcherDefinition.container,
patcherDefinition.variableName
)
"ResourceRequestPatcher" -> ResourceRequestPatcher(
resource,
patcherDefinition.container,
patcherDefinition.variableName
)
"SchedulerNamePatcher" -> SchedulerNamePatcher(resource)
"LabelPatcher" -> LabelPatcher(resource, patcherDefinition.variableName)
else -> throw IllegalArgumentException("Patcher type ${patcherDefinition.type} not found")
return try {
when (patcherDefinition.type) {
"ReplicaPatcher" -> ReplicaPatcher(
k8sResource = resource
)
"NumNestedGroupsLoadGeneratorReplicaPatcher" -> NumNestedGroupsLoadGeneratorReplicaPatcher(
k8sResource = resource,
loadGenMaxRecords = patcherDefinition.properties["loadGenMaxRecords"] !!,
numSensors = patcherDefinition.properties["numSensors"] !!
)
"NumSensorsLoadGeneratorReplicaPatcher" -> NumSensorsLoadGeneratorReplicaPatcher(
k8sResource = resource,
loadGenMaxRecords = patcherDefinition.properties["loadGenMaxRecords"] !!
)
"EnvVarPatcher" -> EnvVarPatcher(
k8sResource = resource,
container = patcherDefinition.properties["container"] !!,
variableName = patcherDefinition.properties["variableName"] !!
)
"NodeSelectorPatcher" -> NodeSelectorPatcher(
k8sResource = resource,
variableName = patcherDefinition.properties["variableName"] !!
)
"ResourceLimitPatcher" -> ResourceLimitPatcher(
k8sResource = resource,
container = patcherDefinition.properties["container"] !!,
limitedResource = patcherDefinition.properties["limitedResource"] !!
)
"ResourceRequestPatcher" -> ResourceRequestPatcher(
k8sResource = resource,
container = patcherDefinition.properties["container"] !!,
requestedResource = patcherDefinition.properties["requestedResource"] !!
)
"SchedulerNamePatcher" -> SchedulerNamePatcher(
k8sResource = resource
)
"LabelPatcher" -> LabelPatcher(
k8sResource = resource,
variableName = patcherDefinition.properties["variableName"] !!
)
else -> throw InvalidPatcherConfigurationException("Patcher type ${patcherDefinition.type} not found.")
}
} catch (e: Exception) {
throw InvalidPatcherConfigurationException("Could not create patcher with type ${patcherDefinition.type}" +
" Probably a required patcher argument was not specified." )
}
}
}
......@@ -18,7 +18,7 @@ class ResourceLimitPatcher(
private val k8sResource: KubernetesResource,
private val container: String,
private val limitedResource: String
) : AbstractPatcher(k8sResource, container, limitedResource) {
) : AbstractPatcher(k8sResource) {
override fun <String> patch(value: String) {
when (k8sResource) {
......
......@@ -18,7 +18,7 @@ class ResourceRequestPatcher(
private val k8sResource: KubernetesResource,
private val container: String,
private val requestedResource: String
) : AbstractPatcher(k8sResource, container, requestedResource) {
) : AbstractPatcher(k8sResource) {
override fun <String> patch(value: String) {
when (k8sResource) {
......
package theodolite.util
class InvalidPatcherConfigurationException(message:String): Exception(message) {
}
package theodolite.util
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import io.quarkus.runtime.annotations.RegisterForReflection
/**
......@@ -19,13 +20,6 @@ class PatcherDefinition {
*/
lateinit var resource: String
/**
* The container which the patcher is applied to
*/
lateinit var container: String
/**
* The variable name for the patcher
*/
lateinit var variableName: String
@JsonSerialize
lateinit var properties: MutableMap<String, String>
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment