Skip to content

Commit

Permalink
Bug fix, add histogram of pod tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
jaclark5 committed Feb 5, 2025
1 parent 8e0e9ec commit 3e85656
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 23 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
KubeCustom
==============================
[//]: # (Badges)
[![GitHub Actions Build Status](https://github.com/jaclark5/kubecustom/workflows/CI/badge.svg)](https://github.com/jaclark5/kubecustom/actions?query=workflow%3ACI)
[![GitHub Actions Build Status](https://github.com/openforcefield/kubecustom/workflows/CI/badge.svg)](https://github.com/openforcefield/kubecustom/actions?query=workflow%3ACI)
[![Documentation Status](https://readthedocs.org/projects/kubecustom/badge/?version=latest)](https://kubecustom.readthedocs.io/en/latest/?badge=latest)
<!--
[![codecov](https://codecov.io/gh/jaclark5/kubecustom/branch/main/graph/badge.svg)](https://codecov.io/gh/jaclark5/kubecustom/branch/main)
[![codecov](https://codecov.io/gh/openforcefield/kubecustom/branch/main/graph/badge.svg)](https://codecov.io/gh/openforcefield/kubecustom/branch/main)
-->

Kubernetes assessment and combined control functions to handle multiple deployments.

**This is a set of informal tools for internal use. We make no guarantees of versioning, functionality, or support.**

## Installation

* Step 1: Download the main branch from our GitHub page as a zip file, or clone it to your working directory with:

``git clone https://github.com/jaclark5/kubecustom``
``git clone https://github.com/openforcefield/kubecustom``

* Step 2 (Optional): If you are using conda and you want to create a new environment for this package you may install with:

Expand Down
2 changes: 1 addition & 1 deletion kubecustom/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
parser = get_parser()
args = parser.parse_args()
kwargs = {key: value for key, value in args.__dict__.items()}
timelag = kwargs.pop("timelag")
timelag = int(kwargs.pop("timelag"))


def repeat_task(scheduler):
Expand Down
7 changes: 4 additions & 3 deletions kubecustom/deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,6 @@ def scale_deployment(deployment_name, replicas, namespace=None, verbose=True):
namespace = MyDataInstance.get_namespace() if namespace is None else namespace

config.load_kube_config()
apps_v1_api = client.AppsV1Api()

dep_info = get_deployment_info(deployment_name, namespace=namespace)
if dep_info["replicas"] == replicas:
Expand All @@ -325,11 +324,13 @@ def scale_deployment(deployment_name, replicas, namespace=None, verbose=True):
delete_pod(pod_list[i], namespace=namespace)

try:
deployment = apps_v1_api.read_namespaced_deployment(deployment_name, namespace)
deployment = client.AppsV1Api().read_namespaced_deployment(
deployment_name, namespace
)
deployment.spec.replicas = replicas

# Apply the patch to update the deployment
apps_v1_api.patch_namespaced_deployment(
client.AppsV1Api().patch_namespaced_deployment(
name=deployment_name, namespace=namespace, body=deployment
)

Expand Down
38 changes: 25 additions & 13 deletions kubecustom/pod.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Create, delete, and extract information for pods"""

import warnings
from collections import defaultdict
from collections import defaultdict, Counter

from kubernetes import client, config
from kubernetes.client.exceptions import ApiException
Expand Down Expand Up @@ -192,13 +192,17 @@ def get_pods_status_info(previous=False, deployment_name=None, namespace=None):
pod_info = {}
for pod in pods:
state, status, status_info = pod_state(pod, previous=previous)
try:
restart_count = pod.status.container_statuses[0].restart_count
except Exception:
restart_count = None
pod_info[pod.metadata.name] = {
"pod_name": pod.metadata.name,
"node_name": pod.spec.node_name,
"host_ip": pod.status.host_ip,
"pod_ip": pod.status.pod_ip,
"phase": pod.status.phase,
"restart_count": pod.status.container_statuses[0].restart_count,
"restart_count": restart_count,
"state": state,
"status": status,
"status_info": status_info,
Expand Down Expand Up @@ -267,7 +271,7 @@ def get_pods_resource_info(
if verbose:
print(
f"Pod: {pod_name}, Container: {container_name}, CPU: {container['usage']['cpu']} {cpu_usage},\t"
"Memory: {container['usage']['memory']} {memory_usage}GB,\tLabels: {pod['metadata']['labels']}"
f"Memory: {container['usage']['memory']} {memory_usage}GB,\tLabels: {pod['metadata']['labels']}"
)

output[pod_name] = {
Expand All @@ -289,12 +293,15 @@ def get_active_tasks(pod_list, verbose=True, namespace=None):
:func:`kubecustom.secret.MyData.get_namespace`.
Returns:
dict: Dictionary of pod names and the number of active tasks each pod has
pod_tasks (dict): Dictionary of pod names and the number of active tasks each pod has
stats (dict): Dictionary of the number of tasks a pod could have, and the number of pods
in that state.
"""

namespace = MyDataInstance.get_namespace() if namespace is None else namespace

output = {}
output = defaultdict(int)
stats = Counter()
for pod in pod_list:
pod_name = pod.metadata.name
try:
Expand All @@ -312,22 +319,27 @@ def get_active_tasks(pod_list, verbose=True, namespace=None):
line_array = line.split()
tasks = int(line_array[-7])
output[pod_name] = tasks
stats[tasks] += 1
if verbose:
print(f" Pod: {pod_name}, Number of Tasks {tasks}")
break
elif "new tasks" in line:
line_array = line.split()
tasks = int(line_array[-3])
output[pod_name] = tasks
if verbose:
print(f" Pod: {pod_name}, Number of Tasks {tasks} new")
break

if pod_name not in output:
output[pod_name] = None
stats["None Yet"] += 1
if verbose:
print(f" Pod: {pod_name}, Number of Tasks None Yet")

except Exception:
stats[None] += 1
output[pod_name] = None
if verbose:
print(f" Pod: {pod_name}, Number of Tasks NA")

return output
if verbose:
print(stats)

return output, stats


def print_pods_summary(deployment_name=None, namespace=None):
Expand Down
3 changes: 2 additions & 1 deletion kubecustom/secret.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ def _update_file(self):
with open(_init_filename, "w") as f:
for i, line in enumerate(_file_contents):
line_array = line.split()
line_array = [line_array[0], str(getattr(self, self._attributes[i]))]
attr = getattr(self, self._attributes[i])
line_array = [line_array[0], str(attr if attr is not None else "None")]
f.write(" ".join(line_array) + "\n")

def get_username(self):
Expand Down
2 changes: 1 addition & 1 deletion kubecustom/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def convert_memory_use(mem_usage):
"M": 0.001,
"k": 1e-6,
"b": 1e-9,
"": 1 - 9,
"": 1e-9,
"m": 9.3132257461548e-13,
}
mem_usage.replace(" ", "")
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ dependencies = [

# Update the urls once the hosting is set up.
[project.urls]
"Source" = "https://github.com/jaclark5/kubecustom/"
"Source" = "https://github.com/openforcefield/kubecustom/"
"Documentation" = "https://kubecustom.readthedocs.io/"

[project.optional-dependencies]
Expand Down

0 comments on commit 3e85656

Please sign in to comment.