Skip to content

Commit 72c51ed

Browse files
committed
deploy: Add warm-cache CronJob
- Introduced a new `warm-cache` CronJob to periodically preload the cache. - Added supporting scripts (`warm-cache.sh`, `warm-cache-init.sh`) to manage the cache warm-up process. - Configured `ServiceAccount` for the frontend deployment to enhance security. - Adjusted HPA minimum replicas from 1 to 2 for better availability. - Set frontend deployment to use debug log level. Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
1 parent 7a9ce5c commit 72c51ed

7 files changed

Lines changed: 166 additions & 3 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
apiVersion: batch/v1
2+
kind: CronJob
3+
metadata:
4+
name: warm-cache
5+
spec:
6+
# Runs every 5 minutes
7+
schedule: "*/5 * * * *"
8+
concurrencyPolicy: Forbid
9+
successfulJobsHistoryLimit: 1
10+
failedJobsHistoryLimit: 1
11+
jobTemplate:
12+
spec:
13+
# Cleanup after 1 hour
14+
ttlSecondsAfterFinished: 3600
15+
backoffLimit: 3
16+
template:
17+
metadata:
18+
labels:
19+
app.kubernetes.io/name: warm-cache
20+
app.kubernetes.io/part-of: frontend
21+
spec:
22+
serviceAccountName: frontend
23+
restartPolicy: OnFailure
24+
initContainers:
25+
- name: warm-cache-init
26+
image: ghcr.io/stefanprodan/podinfo:6.13.0
27+
imagePullPolicy: IfNotPresent
28+
command:
29+
- /bin/sh
30+
- /scripts/warm-cache-init.sh
31+
env:
32+
- name: FRONTEND_URL
33+
value: "http://frontend"
34+
resources:
35+
limits:
36+
cpu: 100m
37+
memory: 32Mi
38+
requests:
39+
cpu: 10m
40+
memory: 16Mi
41+
volumeMounts:
42+
- name: scripts
43+
mountPath: /scripts
44+
containers:
45+
- name: warm-cache
46+
image: ghcr.io/stefanprodan/podinfo:6.13.0
47+
imagePullPolicy: IfNotPresent
48+
command:
49+
- /bin/sh
50+
- /scripts/warm-cache.sh
51+
env:
52+
- name: FRONTEND_URL
53+
value: "http://frontend"
54+
resources:
55+
limits:
56+
cpu: 100m
57+
memory: 32Mi
58+
requests:
59+
cpu: 10m
60+
memory: 16Mi
61+
volumeMounts:
62+
- name: scripts
63+
mountPath: /scripts
64+
volumes:
65+
- name: scripts
66+
configMap:
67+
name: warm-cache-script
68+
defaultMode: 0755

deploy/bases/frontend/deployment.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ spec:
2121
labels:
2222
app.kubernetes.io/name: frontend
2323
spec:
24+
serviceAccountName: frontend
2425
containers:
2526
- name: frontend
2627
image: ghcr.io/stefanprodan/podinfo:6.13.0
@@ -39,7 +40,7 @@ spec:
3940
- ./podinfo
4041
- --port=9898
4142
- --port-metrics=9797
42-
- --level=info
43+
- --level=debug
4344
- --backend-url=http://backend:9898/echo
4445
- --cache-server=tcp://cache:6379
4546
env:

deploy/bases/frontend/hpa.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ spec:
77
apiVersion: apps/v1
88
kind: Deployment
99
name: frontend
10-
minReplicas: 1
10+
minReplicas: 2
1111
maxReplicas: 4
1212
metrics:
1313
- type: Resource
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
apiVersion: kustomize.config.k8s.io/v1beta1
22
kind: Kustomization
33
resources:
4+
- serviceaccount.yaml
45
- service.yaml
56
- deployment.yaml
67
- hpa.yaml
7-
8+
- cronjob-warm-cache.yaml
9+
configMapGenerator:
10+
- name: warm-cache-script
11+
files:
12+
- scripts/warm-cache.sh
13+
- scripts/warm-cache-init.sh
14+
options:
15+
disableNameSuffixHash: true
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/sh
2+
set -e
3+
4+
# Init step for the warm-cache job.
5+
# Calls the frontend in verbose mode so the full connection, request and
6+
# response debug data (DNS, TCP, headers, timings) is dumped to the logs.
7+
8+
FRONTEND="${FRONTEND_URL:-http://frontend}"
9+
10+
echo "Dumping debug data for ${FRONTEND}/api/info"
11+
# -v writes the verbose debug data to stderr, redirect it to stdout so it
12+
# lands in the container logs together with the response body.
13+
curl -v "${FRONTEND}/api/info" 2>&1
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/bin/sh
2+
set -e
3+
4+
# This is a simulation of a cache warming process.
5+
# It fetches the frontend info, stores it in the cache under the job pod
6+
# hostname and reads it back to verify the round-trip.
7+
#
8+
# Log lines mimic the Log4j 2 default PatternLayout:
9+
# %d{yyyy-MM-dd HH:mm:ss,SSS} [%thread] %-5level %logger{36} - %msg
10+
11+
LOGGER="com.stefanprodan.podinfo.WarmCache"
12+
THREAD="main"
13+
14+
log() {
15+
level="$1"
16+
shift
17+
# millisecond precision timestamp; fall back gracefully if %N is unsupported
18+
ts="$(date '+%Y-%m-%d %H:%M:%S,%N' 2>/dev/null)"
19+
case "$ts" in
20+
*%N|*,) ts="$(date '+%Y-%m-%d %H:%M:%S'),000" ;;
21+
*) ts="$(echo "$ts" | cut -c1-23)" ;;
22+
esac
23+
printf '%s [%s] %-5s %s - %s\n' "$ts" "$THREAD" "$level" "$LOGGER" "$*"
24+
}
25+
26+
FRONTEND="${FRONTEND_URL:-http://frontend}"
27+
KEY="$(hostname)"
28+
START="$(date +%s)"
29+
30+
log INFO "Fetching info from ${FRONTEND}/api/info"
31+
# Compact the (pretty-printed) JSON onto a single line so each log event
32+
# stays on one line, as Log4j renders them.
33+
INFO="$(curl -fsS "${FRONTEND}/api/info" | tr -d '\n' | sed 's/ */ /g')"
34+
log INFO "Info: ${INFO}"
35+
36+
# Log each field of the info response on its own line. The /api/info payload
37+
# is a flat JSON object of string values, so we can split it without jq.
38+
echo "$INFO" | sed 's/^{//; s/}$//' | tr ',' '\n' | while IFS= read -r field; do
39+
field="$(echo "$field" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//; s/"//g')"
40+
if [ -n "$field" ]; then
41+
log DEBUG "info ${field}"
42+
fi
43+
done
44+
45+
log INFO "Writing info to cache key ${KEY}"
46+
curl -fsS -X POST -H "Content-Type: application/json" -d "${INFO}" "${FRONTEND}/cache/${KEY}"
47+
48+
# Verify the cached value for 1 minute, polling every 10 seconds.
49+
attempt=1
50+
while [ "$attempt" -le 6 ]; do
51+
log INFO "Reading cache key ${KEY} (attempt ${attempt}/6)"
52+
CACHED="$(curl -fsS "${FRONTEND}/cache/${KEY}")"
53+
54+
if [ "${INFO}" = "${CACHED}" ]; then
55+
log INFO "Cache warm verified: cached value matches info"
56+
else
57+
log ERROR "Cache warm failed: cached value does not match info"
58+
log ERROR "Expected: ${INFO}"
59+
log ERROR "Got: ${CACHED}"
60+
exit 1
61+
fi
62+
63+
attempt=$((attempt + 1))
64+
if [ "$attempt" -le 6 ]; then
65+
sleep 10
66+
fi
67+
done
68+
69+
log INFO "Cache warm finished in $(( $(date +%s) - START ))s"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
apiVersion: v1
2+
kind: ServiceAccount
3+
metadata:
4+
name: frontend

0 commit comments

Comments
 (0)