Skip to content

Kubernetes

You can deploy Atfinity in a Kubernetes Cluster. For this, we provide a helm chart, that also includes descriptions of necessary dependencies.

Note: All support files and credentials are available via your dedicated support agent.

Requirements

Atfinity needs a Kubernetes cluster (at least Version 1.27) that can be prepared to run Atfinity. It needs to be possible to install a custom ingress and cert manager in the cluster. If you would like to run an external database (MariaDB and MySQL, inquire for versions) those also need to be available in a recent version. Apart from that, no further components are required.

Preparing the cluster

Atfinity needs a few components to be installed in the cluster.

  • Atfinity Registry Secrets (will be provided through your support agent)
  • NGINX Ingress
  • Cert Manager

Our readme file outlines our recommended installation procedure.

Installation

Once you have all the necessary credentials and a prepared cluster, you can install or upgrade a release like this

helm upgrade --install NAME oci://atfinity.azurecr.io/helm/atfinity --version 16.0.0

Make sure to change the version to the one you would like to install.

List and description of Pods

"api" Pod

This pod runs the backend of Atfinity. It provides the API for both external systems and the Atfinity Frontend. This pod mounts a persistent volume to store all uploaded files.

The api and api-sse containers declare a startup, a liveness and a readiness probe. Startup probes /health/live and gates the other two until the container first answers, so an upgrade whose migrations run long completes without a restart. Liveness probes /health/live as well and reads no dependency, so a database that refuses connections marks the pod not ready without restarting it. Readiness probes /health/ready, which reads only the database and the cache, so a pod whose Elasticsearch is unreachable stays in the Service. The api-celery container carries no probe; its worker script exits when a worker dies and Kubernetes restarts the container. The deployment runs a single replica with strategy: Recreate, so readiness decides when the Service resumes sending traffic after a restart rather than handing over between replicas.

Period, timeout and failure threshold of each probe are set under api.probes in the Helm values: api.probes.startup, api.probes.liveness and api.probes.readiness. The startup budget is split into apiFailureThreshold and sseFailureThreshold, because only the api container waits for migrations.

"mariadb" Pod (optional)

This runs a MariaDB, to be used as the Atfinity database if you do not choose the external option. All data points about configuration and clients will be stored here. The pod uses a persistent volume for the database.

"elastic" Pod

An ephemeral Elasticsearch is used to provide overviews and full text search.

"web" Pod

This runs a hardened nginx server to serve the web frontend application.

"euw" Pod (optional)

This runs the End User Wizard (EUW), a Next.js application that provides externally facing wizard forms. Enabled by setting wizard.enabled: true in the Helm values. The EUW is served on its own hostname.

Routes overview (ingress)

  • /api/1 serves the API backend
  • /auth/ serves the Atfinity login page
  • / serves the Atfinity web frontend
  • wizard.host (separate hostname) serves the End User Wizard (when enabled)

Metrics

The api pod serves Prometheus metrics on /metrics on port 17001, in the Prometheus text format. The ingress does not route this path, so it is only reachable from inside the cluster. The metrics are the request counts of the API by endpoint, HTTP method and status code, the request latencies by endpoint and method, the request and response sizes, and the process metrics of the Python runtime.

By default the chart annotates the api pod with prometheus.io/scrape, prometheus.io/port and prometheus.io/path, so a Prometheus that discovers targets by annotation picks the pod up without further configuration. Set api.prometheusScrapeAnnotations: false in your values to leave the annotations out, for example when scraping is configured through a ServiceMonitor or a static target instead.