133 lines
4.0 KiB
YAML
133 lines
4.0 KiB
YAML
# services/logging/opensearch-prune-cronjob.yaml
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: opensearch-prune-script
|
|
namespace: logging
|
|
data:
|
|
prune.py: |
|
|
import json
|
|
import os
|
|
import re
|
|
import sys
|
|
import urllib.error
|
|
import urllib.request
|
|
|
|
os_url = os.environ.get("OPENSEARCH_URL", "http://opensearch-master.logging.svc.cluster.local:9200").rstrip("/")
|
|
limit_bytes = int(os.environ.get("LOG_LIMIT_BYTES", str(1024**4)))
|
|
patterns = [p.strip() for p in os.environ.get("LOG_INDEX_PATTERNS", "kube-*,journald-*").split(",") if p.strip()]
|
|
|
|
UNITS = {
|
|
"b": 1,
|
|
"kb": 1024,
|
|
"mb": 1024**2,
|
|
"gb": 1024**3,
|
|
"tb": 1024**4,
|
|
}
|
|
|
|
def parse_size(value: str) -> int:
|
|
if not value:
|
|
return 0
|
|
text = value.strip().lower()
|
|
if text in ("-", "0"):
|
|
return 0
|
|
match = re.match(r"^([0-9.]+)([a-z]+)$", text)
|
|
if not match:
|
|
return 0
|
|
number = float(match.group(1))
|
|
unit = match.group(2)
|
|
if unit not in UNITS:
|
|
return 0
|
|
return int(number * UNITS[unit])
|
|
|
|
def request_json(path: str):
|
|
url = f"{os_url}{path}"
|
|
with urllib.request.urlopen(url, timeout=30) as response:
|
|
payload = response.read().decode("utf-8")
|
|
return json.loads(payload)
|
|
|
|
def delete_index(index: str) -> None:
|
|
url = f"{os_url}/{index}"
|
|
req = urllib.request.Request(url, method="DELETE")
|
|
with urllib.request.urlopen(req, timeout=30) as response:
|
|
_ = response.read()
|
|
print(f"deleted {index}")
|
|
|
|
indices = []
|
|
for pattern in patterns:
|
|
try:
|
|
data = request_json(f"/_cat/indices/{pattern}?format=json&h=index,store.size,creation.date")
|
|
except urllib.error.HTTPError as exc:
|
|
if exc.code == 404:
|
|
continue
|
|
raise
|
|
for item in data:
|
|
index = item.get("index")
|
|
if not index or index.startswith("."):
|
|
continue
|
|
size = parse_size(item.get("store.size", ""))
|
|
created = int(item.get("creation.date", "0") or 0)
|
|
indices.append({"index": index, "size": size, "created": created})
|
|
|
|
total = sum(item["size"] for item in indices)
|
|
print(f"total_log_bytes={total}")
|
|
if total <= limit_bytes:
|
|
print("within limit")
|
|
sys.exit(0)
|
|
|
|
indices.sort(key=lambda item: item["created"])
|
|
for item in indices:
|
|
if total <= limit_bytes:
|
|
break
|
|
delete_index(item["index"])
|
|
total -= item["size"]
|
|
|
|
print(f"remaining_log_bytes={total}")
|
|
---
|
|
apiVersion: batch/v1
|
|
kind: CronJob
|
|
metadata:
|
|
name: opensearch-prune
|
|
namespace: logging
|
|
spec:
|
|
schedule: "23 3 * * *"
|
|
concurrencyPolicy: Forbid
|
|
successfulJobsHistoryLimit: 1
|
|
failedJobsHistoryLimit: 3
|
|
jobTemplate:
|
|
spec:
|
|
backoffLimit: 2
|
|
template:
|
|
spec:
|
|
restartPolicy: OnFailure
|
|
nodeSelector:
|
|
node-role.kubernetes.io/worker: "true"
|
|
hardware: rpi5
|
|
affinity:
|
|
nodeAffinity:
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
nodeSelectorTerms:
|
|
- matchExpressions:
|
|
- key: hardware
|
|
operator: In
|
|
values:
|
|
- rpi5
|
|
containers:
|
|
- name: prune
|
|
image: python:3.11-alpine
|
|
command: ["python", "/scripts/prune.py"]
|
|
env:
|
|
- name: OPENSEARCH_URL
|
|
value: http://opensearch-master.logging.svc.cluster.local:9200
|
|
- name: LOG_LIMIT_BYTES
|
|
value: "1099511627776"
|
|
- name: LOG_INDEX_PATTERNS
|
|
value: "kube-*,journald-*"
|
|
volumeMounts:
|
|
- name: scripts
|
|
mountPath: /scripts
|
|
volumes:
|
|
- name: scripts
|
|
configMap:
|
|
name: opensearch-prune-script
|