Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fa5053aef | ||
|
|
41e894f79e | ||
|
|
86986013d7 | ||
|
|
4b5ecfcd49 |
@@ -52,6 +52,20 @@ spec:
|
|||||||
port: 8080
|
port: 8080
|
||||||
- protocol: TCP
|
- protocol: TCP
|
||||||
port: 9000
|
port: 9000
|
||||||
|
# Allow from paperless namespace (paperless-ai auto-tagging)
|
||||||
|
# Bypasses gateway until service-account JWT token exchange is implemented.
|
||||||
|
# paperless-ai-agent has llm:inference role in Authentik.
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: paperless
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8080
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8000
|
||||||
# Allow intra-namespace (pod-to-pod within llm-serving)
|
# Allow intra-namespace (pod-to-pod within llm-serving)
|
||||||
- from:
|
- from:
|
||||||
- podSelector:
|
- podSelector:
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ spec:
|
|||||||
- name: AI_PROVIDER
|
- name: AI_PROVIDER
|
||||||
value: "custom"
|
value: "custom"
|
||||||
- name: CUSTOM_BASE_URL
|
- name: CUSTOM_BASE_URL
|
||||||
value: "http://api-gateway.api.svc.cluster.local:8080/v1"
|
value: "http://reasoning-predictor.llm-serving.svc.cluster.local:80/v1"
|
||||||
- name: CUSTOM_API_KEY
|
- name: CUSTOM_API_KEY
|
||||||
value: "not-required"
|
value: "not-required"
|
||||||
- name: CUSTOM_MODEL
|
- name: CUSTOM_MODEL
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
# Cluster-wide cleanup of stale failed/completed Jobs and Pods.
|
# Cluster-wide cleanup of stale failed/completed Jobs and Pods.
|
||||||
# Runs daily at 04:00 UTC. Deletes:
|
# Runs every 2 minutes. Deletes:
|
||||||
# - Failed Jobs older than 24h (any namespace)
|
# - Failed Jobs older than 2m (any namespace)
|
||||||
# - Completed Jobs older than 72h with no owning CronJob
|
# - Completed standalone Jobs older than 2m with no owning CronJob
|
||||||
# - Orphan pods in Error/Failed/Evicted state older than 1h
|
# - Orphan pods in Error/Failed/Evicted/Completed state older than 2m
|
||||||
#
|
#
|
||||||
# CronJob-owned Jobs are managed by failedJobsHistoryLimit/successfulJobsHistoryLimit,
|
# CronJob-owned Jobs are managed by failedJobsHistoryLimit/successfulJobsHistoryLimit,
|
||||||
# but standalone Jobs (helm hooks, one-off runs, longhorn maintenance) have no TTL
|
# but standalone Jobs (helm hooks, one-off runs, CI TaskRuns) have no TTL
|
||||||
# and linger forever.
|
# and linger forever. Aggressive schedule keeps the cluster clean.
|
||||||
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
@@ -47,7 +47,7 @@ metadata:
|
|||||||
labels:
|
labels:
|
||||||
app: stale-job-cleanup
|
app: stale-job-cleanup
|
||||||
spec:
|
spec:
|
||||||
schedule: "0 4 * * *"
|
schedule: "*/2 * * * *"
|
||||||
concurrencyPolicy: Forbid
|
concurrencyPolicy: Forbid
|
||||||
successfulJobsHistoryLimit: 3
|
successfulJobsHistoryLimit: 3
|
||||||
failedJobsHistoryLimit: 3
|
failedJobsHistoryLimit: 3
|
||||||
@@ -74,7 +74,9 @@ spec:
|
|||||||
set -e
|
set -e
|
||||||
NOW=$(date +%s)
|
NOW=$(date +%s)
|
||||||
|
|
||||||
echo "=== Cleaning failed Jobs older than 24h ==="
|
TTL=120 # 2 minutes in seconds
|
||||||
|
|
||||||
|
echo "=== Cleaning failed Jobs older than 2m ==="
|
||||||
kubectl get jobs --all-namespaces -o json | \
|
kubectl get jobs --all-namespaces -o json | \
|
||||||
jq -r '.items[] |
|
jq -r '.items[] |
|
||||||
select(.status.conditions[]?.type == "Failed") |
|
select(.status.conditions[]?.type == "Failed") |
|
||||||
@@ -82,15 +84,15 @@ spec:
|
|||||||
"\(.metadata.namespace) \(.metadata.name) \(.status.startTime // .status.completionTime // .metadata.creationTimestamp)"' | \
|
"\(.metadata.namespace) \(.metadata.name) \(.status.startTime // .status.completionTime // .metadata.creationTimestamp)"' | \
|
||||||
while read -r NS NAME TS; do
|
while read -r NS NAME TS; do
|
||||||
JOB_EPOCH=$(date -d "$TS" +%s 2>/dev/null || echo 0)
|
JOB_EPOCH=$(date -d "$TS" +%s 2>/dev/null || echo 0)
|
||||||
AGE_H=$(( (NOW - JOB_EPOCH) / 3600 ))
|
AGE=$(( NOW - JOB_EPOCH ))
|
||||||
if [ "$AGE_H" -ge 24 ]; then
|
if [ "$AGE" -ge "$TTL" ]; then
|
||||||
echo "[delete] $NS/$NAME (failed ${AGE_H}h ago)"
|
echo "[delete] $NS/$NAME (failed ${AGE}s ago)"
|
||||||
kubectl delete job "$NAME" -n "$NS" --cascade=foreground 2>/dev/null || true
|
kubectl delete job "$NAME" -n "$NS" --cascade=foreground 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== Cleaning completed standalone Jobs older than 72h ==="
|
echo "=== Cleaning completed standalone Jobs older than 2m ==="
|
||||||
kubectl get jobs --all-namespaces -o json | \
|
kubectl get jobs --all-namespaces -o json | \
|
||||||
jq -r '.items[] |
|
jq -r '.items[] |
|
||||||
select(.status.succeeded >= 1) |
|
select(.status.succeeded >= 1) |
|
||||||
@@ -98,20 +100,20 @@ spec:
|
|||||||
"\(.metadata.namespace) \(.metadata.name) \(.status.completionTime // .metadata.creationTimestamp)"' | \
|
"\(.metadata.namespace) \(.metadata.name) \(.status.completionTime // .metadata.creationTimestamp)"' | \
|
||||||
while read -r NS NAME TS; do
|
while read -r NS NAME TS; do
|
||||||
JOB_EPOCH=$(date -d "$TS" +%s 2>/dev/null || echo 0)
|
JOB_EPOCH=$(date -d "$TS" +%s 2>/dev/null || echo 0)
|
||||||
AGE_H=$(( (NOW - JOB_EPOCH) / 3600 ))
|
AGE=$(( NOW - JOB_EPOCH ))
|
||||||
if [ "$AGE_H" -ge 72 ]; then
|
if [ "$AGE" -ge "$TTL" ]; then
|
||||||
echo "[delete] $NS/$NAME (completed ${AGE_H}h ago, no owner)"
|
echo "[delete] $NS/$NAME (completed ${AGE}s ago, no owner)"
|
||||||
kubectl delete job "$NAME" -n "$NS" --cascade=foreground 2>/dev/null || true
|
kubectl delete job "$NAME" -n "$NS" --cascade=foreground 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== Cleaning orphan Error/Failed/Evicted pods older than 1h ==="
|
echo "=== Cleaning orphan Error/Failed/Evicted/Completed pods older than 2m ==="
|
||||||
# Evicted pods show as Failed with reason Evicted
|
|
||||||
kubectl get pods --all-namespaces -o json | \
|
kubectl get pods --all-namespaces -o json | \
|
||||||
jq -r '.items[] |
|
jq -r '.items[] |
|
||||||
select(
|
select(
|
||||||
.status.phase == "Failed" or
|
.status.phase == "Failed" or
|
||||||
|
.status.phase == "Succeeded" or
|
||||||
(.status.reason // "") == "Evicted" or
|
(.status.reason // "") == "Evicted" or
|
||||||
(.status.containerStatuses // [] | any(.state.terminated.reason == "Error"))
|
(.status.containerStatuses // [] | any(.state.terminated.reason == "Error"))
|
||||||
) |
|
) |
|
||||||
@@ -119,9 +121,9 @@ spec:
|
|||||||
"\(.metadata.namespace) \(.metadata.name) \(.metadata.creationTimestamp)"' | \
|
"\(.metadata.namespace) \(.metadata.name) \(.metadata.creationTimestamp)"' | \
|
||||||
while read -r NS NAME TS; do
|
while read -r NS NAME TS; do
|
||||||
POD_EPOCH=$(date -d "$TS" +%s 2>/dev/null || echo 0)
|
POD_EPOCH=$(date -d "$TS" +%s 2>/dev/null || echo 0)
|
||||||
AGE_H=$(( (NOW - POD_EPOCH) / 3600 ))
|
AGE=$(( NOW - POD_EPOCH ))
|
||||||
if [ "$AGE_H" -ge 1 ]; then
|
if [ "$AGE" -ge "$TTL" ]; then
|
||||||
echo "[delete] $NS/$NAME (error/evicted ${AGE_H}h ago)"
|
echo "[delete] $NS/$NAME (stale ${AGE}s ago)"
|
||||||
kubectl delete pod "$NAME" -n "$NS" --force 2>/dev/null || true
|
kubectl delete pod "$NAME" -n "$NS" --force 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# CiliumNetworkPolicy for kube-apiserver access.
|
||||||
|
#
|
||||||
|
# Standard K8s NetworkPolicy ipBlock rules don't work for the API server
|
||||||
|
# under Cilium — the except clause on 192.168.1.0/24 blocks the post-DNAT
|
||||||
|
# destination even when a separate rule re-allows a /32 or subnet.
|
||||||
|
#
|
||||||
|
# Cilium's native `kube-apiserver` entity resolves this correctly: it
|
||||||
|
# tracks the API server endpoints regardless of ClusterIP vs node-IP
|
||||||
|
# routing, so the policy stays valid across node changes and NAT paths.
|
||||||
|
apiVersion: cilium.io/v2
|
||||||
|
kind: CiliumNetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: {{ .Release.Name }}-apiserver
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
spec:
|
||||||
|
endpointSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: {{ .Release.Name }}
|
||||||
|
egress:
|
||||||
|
- toEntities:
|
||||||
|
- kube-apiserver
|
||||||
|
toPorts:
|
||||||
|
- ports:
|
||||||
|
- port: "6443"
|
||||||
|
protocol: TCP
|
||||||
Reference in New Issue
Block a user