diff --git a/execution/README.md b/execution/README.md index ff94dfed2fa887c300e8449b7c41dc3f65c7a1e2..ca15111c0ad7000a200c0c50427a2c2aeb75e093 100644 --- a/execution/README.md +++ b/execution/README.md @@ -98,7 +98,7 @@ kubectl apply -f infrastructure/kafka/service-monitor.yaml Other Kafka deployments, for example, using Strimzi, should work in a similar way. *Please note that currently, even if installed differently, the corresponding services must run at -*my-confluent-cp-kafka:9092*, *my-confluent-cp-zookeeper:2181* and *my-confluent-cp-schema-registry:8081*. +`my-confluent-cp-kafka:9092`, `my-confluent-cp-zookeeper:2181` and `my-confluent-cp-schema-registry:8081`.* #### A Kafka Client Pod diff --git a/execution/helm/templates/dashboard-config-map.yaml b/execution/helm/templates/grafana/dashboard-config-map.yaml similarity index 99% rename from execution/helm/templates/dashboard-config-map.yaml rename to execution/helm/templates/grafana/dashboard-config-map.yaml index 87e588f29df7446d0b12000eb53487a9bb88ea6c..1125d7833cc62e78c049436f38b854d926e2a216 100644 --- a/execution/helm/templates/dashboard-config-map.yaml +++ b/execution/helm/templates/grafana/dashboard-config-map.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: ConfigMap metadata: - name: scalability + name: {{ template "theodolite.fullname" . }}-grafana-scalability labels: grafana_dashboard: "1" data: diff --git a/execution/helm/templates/kafka-client.yaml b/execution/helm/templates/kafka/kafka-client.yaml similarity index 87% rename from execution/helm/templates/kafka-client.yaml rename to execution/helm/templates/kafka/kafka-client.yaml index 853cb768672d8888085a3881df81cbdb806ec39d..02e16d33dfc9595dd16c41fa6bfe1404fd7889ab 100644 --- a/execution/helm/templates/kafka-client.yaml +++ b/execution/helm/templates/kafka/kafka-client.yaml @@ -3,7 +3,7 @@ apiVersion: v1 kind: Pod metadata: # name: {{ template "theodolite.fullname" . }}-kafka-client - name: kafka-client + name: {{ template "theodolite.fullname" . }}-kafka-client spec: containers: - name: kafka-client diff --git a/execution/helm/templates/service-monitor.yaml b/execution/helm/templates/kafka/service-monitor.yaml similarity index 83% rename from execution/helm/templates/service-monitor.yaml rename to execution/helm/templates/kafka/service-monitor.yaml index 50e4688cf7f9b919afdc9455462034f682975893..68fd5f7599d36187fa7c4dee2fab211eb263c67d 100644 --- a/execution/helm/templates/service-monitor.yaml +++ b/execution/helm/templates/kafka/service-monitor.yaml @@ -5,7 +5,7 @@ metadata: labels: app: cp-kafka appScope: titan-ccp - name: kafka + name: {{ template "theodolite.fullname" . }}-cp-kafka spec: selector: matchLabels: diff --git a/execution/helm/templates/cluster-role-binding.yaml b/execution/helm/templates/prometheus/cluster-role-binding.yaml similarity index 61% rename from execution/helm/templates/cluster-role-binding.yaml rename to execution/helm/templates/prometheus/cluster-role-binding.yaml index 400a972cdb73dca181b621f49e7a3e79c926e65b..f2f167b94b79ad4db130565777cb8af486762c8c 100644 --- a/execution/helm/templates/cluster-role-binding.yaml +++ b/execution/helm/templates/prometheus/cluster-role-binding.yaml @@ -2,13 +2,13 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: prometheus + name: {{ template "theodolite.fullname" . }}-prometheus roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: prometheus + name: {{ template "theodolite.fullname" . }}-prometheus subjects: - kind: ServiceAccount - name: prometheus + name: {{ template "theodolite.fullname" . }}-prometheus namespace: {{ .Release.Namespace }} {{- end}} \ No newline at end of file diff --git a/execution/helm/templates/cluster-role.yaml b/execution/helm/templates/prometheus/cluster-role.yaml similarity index 86% rename from execution/helm/templates/cluster-role.yaml rename to execution/helm/templates/prometheus/cluster-role.yaml index 2a272718da1413a466d6afed51b3bca1f37a1fe0..c2fea2205451e01474d1ab7ef1ca342a9d975dc9 100644 --- a/execution/helm/templates/cluster-role.yaml +++ b/execution/helm/templates/prometheus/cluster-role.yaml @@ -2,7 +2,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: prometheus + name: {{ template "theodolite.fullname" . }}-prometheus rules: - apiGroups: [""] resources: diff --git a/execution/helm/templates/prometheus-datasource-config-map.yaml b/execution/helm/templates/prometheus/datasource-config-map.yaml similarity index 94% rename from execution/helm/templates/prometheus-datasource-config-map.yaml rename to execution/helm/templates/prometheus/datasource-config-map.yaml index 4e793ff83668ac7a7582a924750ca729d9e277ae..b28157940c4dd7cb05eca3fe04926f6e7726830f 100644 --- a/execution/helm/templates/prometheus-datasource-config-map.yaml +++ b/execution/helm/templates/prometheus/datasource-config-map.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: ConfigMap metadata: - name: prometheus + name: {{ template "theodolite.fullname" . }}-prometheus labels: grafana_datasource: "1" data: diff --git a/execution/helm/templates/prometheus.yaml b/execution/helm/templates/prometheus/prometheus.yaml similarity index 86% rename from execution/helm/templates/prometheus.yaml rename to execution/helm/templates/prometheus/prometheus.yaml index a3060798a8a3b000f730525805c0d050becc7a68..4e297b20290be9686b901fa8c76823136c6fabef 100644 --- a/execution/helm/templates/prometheus.yaml +++ b/execution/helm/templates/prometheus/prometheus.yaml @@ -4,7 +4,7 @@ kind: Prometheus metadata: name: {{ template "theodolite.fullname" . }}-prometheus spec: - serviceAccountName: prometheus + serviceAccountName: {{ template "theodolite.fullname" . }}-prometheus serviceMonitorSelector: matchLabels: #app: cp-kafka diff --git a/execution/helm/templates/service-account.yaml b/execution/helm/templates/prometheus/service-account.yaml similarity index 65% rename from execution/helm/templates/service-account.yaml rename to execution/helm/templates/prometheus/service-account.yaml index 2e14c8eb8ffd912f3d34d1b94aa481cb497b4b90..090284a0cf3c6bb7ca643ee111b2d62d1bd93fb3 100644 --- a/execution/helm/templates/service-account.yaml +++ b/execution/helm/templates/prometheus/service-account.yaml @@ -2,5 +2,5 @@ apiVersion: v1 kind: ServiceAccount metadata: - name: prometheus + name: {{ template "theodolite.fullname" . }}-prometheus {{- end}} \ No newline at end of file diff --git a/theodolite-quarkus/config/BenchmarkType.yaml b/theodolite-quarkus/config/example-benchmark-yaml-resource.yaml similarity index 100% rename from theodolite-quarkus/config/BenchmarkType.yaml rename to theodolite-quarkus/config/example-benchmark-yaml-resource.yaml diff --git a/theodolite-quarkus/config/BenchmarkExecution.yaml b/theodolite-quarkus/config/example-execution-yaml-resource.yaml similarity index 59% rename from theodolite-quarkus/config/BenchmarkExecution.yaml rename to theodolite-quarkus/config/example-execution-yaml-resource.yaml index ef74e14f94b65f077fdec7e6f0b61772a7f3079f..80e4575d653bff8d67d8f66cf4ae9806a1fe102e 100644 --- a/theodolite-quarkus/config/BenchmarkExecution.yaml +++ b/theodolite-quarkus/config/example-execution-yaml-resource.yaml @@ -1,4 +1,4 @@ -name: "Theodolite Test Context" +name: example-execution benchmark: "uc1-kstreams" load: loadType: "NumSensors" @@ -32,19 +32,19 @@ configOverrides: 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" \ No newline at end of file +# - 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" diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt index da59a7e95e5ddd7cef37da3f251f597b43df29e6..36fd00795e3f075ca1fbd171fa59339df8151f85 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt @@ -1,11 +1,16 @@ package theodolite.benchmark +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import io.fabric8.kubernetes.api.model.KubernetesResource +import io.fabric8.kubernetes.api.model.Namespaced +import io.fabric8.kubernetes.client.CustomResource import io.quarkus.runtime.annotations.RegisterForReflection import theodolite.util.ConfigurationOverride import kotlin.properties.Delegates +@JsonDeserialize @RegisterForReflection -class BenchmarkExecution { +class BenchmarkExecution : CustomResource(), Namespaced { var executionId: Int = 0 lateinit var name: String lateinit var benchmark: String @@ -15,16 +20,18 @@ class BenchmarkExecution { lateinit var execution: Execution lateinit var configOverrides: List<ConfigurationOverride?> + @JsonDeserialize @RegisterForReflection - class Execution { + class Execution : KubernetesResource { lateinit var strategy: String var duration by Delegates.notNull<Long>() var repetitions by Delegates.notNull<Int>() lateinit var restrictions: List<String> } + @JsonDeserialize @RegisterForReflection - class Slo { + class Slo : KubernetesResource { lateinit var sloType: String var threshold by Delegates.notNull<Int>() lateinit var prometheusUrl: String @@ -33,14 +40,17 @@ class BenchmarkExecution { var warmup by Delegates.notNull<Int>() } + + @JsonDeserialize @RegisterForReflection - class LoadDefinition { + class LoadDefinition : KubernetesResource { lateinit var loadType: String lateinit var loadValues: List<Int> } + @JsonDeserialize @RegisterForReflection - class ResourceDefinition { + class ResourceDefinition : KubernetesResource { lateinit var resourceType: String lateinit var resourceValues: List<Int> } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecutionList.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecutionList.kt new file mode 100644 index 0000000000000000000000000000000000000000..50e8967f20aebad880ebd218136749af8e3ea6ee --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/BenchmarkExecutionList.kt @@ -0,0 +1,5 @@ +package theodolite.benchmark + +import io.fabric8.kubernetes.client.CustomResourceList + +class BenchmarkExecutionList : CustomResourceList<BenchmarkExecution>() \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KafkaLagExporterRemover.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KafkaLagExporterRemover.kt index 9e241cabfa208a0632635a30c658590faec2c1a8..2b86c51ae87c7b26609683b68bf6cfc12003efc8 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KafkaLagExporterRemover.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KafkaLagExporterRemover.kt @@ -1,14 +1,14 @@ -package theodolite.benchmark; +package theodolite.benchmark import io.fabric8.kubernetes.client.NamespacedKubernetesClient import mu.KotlinLogging private val logger = KotlinLogging.logger {} -class KafkaLagExporterRemover(private val client : NamespacedKubernetesClient) { +class KafkaLagExporterRemover(private val client: NamespacedKubernetesClient) { - fun remove(label: String){ + fun remove(label: String) { this.client.pods().withLabel(label).delete() - logger.info{"Pod with label: $label deleted"} + logger.info { "Pod with label: $label deleted" } } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt index f5a9222546cd63415a8c447a82054eaee1266849..4f630ff6b5da77d4933c77e8741926ac0c37cdf1 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt @@ -1,6 +1,8 @@ package theodolite.benchmark import io.fabric8.kubernetes.api.model.KubernetesResource +import io.fabric8.kubernetes.api.model.Namespaced +import io.fabric8.kubernetes.client.CustomResource import io.fabric8.kubernetes.client.DefaultKubernetesClient import io.quarkus.runtime.annotations.RegisterForReflection import mu.KotlinLogging @@ -9,11 +11,10 @@ import theodolite.patcher.PatcherFactory import theodolite.util.* private val logger = KotlinLogging.logger {} - private var DEFAULT_NAMESPACE = "default" @RegisterForReflection -class KubernetesBenchmark : Benchmark { +class KubernetesBenchmark : Benchmark, CustomResource(), Namespaced { lateinit var name: String lateinit var appResource: List<String> lateinit var loadGenResource: List<String> @@ -24,12 +25,15 @@ class KubernetesBenchmark : Benchmark { lateinit var path: String private fun loadKubernetesResources(resources: List<String>): List<Pair<String, KubernetesResource>> { - //val path = "./../../../resources/main/yaml/" val parser = YamlParser() namespace = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE logger.info { "Using $namespace as namespace." } + path = System.getenv("THEODOLITE_APP_RESOURCES") ?: "./config" + logger.info { "Using $path as path for resources." } + + val loader = K8sResourceLoader(DefaultKubernetesClient().inNamespace(namespace)) return resources .map { resource -> @@ -58,7 +62,9 @@ class KubernetesBenchmark : Benchmark { // Patch the given overrides configurationOverrides.forEach { override -> - override?.let { patcherFactory.createPatcher(it.patcher, resources).patch(override.value) } + override?.let { + patcherFactory.createPatcher(it.patcher, resources).patch(override.value) + } } return KubernetesBenchmarkDeployment( diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkList.kt b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkList.kt new file mode 100644 index 0000000000000000000000000000000000000000..0930875e96146fda58301478bda68b00c229e99f --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkList.kt @@ -0,0 +1,5 @@ +package theodolite.benchmark + +import io.fabric8.kubernetes.client.CustomResourceList + +class KubernetesBenchmarkList : CustomResourceList<KubernetesBenchmark>() \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt index 47a27501f89621d8168ad381c71cbcb504511cdd..0b6c681c9123adace08bc60946a067442ca2baa1 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt @@ -19,7 +19,7 @@ class AnalysisExecutor( offset = Duration.ofHours(slo.offset.toLong()) ) - fun analyse(load: LoadDimension, res: Resource, executionDuration: Duration): Boolean { + fun analyze(load: LoadDimension, res: Resource, executionDuration: Duration): Boolean { var result = false try { diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt index d30ae868732cf026ff2704ebe8362055fe5823a9..a6eae8bbfb1273b90e3d457db3287d6fc1546fbe 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt @@ -8,6 +8,7 @@ import theodolite.util.LoadDimension import theodolite.util.Resource import theodolite.util.Results import java.time.Duration +import java.util.concurrent.atomic.AtomicBoolean private val logger = KotlinLogging.logger {} @@ -28,6 +29,8 @@ abstract class BenchmarkExecutor( val executionId: Int ) { + var run: AtomicBoolean = AtomicBoolean(true) + /** * Run a experiment for the given parametrization, evaluate the experiment and save the result. * @@ -36,19 +39,26 @@ abstract class BenchmarkExecutor( * @return True, if the number of resources are suitable for the given load, false otherwise. */ abstract fun runExperiment(load: LoadDimension, res: Resource): Boolean - + /** * Wait while the benchmark is running and log the number of minutes executed every 1 minute. * */ fun waitAndLog() { logger.info { "Execution of a new benchmark started." } - for (i in 1.rangeTo(executionDuration.toSeconds())) { + var secondsRunning = 0L + + while (run.get() && secondsRunning < executionDuration.toSeconds()) { + secondsRunning++ Thread.sleep(Duration.ofSeconds(1).toMillis()) - if ((i % 60) == 0L) { - logger.info { "Executed: ${i / 60} minutes" } + + if ((secondsRunning % 60) == 0L) { + logger.info { "Executed: ${secondsRunning / 60} minutes." } } } + + logger.debug { "Executor shutdown gracefully." } + } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt index 0a1e37128720247c10e6f99965310b1634186ee9..03c66e757abab9de69bc97ff98a67fffdafdf3d1 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt @@ -23,19 +23,24 @@ class BenchmarkExecutorImpl( executionId: Int ) : BenchmarkExecutor(benchmark, results, executionDuration, configurationOverrides, slo, executionId) { override fun runExperiment(load: LoadDimension, res: Resource): Boolean { + var result = false val benchmarkDeployment = benchmark.buildDeployment(load, res, this.configurationOverrides) - benchmarkDeployment.setup() - this.waitAndLog() - val result = AnalysisExecutor(slo = slo, executionId = executionId).analyse( - load = load, - res = res, - executionDuration = executionDuration - ) + try { + benchmarkDeployment.setup() + this.waitAndLog() + } catch(e: Exception) { + logger.error { "Error while setup experiment." } + logger.error { "Error is: $e" } + this.run.set(false) + } + if (this.run.get()) { + result = + AnalysisExecutor(slo = slo, executionId = executionId).analyze(load = load, res = res, executionDuration = executionDuration) + this.results.setResult(Pair(load, res), result) + } benchmarkDeployment.teardown() - - this.results.setResult(Pair(load, res), result) return result } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/Main.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/Main.kt new file mode 100644 index 0000000000000000000000000000000000000000..3246d0a7930aab22d16ed94a6c0f10a9d3fde10e --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/Main.kt @@ -0,0 +1,25 @@ +package theodolite.execution + +import io.quarkus.runtime.annotations.QuarkusMain +import mu.KotlinLogging +import theodolite.execution.operator.TheodoliteOperator +import kotlin.system.exitProcess + +private val logger = KotlinLogging.logger {} + +@QuarkusMain +object Main { + + @JvmStatic + fun main(args: Array<String>) { + + val mode = System.getenv("MODE") ?: "operator" + logger.info { "Start Theodolite with mode $mode" } + + when(mode) { + "yaml-executor" -> TheodoliteYamlExecutor().start() + "operator" -> TheodoliteOperator().start() + else -> {logger.error { "MODE $mode not found" }; exitProcess(1)} + } + } +} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/Shutdown.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/Shutdown.kt index 9ca7e70f6ecd5ed30120940be8de965c73f79a6a..589dee1ac2e39d107794df1e3aa85ea56d6db92b 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/Shutdown.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/Shutdown.kt @@ -8,10 +8,9 @@ import theodolite.util.Resource private val logger = KotlinLogging.logger {} -class Shutdown(private val benchmarkExecution: BenchmarkExecution, private val benchmark: KubernetesBenchmark) : - Thread() { +class Shutdown(private val benchmarkExecution: BenchmarkExecution, private val benchmark: KubernetesBenchmark) { - override fun run() { + fun run() { // Build Configuration to teardown logger.info { "Received shutdown signal -> Shutting down" } val deployment = @@ -20,8 +19,8 @@ class Shutdown(private val benchmarkExecution: BenchmarkExecution, private val b res = Resource(0, emptyList()), configurationOverrides = benchmarkExecution.configOverrides ) - logger.info { "Teardown the everything deployed" } + logger.info { "Teardown everything deployed" } deployment.teardown() logger.info { "Teardown completed" } } -} +} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt index ebddce03768cf8532bc719436344ef9e8f82e2b3..0c3e0d2fd6d1f40df5299c64b214d84323cba853 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt @@ -17,6 +17,7 @@ class TheodoliteExecutor( private val config: BenchmarkExecution, private val kubernetesBenchmark: KubernetesBenchmark ) { + lateinit var executor: BenchmarkExecutor private fun buildConfig(): Config { val results = Results() @@ -24,14 +25,19 @@ class TheodoliteExecutor( val executionDuration = Duration.ofSeconds(config.execution.duration) - val resourcePatcherDefinition = PatcherDefinitionFactory().createPatcherDefinition( - config.resources.resourceType, - this.kubernetesBenchmark.resourceTypes - ) + val resourcePatcherDefinition = + PatcherDefinitionFactory().createPatcherDefinition( + config.resources.resourceType, + this.kubernetesBenchmark.resourceTypes + ) + val loadDimensionPatcherDefinition = - PatcherDefinitionFactory().createPatcherDefinition(config.load.loadType, this.kubernetesBenchmark.loadTypes) + PatcherDefinitionFactory().createPatcherDefinition( + config.load.loadType, + this.kubernetesBenchmark.loadTypes + ) - val executor = + executor = BenchmarkExecutorImpl( benchmark = kubernetesBenchmark, results = results, @@ -60,6 +66,14 @@ class TheodoliteExecutor( ) } + fun getExecution(): BenchmarkExecution { + return this.config + } + + fun getBenchmark(): KubernetesBenchmark { + return this.kubernetesBenchmark + } + fun run() { storeAsFile(this.config, "${this.config.executionId}-execution-configuration") storeAsFile(kubernetesBenchmark, "${this.config.executionId}-benchmark-configuration") @@ -67,7 +81,9 @@ class TheodoliteExecutor( val config = buildConfig() // execute benchmarks for each load for (load in config.loads) { - config.compositeStrategy.findSuitableResource(load, config.resources) + if (executor.run.get()) { + config.compositeStrategy.findSuitableResource(load, config.resources) + } } storeAsFile(config.compositeStrategy.benchmarkExecutor.results, "${this.config.executionId}-result") } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteYamlExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteYamlExecutor.kt index 8e856cac7286b6eb547b143e6cde8d1b7b56fb2b..f35e43a8f95d5fc20a9000af7b55d95881694804 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteYamlExecutor.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/TheodoliteYamlExecutor.kt @@ -1,18 +1,18 @@ package theodolite.execution -import io.quarkus.runtime.annotations.QuarkusMain import mu.KotlinLogging import theodolite.benchmark.BenchmarkExecution import theodolite.benchmark.KubernetesBenchmark import theodolite.util.YamlParser +import kotlin.concurrent.thread import kotlin.system.exitProcess private val logger = KotlinLogging.logger {} -@QuarkusMain(name = "TheodoliteYamlExecutor") -object TheodoliteYamlExecutor { - @JvmStatic - fun main(args: Array<String>) { +class TheodoliteYamlExecutor { + private val parser = YamlParser() + + fun start() { logger.info { "Theodolite started" } val executionPath = System.getenv("THEODOLITE_EXECUTION") ?: "./config/BenchmarkExecution.yaml" @@ -25,7 +25,6 @@ object TheodoliteYamlExecutor { // load the BenchmarkExecution and the BenchmarkType - val parser = YamlParser() val benchmarkExecution = parser.parse(path = executionPath, E = BenchmarkExecution::class.java)!! val benchmark = @@ -33,12 +32,12 @@ object TheodoliteYamlExecutor { benchmark.path = appResource val shutdown = Shutdown(benchmarkExecution, benchmark) - Runtime.getRuntime().addShutdownHook(shutdown) + Runtime.getRuntime().addShutdownHook(thread { shutdown.run()}) val executor = TheodoliteExecutor(benchmarkExecution, benchmark) executor.run() logger.info { "Theodolite finished" } - Runtime.getRuntime().removeShutdownHook(shutdown) + Runtime.getRuntime().removeShutdownHook(thread { shutdown.run()}) exitProcess(0) } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/BenchmarkEventHandler.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/BenchmarkEventHandler.kt new file mode 100644 index 0000000000000000000000000000000000000000..2b4a784315c2961c5782264c44f2c7e4e8f0d2e8 --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/BenchmarkEventHandler.kt @@ -0,0 +1,35 @@ +package theodolite.execution.operator + +import io.fabric8.kubernetes.client.informers.ResourceEventHandler +import mu.KotlinLogging +import theodolite.benchmark.KubernetesBenchmark +private val logger = KotlinLogging.logger {} + +class BenchmarkEventHandler(private val controller: TheodoliteController): ResourceEventHandler<KubernetesBenchmark> { + override fun onAdd(benchmark: KubernetesBenchmark) { + benchmark.name = benchmark.metadata.name + logger.info { "Add new benchmark ${benchmark.name}." } + this.controller.benchmarks[benchmark.name] = benchmark + } + + override fun onUpdate(oldBenchmark: KubernetesBenchmark, newBenchmark: KubernetesBenchmark) { + logger.info { "Update benchmark ${newBenchmark.metadata.name}." } + newBenchmark.name = newBenchmark.metadata.name + if (this.controller.isInitialized() && this.controller.executor.getBenchmark().name == oldBenchmark.metadata.name) { + this.controller.isUpdated.set(true) + this.controller.executor.executor.run.compareAndSet(true, false) + } else { + onAdd(newBenchmark) + } + } + + override fun onDelete(benchmark: KubernetesBenchmark, b: Boolean) { + logger.info { "Delete benchmark ${benchmark.metadata.name}." } + this.controller.benchmarks.remove(benchmark.metadata.name) + if ( this.controller.isInitialized() && this.controller.executor.getBenchmark().name == benchmark.metadata.name) { + this.controller.isUpdated.set(true) + this.controller.executor.executor.run.compareAndSet(true, false) + logger.info { "Current benchmark stopped." } + } + } +} diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt new file mode 100644 index 0000000000000000000000000000000000000000..1752ac112ea84ea179e238f7ab8d808779014d1b --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt @@ -0,0 +1,36 @@ +package theodolite.execution.operator + +import io.fabric8.kubernetes.client.informers.ResourceEventHandler +import mu.KotlinLogging +import theodolite.benchmark.BenchmarkExecution + +private val logger = KotlinLogging.logger {} + +class ExecutionHandler(private val controller: TheodoliteController): ResourceEventHandler<BenchmarkExecution> { + override fun onAdd(execution: BenchmarkExecution) { + execution.name = execution.metadata.name + logger.info { "Add new execution ${execution.metadata.name} to queue." } + this.controller.executionsQueue.add(execution) + } + + override fun onUpdate(oldExecution: BenchmarkExecution, newExecution: BenchmarkExecution) { + logger.info { "Add updated execution to queue." } + newExecution.name = newExecution.metadata.name + this.controller.executionsQueue.removeIf { e -> e.name == newExecution.metadata.name } + this.controller.executionsQueue.addFirst(newExecution) + if (this.controller.isInitialized() && this.controller.executor.getExecution().name == newExecution.metadata.name) { + this.controller.isUpdated.set(true) + this.controller.executor.executor.run.compareAndSet(true, false) + } + } + + override fun onDelete(execution: BenchmarkExecution, b: Boolean) { + logger.info { "Delete execution ${execution.metadata.name} from queue." } + this.controller.executionsQueue.removeIf { e -> e.name == execution.metadata.name } + if (this.controller.isInitialized() && this.controller.executor.getExecution().name == execution.metadata.name) { + this.controller.isUpdated.set(true) + this.controller.executor.executor.run.compareAndSet(true, false) + logger.info { "Current benchmark stopped." } + } + } +} diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/K8sContextFactory.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/K8sContextFactory.kt new file mode 100644 index 0000000000000000000000000000000000000000..94adf61a435df743aea168c5451b2f3faa24ca17 --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/K8sContextFactory.kt @@ -0,0 +1,15 @@ +package theodolite.execution.operator + +import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext + +class K8sContextFactory { + + fun create(api: String, scope: String, group: String, plural: String ) : CustomResourceDefinitionContext{ + return CustomResourceDefinitionContext.Builder() + .withVersion(api) + .withScope(scope) + .withGroup(group) + .withPlural(plural) + .build() + } +} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt new file mode 100644 index 0000000000000000000000000000000000000000..c966739a4744f448f60223738d379753b098c060 --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt @@ -0,0 +1,77 @@ +package theodolite.execution.operator + +import io.fabric8.kubernetes.client.NamespacedKubernetesClient +import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext +import mu.KotlinLogging +import theodolite.benchmark.BenchmarkExecution +import theodolite.benchmark.KubernetesBenchmark +import theodolite.execution.TheodoliteExecutor +import java.lang.Thread.sleep +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ConcurrentLinkedDeque +import java.util.concurrent.atomic.AtomicBoolean + +private val logger = KotlinLogging.logger {} + +class TheodoliteController( + val client: NamespacedKubernetesClient, + val executionContext: CustomResourceDefinitionContext +) { + lateinit var executor: TheodoliteExecutor + val executionsQueue: ConcurrentLinkedDeque<BenchmarkExecution> = ConcurrentLinkedDeque() + val benchmarks: ConcurrentHashMap<String, KubernetesBenchmark> = ConcurrentHashMap() + var isUpdated = AtomicBoolean(false) + + fun run() { + while (true) { + try { + reconcile() + logger.info { "Theodolite is waiting for new matching benchmark and execution." } + logger.info { "Currently available executions: " } + executionsQueue.forEach { + logger.info { "${it.name} : waiting for : ${it.benchmark}" } + } + logger.info { "Currently available benchmarks: " } + benchmarks.forEach { + logger.info { it.key } + } + sleep(2000) + } catch (e: InterruptedException) { + logger.error { "Execution interrupted with error: $e." } + } + } + } + + @Synchronized + private fun reconcile() { + while (executionsQueue.isNotEmpty()) { + val execution = executionsQueue.peek() + val benchmark = benchmarks[execution.benchmark] + + if (benchmark == null) { + logger.debug { "No benchmark found for execution ${execution.name}." } + sleep(1000) + } else { + runExecution(execution, benchmark) + } + } + } + + @Synchronized + fun runExecution(execution: BenchmarkExecution, benchmark: KubernetesBenchmark) { + isUpdated.set(false) + logger.info { "Start execution ${execution.name} with benchmark ${benchmark.name}." } + executor = TheodoliteExecutor(config = execution, kubernetesBenchmark = benchmark) + executor.run() + + if (!isUpdated.get()) { + client.customResource(executionContext).delete(client.namespace, execution.metadata.name) + } + logger.info { "Execution of ${execution.name} is finally stopped." } + } + + @Synchronized + fun isInitialized(): Boolean { + return ::executor.isInitialized + } +} diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt new file mode 100644 index 0000000000000000000000000000000000000000..33b71c8fa247511c371b7a154071634db7092660 --- /dev/null +++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt @@ -0,0 +1,64 @@ +package theodolite.execution.operator + +import io.fabric8.kubernetes.client.DefaultKubernetesClient +import io.fabric8.kubernetes.internal.KubernetesDeserializer +import mu.KotlinLogging +import theodolite.benchmark.BenchmarkExecution +import theodolite.benchmark.BenchmarkExecutionList +import theodolite.benchmark.KubernetesBenchmark +import theodolite.benchmark.KubernetesBenchmarkList + + +private const val DEFAULT_NAMESPACE = "default" +private const val SCOPE = "Namespaced" +private const val EXECUTION_SINGULAR = "execution" +private const val EXECUTION_PLURAL = "executions" +private const val BENCHMARK_SINGULAR = "benchmark" +private const val BENCHMARK_PLURAL = "benchmarks" +private const val API_VERSION = "v1alpha1" +private const val RESYNC_PERIOD = 10 * 60 * 1000.toLong() +private const val GROUP = "theodolite.com" +private val logger = KotlinLogging.logger {} + +class TheodoliteOperator { + private val namespace = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE + + fun start() { + logger.info { "Using $namespace as namespace." } + val client = DefaultKubernetesClient().inNamespace(namespace) + + KubernetesDeserializer.registerCustomKind( + "$GROUP/$API_VERSION", + EXECUTION_SINGULAR, + BenchmarkExecution::class.java + ) + + KubernetesDeserializer.registerCustomKind( + "$GROUP/$API_VERSION", + BENCHMARK_SINGULAR, + KubernetesBenchmark::class.java + ) + + val contextFactory = K8sContextFactory() + val executionContext = contextFactory.create(API_VERSION, SCOPE, GROUP, EXECUTION_PLURAL) + val benchmarkContext = contextFactory.create(API_VERSION, SCOPE, GROUP, BENCHMARK_PLURAL) + + val controller = TheodoliteController(client = client, executionContext = executionContext) + + val informerFactory = client.informers() + val informerExecution = informerFactory.sharedIndexInformerForCustomResource( + executionContext, BenchmarkExecution::class.java, + BenchmarkExecutionList::class.java, RESYNC_PERIOD + ) + val informerBenchmark = informerFactory.sharedIndexInformerForCustomResource( + benchmarkContext, KubernetesBenchmark::class.java, + KubernetesBenchmarkList::class.java, RESYNC_PERIOD + ) + + informerExecution.addEventHandler(ExecutionHandler(controller)) + informerBenchmark.addEventHandler(BenchmarkEventHandler(controller)) + informerFactory.startAllRegisteredInformers() + + controller.run() + } +} diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/TopicManager.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/TopicManager.kt index 1336f57517ef74d8c781cc3b51bf130dbf8d99c5..390974cd247645197ebe6044bf785710164155aa 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/TopicManager.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/TopicManager.kt @@ -12,52 +12,35 @@ private val logger = KotlinLogging.logger {} * Manages the topics related tasks * @param kafkaConfig Kafka Configuration as HashMap */ -class TopicManager(kafkaConfig: HashMap<String, Any>) { - private lateinit var kafkaAdmin: AdminClient - - init { - try { - kafkaAdmin = AdminClient.create(kafkaConfig) - } catch (e: Exception) { - logger.error { e.toString() } - } - } +class TopicManager(private val kafkaConfig: HashMap<String, Any>) { /** * Creates topics. * @param newTopics List of all Topic which should be created */ fun createTopics(newTopics: Collection<NewTopic>) { + var kafkaAdmin: AdminClient = AdminClient.create(this.kafkaConfig) kafkaAdmin.createTopics(newTopics) + kafkaAdmin.close() logger.info { "Topics created" } } - fun createTopics(topics: List<String>, numPartitions: Int, replicationFactor: Short) { - val newTopics = mutableSetOf<NewTopic>() - for (i in topics) { - val tops = NewTopic(i, numPartitions, replicationFactor) - newTopics.add(tops) - } - kafkaAdmin.createTopics(newTopics) - logger.info { "Creation of $topics started" } - } /** * Removes topics. * @param topics */ fun removeTopics(topics: List<String>) { + var kafkaAdmin: AdminClient = AdminClient.create(this.kafkaConfig) val result = kafkaAdmin.deleteTopics(topics) try { result.all().get() - } catch (ex: Exception) { - logger.error { ex.toString() } + } catch (e: Exception) { + logger.error { "Error while removing topics: $e" } + logger.debug { "Existing topics are: ${kafkaAdmin.listTopics()}." } } + kafkaAdmin.close() logger.info { "Topics removed" } } - - fun getTopics(): ListTopicsResult? { - return kafkaAdmin.listTopics() - } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ReplicaPatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ReplicaPatcher.kt index ca34e9e3511f0ee35eff8f2ccf0cbd0582fc8646..b4b33fabc5a27e3cc52f5cda889f63bc61adbf5f 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ReplicaPatcher.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/ReplicaPatcher.kt @@ -4,10 +4,10 @@ import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.api.model.apps.Deployment class ReplicaPatcher(private val k8sResource: KubernetesResource) : AbstractPatcher(k8sResource) { - override fun <Int> patch(value: Int) { + override fun <String> patch(value: String) { if (k8sResource is Deployment) { - if (value is kotlin.Int) { - this.k8sResource.spec.replicas = value + if (value is kotlin.String) { + this.k8sResource.spec.replicas = Integer.parseInt(value) } } } diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/SchedulerNamePatcher.kt b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/SchedulerNamePatcher.kt index 88d9a978f23c8c5612d2ad46df795b7e3ba8cd19..6d6505192daac3331e5c99b9706ca7413e98ea7d 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/patcher/SchedulerNamePatcher.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/patcher/SchedulerNamePatcher.kt @@ -3,10 +3,10 @@ package theodolite.patcher import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.api.model.apps.Deployment -class SchedulerNamePatcher(private val k8sResource: KubernetesResource): Patcher { +class SchedulerNamePatcher(private val k8sResource: KubernetesResource) : Patcher { override fun <String> patch(value: String) { if (k8sResource is Deployment) { - k8sResource.spec.template.spec.schedulerName = value as kotlin.String; + k8sResource.spec.template.spec.schedulerName = value as kotlin.String } } } \ No newline at end of file diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/ConfigurationOverride.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/ConfigurationOverride.kt index bf517595ac7a28d2dada3f4f1d5f75b6db1dae0e..c4801dfbab0beb01cab025200cceab17efb0053d 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/util/ConfigurationOverride.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/ConfigurationOverride.kt @@ -1,7 +1,9 @@ package theodolite.util +import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.quarkus.runtime.annotations.RegisterForReflection +@JsonDeserialize @RegisterForReflection class ConfigurationOverride { lateinit var patcher: PatcherDefinition diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/KafkaConfig.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/KafkaConfig.kt index 46960ccdb1aedad1c104f6f5ec2082077f55e4de..cb94c8b7bfac4c3bc043e04a67d673ccaddea3c5 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/util/KafkaConfig.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/KafkaConfig.kt @@ -1,10 +1,12 @@ package theodolite.util +import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.quarkus.runtime.annotations.RegisterForReflection import org.apache.kafka.clients.admin.NewTopic import kotlin.properties.Delegates @RegisterForReflection +@JsonDeserialize class KafkaConfig { lateinit var bootstrapServer: String lateinit var topics: List<TopicWrapper> diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/PatcherDefinition.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/PatcherDefinition.kt index 9ebe82a66382d238f314e1c6853265eca6690abd..e78048cd7691f8bfd14f663d401384ae6c329d4b 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/util/PatcherDefinition.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/PatcherDefinition.kt @@ -1,7 +1,9 @@ package theodolite.util +import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.quarkus.runtime.annotations.RegisterForReflection +@JsonDeserialize @RegisterForReflection class PatcherDefinition { lateinit var type: String diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/util/TypeName.kt b/theodolite-quarkus/src/main/kotlin/theodolite/util/TypeName.kt index 2a83eef700edd1f1017dcb5d9fdbffbc20d6dafd..20758466c5d5efbcb999bf0bf9c4edbe63ea1032 100644 --- a/theodolite-quarkus/src/main/kotlin/theodolite/util/TypeName.kt +++ b/theodolite-quarkus/src/main/kotlin/theodolite/util/TypeName.kt @@ -1,8 +1,10 @@ package theodolite.util +import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.quarkus.runtime.annotations.RegisterForReflection @RegisterForReflection +@JsonDeserialize class TypeName { lateinit var typeName: String lateinit var patchers: List<PatcherDefinition> diff --git a/theodolite-quarkus/src/main/resources/application.properties b/theodolite-quarkus/src/main/resources/application.properties index 318ce68ff1ae344f44288bfaacfbc43538211f50..d5ff26fd074ec74c02a25bc4dd0dd3734433401b 100644 --- a/theodolite-quarkus/src/main/resources/application.properties +++ b/theodolite-quarkus/src/main/resources/application.properties @@ -1,4 +1,3 @@ -quarkus.package.main-class=TheodoliteYamlExecutor quarkus.native.additional-build-args=\ --initialize-at-run-time=io.fabric8.kubernetes.client.internal.CertUtils,\ --report-unsupported-elements-at-runtime \ No newline at end of file diff --git a/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml b/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8fb3de1928f051d338a78ee58da074a73ef933c1 --- /dev/null +++ b/theodolite-quarkus/src/main/resources/operator/benchmarkCRD.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: benchmarks.theodolite.com +spec: + group: theodolite.com + version: v1alpha1 + names: + kind: benchmark + plural: benchmarks + scope: Namespaced + subresources: + status: {} \ No newline at end of file diff --git a/theodolite-quarkus/src/main/resources/operator/example-benchmark-k8s-resource.yaml b/theodolite-quarkus/src/main/resources/operator/example-benchmark-k8s-resource.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9fc16f92e303f05a449f7e8b83600c3b299f215d --- /dev/null +++ b/theodolite-quarkus/src/main/resources/operator/example-benchmark-k8s-resource.yaml @@ -0,0 +1,29 @@ +apiVersion: theodolite.com/v1alpha1 +kind: benchmark +metadata: + name: uc1-kstreams +appResource: + - "uc1-kstreams-deployment.yaml" + - "aggregation-service.yaml" + - "jmx-configmap.yaml" +loadGenResource: + - "uc1-load-generator-deployment.yaml" + - "uc1-load-generator-service.yaml" +resourceTypes: + - typeName: "Instances" + patchers: + - 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" +kafkaConfig: + bootstrapServer: "localhost:31290" + topics: + - name: "input" + numPartitions: 40 + replicationFactor: 1 \ No newline at end of file diff --git a/theodolite-quarkus/src/main/resources/operator/example-execution-k8s-resource.yaml b/theodolite-quarkus/src/main/resources/operator/example-execution-k8s-resource.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ef625dfe6ec78c2cc0ed099dfee0f767d57263bb --- /dev/null +++ b/theodolite-quarkus/src/main/resources/operator/example-execution-k8s-resource.yaml @@ -0,0 +1,37 @@ +apiVersion: theodolite.com/v1alpha1 +kind: execution +metadata: + name: theodolite-example-execution +benchmark: "uc1-kstreams" +load: + loadType: "NumSensors" + loadValues: + - 50000 +resources: + resourceType: "Instances" + resourceValues: + - 1 +slos: + - sloType: "lag trend" + threshold: 1000 + prometheusUrl: "http://localhost:32656" + externalSloUrl: "http://localhost:80/evaluate-slope" + offset: 0 + warmup: 0 +execution: + strategy: "LinearSearch" + duration: 60 + repetitions: 1 + 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" \ No newline at end of file diff --git a/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml b/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0bdb83c6201112a750bad41b81321b7a108a66fa --- /dev/null +++ b/theodolite-quarkus/src/main/resources/operator/executionCRD.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: executions.theodolite.com +spec: + group: theodolite.com + version: v1alpha1 + names: + kind: execution + plural: executions + scope: Namespaced + subresources: + status: {} \ No newline at end of file