Skip to content

Commit

Permalink
Include a new Kubernetes event source
Browse files Browse the repository at this point in the history
This commit includes a new events source
plugin for monitoring changes in a Kubernetes cluster.
This plugin enables the usage of any API class
from the Kubernetes Python client.

Closes: ansible#36
Closes: ansible#37
  • Loading branch information
ccamacho committed Jun 13, 2023
1 parent 778f623 commit 62e8184
Show file tree
Hide file tree
Showing 17 changed files with 501 additions and 4 deletions.
4 changes: 2 additions & 2 deletions demos/dynatrace-demo/instructions.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Ansible Rulebook + Dynatrace DEMO

## Description
In this demo we will register a host to Dynatrace and set up a webhook to send
In this demo, we will register a host to Dynatrace and set up a webhook to send
problem notifications to ansible-rulebook CLI. Dynatrace monitors the
availability of a process. Upon receiving a problem notification the ansible-
rulebook CLI runs a remedy playbook to restart the process.
Expand Down Expand Up @@ -30,7 +30,7 @@ crashing.
3. Update `inventory.yml` with correct ip and user to access the client node
4. Start the rulebook CLI:
```
ansible-rulebook -i demos/dynatrace-demo/inventory.yml --rules demos/dynatrace-demo/rulebook.yml
ansible-rulebook -i demos/dynatrace-demo/inventory.yml -r demos/dynatrace-demo/rulebook.yml
```
This rulebook starts an alertmanager source that listens on port 5050

Expand Down
7 changes: 7 additions & 0 deletions demos/kubernetes/example_playbook.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
- name: Example triggered playbook
hosts: localhost
tasks:
- name: Print a debug message
ansible.builtin.debug:
msg: This is just an example of a triggered event
137 changes: 137 additions & 0 deletions demos/kubernetes/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Ansible Rulebook + Kubernetes

## Description

In this demo, we will configure a single-node K8s development environment,
and we will set up ansible-rulebook CLI to consume events from the
cluster using the Kubernetes event source. Upon triggering this watcher
method the ansible-rulebook CLI will run a playbook to execute any additional
action in response to this event.

## Instructions

### Installing a development environment

The method to install a small development environment is straightforward. The reasoning
for choosing K3D is based on the fact that GitHub actions support Ubuntu with Docker so
the next steps can be easily integrated into a functional end-to-end GitHub actions workflow.

```
# Installing kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
# Installing K3D
curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash
# Creating a cluster
k3d cluster create testcluster --api-port 6443 --servers 1 --agents 1 --port "30500-31000:30500-31000@server:0"
# Test the cluster
kubectl get nodes
```

### Rulebook return parameters

When an event is triggered and returned, there are two keys in the
result dictionary, `type`, and `resource`.

These output parameters come from the
[stream method](https://github.com/kubernetes-client/python/blob/master/kubernetes/base/watch/watch.py#L116)
in the watch class monitoring for changes in the state of the cluster.

The possible values of type are the types of event such as "ADDED", "DELETED", etc.
The resource value is a dictionary representing the watched object.

For example, a condition that can be monitored is:

```
condition: event.type == "ADDED" and event.resource.kind == 'Pod'
```

The previous condition will be met after there was `ADDED` a new object of the kind `Pod`.

For the further implementation of additional rules, the user must know the
representation of the watched object.
This logic will be handled in the rulebook rules and not in the event source plugin
enabling users to use the Python Kubernetes client without restrictions.

### Monitoring resources

For a better reference review the main list of APIs and methods that are
[supported](https://github.com/kubernetes-client/python/blob/master/kubernetes/README.md).

#### Monitoring for new ADDED Pods

1. Have ansible-rulebook CLI and its dependencies installed
2. Have ansible.eda collection installed with the Kubernetes event source
3. Start the rulebook CLI:
```
# Go to the Kubernetes demos folder and run:
ansible-rulebook -i inventory.yml -r rulebook_monitor_pods.yml
```
4. Once the ansible-rulebook is running, add a pod to the cluster by running:
```
kubectl apply -f k8s_deployment_no_namespace.yml
```

An event for the new Pod creation should be triggered and
the `demos/kubernetes/example_playbook.yml` playbook executed.

#### Monitoring for a new ADDED deployment

It is possible also to monitor deployments, for instance,
run the rulebook to check the status of the deployments:

```
ansible-rulebook -i inventory.yml -r rulebook_monitor_deployment.yml
```

Or by namespaces:

```
ansible-rulebook -i inventory.yml -r rulebook_monitor_deploymentns.yml
```

And then create the deployments:

```
kubectl apply -f k8s_deployment_no_namespace.yml
```

Or create a deployment in a namespace:

```
kubectl apply -f k8s_deployment_namespace.yml
kubectl apply -f k8s_deployment_with_namespace.yml
```

#### Monitoring for a new ADDED custom resource

Custom resources can be monitored also, any resource as long it has
a valid API and method to watch for changes should work without any
major change.

Let's watch for changes in the CR.

```
ansible-rulebook -i inventory.yml -r rulebook_monitor_cr.yml
```

Create a custom resource definition with its custom object:
```
kubectl apply -f k8s_crontab_crd.yml
kubectl apply -f k8s_crontab_cr.yml
```

#### Monitoring for a new ADDED config maps

It is possible also for looking for changes in con

```
ansible-rulebook -i inventory.yml -r rulebook_monitor_configmaps.yml
```

Create a custom resource definition with the configmap:
```
kubectl apply -f k8s_configmap.yml
```
5 changes: 5 additions & 0 deletions demos/kubernetes/inventory.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
hosts:
vars:
ansible_connection: local
ansible_python_interpreter: "{{ansible_playbook_python}}"
8 changes: 8 additions & 0 deletions demos/kubernetes/k8s_configmap.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: configmap-demo
data:
parameter_1: "value_1"
parameter_2: "value_2"
7 changes: 7 additions & 0 deletions demos/kubernetes/k8s_crontab_cr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
41 changes: 41 additions & 0 deletions demos/kubernetes/k8s_crontab_crd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# name must match the spec fields below, and be in the form: <plural>.<group>
name: crontabs.stable.example.com
spec:
# group name to use for REST API: /apis/<group>/<version>
group: stable.example.com
# list of versions supported by this CustomResourceDefinition
versions:
- name: v1
# Each version can be enabled/disabled by Served flag.
served: true
# One and only one version must be marked as the storage version.
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
replicas:
type: integer
# either Namespaced or Cluster
scope: Namespaced
names:
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
plural: crontabs
# singular name to be used as an alias on the CLI and for display
singular: crontab
# kind is normally the CamelCased singular type. Your resource manifests use this.
kind: CronTab
# shortNames allow shorter string to match your resource on the CLI
shortNames:
- ct
7 changes: 7 additions & 0 deletions demos/kubernetes/k8s_deployment_namespace.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
kind: Namespace
apiVersion: v1
metadata:
name: nginx-deployment-namespaced
labels:
name: nginx-deployment-namespaced
20 changes: 20 additions & 0 deletions demos/kubernetes/k8s_deployment_no_namespace.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
21 changes: 21 additions & 0 deletions demos/kubernetes/k8s_deployment_with_namespace.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-namespaced
namespace: nginx-deployment-namespaced
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
18 changes: 18 additions & 0 deletions demos/kubernetes/rulebook_monitor_configmaps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
- name: Listen for changes in a custom resource
hosts: localhost
sources:
- name: Check for configmaps in the cluster
ansible.eda.kubernetes:
api: CoreV1Api
method: list_config_map_for_all_namespaces
params: {}
rules:
- name: A configmap was found
condition: >
event.type == "ADDED" and
event.resource.kind == 'ConfigMap' and
event.resource.metadata.name == 'configmap-demo'
action:
run_playbook:
name: example_playbook.yml
18 changes: 18 additions & 0 deletions demos/kubernetes/rulebook_monitor_cr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
- name: Listen for changes in a custom resource
hosts: localhost
sources:
- name: Check for pods in the cluster
ansible.eda.kubernetes:
api: CustomObjectsApi
method: list_cluster_custom_object
params:
group: stable.example.com
version: v1
plural: crontabs
rules:
- name: A CustomResource was found
condition: event.type == "ADDED"
action:
run_playbook:
name: example_playbook.yml
15 changes: 15 additions & 0 deletions demos/kubernetes/rulebook_monitor_deployment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
- name: Listen for changes in pods on a Kubernetes cluster
hosts: localhost
sources:
- name: Check for deployments in the cluster
ansible.eda.kubernetes:
api: AppsV1Api
method: list_deployment_for_all_namespaces
params: {}
rules:
- name: A deployment creation was found with a name nginx-deployment
condition: event.type == "ADDED" and event.resource.kind == 'Deployment' and event.resource.metadata.name == 'nginx-deployment'
action:
run_playbook:
name: example_playbook.yml
16 changes: 16 additions & 0 deletions demos/kubernetes/rulebook_monitor_deploymentns.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
- name: Listen for changes in pods on a Kubernetes cluster
hosts: localhost
sources:
- name: Check for deployments in the cluster
ansible.eda.kubernetes:
api: AppsV1Api
method: list_namespaced_deployment
params:
namespace: nginx-deployment-namespaced
rules:
- name: A deployment condition matched
condition: event.type == "ADDED" and event.resource.metadata.namespace == 'nginx-deployment-namespaced'
action:
run_playbook:
name: example_playbook.yml
15 changes: 15 additions & 0 deletions demos/kubernetes/rulebook_monitor_pods.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
- name: Listen for changes in pods on a Kubernetes cluster
hosts: localhost
sources:
- name: Check for pods in the cluster
ansible.eda.kubernetes:
api: CoreV1Api
method: list_pod_for_all_namespaces
params: {}
rules:
- name: A pod condition was found
condition: event.type == "ADDED" and event.resource.kind == 'Pod'
action:
run_playbook:
name: example_playbook.yml
Loading

0 comments on commit 62e8184

Please sign in to comment.