# Kopf > # Kubernetes Operator Pythonic Framework (Kopf) > > [![GitHub](https://img.shields.io/github/stars/nolar/kopf?style=flat&label=GitHub%E2%AD%90%EF%B8%8F)](https://github.com/nolar/kopf) > [![CI](https://github.com/nolar/kopf/actions/workflows/thorough.yaml/badge.svg)](https://github.com/nolar/kopf/actions/workflows/thorough.yaml) > [![Supported Python versions](https://img.shields.io/pypi/pyversions/kopf.svg)](https://pypi.org/project/kopf/) > [![codecov](https://codecov.io/gh/nolar/kopf/branch/main/graph/badge.svg)](https://codecov.io/gh/nolar/kopf) > [![coverage](https://coveralls.io/repos/github/nolar/kopf/badge.svg?branch=main)](https://coveralls.io/github/nolar/kopf?branch=main) > > **Kopf** — Kubernetes Operator Pythonic Framework — is a framework and a library > to make Kubernetes operator development easier, in just a few lines of Python code. > > The main goal is to bring the Domain-Driven Design to the infrastructure level, > with Kubernetes being an orchestrator/database of the domain objects (custom resources), > and the operators containing the domain logic (with no or minimal infrastructure logic). > > The project was originally started as `zalando-incubator/kopf` in March 2019, > and then forked as `nolar/kopf` in August 2020 — but it is the same codebase, > the same packages, the same developer(s). > > ## Documentation > > * https://docs.kopf.dev/ > > ## Status > > Kopf is production-ready and stable (semantic v1). > Major bugs are fixed ASAP (there were none for a long time). > Minor bugs are fixed as time and energy permit, or a workaround is provided. > > There is no active development of **new major** functionality for Kopf — the whole idea of a framework for operators is fully expressed and implemented, I have nothing more to add. This piece of art is finished. (This might change.) > > Minor feature requests can be implemented from time to time. > Maintenance for new versions of Python and Kubernetes is performed regularly. > Some internal optimizations are planned, such as minimizing the memory footprint, high-load readiness, or agentic friendliness — but will be backwards-compatible (no semantic v2 with breaking changes on the horizon). > > ## Features > > * Simple, but powerful: > * A full-featured operator in just 2 files: a `Dockerfile` + a Python file (*). > * Handling functions registered via decorators with a declarative approach. > * No infrastructure boilerplate code for K8s API communication. > * Both sync and async handlers, with sync ones being threaded under the hood. > * Detailed documentation with examples. > * Intuitive mapping of Python concepts to Kubernetes concepts and back: > * Marshalling of resources' data to the handlers' kwargs. > * Marshalling of handlers' results to the resources' statuses. > * Publishing of logging messages as Kubernetes events linked to the resources. > * Support for anything that exists in K8s: > * Custom K8s resources. > * Built-in K8s resources (pods, namespaces, etc). > * Multiple resource types in one operator. > * Both cluster and namespaced operators. > * All the ways of handling that a developer can wish for: > * Low-level handlers for events received from K8s APIs "as is" (an equivalent of _informers_). > * High-level handlers for detected causes of changes (creation, updates with diffs, deletion). > * Handling of selected fields only instead of the whole objects (if needed). > * Dynamically generated or conditional sub-handlers (an advanced feature). > * Timers that tick as long as the resource exists, optionally with a delay since the last change. > * Daemons that run as long as the resource exists (in threads or asyncio-tasks). > * Validating and mutating admission webhook (with dev-mode tunneling). > * Live in-memory indexing of resources or their excerpts. > * Filtering with stealth mode (no logging): by arbitrary filtering functions, > by labels/annotations with values, presence/absence, or dynamic callbacks. > * In-memory all-purpose containers to store non-serializable objects for individual resources. > * Eventual consistency of handling: > * Retrying the handlers in case of arbitrary errors until they succeed. > * Special exceptions to request a special retry or to never retry again. > * Custom limits for the number of attempts or the time allowed. > * Implicit persistence of the progress that survives the operator restarts. > * Tolerance to restarts and lengthy downtimes: handles the changes afterwards. > * Awareness of other Kopf-based operators: > * Configurable identities for different Kopf-based operators for the same resource kinds. > * Avoiding double-processing due to cross-pod awareness of the same operator ("peering"). > * Pausing of a deployed operator when a dev-mode operator runs outside of the cluster. > * Extra toolkits and integrations: > * Some limited support for object hierarchies with name/labels propagation. > * Friendly to any K8s client libraries (and is client agnostic). > * Startup/cleanup operator-level handlers. > * Liveness probing endpoints and rudimentary metrics exports. > * Basic testing toolkit for in-memory per-test operator running. > * Embeddable into other Python applications. > * Highly configurable (to some reasonable extent). > > (*) _Small font: two files of the operator itself, plus some amount of > deployment files like RBAC roles, bindings, service accounts, network policies > — everything needed to deploy an application in your specific infrastructure._ > > > ## Examples > > See [examples](https://github.com/nolar/kopf/tree/main/examples) > for examples of typical use cases. > > A minimalistic operator can look like this: > > ```python > import kopf > > @kopf.on.create('kopfexamples') > def create_fn(spec, name, meta, status, **kwargs): > print(f"And here we are! Created {name} with spec: {spec}") > ``` > > Numerous kwargs are available, such as `body`, `meta`, `spec`, `status`, > `name`, `namespace`, `retry`, `diff`, `old`, `new`, `logger`, etc: > see [Arguments](https://docs.kopf.dev/en/latest/kwargs/) > > To run a never-exiting function for every resource as long as it exists: > > ```python > import time > import kopf > > @kopf.daemon('kopfexamples') > def my_daemon(spec, stopped, **kwargs): > while not stopped: > print(f"Object's spec: {spec}") > time.sleep(1) > ``` > > Or the same with the timers: > > ```python > import kopf > > @kopf.timer('kopfexamples', interval=1) > def my_timer(spec, **kwargs): > print(f"Object's spec: {spec}") > ``` > > That's easy! For more features, see the [documentation](https://docs.kopf.dev/). > > > ## Usage > > Python 3.10+ is required: > [CPython](https://www.python.org/) and [PyPy](https://www.pypy.org/) > are officially supported and tested; other Python implementations can work too. > > We assume that when the operator is executed in the cluster, it must be packaged > into a docker image with a CI/CD tool of your preference. > > ```dockerfile > FROM python:3.14 > ADD . /src > RUN pip install kopf > CMD kopf run /src/handlers.py --verbose > ``` > > Where `handlers.py` is your Python script with the handlers > (see `examples/*/example.py` for examples). > > For quick experimentation, a pre-built image with all extras is available > on GHCR — just mount your operator file and go: > > ```bash > # Minimize the credentials exposure. > kubectl config view --minify --flatten > dev.kubeconfig > > # Run the operator locally, target a local cluster (host networking). > docker run --rm -it --network=host \ > -v ./handlers.py:/app/main.py:ro \ > -v ./dev.kubeconfig:/root/.kube/config:ro \ > ghcr.io/nolar/kopf > ``` > > See the [Docker image documentation](https://docs.kopf.dev/en/latest/docker/) > for more details. > > See `kopf run --help` for other ways of attaching the handlers. > > > ## Contributing > > Please read [CONTRIBUTING.md](https://github.com/nolar/kopf/blob/main/CONTRIBUTING.md) > for details on our process for submitting pull requests to us, and please ensure > you follow the [CODE_OF_CONDUCT.md](https://github.com/nolar/kopf/blob/main/CODE_OF_CONDUCT.md). > > To install the environment for the local development, > read [DEVELOPMENT.md](https://github.com/nolar/kopf/blob/main/DEVELOPMENT.md). > > > ## Versioning > > We use [SemVer](http://semver.org/) for versioning. For the versions available, > see the [releases on this repository](https://github.com/nolar/kopf/releases). > > > ## License > > This project is licensed under the MIT License — > see the [LICENSE](https://github.com/nolar/kopf/blob/main/LICENSE) file for details. > > > ## Acknowledgments > > * Thanks to Zalando for starting this project in Zalando's Open-Source Incubator > in the first place. > * Thanks to [@side8](https://github.com/side8) and their [k8s-operator](https://github.com/side8/k8s-operator) > for inspiration. 2020-2026 Sergey Vasilyev; 2019-2020 Zalando SE ## Pages - [Error handling](errors/index.html.md): Kopf tracks the status of the handlers (except for the low-level event handlers), - [Command-line options](cli/index.html.md): Most of the options relate to `kopf run`, though some are shared by other - [Kopf: Kubernetes Operators Framework](index.html.md): * [Installation](install.md) - [Health-checks](probing/index.html.md): Kopf provides a minimalistic HTTP server to report its health status. - [Troubleshooting](troubleshooting/index.html.md): This can happen if the operator is down at the moment of deletion. - [Reconciliation](reconciliation/index.html.md): Reconciliation is, in plain words, bringing the *actual state* of a system - [Minikube](minikube/index.html.md): To develop the framework and operators in an isolated Kubernetes cluster, - [Daemons](daemons/index.html.md): Daemons are a special type of handlers for background logic that accompanies - [Impressum & Datenschutz](impressum/index.html.md): For the Impressum & Datenschutz documents, see the main website: - [Critiques](critiques/index.html.md): > Critique is a constructive, detailed analysis aimed at improvement, focusing on both strengths and... - [Naming](naming/index.html.md): Kopf is an abbreviation either for - [Resource specification](resources/index.html.md): The following notations are supported to specify the resources to be handled. - [Vision](vision/index.html.md): Kubernetes [has become a de facto standard](https://www.google.com/search?q=kubernetes+standard+de+f... - [Events](events/index.html.md): Kubernetes itself contains a terminology conflict: - [Continuity](continuity/index.html.md): Kopf does not have any database. It stores all the information directly - [Docker image](docker/index.html.md): Kopf provides pre-built Docker images on the GitHub Container Registry (GHCR) - [Peering](peering/index.html.md): All running operators communicate with each other via peering objects - [Startup](startup/index.html.md): The startup handlers are slightly different from the module-level code: - [Concepts](concepts/index.html.md): **Kubernetes** is a container orchestrator. - [Alternatives](alternatives/index.html.md): The closest equivalent of Kopf is [Metacontroller](https://metacontroller.github.io/metacontroller/)... - [Operator testing](testing/index.html.md): Kopf provides some tools for testing Kopf-based operators - [Shutdown](shutdown/index.html.md): The cleanup handlers are executed when the operator exits, - [Development Status](status/index.html.md): Kopf is production-ready and stable (semantic v1). - [Idempotence](idempotence/index.html.md): Kopf provides tools to make the handlers idempotent. - [In-memory containers](memos/index.html.md): Kopf provides several ways of storing and exchanging the data in-memory - [Scopes](scopes/index.html.md): An operator can be restricted to handling custom resources in one namespace only: - [Hierarchies](hierarchies/index.html.md): One of the most common operator patterns is to create - [Arguments](kwargs/index.html.md): `**kwargs` is required in all handlers for forward compatibility: - [Authentication](authentication/index.html.md): To access a Kubernetes cluster, an endpoint and some credentials are needed. - [Deployment](deployment/index.html.md): Kopf can be run outside the cluster, as long as the environment is - [In-memory indexing](indexing/index.html.md): Indexers automatically maintain in-memory overviews of resources (indices), - [Installation](install/index.html.md): Prerequisites: - [Embedding](embedding/index.html.md): Kopf is designed to be embeddable into other applications that require - [Results delivery](results/index.html.md): All handlers can return arbitrary JSON-serializable values. - [Admission control](admission/index.html.md): Admission hooks are callbacks from Kubernetes to the operator before - [Contributing](contributing/index.html.md): In a nutshell, to contribute, follow this scenario: - [Architecture](architecture/index.html.md): The framework is organized into several layers, which are themselves layered. - [Handlers](handlers/index.html.md): Handlers are Python functions with the actual behavior - [Timers](timers/index.html.md): Timers are schedules of regular handler execution as long as the object exists, - [Filtering](filters/index.html.md): Handlers can be restricted to only the resources that match certain criteria. - [Loading and importing](loading/index.html.md): Kopf requires the source files with the handlers to be specified on the command line. - [Configuration](configuration/index.html.md): It is possible to fine-tune some aspects of Kopf-based operators, - [Patching](patches/index.html.md): Handlers can modify the Kubernetes resource they are handling - [Tips & Tricks](tips-and-tricks/index.html.md): Both successful executions and permanent errors of change-detecting handlers - [Async/Await](async/index.html.md): Kopf supports asynchronous handler functions: - [kopf.on module](packages/kopf.on/index.html.md): The decorators for the event handlers. Usually used as: - [kopf package](packages/kopf/index.html.md): The main Kopf module for all the exported functions and classes. - [kopf.testing module](packages/kopf.testing/index.html.md): Helper tools to test the Kopf-based operators. - [kopf.cli module](packages/kopf.cli/index.html.md): Bases: [`object`](https://docs.python.org/3/library/functions.html#object) - [Cascaded deletion](walkthrough/deletion/index.html.md): Previously ([Creating the objects](creation.md) & [Updating the objects](updates.md) & [Diffing the ... - [Custom Resources](walkthrough/resources/index.html.md): Let us define a CRD (custom resource definition) for our object: - [Cleanup](walkthrough/cleanup/index.html.md): To clean up the cluster after all the experiments are finished: - [Starting the operator](walkthrough/starting/index.html.md): Previously, we have defined a [problem](problem.md) that we are solving, - [Diffing the fields](walkthrough/diffs/index.html.md): Previously ([Updating the objects](updates.md)), we set up cascaded updates so that - [Updating the objects](walkthrough/updates/index.html.md): Unfortunately, Minikube cannot handle the PVC/PV resizing, - [Sample Problem](walkthrough/problem/index.html.md): Throughout this user documentation, we solve - [Environment Setup](walkthrough/prerequisites/index.html.md): We need a running Kubernetes cluster and some tools for our experiments. - [Creating the objects](walkthrough/creation/index.html.md): Previously ([Starting the operator](starting.md)), --- For more comprehensive documentation, see [llms-full.txt](llms-full.txt)