Skip to content

Commit 6a93b1e

Browse files
Fixing logic for calculating usage %age and name mapping
1 parent 8b3686d commit 6a93b1e

File tree

1 file changed

+45
-42
lines changed

1 file changed

+45
-42
lines changed

Kubernetes/legos/k8s_check_service_pvc_utilization/k8s_check_service_pvc_utilization.py

Lines changed: 45 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,8 @@ class InputSchema(BaseModel):
2626
title="Threshold (in %)",
2727
)
2828

29-
30-
def k8s_check_service_pvc_utilization_printer(output):
31-
status, pvc_info = output
32-
33-
if status:
34-
print("Disk sizes for all checked services are within the threshold.")
35-
else:
36-
print("ALERT: One or more PVC disk sizes are above threshold:")
37-
print("-" * 40)
38-
for pvc in pvc_info:
39-
print(
40-
f"PVC: {pvc['pvc_name']} - Utilized: {pvc['used']} of {pvc['capacity']}"
41-
)
42-
print("-" * 40)
43-
44-
4529
def k8s_check_service_pvc_utilization(
46-
handle, core_services: list, namespace: str, threshold: int = 80
30+
handle, core_services: list, namespace: str, threshold: int = 60
4731
) -> Tuple:
4832
"""
4933
k8s_check_service_pvc_utilization checks the utilized disk size of a service's PVC against a given threshold.
@@ -70,6 +54,9 @@ def k8s_check_service_pvc_utilization(
7054

7155
alert_pvcs_all_services = []
7256
services_without_pvcs = []
57+
58+
# Keep track of processed PVCs to avoid duplicates
59+
processed_pvcs = set()
7360

7461
for svc in core_services:
7562
# Get label associated with the service
@@ -110,9 +97,7 @@ def k8s_check_service_pvc_utilization(
11097
else:
11198
json_path_cmd = "{.metadata.name}:{range .spec.volumes[*].persistentVolumeClaim}{.claimName}{end}"
11299

113-
get_pvc_names_command = (
114-
f"kubectl get pod {pod_names} -n {namespace} -o=jsonpath='{json_path_cmd}'"
115-
)
100+
get_pvc_names_command = f"kubectl get pod {pod_names} -n {namespace} -o=jsonpath='{json_path_cmd}'"
116101

117102
response = handle.run_native_cmd(get_pvc_names_command)
118103
if not response or response.stderr:
@@ -129,7 +114,6 @@ def k8s_check_service_pvc_utilization(
129114

130115
pvc_mounts = []
131116
alert_pvcs = []
132-
all_pvcs = []
133117

134118
for element in pod_and_pvc_names:
135119
pod_name, claim_name = element.split(":")
@@ -146,7 +130,9 @@ def k8s_check_service_pvc_utilization(
146130
# df -kh is the command used to get the disk utilization. This is accurate as we get
147131
# the disk utilization from the POD directly, rather than checking the resource limit
148132
# and resource request from the deployment / stateful YAML file.
149-
get_pod_json_command = f"kubectl get pod {pod_name} -n {namespace} -o json"
133+
get_pod_json_command = (
134+
f"kubectl get pod {pod_name} -n {namespace} -o json"
135+
)
150136
pod_json_output = handle.run_native_cmd(get_pod_json_command)
151137
if not pod_json_output or pod_json_output.stderr:
152138
raise ApiException(
@@ -165,36 +151,44 @@ def k8s_check_service_pvc_utilization(
165151
claim_name = volume["persistentVolumeClaim"][
166152
"claimName"
167153
]
168-
pvc_mounts.append(
169-
{
170-
"container_name": container["name"],
171-
"mount_path": mount["mountPath"],
172-
"pvc_name": claim_name if claim_name else None,
173-
}
174-
)
154+
print(f"ClaimName: {claim_name}: MountName: {mount['name']} ContainerName: {container['name']}")
155+
156+
# Add mount info if not already added
157+
mount_info = {
158+
"container_name": container["name"],
159+
"mount_path": mount["mountPath"],
160+
"pvc_name": claim_name if claim_name else None,
161+
"pod_name": pod_name
162+
}
163+
164+
# Only add if this specific mount combination hasn't been processed yet
165+
mount_key = f"{pod_name}:{container['name']}:{mount['mountPath']}:{claim_name}"
166+
if mount_key not in processed_pvcs:
167+
pvc_mounts.append(mount_info)
168+
processed_pvcs.add(mount_key)
169+
175170
except KeyError as e:
176171
# Handle the KeyError (e.g., log the error, skip this iteration, etc.)
177172
print(f"KeyError: {e}. Skipping this entry.")
178173
except IndexError as e:
179174
# Handle the IndexError (e.g., log the error, skip this iteration, etc.)
180175
print(f"IndexError: {e}. Skipping this entry.")
181176

182-
all_mounts = [mount.get("mount_path") for mount in pvc_mounts]
183-
all_mounts = " ".join(all_mounts).strip()
177+
# Create a dictionary to store processed PVC info
178+
pvc_info_dict = {}
179+
180+
# Process each mount separately with a single df command
184181
for mount in pvc_mounts:
185182
container_name = mount["container_name"]
186183
mount_path = mount["mount_path"]
187184
pvc_name = mount["pvc_name"]
188-
all_pvcs.append(
189-
{
190-
"pvc_name": pvc_name,
191-
"mount_path": mount_path,
192-
"used": None,
193-
"capacity": None,
194-
}
195-
)
196-
197-
du_command = f"kubectl exec -n {namespace} {pod_name} -c {container_name} -- df -kh {all_mounts} | grep -v Filesystem"
185+
pod_name = mount["pod_name"]
186+
187+
# Skip if we've already processed this PVC
188+
if pvc_name in pvc_info_dict:
189+
continue
190+
191+
du_command = f"kubectl exec -n {namespace} {pod_name} -c {container_name} -- df -kh {mount_path} | grep -v Filesystem"
198192
du_output = handle.run_native_cmd(du_command)
199193

200194
if du_output and not du_output.stderr:
@@ -228,16 +222,25 @@ def k8s_check_service_pvc_utilization(
228222
"used": used_percentage,
229223
"capacity": total_capacity,
230224
}
225+
226+
# Store in dictionary to prevent duplicates
227+
pvc_info_dict[pvc_name] = pvc_info
231228

232229
# Check if usage exceeds threshold
233230
if used_percentage > threshold:
234231
alert_pvcs.append(pvc_info)
235232

236-
alert_pvcs_all_services.extend(alert_pvcs)
233+
# Add unique alert PVCs to the main list
234+
for pvc_info in alert_pvcs:
235+
if pvc_info not in alert_pvcs_all_services:
236+
alert_pvcs_all_services.append(pvc_info)
237237

238238
if services_without_pvcs:
239239
print("Following services do not have any PVCs attached:")
240240
for service in services_without_pvcs:
241241
print(f"- {service}")
242242

243+
if alert_pvcs_all_services:
244+
print(json.dumps(alert_pvcs_all_services, indent=4))
245+
243246
return (not bool(alert_pvcs_all_services), alert_pvcs_all_services)

0 commit comments

Comments
 (0)