Kubernetes¶
Run the importer as a CronJob (run-once on a schedule) or a Deployment (long-running with internal cron). The CronJob pattern is more idiomatic for Kubernetes and avoids the SCHEDULE env var.
Pattern 1 — CronJob (recommended)¶
Let Kubernetes own the schedule; let the importer be a one-shot job.
apiVersion: batch/v1
kind: CronJob
metadata:
name: israeli-bank-importer
spec:
schedule: "0 */8 * * *"
timeZone: "Asia/Jerusalem"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
backoffLimit: 1
template:
spec:
restartPolicy: OnFailure
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
containers:
- name: importer
image: sergienko4/israeli-bank-importer:latest
imagePullPolicy: IfNotPresent
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
add:
- SYS_ADMIN
readOnlyRootFilesystem: false
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 2Gi
cpu: "1.5"
env:
- name: TZ
value: Asia/Jerusalem
- name: CREDENTIALS_ENCRYPTION_PASSWORD
valueFrom:
secretKeyRef:
name: importer-encryption
key: password
volumeMounts:
- name: config
mountPath: /app/config.json
subPath: config.json
readOnly: true
- name: data
mountPath: /app/data
- name: cache
mountPath: /app/cache
- name: logs
mountPath: /app/logs
- name: shm
mountPath: /dev/shm
volumes:
- name: config
secret:
secretName: importer-config
- name: data
persistentVolumeClaim:
claimName: importer-data
- name: cache
emptyDir: {}
- name: logs
emptyDir: {}
- name: shm
emptyDir:
medium: Memory
sizeLimit: 256Mi
Pattern 2 — Deployment (long-running)¶
Use this if you want to keep the Telegram bot's long-polling alive 24/7.
apiVersion: apps/v1
kind: Deployment
metadata:
name: israeli-bank-importer
spec:
replicas: 1
strategy:
type: Recreate # never run two pollers at once
selector:
matchLabels: { app: israeli-bank-importer }
template:
metadata:
labels: { app: israeli-bank-importer }
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
containers:
- name: importer
image: sergienko4/israeli-bank-importer:latest
env:
- name: TZ
value: Asia/Jerusalem
- name: SCHEDULE
value: "0 */8 * * *"
- name: CREDENTIALS_ENCRYPTION_PASSWORD
valueFrom:
secretKeyRef:
name: importer-encryption
key: password
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
add: [SYS_ADMIN]
resources:
requests: { memory: 512Mi, cpu: 250m }
limits: { memory: 2Gi, cpu: "1.5" }
volumeMounts:
- { name: config, mountPath: /app/config.json, subPath: config.json, readOnly: true }
- { name: data, mountPath: /app/data }
- { name: cache, mountPath: /app/cache }
- { name: logs, mountPath: /app/logs }
- { name: shm, mountPath: /dev/shm }
volumes:
- name: config
secret: { secretName: importer-config }
- name: data
persistentVolumeClaim: { claimName: importer-data }
- name: cache
emptyDir: {}
- name: logs
emptyDir: {}
- name: shm
emptyDir: { medium: Memory, sizeLimit: 256Mi }
Resource limits¶
Both patterns set resources.limits.memory: 2Gi. Keep it. A stalled bank scrape can strand a browser process; without a limit the pod keeps allocating node RAM until the kubelet evicts unrelated workloads or the node stops responding. With the limit, only this pod is OOM-killed.
The 2 Gi figure is measured: ~200 MB Node baseline + ~1 GB worst-case bank browser + ~300 MB receipt OCR + headroom. Setting NODE_OPTIONS=--max-old-space-size instead does not work — it caps only the JS heap, while most of the footprint is native browser memory.
Secrets¶
Use Sealed Secrets or SOPS for credentials in Git. Never commit raw config.json.
# Plain config-from-file (development)
kubectl create secret generic importer-config \
--from-file=config.json=./config.json
# Production: encrypt with sealed-secrets or sops first
Health and observability¶
- Container logs → stdout (
logConfig.format: "json"for Loki/ELK ingestion). - Annotate the namespace for Prometheus pod-scrape if you front the importer with a sidecar metrics exporter (not bundled — see Roadmap).
See also¶
- Encrypted config (recommended even with k8s secrets)
- Scheduling
- Logging