1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
How to write an Operator
========================
Pykube can be used to implement Kubernetes Operators. Here is how to write a very simple operator which adds a label ``foo`` with value ``bar`` to every deployment object which has the ``pykube-test-operator`` annotation:
.. code-block:: python
# simplified example script, no error handling!
import pykube, time
while True:
# loads in-cluster auth or local ~/.kube/config for testing
config = pykube.KubeConfig.from_env()
api = pykube.HTTPClient(config)
for deploy in pykube.Deployment.objects(api, namespace=pykube.all):
if 'pykube-test-operator' in deploy.annotations:
print(f'Updating deployment {deploy.namespace}/{deploy.name}..')
deploy.labels['foo'] = 'bar'
deploy.update()
time.sleep(15)
Save the above Python script as ``main.py``.
Testing
-------
You can now test the script locally with Pipenv_ and Minikube_ (run ``minikube start`` first):
.. code-block:: bash
pipenv install pykube-ng
pipenv run python3 main.py
See the operator in action by creating a deployment with the right annotation:
.. code-block:: bash
kubectl run nginx --image=nginx
kubectl annotate deploy nginx pykube-test-operator=true
The operator should should now assign the ``foo`` label to the ``nginx`` deployment.
Building the Docker image
-------------------------
Create a ``Dockerfile`` in the same directory as ``main.py``:
.. code-block:: Dockerfile
FROM python:3.7-alpine3.10
WORKDIR /
RUN pip3 install pykube-ng
COPY main.py /
ENTRYPOINT ["python3", "main.py"]
Now build it:
.. code-block:: bash
docker build -t pykube-test-operator .
You need to push the Docker image to some Docker registry before you can deploy it.
Deployment
----------
Now deploy the Docker image to your Kubernetes cluster using a service account with the necessary permissions (in this case to list and update deployments).
To create such an service account with the necessary RBAC rights create ``rbac.yaml`` with these contents:
.. code-block:: yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: pykube-test-operator
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pykube-test-operator
rules:
- apiGroups:
- apps
resources:
- deployments
verbs:
- get
- watch
- list
- update
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: pykube-test-operator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: pykube-test-operator
subjects:
- kind: ServiceAccount
name: pykube-test-operator
namespace: default
Apply the RBAC role via ``kubectl apply -f rbac.yaml``.
Finally, the deployment of the operator would then look like (``deployment.yaml``):
.. code-block:: yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: pykube-test-operator
spec:
replicas: 1
selector:
matchLabels:
app: pykube-test-operator
template:
metadata:
labels:
app: pykube-test-operator
spec:
serviceAccountName: pykube-test-operator
containers:
- name: operator
# this image needs have been pushed to some Docker registry!
image: pykube-test-operator
resources:
limits:
memory: 50Mi
requests:
cpu: 5m
memory: 50Mi
securityContext:
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
Create the deployment via ``kubectl apply -f deployment.yaml``.
You should now have a working operator deployment in your cluster.
.. _Pipenv: https://pipenv.readthedocs.io/en/latest/
.. _Minikube: https://github.com/kubernetes/minikube
|