Skip to content
This repository has been archived by the owner on Sep 14, 2020. It is now read-only.

Commit

Permalink
Add an example for built-in pods controller
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergey Vasilyev committed Jun 18, 2019
1 parent d3e23ab commit 125c5d0
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
43 changes: 43 additions & 0 deletions examples/09-builtins/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Kopf example for built-in resources

Kopf can also handle the built-in resources, such as Pods, Jobs, etc.

In this example, we take control all over the pods (namespaced/cluster-wide),
and allow the pods to exist for no longer than 30 seconds --
either after creation or after the operator restart.

For no specific reason, just for fun. Maybe, as a way of Chaos Engineering
to force making the resilient applications (tolerant to pod killing).

However, the system namespaces (kube-system, etc) are explicitly protected --
to prevent killing the cluster itself.

Start the operator:

```bash
kopf run example.py --verbose
```

Start a sample pod:

```bash
kubectl run -it --image=ubuntu expr1 -- bash -i
# wait for 30s
```

Since `kubectl run` creates a Deployment, not just a Pod,
a new pod will be created every 30 seconds. Observe with:

```bash
kubectl get pods --watch
```

*Please note that Kopf puts a finalizer on the managed resources,
so the pod deletion will be blocked unless the operator is running
(to remove the finalizer). This will be made optional in #24.*

Cleanup in the end:

```bash
$ kubectl delete deployment expr1
```
43 changes: 43 additions & 0 deletions examples/09-builtins/example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import asyncio

import kopf
import pykube

TIMEOUT = 30
tasks = {} # dict{namespace: dict{name: asyncio.Task}}


@kopf.on.resume('', 'v1', 'pods')
@kopf.on.create('', 'v1', 'pods')
async def pod_in_sight(namespace, name, logger, **kwargs):
if namespace.startswith('kube-'):
return
else:
task = asyncio.create_task(pod_killer(namespace, name, logger))
tasks.setdefault(namespace, {})
tasks[namespace][name] = task


@kopf.on.delete('', 'v1', 'pods')
async def pod_deleted(namespace, name, **kwargs):
if namespace in tasks and name in tasks[namespace]:
task = tasks[namespace][name]
task.cancel() # it will also remove from `tasks`


async def pod_killer(namespace, name, logger):
try:
logger.info(f"=== Pod killing happens in {TIMEOUT}s.")
await asyncio.sleep(TIMEOUT)
logger.info(f"=== Pod killing happens NOW!")

api = kopf.get_pykube_api()
pod = pykube.Pod.objects(api, namespace=namespace).get_by_name(name)
pod.delete()

except asyncio.CancelledError:
logger.info(f"=== Pod killing is cancelled!")

finally:
if namespace in tasks and name in tasks[namespace]:
del tasks[namespace][name]

0 comments on commit 125c5d0

Please sign in to comment.