Skip to content

Commit

Permalink
Merge pull request #30 from open-traffic-generator/dev-resource-limit
Browse files Browse the repository at this point in the history
Minimum resource request for all components
  • Loading branch information
ashutshkumr authored Sep 5, 2023
2 parents b279cd5 + e1115ee commit 7c4f10f
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 2 deletions.
56 changes: 56 additions & 0 deletions controllers/ixiatg_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (

corev1 "k8s.io/api/core/v1"
errapi "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -112,6 +113,13 @@ const (
LIVENESS_DELAY int32 = 1
LIVENESS_PERIOD int32 = 10
LIVENESS_FAILURE int32 = 6

MIN_MEM_CONTROLLER string = "30Mi"
MIN_MEM_GNMI string = "20Mi"
MIN_CPU_PROTOCOL string = "200m"
MIN_CPU_TRAFFIC string = "200m"
MIN_CPU_CONTROLLER string = "10m"
MIN_CPU_GNMI string = "10m"
)

var (
Expand All @@ -138,6 +146,7 @@ type componentRel struct {
LiveNessDelay int32 `json:"liveness-initial-delay,omitempty"`
LiveNessPeriod int32 `json:"liveness-period,omitempty"`
LiveNessFailure int32 `json:"liveness-failure,omitempty"`
MinResource map[string]string `json:"min-resource"`
Name string `json:"name"`
Path string `json:"path"`
Port int32
Expand Down Expand Up @@ -1159,17 +1168,38 @@ func (r *IxiaTGReconciler) containersForController(ixia *networkv1beta1.IxiaTG,
}
newGNMI = false
err = nil
resRequest := corev1.ResourceList{}
if r, ok := comp.MinResource["cpu"]; ok {
resRequest["cpu"] = resource.MustParse(r)
}
if r, ok := comp.MinResource["memory"]; ok {
resRequest["memory"] = resource.MustParse(r)
}
if name == GNMI_NAME {
tcpSock := corev1.TCPSocketAction{Port: intstr.IntOrString{IntVal: CTRL_GNMI_PORT}}
pbHdlr = corev1.ProbeHandler{TCPSocket: &tcpSock}
newGNMI, err = versionLaterOrEqual(GNMI_NEW_BASE_VERSION, comp.Tag)
if err != nil {
log.Error(err)
}
if _, ok := resRequest["cpu"]; !ok {
resRequest["cpu"] = resource.MustParse(MIN_CPU_GNMI)
}
if _, ok := resRequest["memory"]; !ok {
resRequest["memory"] = resource.MustParse(MIN_MEM_GNMI)
}
} else if name == CONTROLLER_NAME {
tcpSock := corev1.TCPSocketAction{Port: intstr.IntOrString{IntVal: CTRL_GRPC_PORT}}
pbHdlr = corev1.ProbeHandler{TCPSocket: &tcpSock}
if _, ok := resRequest["cpu"]; !ok {
resRequest["cpu"] = resource.MustParse(MIN_CPU_CONTROLLER)
}
if _, ok := resRequest["memory"]; !ok {
resRequest["memory"] = resource.MustParse(MIN_MEM_CONTROLLER)
}
}
container.Resources.Requests = resRequest

if comp.LiveNessEnable == nil || *comp.LiveNessEnable {
probe := corev1.Probe{
ProbeHandler: pbHdlr,
Expand Down Expand Up @@ -1226,13 +1256,39 @@ func (r *IxiaTGReconciler) containersForIxia(podName string, intfList []string,
for k, v := range comp.DefEnv {
compCopy.DefEnv[k] = v
}
resRequest := corev1.ResourceList{}
if r, ok := comp.MinResource["cpu"]; ok {
resRequest["cpu"] = resource.MustParse(r)
}
if r, ok := comp.MinResource["memory"]; ok {
resRequest["memory"] = resource.MustParse(r)
}
if cName == IMAGE_PROTOCOL_ENG {
compCopy.DefEnv["INTF_LIST"] = strings.Join(intfList, ",")
tcpSock = corev1.TCPSocketAction{Port: intstr.IntOrString{IntVal: PROTOCOL_ENG_PORT}}
if _, ok := resRequest["cpu"]; !ok {
resRequest["cpu"] = resource.MustParse(MIN_CPU_PROTOCOL)
}
if _, ok := resRequest["memory"]; !ok {
min_mem := 350
if len(intfList) > 1 {
min_mem = 380 + (15 * len(intfList))
}
resRequest["memory"] = resource.MustParse(fmt.Sprintf("%vMi", min_mem))
}
} else {
compCopy.DefEnv["ARG_IFACE_LIST"] = argIntfList
tcpSock = corev1.TCPSocketAction{Port: intstr.IntOrString{IntVal: TRAFFIC_ENG_PORT}}
if _, ok := resRequest["cpu"]; !ok {
resRequest["cpu"] = resource.MustParse(MIN_CPU_TRAFFIC)
}
if _, ok := resRequest["memory"]; !ok {
min_mem := 48 + (11 * len(intfList))
resRequest["memory"] = resource.MustParse(fmt.Sprintf("%vMi", min_mem))
}
}
container.Resources.Requests = resRequest

if compCopy.LiveNessEnable == nil || *compCopy.LiveNessEnable {
pbHdlr := corev1.ProbeHandler{TCPSocket: &tcpSock}
probe := corev1.Probe{
Expand Down
60 changes: 60 additions & 0 deletions operator-tests/py/default/test_min_resource_custom_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import pytest
import utils
import time


def test_min_resource_custom_config():
"""
Deploy b2b kne topology with default version,
- namespace - 1: ixia-c
Delete b2b kne topology,
- namespace - 1: ixia-c
Validate,
- default minimum resource for all components
"""
namespace1 = 'ixia-c'
namespace1_config = 'ixia_c_default_config.txt'
expected_pods = [
'otg-controller',
'otg-port-eth1',
'otg-port-eth2'
]
container_extensions = [
'-protocol-engine',
'-traffic-engine'
]
try:
custom_resource_params = {'protocol-engine':{'cpu': '300m','memory': '50Mi'}, 'traffic-engine':{'cpu': '50m', 'memory': '170Mi'}, 'controller':{'cpu': '50m', 'memory': '190Mi'}, 'gnmi-server':{'cpu': '70m', 'memory': '90Mi'}}
op_rscount = utils.get_operator_restart_count()
print("[Namespace:{}]Deploying KNE topology".format(
namespace1
))
utils.load_min_resource_configmap(custom_resource_params)
utils.create_kne_config(namespace1_config, namespace1)
utils.ixia_c_pods_ok(namespace1, expected_pods)
utils.check_min_resource_data('ixia-c', expected_pods[0], namespace1, '190Mi', '50m')
utils.check_min_resource_data('gnmi', expected_pods[0], namespace1, '90Mi', '70m')
utils.check_min_resource_data(expected_pods[1]+container_extensions[0], expected_pods[1], namespace1, '50Mi', '300m')
utils.check_min_resource_data(expected_pods[1]+container_extensions[1], expected_pods[1], namespace1, '170Mi', '50m')
utils.check_min_resource_data(expected_pods[2]+container_extensions[0], expected_pods[2], namespace1, '50Mi', '300m')
utils.check_min_resource_data(expected_pods[2]+container_extensions[1], expected_pods[2], namespace1, '170Mi', '50m')
op_rscount = utils.ixia_c_operator_ok(op_rscount)

print("[Namespace:{}]Deleting KNE topology".format(
namespace1
))
utils.delete_kne_config(namespace1_config, namespace1)
utils.ixia_c_pods_ok(namespace1, [])
op_rscount = utils.ixia_c_operator_ok(op_rscount)

finally:
utils.delete_kne_config(namespace1_config, namespace1)
utils.ixia_c_pods_ok(namespace1, [])
utils.reset_configmap()

utils.wait_for(
lambda: utils.topology_deleted(namespace1),
'topology deleted',
timeout_seconds=30
)
time.sleep(5)
57 changes: 57 additions & 0 deletions operator-tests/py/default/test_min_resource_default_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import pytest
import utils
import time


def test_min_resource_default_config():
"""
Deploy b2b kne topology with default version,
- namespace - 1: ixia-c
Delete b2b kne topology,
- namespace - 1: ixia-c
Validate,
- default minimum resource for all components
"""
namespace1 = 'ixia-c'
namespace1_config = 'ixia_c_default_config.txt'
expected_pods = [
'otg-controller',
'otg-port-eth1',
'otg-port-eth2'
]
container_extensions = [
'-protocol-engine',
'-traffic-engine'
]
try:
op_rscount = utils.get_operator_restart_count()
print("[Namespace:{}]Deploying KNE topology".format(
namespace1
))
utils.create_kne_config(namespace1_config, namespace1)
utils.ixia_c_pods_ok(namespace1, expected_pods)
utils.check_min_resource_data('ixia-c', expected_pods[0], namespace1, '30Mi', '10m')
utils.check_min_resource_data('gnmi', expected_pods[0], namespace1, '20Mi', '10m')
utils.check_min_resource_data(expected_pods[1]+container_extensions[0], expected_pods[1], namespace1, '350Mi', '200m')
utils.check_min_resource_data(expected_pods[1]+container_extensions[1], expected_pods[1], namespace1, '59Mi', '200m')
utils.check_min_resource_data(expected_pods[2]+container_extensions[0], expected_pods[2], namespace1, '350Mi', '200m')
utils.check_min_resource_data(expected_pods[2]+container_extensions[1], expected_pods[2], namespace1, '59Mi', '200m')
op_rscount = utils.ixia_c_operator_ok(op_rscount)

print("[Namespace:{}]Deleting KNE topology".format(
namespace1
))
utils.delete_kne_config(namespace1_config, namespace1)
utils.ixia_c_pods_ok(namespace1, [])
op_rscount = utils.ixia_c_operator_ok(op_rscount)

finally:
utils.delete_kne_config(namespace1_config, namespace1)
utils.ixia_c_pods_ok(namespace1, [])

utils.wait_for(
lambda: utils.topology_deleted(namespace1),
'topology deleted',
timeout_seconds=30
)
time.sleep(5)
57 changes: 57 additions & 0 deletions operator-tests/py/lag/test_lag_min_resource.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import pytest
import utils
import time


def test_lag_min_resource():
"""
Deploy lag kne topology,
- namespace - 1: ixia-c
Delete lag kne topology,
- namespace - 1: ixia-c
Validate,
- default minimum resource for all components
"""
namespace1 = 'ixia-c'
namespace1_config = 'lag_ixia_c_namespace.txt'
expected_pods = [
'otg-controller',
'arista1',
'otg-port-eth1',
'otg-port-eth2',
'otg-port-group-lag'
]
container_extensions = [
'-protocol-engine',
'-traffic-engine'
]
try:
op_rscount = utils.get_operator_restart_count()
print("[Namespace:{}]Deploying KNE topology".format(
namespace1
))
utils.create_kne_config(namespace1_config, namespace1)
utils.ixia_c_pods_ok(namespace1, expected_pods)
utils.check_min_resource_data('ixia-c', expected_pods[0], namespace1, '30Mi', '10m')
utils.check_min_resource_data('gnmi', expected_pods[0], namespace1, '20Mi', '10m')
utils.check_min_resource_data(expected_pods[4]+container_extensions[0], expected_pods[4], namespace1, '410Mi', '200m')
utils.check_min_resource_data(expected_pods[4]+container_extensions[1], expected_pods[4], namespace1, '70Mi', '200m')
op_rscount = utils.ixia_c_operator_ok(op_rscount)

print("[Namespace:{}]Deleting KNE topology".format(
namespace1
))
utils.delete_kne_config(namespace1_config, namespace1)
utils.ixia_c_pods_ok(namespace1, [])
op_rscount = utils.ixia_c_operator_ok(op_rscount)

finally:
utils.delete_kne_config(namespace1_config, namespace1)
utils.ixia_c_pods_ok(namespace1, [])

utils.wait_for(
lambda: utils.topology_deleted(namespace1),
'topology deleted',
timeout_seconds=30
)
time.sleep(5)
37 changes: 37 additions & 0 deletions operator-tests/py/utils/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,28 @@ def load_liveness_configmap(probe):
os.remove(custom_configmap_path)


def load_min_resource_configmap(resource):
print("Loading custom min resource config...")
cmd = "cat ./{}".format(
IXIA_CONFIGMAP_FILE
)
out, _ = exec_shell(cmd, False, True)
yaml_obj = yaml.safe_load(out)
json_obj = json.loads(yaml_obj["data"]["versions"])
for elem in json_obj["images"]:
if elem["name"] in resource.keys():
elem["min-resource"] = dict()
for key in resource[elem["name"]]:
elem["min-resource"][key] = resource[elem["name"]][key]
yaml_obj["data"]["versions"] = json.dumps(json_obj)
custom_configmap_path = "{}".format(CUSTOM_CONFIGMAP_FILE)
with open(custom_configmap_path, "w") as yaml_file:
yaml.dump(yaml_obj, yaml_file)

apply_configmap(custom_configmap_path)
os.remove(custom_configmap_path)


def seconds_elapsed(start_seconds):
return int(round(time.time() - start_seconds))

Expand Down Expand Up @@ -559,6 +581,21 @@ def check_liveness_data(cont, pod, namespace, enabled=True, delay=0, period=0, f
assert key in res.keys() and failure == res[key], "FailureThreshold mismatch, expected {}, found {}".format(failure, res[key])


def check_min_resource_data(cont, pod, namespace, memory="", cpu=""):
base_cmd = "'jsonpath={.spec.containers[?(@.name==\"" + cont + "\")].resources.requests"
base_cmd = "kubectl get pod/{} -n {} -o ".format(pod, namespace) + base_cmd
cmd = base_cmd + "}'"
out, _ = exec_shell(cmd, True, True)
print(out)
res = json.loads(out)
if memory != "":
key = 'memory'
assert key in res.keys() and memory == res[key], "Memory resource mismatch, expected {}, found {}".format(memory, res[key])
if cpu != "":
key = 'cpu'
assert key in res.keys() and cpu == res[key], "Cpu resource mismatch, expected {}, found {}".format(cpu, res[key])


def generate_rest_config_from_temaplate(config, ixia_c_release):
template_config_path = get_kne_config_path(
'template_' + config
Expand Down
3 changes: 1 addition & 2 deletions version
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
0.3.4

0.3.5

0 comments on commit 7c4f10f

Please sign in to comment.