Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add pop sizing #67

Merged
merged 22 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,13 @@ Upgrade `synctl` to a specified version.
pip3 install --upgrade synctl==<version>
```

# Size the PoP hardware configuration
synctl can be used to find the size of the PoP hardware configuration.
swethalohith2 marked this conversation as resolved.
Show resolved Hide resolved

### synctl pop-sizing Syntax
```
synctl --pop-sizing-estimate
swethalohith2 marked this conversation as resolved.
Show resolved Hide resolved
```
swethalohith2 marked this conversation as resolved.
Show resolved Hide resolved
# Configure an Instana Backend
`synctl` support three types of configurations:
- Use configurations file, the default config file is under `~/.synthetic/config.json`.
Expand Down
123 changes: 123 additions & 0 deletions synctl/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import tarfile
import getpass
import math
# import textwrap
import time
from datetime import datetime
Expand Down Expand Up @@ -331,6 +332,119 @@ def exit_synctl(self, error_code=-1, message=''):
print(message)
sys.exit(error_code)

class PopConfiguration(Base):
def __init__(self) -> None:
Base.__init__(self)
self.agent = {
"cpuLimit" : 1500,
"memLimit" : 768,
"imageSize" : 600,
}
self.k8ssensor = {
"cpuLimit" : 500,
"memLimit" : 1536,
"imageSize" : 80,
}
self.controller = {
"cpuLimit" : 300,
"memLimit" : 300,
"imageSize" : 900,
}
self.redis = {
"cpuLimit" : 300,
"memLimit" : 200,
"imageSize" : 500,
}
self.http = {
"testCount" : 2000,
"frequency": 1,
"cpuLimit" : 300,
"memLimit" : 500,
"imageSize" : 400,
}
self.javascript = {
"testCount" : 20,
"frequency": 1,
"cpuLimit" : 800,
"memLimit" : 300,
"imageSize" : 400,
}
self.browserscript = {
"testCount" : 5,
"frequency": 5,
"cpuLimit" : 4000,
"memLimit" : 3000,
"imageSize" : 1500,
swethalohith2 marked this conversation as resolved.
Show resolved Hide resolved
}

def ask_question(self,question, options=None):
answer = input(question)
if options:
while answer not in options:
print("Invalid input.")
answer = input(question)
return answer

def size_estimate(self, user_tests, default_frequency, user_frequency, default_tests):

pod_estimate = int(user_tests * default_frequency) / int(user_frequency * default_tests)
return math.ceil(pod_estimate)


def pop_size_estimate(self):
print("Please answer below questions for estimating the self-hosted PoP hardware size\n")
try:
api_simple = int(self.ask_question("How many API Simple tests do you want to create? (0 if no) "))
if api_simple != 0:
api_simple_frequency = int(self.ask_question("What is the test frequency for your API Simple tests ? (1-120) "))
swethalohith2 marked this conversation as resolved.
Show resolved Hide resolved
http_pod_count = int(self.size_estimate(api_simple, self.http["frequency"], api_simple_frequency, self.http["testCount"]))
else:
http_pod_count = 0

api_script = int(self.ask_question("How many API Script tests do you want to create? (0 if no) "))
swethalohith2 marked this conversation as resolved.
Show resolved Hide resolved
if api_script != 0:
api_script_frequency = int(self.ask_question("What is the test frequency for your API Script tests ? (1-120) "))
swethalohith2 marked this conversation as resolved.
Show resolved Hide resolved
javascript_pod_count = int(self.size_estimate(api_script, self.javascript["frequency"], api_script_frequency, self.javascript["testCount"]))
else:
javascript_pod_count = 0

browser_script = int(self.ask_question("How many Browser tests (Webpage Action, Webage Script and BrowserScript) do you want to create? (0 if no) "))
swethalohith2 marked this conversation as resolved.
Show resolved Hide resolved
if browser_script != 0:
browser_script_frequency = int(self.ask_question("What is the test frequency for Browser tests ? (1-120) "))
browserscript_pod_count = int(self.size_estimate(browser_script, self.browserscript["frequency"], browser_script_frequency, self.browserscript["testCount"]))
else:
browserscript_pod_count = 0

agent = self.ask_question("Do you want to install the Instana-agent to monitor your PoP? (Y/N) ", options=["Y", "N"])
if agent == "Y":
worker_nodes = int(self.ask_question("How many worker nodes in your kubernetes cluster? "))
else:
worker_nodes = 0

controller_pod_count = 1
redis_pod_count = 1
k8ssensor_pod_count = 3

cpu = self.controller["cpuLimit"] * controller_pod_count + self.redis["cpuLimit"] * redis_pod_count + http_pod_count * self.http["cpuLimit"] + \
javascript_pod_count * self.javascript["cpuLimit"] + browserscript_pod_count * self.browserscript["cpuLimit"] + \
worker_nodes * self.agent["cpuLimit"] + self.k8ssensor["cpuLimit"] * k8ssensor_pod_count

memory = http_pod_count * self.http["memLimit"] + javascript_pod_count * self.javascript["memLimit"] + \
browserscript_pod_count * self.browserscript["memLimit"] + worker_nodes * self.agent["memLimit"] + \
self.k8ssensor["memLimit"] * k8ssensor_pod_count + self.controller["memLimit"] * controller_pod_count + \
self.redis["memLimit"] * redis_pod_count

disk_size = http_pod_count * self.http["imageSize"] + javascript_pod_count * self.javascript["imageSize"] + \
browserscript_pod_count * self.browserscript["imageSize"] + controller_pod_count * self.controller["imageSize"] + \
redis_pod_count * self.redis["imageSize"] + worker_nodes * self.agent["imageSize"] + \
k8ssensor_pod_count * self.k8ssensor["imageSize"]

print(f"\nThe estimated sizing is: CPU {cpu}m, Memory: {memory} Mi, Disk: {disk_size} GB")
swethalohith2 marked this conversation as resolved.
Show resolved Hide resolved
print(f"\nThe recommended engine pods: {http_pod_count} http playback engines, {javascript_pod_count} javascript engines,"
f"{browserscript_pod_count} browserscript engines")
except ValueError:
print("Invalid input")


class ConfigurationFile(Base):
def __init__(self) -> None:
Expand Down Expand Up @@ -3911,6 +4025,9 @@ def global_options(self):
'--version', '-v', action="store_true", default=True, help="show version")
self.parser.add_argument(
"--verify-tls", action="store_true", default=False, help="verify tls certificate")
self.parser.add_argument(
"--pop-sizing-estimate", action="store_true", help="show estimate pop size"
)

def config_command_options(self):
self.parser_config.add_argument(
Expand Down Expand Up @@ -4301,6 +4418,7 @@ def main():
show_version()
sys.exit(NORMAL_CODE)

pop_estimate = PopConfiguration()
auth_instance = Authentication()

syn_instance = SyntheticTest()
Expand All @@ -4314,6 +4432,11 @@ def main():
summary_instance = SyntheticResult()
app_instance = Application()

# show pop size
if "--pop-sizing-estimate" in sys_args:
pop_estimate.pop_size_estimate()
sys.exit(NORMAL_CODE)

# set --verify-tls
if get_args.verify_tls is not None:
syn_instance.set_insecure(get_args.verify_tls)
Expand Down