commit 8fb5af1285d081a96dbb3f87501fa903f5ad2970 Author: Patryk Gudalewicz Date: Thu Oct 27 13:06:35 2022 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d132723 --- /dev/null +++ b/.gitignore @@ -0,0 +1,143 @@ +dashboard_tiles_* +\[STAGING\]* +<<<<<<< HEAD +shared_configuration/ +archive/ +======= + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +### Terraform stuff +**/.terraform/* +crash.log +*.tfvars + +>>>>>>> 746e496e7a7c5e8134cda7921311f6a9ba22f8d3 diff --git a/createDash.py b/createDash.py new file mode 100644 index 0000000..8dae2b3 --- /dev/null +++ b/createDash.py @@ -0,0 +1,129 @@ +import yaml +from decouple import config +import json +import argparse +import requests +from datetime import datetime +from git import Repo +import os +DASHBOARD_NAME = " - Kubernetes cluster overview" +parser = argparse.ArgumentParser(description="Generate and deploy the Kubernetes Overview Dashboard as Code.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + +parser.add_argument("-C", "--cluster", type=str,required=True, help="Name of the Kubernetes cluster") +parser.add_argument('--remove', default=False, action='store_true', help="Remove dashboard for given cluster. If not specified dashboard will be created or updated") +parser.add_argument('-E', '--environment', type=str, help="Name of the environment (the same as in environment.yaml file. Used to upload dashboard to specific Dynatrace environment. If not specified all environments in file will be used") + +args = parser.parse_args() +def make_request(url, DTAPIToken,verify, method, jsondata): + headers = { + 'Content-Type': 'application/json', + 'Authorization': 'Api-Token ' + DTAPIToken + } + try: + if method == "get": + response = requests.get(url, headers=headers,verify=verify) + elif method == "post": + response = requests.post(url, headers=headers,verify=verify, data=jsondata) + elif method == "put": + response = requests.put(url, headers=headers,verify=verify, data=jsondata) + elif method == "delete": + response = requests.delete(url, headers=headers,verify=verify) + response.raise_for_status() + except requests.exceptions.HTTPError as errh: + return "An Http Error occurred:" + repr(errh) + except requests.exceptions.ConnectionError as errc: + return "An Error Connecting to the API occurred:" + repr(errc) + except requests.exceptions.Timeout as errt: + return "A Timeout Error occurred:" + repr(errt) + except requests.exceptions.RequestException as err: + return "An Unknown Error occurred" + repr(err) + + return response + +def get_all_dashboards_withname(DTAPIToken, DTENV,name): + DTAPIURL= DTENV + "api/config/v1/dashboards" + r = make_request(DTAPIURL,DTAPIToken,True,"get",None) + print(r) + entityResponse = r.json() + result = [] + if("dashboards" in entityResponse): + for dashboard in entityResponse["dashboards"]: + if(dashboard["name"]).startswith(name): + result.append(dashboard) + result = sorted(result, key=lambda x : x['name'], reverse=False) + return result + +def remove_dashboards(DTAPIToken, DTENV, dashboards): + for dashboard in dashboards: + print("Removing dashboard from Dynatrace: "+dashboard["name"]) + DTAPIURL = DTENV + "api/config/v1/dashboards/" + dashboard["id"] + print(make_request(DTAPIURL,DTAPIToken,True,"delete",None)) + +def create_or_update_dashboard(DTAPIToken, DTENV, dashboards, templatename, dashname): + with open('./'+templatename) as file: + data = file.read() + data = data.replace("", args.cluster) + tilesjson = json.loads(data) + if tilesjson: + if any(dashboard["name"] == dashname for dashboard in dashboards): + existingdashboard = next((dashboard for dashboard in dashboards if dashboard["name"] == dashname), None) + if existingdashboard: + print("Found dashboard, Name: "+ existingdashboard["name"]) + DTAPIURL = DTENV + "api/config/v1/dashboards/" + existingdashboard["id"] + r = make_request(DTAPIURL,DTAPIToken,True,"get",None) + entityResponse = r.json() + entityResponse["tiles"] = tilesjson + print("Updating dashboard: "+entityResponse["dashboardMetadata"]["name"]) + print(make_request(DTAPIURL,DTAPIToken,True,"put",json.dumps(entityResponse))) + else: + newdashboard = { + "dashboardMetadata":{ + "name": dashname, + "owner": config("DASHBOARD_OWNER"), + "tags": ["Kubernetes"], + "preset": 'true', + "shared":'true' + }, + "tiles":[] + } + DTAPIURL = DTENV + "api/config/v1/dashboards" + newdashboard["tiles"] = tilesjson + print("Creating dashboard: "+newdashboard["dashboardMetadata"]["name"]) + print(make_request(DTAPIURL,DTAPIToken,True,"post",json.dumps(newdashboard))) +def main(slo_path): + print("Generating dashboard...") + if args.cluster: + FULL_DASHBOARD_NAME = args.cluster + DASHBOARD_NAME + print("Getting existing dashboards from Dynatrace") + with open('./environment.yaml') as file: + doc = yaml.safe_load(file) + + for item, doc in doc.items(): + token = dict(doc[2]) + url = dict(doc[1]) + print("Crawling through: " + item) + print("Gather data, hold on a minute") + DTTOKEN = config(token.get('env-token-name')) + DTURL = url.get('env-url') + existingdashboards = get_all_dashboards_withname(DTTOKEN, DTURL,FULL_DASHBOARD_NAME) + if not args.environment: + if not args.remove: + print("Uploading dashboard to Dynatrace...") + create_or_update_dashboard(DTTOKEN, DTURL, existingdashboards, "kubernetes_tiles_template.json", FULL_DASHBOARD_NAME) + else: + remove_dashboards(DTTOKEN, DTURL, existingdashboards) + else: + if args.environment == item: + if not args.remove: + print("Uploading dashboard to Dynatrace ("+item+")...") + create_or_update_dashboard(DTTOKEN, DTURL, existingdashboards, "kubernetes_tiles_template.json", FULL_DASHBOARD_NAME) + break + else: + remove_dashboards(DTTOKEN, DTURL, existingdashboards) + else: + print("ERROR: No cluster specified") + + +if __name__ == "__main__": + main('./shared_configuration/slo_parameter.yaml') \ No newline at end of file diff --git a/environment.yaml b/environment.yaml new file mode 100644 index 0000000..07a4028 --- /dev/null +++ b/environment.yaml @@ -0,0 +1,4 @@ +eupreprod: + - name: "eupreprod" + - env-url: "https://qqk70169.live.dynatrace.com/" + - env-token-name: "EMEA_PREPROD_CONFIG_TOKEN" \ No newline at end of file diff --git a/kubernetes_tiles_template.json b/kubernetes_tiles_template.json new file mode 100644 index 0000000..0d62450 --- /dev/null +++ b/kubernetes_tiles_template.json @@ -0,0 +1,1793 @@ +[ + { + "name": "Markdown", + "tileType": "MARKDOWN", + "configured": true, + "bounds": { + "top": 0, + "left": 0, + "width": 684, + "height": 38 + }, + "tileFilter": {}, + "markdown": "## Cluster overview" + }, + { + "name": "", + "tileType": "HOSTS", + "configured": true, + "bounds": { + "top": 38, + "left": 342, + "width": 342, + "height": 304 + }, + "tileFilter": {}, + "filterConfig": { + "type": "HOST", + "customName": "Full-Stack Kubernetes nodes", + "defaultName": "Full-Stack Kubernetes nodes", + "chartConfig": { + "legendShown": true, + "type": "TIMESERIES", + "series": [], + "resultMetadata": {} + }, + "filtersPerEntityType": { + "HOST": { + "HOST_KUBERNETES_CLUSTER_ID": [ + "KUBERNETES_CLUSTER-1A31BABF3BCE56BB|" + ], + "HOST_SOFTWARE_TECH": [ + "KUBERNETES" + ] + } + } + }, + "chartVisible": true + }, + { + "name": "Markdown", + "tileType": "MARKDOWN", + "configured": true, + "bounds": { + "top": 684, + "left": 0, + "width": 1672, + "height": 38 + }, + "tileFilter": { + "timeframe": "-5m" + }, + "markdown": "## Node resources" + }, + { + "name": "Markdown", + "tileType": "MARKDOWN", + "configured": true, + "bounds": { + "top": 0, + "left": 722, + "width": 950, + "height": 38 + }, + "tileFilter": { + "timeframe": "-5m" + }, + "markdown": "## Pods overview" + }, + { + "name": "Markdown", + "tileType": "MARKDOWN", + "configured": true, + "bounds": { + "top": 342, + "left": 0, + "width": 1672, + "height": 38 + }, + "tileFilter": { + "timeframe": "-5m" + }, + "markdown": "## Cluster resources" + }, + { + "name": "Running pods", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 38, + "left": 722, + "width": 304, + "height": 304 + }, + "tileFilter": {}, + "customName": "Running pods", + "queries": [ + { + "id": "B", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.cloud_application_namespace", + "dt.entity.kubernetes_cluster" + ], + "metricSelector": "builtin:kubernetes.pods:last:filter(and(eq(\"pod_phase\",\"Running\"),in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\")))):splitBy(\"dt.entity.cloud_application_namespace\",\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))", + "enabled": true + } + ], + "visualConfig": { + "type": "TOP_LIST", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "B:", + "properties": { + "color": "DEFAULT" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "visible": true + }, + "yAxes": [] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "value": 0, + "color": "#5ead35" + }, + { + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&(builtin:kubernetes.pods:last:filter(and(eq(pod_phase,Running),in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\")))):splitBy(\"dt.entity.cloud_application_namespace\",\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))):limit(100):names:fold(auto)" + ] + }, + { + "name": "Pods by phase", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 38, + "left": 1026, + "width": 342, + "height": 304 + }, + "tileFilter": {}, + "customName": "Pods", + "queries": [ + { + "id": "C", + "timeAggregation": "DEFAULT", + "splitBy": [ + "pod_phase" + ], + "metricSelector": "builtin:kubernetes.node.pods:last:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):splitBy(pod_phase):sum:sort(value(sum,descending))", + "enabled": true + } + ], + "visualConfig": { + "type": "PIE_CHART", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "C:", + "unitTransform": "auto", + "valueFormat": "auto", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [ + { + "name": "Running", + "color": "#5ead35" + }, + { + "name": "Pending", + "color": "#7c38a1" + }, + { + "name": "Failed", + "color": "#f5d30f" + }, + { + "name": "Succeeded", + "color": "#008cdb" + } + ] + } + ], + "axes": { + "xAxis": { + "visible": true + }, + "yAxes": [] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "color": "#7dc540" + }, + { + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&(builtin:kubernetes.node.pods:last:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):splitBy(pod_phase):sum:sort(value(sum,descending))):limit(100):names:fold(auto)" + ] + }, + { + "name": "Failed pods", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 38, + "left": 1368, + "width": 304, + "height": 152 + }, + "tileFilter": {}, + "customName": "Pods", + "queries": [ + { + "id": "C", + "timeAggregation": "DEFAULT", + "splitBy": [ + "k8s.namespace.name", + "dt.entity.kubernetes_cluster" + ], + "metricSelector": "builtin:kubernetes.pods:last:filter(and(eq(\"pod_phase\", \"Failed\")),in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):splitBy(\"k8s.namespace.name\",\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))", + "enabled": true + } + ], + "visualConfig": { + "type": "TOP_LIST", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "C:", + "unitTransform": "auto", + "valueFormat": "0", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [ + { + "name": "Select series", + "color": "#5ead35" + }, + { + "name": "Select series", + "color": "#f5d30f" + }, + { + "name": "Select series", + "color": "#c41425" + }, + { + "name": "Select series", + "color": "#008cdb" + } + ] + } + ], + "axes": { + "xAxis": { + "visible": true + }, + "yAxes": [] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "color": "#7dc540" + }, + { + "value": 0, + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&(builtin:kubernetes.pods:last:filter(and(eq(pod_phase,Failed)),in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):splitBy(\"k8s.namespace.name\",\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))):limit(100):names:fold(auto)" + ] + }, + { + "name": "Pending pods", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 190, + "left": 1368, + "width": 304, + "height": 152 + }, + "tileFilter": {}, + "customName": "Pods", + "queries": [ + { + "id": "C", + "timeAggregation": "DEFAULT", + "splitBy": [ + "k8s.namespace.name", + "dt.entity.kubernetes_cluster" + ], + "metricSelector": "builtin:kubernetes.pods:last:filter(and(eq(\"pod_phase\",\"Pending\")),in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):splitBy(\"k8s.namespace.name\",\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))", + "enabled": true + } + ], + "visualConfig": { + "type": "TOP_LIST", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "C:", + "unitTransform": "auto", + "valueFormat": "0", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [ + { + "name": "Select series", + "color": "#5ead35" + }, + { + "name": "Select series", + "color": "#f5d30f" + }, + { + "name": "Select series", + "color": "#c41425" + }, + { + "name": "Select series", + "color": "#008cdb" + } + ] + } + ], + "axes": { + "xAxis": { + "visible": true + }, + "yAxes": [] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "color": "#7dc540" + }, + { + "value": 0, + "color": "#7c38a1" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&(builtin:kubernetes.pods:last:filter(and(eq(pod_phase,Pending)),in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):splitBy(\"k8s.namespace.name\",\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))):limit(100):names:fold(auto)" + ] + }, + { + "name": "Allocatable CPU", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 380, + "left": 0, + "width": 418, + "height": 304 + }, + "tileFilter": {}, + "customName": "Cluster nodes", + "queries": [ + { + "id": "C", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.kubernetes_cluster" + ], + "metricSelector": "builtin:kubernetes.node.cpu_allocatable:last:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):splitBy(\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))", + "enabled": true + } + ], + "visualConfig": { + "type": "SINGLE_VALUE", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "C:", + "unitTransform": "Cores", + "valueFormat": "0,0", + "properties": { + "color": "DEFAULT", + "seriesType": "STACKED_COLUMN" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "visible": true + }, + "yAxes": [] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "singleValueSettings": { + "showTrend": true, + "showSparkLine": true, + "linkTileColorToThreshold": true + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "color": "#7dc540" + }, + { + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&(builtin:kubernetes.node.cpu_allocatable:last:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):splitBy(\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))):limit(100):names:fold(auto)", + "resolution=null&(builtin:kubernetes.node.cpu_allocatable:last:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):splitBy(\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending)))" + ] + }, + { + "name": "Number of nodes", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 38, + "left": 0, + "width": 342, + "height": 304 + }, + "tileFilter": {}, + "customName": "Cluster nodes", + "queries": [ + { + "id": "C", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.kubernetes_cluster", + "k8s.cluster.name", + "node_condition_disk_pressure", + "node_condition_memory_pressure", + "node_condition_pid_pressure", + "node_condition_ready" + ], + "metricSelector": "builtin:kubernetes.nodes:last:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\")))", + "enabled": true + } + ], + "visualConfig": { + "type": "SINGLE_VALUE", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "C:", + "properties": { + "color": "DEFAULT" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "visible": true + }, + "yAxes": [] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "singleValueSettings": { + "showTrend": true, + "showSparkLine": true, + "linkTileColorToThreshold": true + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "color": "#7dc540" + }, + { + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&(builtin:kubernetes.nodes:last:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\")))):limit(100):names:fold(auto)", + "resolution=null&(builtin:kubernetes.nodes:last:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))))" + ] + }, + { + "name": "CPU requests in % of allocatable", + "nameSize": "", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 380, + "left": 418, + "width": 418, + "height": 304 + }, + "tileFilter": {}, + "customName": "Memory available", + "queries": [ + { + "id": "B", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.kubernetes_cluster" + ], + "metricSelector": "(builtin:kubernetes.node.requests_cpu:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum / builtin:kubernetes.node.cpu_allocatable:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum * 100):sort(value(sum,descending))", + "enabled": true + } + ], + "visualConfig": { + "type": "SINGLE_VALUE", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "B:", + "unitTransform": "%", + "valueFormat": "0", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "displayName": "", + "visible": true + }, + "yAxes": [ + { + "displayName": "", + "visible": true, + "min": "0", + "max": "100", + "position": "LEFT", + "queryIds": [ + "B" + ], + "defaultAxis": true + } + ] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "singleValueSettings": { + "showTrend": true, + "showSparkLine": true, + "linkTileColorToThreshold": true + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "value": 0, + "color": "#7dc540" + }, + { + "value": 90, + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "", + "foldTransformation": "LAST_VALUE" + }, + "metricExpressions": [ + "resolution=null&((builtin:kubernetes.node.requests_cpu:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum/builtin:kubernetes.node.cpu_allocatable:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum*100):sort(value(sum,descending))):limit(100):names:last", + "resolution=null&((builtin:kubernetes.node.requests_cpu:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum/builtin:kubernetes.node.cpu_allocatable:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum*100):sort(value(sum,descending)))" + ] + }, + { + "name": "Allocatable Memory", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 380, + "left": 836, + "width": 418, + "height": 304 + }, + "tileFilter": {}, + "customName": "Cluster nodes", + "queries": [ + { + "id": "C", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.kubernetes_cluster" + ], + "metricSelector": "builtin:kubernetes.node.memory_allocatable:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))", + "enabled": true + } + ], + "visualConfig": { + "type": "SINGLE_VALUE", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "C:", + "unitTransform": "GibiByte", + "valueFormat": "0,0", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "visible": true + }, + "yAxes": [] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "singleValueSettings": { + "showTrend": true, + "showSparkLine": true, + "linkTileColorToThreshold": true + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "color": "#7dc540" + }, + { + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&(builtin:kubernetes.node.memory_allocatable:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))):limit(100):names:fold(auto)", + "resolution=null&(builtin:kubernetes.node.memory_allocatable:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending)))" + ] + }, + { + "name": "Memory requests in % of allocatable", + "nameSize": "", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 380, + "left": 1254, + "width": 418, + "height": 304 + }, + "tileFilter": {}, + "customName": "Memory available", + "queries": [ + { + "id": "B", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.kubernetes_cluster" + ], + "metricSelector": "(builtin:kubernetes.node.requests_memory:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum / builtin:kubernetes.node.memory_allocatable:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum * 100):setUnit(Percent):sort(value(sum,descending))", + "enabled": true + } + ], + "visualConfig": { + "type": "SINGLE_VALUE", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "B:", + "unitTransform": "Percent", + "valueFormat": "0", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "displayName": "", + "visible": true + }, + "yAxes": [ + { + "displayName": "", + "visible": true, + "min": "0", + "max": "100", + "position": "LEFT", + "queryIds": [ + "B" + ], + "defaultAxis": true + } + ] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "singleValueSettings": { + "showTrend": true, + "showSparkLine": true, + "linkTileColorToThreshold": true + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "value": 0, + "color": "#7dc540" + }, + { + "value": 90, + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&((builtin:kubernetes.node.requests_memory:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum/builtin:kubernetes.node.memory_allocatable:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum*100):setUnit(Percent):sort(value(sum,descending))):limit(100):names:fold(auto)", + "resolution=null&((builtin:kubernetes.node.requests_memory:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum/builtin:kubernetes.node.memory_allocatable:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_cluster\"):sum*100):setUnit(Percent):sort(value(sum,descending)))" + ] + }, + { + "name": "Allocatable CPU", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 722, + "left": 0, + "width": 418, + "height": 304 + }, + "tileFilter": {}, + "customName": "Cluster nodes", + "queries": [ + { + "id": "C", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.kubernetes_node", + "dt.entity.kubernetes_cluster" + ], + "metricSelector": "builtin:kubernetes.node.cpu_allocatable:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_node\", \"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))", + "enabled": true + } + ], + "visualConfig": { + "type": "TOP_LIST", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "C:", + "unitTransform": "Cores", + "valueFormat": "0,0", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "visible": true + }, + "yAxes": [] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "singleValueSettings": { + "showTrend": true, + "showSparkLine": true, + "linkTileColorToThreshold": true + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "columnId": "Kubernetes: Node - CPU allocatable", + "rules": [ + { + "color": "#7dc540" + }, + { + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "C", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&(builtin:kubernetes.node.cpu_allocatable:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_node\",\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))):limit(100):names:fold(auto)" + ] + }, + { + "name": "CPU requests in % of allocatable", + "nameSize": "", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 722, + "left": 418, + "width": 418, + "height": 304 + }, + "tileFilter": {}, + "customName": "Memory available", + "queries": [ + { + "id": "B", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.kubernetes_node", + "dt.entity.kubernetes_cluster" + ], + "metricSelector": "(\n builtin:kubernetes.node.requests_cpu:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_node\",\"dt.entity.kubernetes_cluster\"):sum \n / builtin:kubernetes.node.cpu_allocatable:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_node\",\"dt.entity.kubernetes_cluster\"):sum \n * 100\n):setUnit(Percent):sort(value(sum,descending))", + "enabled": true + } + ], + "visualConfig": { + "type": "TOP_LIST", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "B:", + "unitTransform": "auto", + "valueFormat": "0", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "displayName": "", + "visible": true + }, + "yAxes": [ + { + "displayName": "", + "visible": true, + "min": "0", + "max": "100", + "position": "LEFT", + "queryIds": [ + "B" + ], + "defaultAxis": true + } + ] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "value": 0, + "color": "#7dc540" + }, + { + "value": 90, + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&((builtin:kubernetes.node.requests_cpu:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_node\",\"dt.entity.kubernetes_cluster\"):sum/builtin:kubernetes.node.cpu_allocatable:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_node\",\"dt.entity.kubernetes_cluster\"):sum*100):setUnit(Percent):sort(value(sum,descending))):limit(100):names:fold(auto)" + ] + }, + { + "name": "Allocatable Memory", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 722, + "left": 836, + "width": 418, + "height": 304 + }, + "tileFilter": {}, + "customName": "Cluster nodes", + "queries": [ + { + "id": "C", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.kubernetes_node", + "dt.entity.kubernetes_cluster" + ], + "metricSelector": "builtin:kubernetes.node.memory_allocatable:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_node\", \"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))", + "enabled": true + } + ], + "visualConfig": { + "type": "TOP_LIST", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "C:", + "unitTransform": "GibiByte", + "valueFormat": "0,0", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "visible": true + }, + "yAxes": [] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "color": "#7dc540" + }, + { + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&(builtin:kubernetes.node.memory_allocatable:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_node\",\"dt.entity.kubernetes_cluster\"):sum:sort(value(sum,descending))):limit(100):names:fold(auto)" + ] + }, + { + "name": "Memory requests in % of allocatable", + "nameSize": "", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 722, + "left": 1254, + "width": 418, + "height": 304 + }, + "tileFilter": {}, + "customName": "Memory available", + "queries": [ + { + "id": "B", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.kubernetes_node", + "dt.entity.kubernetes_cluster" + ], + "metricSelector": "(builtin:kubernetes.node.requests_memory:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_node\",\"dt.entity.kubernetes_cluster\"):sum / builtin:kubernetes.node.memory_allocatable:filter(in(\"dt.entity.kubernetes_cluster\", entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_node\",\"dt.entity.kubernetes_cluster\"):sum * 100):setUnit(Percent):sort(value(sum,descending))", + "enabled": true + } + ], + "visualConfig": { + "type": "TOP_LIST", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "B:", + "unitTransform": "Percent", + "valueFormat": "0", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "displayName": "", + "visible": true + }, + "yAxes": [ + { + "displayName": "", + "visible": true, + "min": "0", + "max": "100", + "position": "LEFT", + "queryIds": [ + "B" + ], + "defaultAxis": true + } + ] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "value": 0, + "color": "#7dc540" + }, + { + "value": 90, + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&((builtin:kubernetes.node.requests_memory:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_node\",\"dt.entity.kubernetes_cluster\"):sum/builtin:kubernetes.node.memory_allocatable:filter(in(\"dt.entity.kubernetes_cluster\",entitySelector(\"type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\")\"))):last:splitBy(\"dt.entity.kubernetes_node\",\"dt.entity.kubernetes_cluster\"):sum*100):setUnit(Percent):sort(value(sum,descending))):limit(100):names:fold(auto)" + ] + }, + { + "name": "Top 10 CPU usage", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 1026, + "left": 0, + "width": 418, + "height": 304 + }, + "tileFilter": {}, + "customName": "CPU usage % ", + "queries": [ + { + "id": "A", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.host" + ], + "metricSelector": "builtin:host.cpu.usage:filter(and(in(\"dt.entity.host\",entitySelector(\"type(host),softwaretechnologies(~\"KUBERNETES~\")\"))),in(\"dt.entity.host\", entitySelector(\"type(~\"HOST~\"),toRelationship.isClusterOfHost(type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\"))\"))):splitBy(\"dt.entity.host\"):sort(value(avg,descending)):limit(10)", + "enabled": true + } + ], + "visualConfig": { + "type": "GRAPH_CHART", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "A:", + "unitTransform": "Percent", + "valueFormat": "0", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "displayName": "", + "visible": true + }, + "yAxes": [ + { + "displayName": "", + "visible": true, + "min": "0", + "max": "100", + "position": "LEFT", + "queryIds": [ + "A" + ], + "defaultAxis": true + } + ] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "color": "#7dc540" + }, + { + "value": 90, + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&(builtin:host.cpu.usage:filter(and(in(\"dt.entity.host\",entitySelector(\"type(host),softwaretechnologies(~\"KUBERNETES~\")\"))),in(\"dt.entity.host\",entitySelector(\"type(~\"HOST~\"),toRelationship.isClusterOfHost(type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\"))\"))):splitBy(\"dt.entity.host\"):sort(value(avg,descending)):limit(10)):limit(100):names" + ] + }, + { + "name": "Top 10 memory usage", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 1026, + "left": 418, + "width": 418, + "height": 304 + }, + "tileFilter": {}, + "customName": "Memory usage % ", + "queries": [ + { + "id": "A", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.host" + ], + "metricSelector": "builtin:host.mem.usage:filter(and(in(\"dt.entity.host\",entitySelector(\"type(host),softwaretechnologies(~\"KUBERNETES~\")\"))),in(\"dt.entity.host\", entitySelector(\"type(~\"HOST~\"),toRelationship.isClusterOfHost(type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\"))\"))):splitBy(\"dt.entity.host\"):sort(value(avg,descending)):limit(10)", + "enabled": true + } + ], + "visualConfig": { + "type": "GRAPH_CHART", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "A:", + "unitTransform": "Percent", + "valueFormat": "0", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "displayName": "", + "visible": true + }, + "yAxes": [ + { + "displayName": "", + "visible": true, + "min": "0", + "max": "100", + "position": "LEFT", + "queryIds": [ + "A" + ], + "defaultAxis": true + } + ] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "color": "#7dc540" + }, + { + "value": 90, + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&(builtin:host.mem.usage:filter(and(in(\"dt.entity.host\",entitySelector(\"type(host),softwaretechnologies(~\"KUBERNETES~\")\"))),in(\"dt.entity.host\",entitySelector(\"type(~\"HOST~\"),toRelationship.isClusterOfHost(type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\"))\"))):splitBy(\"dt.entity.host\"):sort(value(avg,descending)):limit(10)):limit(100):names" + ] + }, + { + "name": "Top 10 disk usage", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 1026, + "left": 836, + "width": 418, + "height": 304 + }, + "tileFilter": {}, + "customName": "Disk usage % ", + "queries": [ + { + "id": "A", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.host", + "dt.entity.disk" + ], + "metricSelector": "builtin:host.disk.usedPct:filter(and(in(\"dt.entity.host\",entitySelector(\"type(host),softwaretechnologies(~\"KUBERNETES~\")\"))),in(\"dt.entity.host\", entitySelector(\"type(~\"HOST~\"),toRelationship.isClusterOfHost(type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\"))\"))):splitBy(\"dt.entity.host\",\"dt.entity.disk\"):avg:sort(value(avg,descending)):limit(10)", + "enabled": true + } + ], + "visualConfig": { + "type": "GRAPH_CHART", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "A:", + "unitTransform": "Percent", + "valueFormat": "0", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "displayName": "", + "visible": true + }, + "yAxes": [ + { + "displayName": "", + "visible": true, + "min": "0", + "max": "100", + "position": "LEFT", + "queryIds": [ + "A" + ], + "defaultAxis": true + } + ] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "color": "#7dc540" + }, + { + "value": 90, + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&(builtin:host.disk.usedPct:filter(and(in(\"dt.entity.host\",entitySelector(\"type(host),softwaretechnologies(~\"KUBERNETES~\")\"))),in(\"dt.entity.host\",entitySelector(\"type(~\"HOST~\"),toRelationship.isClusterOfHost(type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\"))\"))):splitBy(\"dt.entity.host\",\"dt.entity.disk\"):avg:sort(value(avg,descending)):limit(10)):limit(100):names" + ] + }, + { + "name": "Top 10 traffic in/out", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 1026, + "left": 1254, + "width": 418, + "height": 304 + }, + "tileFilter": {}, + "customName": "Traffic in/out", + "queries": [ + { + "id": "A", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.host" + ], + "metricSelector": "builtin:host.net.nic.trafficIn:avg:filter(and(in(\"dt.entity.host\",entitySelector(\"type(host),softwaretechnologies(~\"KUBERNETES~\")\"))),in(\"dt.entity.host\", entitySelector(\"type(~\"HOST~\"),toRelationship.isClusterOfHost(type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\"))\"))):splitBy(\"dt.entity.host\"):sum:auto:sort(value(sum,descending)):limit(10)", + "enabled": true + }, + { + "id": "B", + "timeAggregation": "DEFAULT", + "splitBy": [ + "dt.entity.host" + ], + "metricSelector": "builtin:host.net.nic.trafficOut:avg:filter(and(in(\"dt.entity.host\",entitySelector(\"type(host),softwaretechnologies(~\"KUBERNETES~\")\"))),in(\"dt.entity.host\", entitySelector(\"type(~\"HOST~\"),toRelationship.isClusterOfHost(type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\"))\"))):splitBy(\"dt.entity.host\"):sum:auto:sort(value(sum,descending)):limit(10)", + "enabled": true + } + ], + "visualConfig": { + "type": "GRAPH_CHART", + "global": { + "hideLegend": false + }, + "rules": [ + { + "matcher": "A:", + "unitTransform": "auto", + "valueFormat": "auto", + "properties": { + "color": "BLUE", + "seriesType": "LINE" + }, + "seriesOverrides": [] + }, + { + "matcher": "B:", + "unitTransform": "auto", + "valueFormat": "auto", + "properties": { + "color": "ORANGE", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "displayName": "", + "visible": true + }, + "yAxes": [ + { + "displayName": "", + "visible": true, + "min": "AUTO", + "max": "AUTO", + "position": "LEFT", + "queryIds": [ + "A", + "B" + ], + "defaultAxis": true + } + ] + }, + "heatmapSettings": { + "yAxis": "VALUE" + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "color": "#7dc540" + }, + { + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "queryId": "", + "visible": true + } + ], + "tableSettings": { + "isThresholdBackgroundAppliedToCell": false + }, + "graphChartSettings": { + "connectNulls": false + }, + "honeycombSettings": { + "showHive": true, + "showLegend": true, + "showLabels": false + } + }, + "queriesSettings": { + "resolution": "" + }, + "metricExpressions": [ + "resolution=null&(builtin:host.net.nic.trafficIn:avg:filter(and(in(\"dt.entity.host\",entitySelector(\"type(host),softwaretechnologies(~\"KUBERNETES~\")\"))),in(\"dt.entity.host\",entitySelector(\"type(~\"HOST~\"),toRelationship.isClusterOfHost(type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\"))\"))):splitBy(\"dt.entity.host\"):sum:auto:sort(value(sum,descending)):limit(10)):limit(100):names,(builtin:host.net.nic.trafficOut:avg:filter(and(in(\"dt.entity.host\",entitySelector(\"type(host),softwaretechnologies(~\"KUBERNETES~\")\"))),in(\"dt.entity.host\",entitySelector(\"type(~\"HOST~\"),toRelationship.isClusterOfHost(type(~\"KUBERNETES_CLUSTER~\"),entityName.equals(~\"~\"))\"))):splitBy(\"dt.entity.host\"):sum:auto:sort(value(sum,descending)):limit(10)):limit(100):names" + ] + } + ] diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..b1a15fd --- /dev/null +++ b/readme.md @@ -0,0 +1,57 @@ +# Kubernetes dashboard as a code +This repository holds the code to generate the Kubernetes overwiew Dashboard as Code. + +Dashboard is generated for specific cluster provided as parameter for the script. + +Dashboard naming convention is: "[PROVIDED CLUSTER NAME] - Kubernetes cluster overview" + +# Prerequisites + +## Python packages +Before executing scripts, python requirements have to be satisfied. To do so, execute following command: + pip install -r requirements.txt + +## .env file + +To provide authentication for API calls, create ".env" file in the script directory with following definition: + + = + is name of environment variable. This name should be passed to "environment.yaml" file as "env-token-name" parameter + Example: + environment.yaml file: "- env-token-name: "GLOBAL_CONFIG_TOKEN" + .env file: "GLOBAL_CONFIG_TOKEN=XXXXXXXXXXX" + +# Usage + + usage: createDash.py [-h] -C CLUSTER [--remove] [-E ENVIRONMENT] + + Generate and deploy the Kubernetes Overview Dashboard as Code. + + options: + -h, --help show this help message and exit + -C CLUSTER, --cluster CLUSTER + Name of the Kubernetes cluster (default: None) + --remove Remove dashboard for given cluster. If not specified dashboard will be created or updated (default: False) + -E ENVIRONMENT, --environment ENVIRONMENT + Name of the environment (the same as in environment.yaml file. Used to upload dashboard to specific Dynatrace environment. If not specified all environments in file will be used (default: None) +# Files + +## createDash.py + +This scripts generates Dashboard and uploads it to Dynatrace. + +## environment.yaml +File containing environments to connect to Dynatrace tenant + + Environment name: + name: string #name ov environment + env-url: str #url of environment + env-token-name: str #name of environment variable containing API token + +## requirements.txt + +File containing required python packages + +## kubernetes_tiles_template.json + +File containing template for dashboard \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c8afe58 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +python-decouple +pyyaml +requests +datetime +argparse +GitPython \ No newline at end of file