This is an automated email from the ASF dual-hosted git repository.

wwei pushed a commit to branch soak-test
in repository https://gitbox.apache.org/repos/asf/yunikorn-release.git


The following commit(s) were added to refs/heads/soak-test by this push:
     new 3a04994  [YUNIKORN-3010] Environment setup scripts that installs Kind, 
Kwok, YuniKorn (#187)
3a04994 is described below

commit 3a0499434067c072dd71ad2f5497952a043d9f02
Author: junyan-ling <[email protected]>
AuthorDate: Wed Feb 12 20:47:24 2025 -0800

    [YUNIKORN-3010] Environment setup scripts that installs Kind, Kwok, 
YuniKorn (#187)
    
    This PR adds the init script for setting up the soak testing environment, 
that installs Kind, Kwok and YuniKorn.
    
    Co-authored-by: Junyan Ling <[email protected]>
---
 soak/pkg/constants/constants.go        |  23 +++++
 soak/pkg/setup/setup.go                | 174 +++++++++++++++++++++++++++++++++
 soak/scripts/README.md                 |  28 ++++++
 soak/scripts/initial_setup.sh          |  32 ++++++
 soak/templates/autoscaling-queues.yaml |  37 +++++++
 soak/templates/kwok-node-template.yaml |  58 +++++++++++
 6 files changed, 352 insertions(+)

diff --git a/soak/pkg/constants/constants.go b/soak/pkg/constants/constants.go
new file mode 100644
index 0000000..0ee39c2
--- /dev/null
+++ b/soak/pkg/constants/constants.go
@@ -0,0 +1,23 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package constants
+
+const (
+       KindSoakTestCluster = "kind-soak-test-cluster"
+)
diff --git a/soak/pkg/setup/setup.go b/soak/pkg/setup/setup.go
new file mode 100644
index 0000000..307d170
--- /dev/null
+++ b/soak/pkg/setup/setup.go
@@ -0,0 +1,174 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+     http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package setup
+
+import (
+       "fmt"
+       "github.com/apache/yunikorn-core/pkg/log"
+       "github.com/apache/yunikorn-release/soak/pkg/constants"
+       "github.com/apache/yunikorn-release/soak/pkg/framework"
+       "go.uber.org/zap"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "strings"
+)
+
+var logger *zap.Logger = log.Log(log.Test)
+
+func setK8sContext() error {
+       homeDir, err := os.UserHomeDir()
+       if err != nil {
+               return fmt.Errorf("failed to get home directory: %v", err)
+       }
+       kubeconfigPath := filepath.Join(homeDir, ".kube", "config")
+       os.Setenv("KUBECONFIG", kubeconfigPath)
+       logger.Info("Set KUBECONFIG", zap.String("path", kubeconfigPath))
+
+       contextCmd := exec.Command("kubectl", "config", "use-context", 
constants.KindSoakTestCluster)
+       contextOutput, err := contextCmd.CombinedOutput()
+       if err != nil {
+               return fmt.Errorf("failed to switch kubectl context: %v, 
output: %s", err, string(contextOutput))
+       }
+       logger.Info("Kubectl context switch output", zap.String("output", 
strings.TrimSpace(string(contextOutput))))
+
+       currentContextCmd := exec.Command("kubectl", "config", 
"current-context")
+       _, err = currentContextCmd.CombinedOutput()
+       if err != nil {
+               return fmt.Errorf("failed to get current context: %v", err)
+       }
+
+       return nil
+}
+
+func upgradeSchedulerPerConfig(scheduler framework.TemplateFields) error {
+       if err := setK8sContext(); err != nil {
+               logger.Fatal("failed to set kubernetes context", zap.Error(err))
+               return err
+       }
+
+       logger.Info("Scheduler details",
+               zap.String("VcoreRequests", *scheduler.VcoreRequests),
+               zap.String("MemoryRequests", *scheduler.MemoryRequests),
+               zap.String("VcoreLimits", *scheduler.VcoreLimits),
+               zap.String("MemoryLimits", *scheduler.MemoryLimits),
+               zap.String("path", *scheduler.Path))
+
+       args := []string{
+               "upgrade",
+               "yunikorn",
+               "yunikorn/yunikorn",
+               "-n", "yunikorn",
+       }
+
+       var moreArgs []string
+
+       if scheduler.VcoreRequests != nil {
+               moreArgs = append(moreArgs, "--set", 
fmt.Sprintf("resources.requests.cpu=%s", *scheduler.VcoreRequests))
+       }
+       if scheduler.MemoryRequests != nil {
+               moreArgs = append(moreArgs, "--set", 
fmt.Sprintf("resources.requests.memory=%s", *scheduler.MemoryRequests))
+       }
+       if scheduler.VcoreLimits != nil {
+               moreArgs = append(moreArgs, "--set", 
fmt.Sprintf("resources.limits.cpu=%s", *scheduler.VcoreLimits))
+       }
+       if scheduler.MemoryLimits != nil {
+               moreArgs = append(moreArgs, "--set", 
fmt.Sprintf("resources.limits.memory=%s", *scheduler.MemoryLimits))
+       }
+
+       if len(moreArgs) > 0 {
+               args = append(args, moreArgs...)
+
+               cmd := exec.Command("helm", args...)
+
+               logger.Info("Helm command to be executed",
+                       zap.String("command", fmt.Sprintf("helm %s", 
strings.Join(args, " "))))
+
+               output, err := cmd.CombinedOutput()
+               if err != nil {
+                       return fmt.Errorf("helm upgrade failed: %v", err)
+               }
+
+               logger.Info("Helm upgrade successful",
+                       zap.String("command", fmt.Sprintf("helm %s", 
strings.Join(args, " "))),
+                       zap.String("output", string(output)))
+       }
+
+       if scheduler.Path != nil {
+               kubectlArgs := []string{"apply"}
+               kubectlArgs = append(kubectlArgs, "-f", *scheduler.Path, "-n", 
"yunikorn")
+               kubectlCmd := exec.Command("kubectl", kubectlArgs...)
+               logger.Info("Kubectl command to be executed",
+                       zap.String("command", fmt.Sprintf("kubectl %s", 
strings.Join(kubectlArgs, " "))))
+
+               kubectlOutput, err := kubectlCmd.CombinedOutput()
+               if err != nil {
+                       return fmt.Errorf("kubectl apply failed: %v", err)
+               }
+               logger.Info("Kubectl apply successful", zap.String("output", 
strings.TrimSpace(string(kubectlOutput))))
+       }
+
+       return nil
+}
+
+func setNodeScalePerConfig(node framework.TemplateFields) error {
+       if err := setK8sContext(); err != nil {
+               logger.Fatal("failed to set kubernetes context", zap.Error(err))
+               return err
+       }
+
+       logger.Info("Node details",
+               zap.String("path", *node.Path),
+               zap.Int("NodesDesiredCount", *node.DesiredCount),
+               zap.Int("maxCount", *node.MaxCount))
+
+       templateContent, err := 
os.ReadFile("soak/templates/kwok-node-template.yaml")
+       if err != nil {
+               return fmt.Errorf("failed to read template file: %v", err)
+       }
+       desiredCount := *node.DesiredCount
+
+       for i := 0; i < desiredCount; i++ {
+               currentNodeName := fmt.Sprintf("kwok-node-%d", i)
+               nodeContent := strings.ReplaceAll(string(templateContent), 
"kwok-node-i", currentNodeName)
+
+               tmpfile, err := os.CreateTemp("", "node-*.yaml")
+               if err != nil {
+                       return fmt.Errorf("failed to create temp file: %v", err)
+               }
+               defer os.Remove(tmpfile.Name()) // Clean up
+
+               if _, err := tmpfile.WriteString(nodeContent); err != nil {
+                       return fmt.Errorf("failed to write to temp file: %v", 
err)
+               }
+               if err := tmpfile.Close(); err != nil {
+                       return fmt.Errorf("failed to close temp file: %v", err)
+               }
+
+               cmd := exec.Command("kubectl", "apply", "-f", tmpfile.Name())
+               output, err := cmd.CombinedOutput()
+               if err != nil {
+                       return fmt.Errorf("failed to apply node configuration: 
%v", err)
+               }
+
+               logger.Info("Applied node configuration",
+                       zap.String("nodeName", currentNodeName),
+                       zap.String("output", string(output)))
+       }
+
+       return nil
+}
diff --git a/soak/scripts/README.md b/soak/scripts/README.md
new file mode 100644
index 0000000..96f58f7
--- /dev/null
+++ b/soak/scripts/README.md
@@ -0,0 +1,28 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to you under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+### Prerequisites
+- [Helm](https://github.com/helm/helm#install)
+- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
+- [Docker](https://docs.docker.com/get-docker/)
+- [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation)
+- [Kwok](https://kwok.sigs.k8s.io/docs/user/installation/)
+
+# set up initial soak test environment
+```
+sh soak/setup/initial_setup.sh
+```
diff --git a/soak/scripts/initial_setup.sh b/soak/scripts/initial_setup.sh
new file mode 100644
index 0000000..4b4bc33
--- /dev/null
+++ b/soak/scripts/initial_setup.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# create a kind cluster
+kind create cluster --name soak-test-cluster
+
+# install YuniKorn scheduler on kind Cluster
+helm repo add yunikorn https://apache.github.io/yunikorn-release
+helm repo update
+kubectl create namespace yunikorn
+# TODO: allow to install a customized YuniKorn version to run the soak test
+helm install yunikorn yunikorn/yunikorn --namespace yunikorn
+
+## Deploy kwok in a Cluster
+helm repo add kwok https://kwok.sigs.k8s.io/charts/
+helm upgrade --namespace kube-system --install kwok kwok/kwok
+helm upgrade --install kwok kwok/stage-fast
diff --git a/soak/templates/autoscaling-queues.yaml 
b/soak/templates/autoscaling-queues.yaml
new file mode 100644
index 0000000..89bafdd
--- /dev/null
+++ b/soak/templates/autoscaling-queues.yaml
@@ -0,0 +1,37 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: yunikorn-defaults
+  namespace: yunikorn
+data:
+  queues.yaml: |-
+    partitions:
+      - name: default
+        queues:
+        - name: root
+          submitacl: '*'
+          queues:
+          - name: queue-a
+            submitacl: '*'
+            properties:
+              application.sort.policy: fair
+          - name: queue-b
+            submitacl: '*'
+            properties:
+              application.sort.policy: fifo
diff --git a/soak/templates/kwok-node-template.yaml 
b/soak/templates/kwok-node-template.yaml
new file mode 100644
index 0000000..5f1de38
--- /dev/null
+++ b/soak/templates/kwok-node-template.yaml
@@ -0,0 +1,58 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: v1
+kind: Node
+metadata:
+  annotations:
+    node.alpha.kubernetes.io/ttl: "0"
+    kwok.x-k8s.io/node: fake
+  labels:
+    beta.kubernetes.io/arch: amd64
+    beta.kubernetes.io/os: linux
+    kubernetes.io/arch: amd64
+    kubernetes.io/hostname: kwok-node-i
+    kubernetes.io/os: linux
+    kubernetes.io/role: agent
+    node-role.kubernetes.io/agent: ""
+    type: kwok
+  name: kwok-node-i
+spec:
+  taints: # Avoid scheduling actual running pods to fake Node
+    - effect: NoSchedule
+      key: kwok.x-k8s.io/node
+      value: fake
+status:
+  allocatable:
+    cpu: 32
+    memory: 256Gi
+    pods: 110
+  capacity:
+    cpu: 32
+    memory: 256Gi
+    pods: 110
+  nodeInfo:
+    architecture: amd64
+    bootID: ""
+    containerRuntimeVersion: ""
+    kernelVersion: ""
+    kubeProxyVersion: fake
+    kubeletVersion: fake
+    machineID: ""
+    operatingSystem: linux
+    osImage: ""
+    systemUUID: ""
+  phase: Running


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to