Skip to main content

flickr-immich-k8s-sync-operator

black-lint mypy and pytests Cumulative Clones Docker Pulls PyPI Downloads

Gemini_Generated_Image_gwjk7ggwjk7ggwjk_250x250.png

Kubernetes operator that watches per-user Flickr download Jobs in a namespace, restarts failed Jobs after a configurable delay, and retrieves pod logs and exit codes for failed Jobs before restarting them. Designed to run alongside Immich (self-hosted photo management).

Screenshots

Operator startup with configuration overview

Operator monitoring jobs across multiple check cycles

Operator detecting failures and scheduling restarts

Status

Beta (v0.0.4) — the core job-restart loop is stable and actively deployed. OOMKilled-aware restart logic, structured startup/configuration logging, and full CI (black + mypy + pytest) are in place.

Architecture

  • Runs as a single-replica Deployment in a dedicated namespace (default: flickr-downloader)
  • Uses the Kubernetes Python client with in-cluster config
  • Periodically checks configured Job names for failure conditions
  • On failure (after a configurable delay), deletes the Job with Foreground propagation policy and recreates it from a cached manifest
  • Logs pod exit codes and tail logs before every restart

How it works

  1. An Ansible playbook (kubectlstuff_flickr_downloader.yml) creates per-user Flickr download Jobs in the flickr-downloader namespace
  2. Each Job runs flickr_download with BACKOFF_EXIT_ON_429=true, so it exits immediately on HTTP 429 rate-limit errors instead of sleeping
  3. Jobs mount host directories for config, backup, and cache per user
  4. This operator watches all configured Jobs for failure conditions
  5. When a Job fails, the operator logs pod exit codes and tail logs, waits RESTART_DELAY seconds (default 1 hour), then deletes and recreates the Job from a cached manifest
  6. The operator uses namespace-scoped RBAC with minimal permissions (Jobs, Pods, Pod logs)

Prerequisites

  • A running Kubernetes cluster
  • Per-user Flickr download Jobs already deployed (e.g. via the Ansible playbook above) — the operator manages their lifecycle (restart on failure), not initial creation
  • An Immich instance (for planned sync functionality)

Configuration

Variable Description Default
LOGURU_LEVEL Log verbosity (DEBUG, INFO, WARNING, …) DEBUG
NAMESPACE Namespace to watch flickr-downloader
JOB_NAMES Comma-separated Job names to monitor (required) —
CHECK_INTERVAL Seconds between check cycles 60
RESTART_DELAY Seconds to wait after failure before restart 3600
SKIP_DELAY_ON_OOM Skip restart delay when failure reason is OOMKilled false

Kubernetes Deployment

RBAC

The operator requires a ServiceAccount with a Role scoped to the target namespace:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: flickr-operator
  namespace: flickr-downloader
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: flickr-operator
  namespace: flickr-downloader
rules:
  - apiGroups: ["batch"]
    resources: ["jobs"]
    verbs: ["get", "list", "create", "delete"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "delete"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: flickr-operator
  namespace: flickr-downloader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: flickr-operator
subjects:
  - kind: ServiceAccount
    name: flickr-operator
    namespace: flickr-downloader

Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flickr-operator
  namespace: flickr-downloader
spec:
  replicas: 1
  selector:
    matchLabels:
      app: flickr-operator
  template:
    metadata:
      labels:
        app: flickr-operator
    spec:
      serviceAccountName: flickr-operator
      containers:
        - name: operator
          image: xomoxcc/flickr-immich-k8s-sync-operator:latest
          env:
            - name: JOB_NAMES
              value: "flickr-downloader-alice,flickr-downloader-bob"
            - name: LOGURU_LEVEL
              value: "DEBUG"
            # - name: NAMESPACE
            #   value: "flickr-downloader"      # default
            # - name: CHECK_INTERVAL
            #   value: "60"                      # default
            # - name: RESTART_DELAY
            #   value: "3600"                    # default
            # - name: SKIP_DELAY_ON_OOM
            #   value: "false"                   # default
          resources:
            requests:
              cpu: 50m
              memory: 64Mi
            limits:
              cpu: 1500m
              memory: 128Mi

Installation

From PyPI

pip install flickr-immich-k8s-sync-operator

From source

git clone https://github.com/vroomfondel/flickr-immich-k8s-sync-operator.git
cd flickr-immich-k8s-sync-operator
make venv
source .venv/bin/activate
pip install .

Docker

docker build -t flickr-immich-k8s-sync-operator .
docker run --rm flickr-immich-k8s-sync-operator

Or via Makefile:

make docker

Usage

# Run directly
flickr-immich-k8s-sync-operator

# Or via Python module
python -m flickr_immich_k8s_sync_operator

Development

Makefile targets

Target Description
make venv Create virtualenv and install all dependencies
make tests Run pytest
make lint Format code with black (line length 120)
make isort Sort imports with isort
make tcheck Static type checking with mypy
make commit-checks Run pre-commit hooks on all files
make prepare Run tests + commit-checks
make pypibuild Build sdist + wheel with hatch
make pypipush Publish to PyPI with hatch
make docker Build Docker image
make gitleaks Run gitleaks secret scanner via pre-commit
make update-all-dockerhub-readmes Push DOCKERHUB_OVERVIEW.md to Docker Hub repo description

License

GNU Lesser General Public License v3

Metadata

Release files for flickr-immich-k8s-sync-operator 0.0.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for flickr-immich-k8s-sync-operator 0.0.7
File Size Uploaded Provenance Actions
flickr_immich_k8s_sync_operator-0.0.7.tar.gz 13.1 kB Without provenance Details for flickr_immich_k8s_sync_operator-0.0.7.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for flickr-immich-k8s-sync-operator 0.0.7
File Interpreter ABI Platform Actions
flickr_immich_k8s_sync_operator-0.0.7-py3-none-any.whl Python 3 none any Details for flickr_immich_k8s_sync_operator-0.0.7-py3-none-any.whl

Total release size: 28.0 kB

Release files / flickr_immich_k8s_sync_operator-0.0.7.tar.gz

Download URL flickr_immich_k8s_sync_operator-0.0.7.tar.gz
Size 13.1 kB
Tags Source
SHA-256 checksum
How to use checksums
456bc356af13c075e5624912d883de8f2ae8579e99192d330a77748785ad8be5
BLAKE2b-256 checksum
How to use checksums
6907436d9637df8f5d6fed5a9ea276f2acafd0c8353d1c77051fbf3bbafdbba2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via Hatch/1.18.2 {"ci":null,"cpu":"x86_64","distro":{"id":"resolute","libc":{"lib":"glibc","version":"2.43"},"name":"Ubuntu","version":"26.04"},"implementation":{"name":"CPython","version":"3.14.4"},"installer":{"name":"hatch","version":"1.18.2"},"openssl_version":"OpenSSL 3.5.6 7 Apr 2026","python":"3.14.4","system":{"name":"Linux","release":"7.3.1-custom"}} HTTPX2/2.16.0

Release files / flickr_immich_k8s_sync_operator-0.0.7-py3-none-any.whl

Download URL flickr_immich_k8s_sync_operator-0.0.7-py3-none-any.whl
Size 14.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e0e0b9c5a9645d6514cf855da4f3760d784bb4b87f170eaac463eb1c1c033077
BLAKE2b-256 checksum
How to use checksums
ecc79d7d71f966e451349cccdcf43037f1d17306811f3b6e0f3764358f427087
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via Hatch/1.18.2 {"ci":null,"cpu":"x86_64","distro":{"id":"resolute","libc":{"lib":"glibc","version":"2.43"},"name":"Ubuntu","version":"26.04"},"implementation":{"name":"CPython","version":"3.14.4"},"installer":{"name":"hatch","version":"1.18.2"},"openssl_version":"OpenSSL 3.5.6 7 Apr 2026","python":"3.14.4","system":{"name":"Linux","release":"7.3.1-custom"}} HTTPX2/2.16.0

Security for flickr-immich-k8s-sync-operator 0.0.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page