Skip to content

Commit

Permalink
feat(ingress-creation): implement ingress creation from YAML file
Browse files Browse the repository at this point in the history
  • Loading branch information
SQuent committed Feb 4, 2025
1 parent f07ab58 commit cb2ea93
Show file tree
Hide file tree
Showing 3 changed files with 281 additions and 27 deletions.
76 changes: 53 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

## Overview

Kuma ingress watcher is a kubernetes controller designed to automatically monitor `Kubernetes Ingress` and `Traefik Ingressroutes` in a Kubernetes cluster and create corresponding monitors in `Uptime Kuma`. It provides seamless integration between Kubernetes ingress resources and Uptime Kuma monitoring, allowing for easy and efficient monitoring of web services deployed on Kubernetes.
Kuma ingress watcher is a Kubernetes controller designed to automatically monitor `Kubernetes Ingress` and `Traefik Ingressroutes` in a Kubernetes cluster and create corresponding monitors in `Uptime Kuma`. It provides seamless integration between Kubernetes ingress resources and Uptime Kuma monitoring, allowing for easy and efficient monitoring of web services deployed on Kubernetes.

## Features

- Automatically creates, updates and deletes monitors in Uptime Kuma for `Kubernetes Ingress` and `Traefik Ingressroutes`.
- Automatically creates, updates, and deletes monitors in Uptime Kuma for `Kubernetes Ingress` and `Traefik Ingressroutes`.
- Supports both single and multiple routes per Ingress resource.
- Customizable monitors by annotate Ingressroutes and Ingress.
- Customizable monitors by annotating Ingressroutes and Ingress.
- **File-based Monitor Configuration**: Define static monitors using a YAML file.

## Installation

Expand All @@ -18,7 +19,6 @@ Kuma ingress watcher is a kubernetes controller designed to automatically monito
- Kubernetes cluster
- Uptime Kuma instance


## Configuration

### Environment variables
Expand All @@ -31,10 +31,37 @@ Before running the controller, make sure to configure the following environment
- `WATCH_INGRESS`: Set to `True` to enable monitoring of Kubernetes Ingress resources.
- `WATCH_INTERVAL`: Interval in seconds between each check for changes in Ingress or IngressRoutes (default is `10` seconds).
- `USE_TRAEFIK_V3_CRD_GROUP`: Whether to use Traefik V3 API CRD group (`traefik.io`); default to `False`.
- `ENABLE_FILE_MONITOR`: Set to `True` to enable file-based monitor configuration.
- `FILE_MONITOR_PATH`: The path to the YAML file containing monitor definitions (default `/etc/kuma-controller/monitors.yaml`).

### File-Based Monitor Configuration

If `ENABLE_FILE_MONITOR` is set to `True`, the controller will load monitor definitions from the YAML file specified by `FILE_MONITOR_PATH`.

#### Example YAML File

```yaml
monitors:
- name: example-monitor
url: https://example.com
type: http
interval: 60
- name: another-monitor
url: https://another.com
type: tcp
interval: 120
```
#### Validation Rules
- Each monitor entry must include `name` and `url` fields.
- Optional fields: `type` (default: `http`), `interval` (default: `60`), `headers` (default `{}`).

The controller will create or update these monitors in Uptime Kuma upon startup.

### Annotations for Uptime Kuma Autodiscovery

These annotations apply to both Kubernetes Ingress and Traefik Ingressroutes resources, allowing you to customize the behavior of Uptime Kuma monitors for each.:
These annotations apply to both Kubernetes Ingress and Traefik Ingressroutes resources, allowing you to customize the behavior of Uptime Kuma monitors for each:

1. **`uptime-kuma.autodiscovery.probe.interval`**
- Sets the probing interval in seconds for the monitor.
Expand Down Expand Up @@ -67,15 +94,15 @@ These annotations apply to both Kubernetes Ingress and Traefik Ingressroutes res
- **Example:** `uptime-kuma.autodiscovery.probe.headers: {"Authorization": "Bearer token"}`

6. **`uptime-kuma.autodiscovery.probe.host`**
- force the host for the probe. **WARNING: Be carefull with this paramter if you are using multiple hosts in a same Ingress object**
- Force the host for the probe. **WARNING: Be careful with this parameter if you are using multiple hosts in the same Ingress object.**
- **Type:** String
- **Default:** `null` (host grep from ingress)
- **Default:** `null` (host grabbed from ingress)
- **Example:** `uptime-kuma.autodiscovery.probe.host: example.com`

7. **`uptime-kuma.autodiscovery.probe.path`**
- url sub path for the probe.
- URL sub-path for the probe.
- **Type:** String
- **Default:** `null`
- **Default:** `null`
- **Example:** `uptime-kuma.autodiscovery.probe.path: /tintin`

8. **`uptime-kuma.autodiscovery.probe.port`**
Expand All @@ -95,10 +122,10 @@ These annotations apply to both Kubernetes Ingress and Traefik Ingressroutes res
Here's an example of annotations configured in a Kubernetes Ingress Resource:

```yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingressroute
name: example-ingress
namespace: my-namespace
annotations:
uptime-kuma.autodiscovery.probe.interval: 120
Expand All @@ -111,14 +138,15 @@ metadata:
uptime-kuma.autodiscovery.probe.port: 8080
uptime-kuma.autodiscovery.probe.method: GET
spec:
# Your Ingress route specification here
# Your Ingress route specification here
```


## Usage

Once the controller is running, it will automatically monitor any changes to Ingress resources in your Kubernetes cluster and create/update corresponding monitors in Uptime Kuma. Simply deploy your applications using Kubernetes Ingress, and the controller will take care of the rest!

If `ENABLE_FILE_MONITOR` is enabled, the controller will also create monitors defined in the specified YAML file.

## Important Notes

### Tag Addition Limitation
Expand All @@ -127,17 +155,12 @@ Currently, the addition of tags to monitors is not supported due to limitations

### Custom Watcher for IngressRoutes

The Kubernetes event watcher (`watch`) does not provide specific details on creation, modification, or deletion events for IngressRoutes. To overcome this limitation, this controller implements a custom watcher mechanism that continuously monitors IngressRoutes and triggers appropriate actions based on changes detected. homemade watcher is used for Ingress objects too. This custom solution ensures accurate monitoring and synchronization with Uptime Kuma configurations.

Here’s the passage with the new **Improvements** section included:

---
The Kubernetes event watcher (`watch`) does not provide specific details on creation, modification, or deletion events for IngressRoutes. To overcome this limitation, this controller implements a custom watcher mechanism that continuously monitors IngressRoutes and triggers appropriate actions based on changes detected. This custom solution ensures accurate monitoring and synchronization with Uptime Kuma configurations.

## Improvements

- **File-Based Monitor Configuration**: Define static monitors using a YAML file.
- **IngressRoute Version Selection**: You can now choose which version of IngressRoutes to watch. This allows you to customize the controller's behavior based on the version of Traefik you're using.
- **Tag Addition for Monitors**: Currently, the addition of tags to monitors is not supported due to limitations in the Uptime Kuma API. Future updates may include support for this feature, allowing you to tag monitors directly through the controller.


## Contributing

Expand All @@ -152,10 +175,17 @@ To run unit tests for this project:
- Python 3.12 or higher installed.
- Poetry installed.

````
```bash
poetry install
poetry run pytest
````
```

### Pre-commit Hook

```bash
pre-commit install
pre-commit run --all-files
```

## License

Expand Down
58 changes: 54 additions & 4 deletions kuma_ingress_watcher/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import time
import logging
import sys
import yaml
from uptime_kuma_api import UptimeKumaApi
from kubernetes import client, config

Expand All @@ -22,7 +23,8 @@ def str_to_bool(value):
WATCH_INGRESS = str_to_bool(os.getenv("WATCH_INGRESS", False))
USE_TRAEFIK_V3_CRD_GROUP = str_to_bool(os.getenv("USE_TRAEFIK_V3_CRD_GROUP", False))
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper()

LOAD_MONITOR_FROM_FILE = str_to_bool(os.getenv("ENABLE_FILE_MONITOR", False))
FILE_MONITOR_PATH = os.getenv("FILE_MONITOR_PATH", "/etc/kuma-controller/monitors.yaml")

LOG_LEVELS = {
"DEBUG": logging.DEBUG,
Expand All @@ -32,14 +34,12 @@ def str_to_bool(value):
"CRITICAL": logging.CRITICAL,
}

# Logging configuration
logging.basicConfig(
level=LOG_LEVELS.get(LOG_LEVEL, "INFO"),
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
logger = logging.getLogger(__name__)

# Global variables for Kubernetes and Uptime Kuma
kuma = None
custom_api_instance = None
networking_api_instance = None
Expand Down Expand Up @@ -314,10 +314,60 @@ def watch_ingress_resources():
time.sleep(WATCH_INTERVAL)


def process_monitor_file(file_path):
try:
with open(file_path, "r") as file:
file_content = file.read()

if not file_content.strip():
logger.info(f"The file {file_path} is empty or contains only whitespace.")
return

try:
ingress_data = yaml.safe_load(file_content)
except yaml.YAMLError as e:
logger.error(
f"Failed to process file {file_path}: Invalid YAML format ({str(e)})"
)
return

for entry in ingress_data:
try:
if not isinstance(entry, dict):
raise ValueError(f"Invalid entry format: {entry}")
if "name" not in entry or "url" not in entry:
raise KeyError(f"Missing required fields in entry: {entry}")

create_or_update_monitor(
entry.get("name"),
entry.get("url"),
entry.get("interval", 60),
entry.get("type", "http"),
entry.get("headers", {}),
entry.get("method", "GET"),
)
except (ValueError, KeyError) as e:
logger.warning(f"Skipping invalid entry: {entry} ({str(e)})")

except FileNotFoundError:
logger.error(f"File {file_path} not found.")
except Exception as e:
logger.error(
f"An unexpected error occurred while processing file {file_path}: {str(e)}"
)


def main():
check_config()
init_kuma_api()
init_kubernetes_client()

if LOAD_MONITOR_FROM_FILE:
logger.info("File-based Monitor creation is enabled.")
process_monitor_file(FILE_MONITOR_PATH)

if WATCH_INGRESSROUTES or WATCH_INGRESS:
init_kubernetes_client()
watch_ingress_resources()


if __name__ == "__main__":
Expand Down
Loading

0 comments on commit cb2ea93

Please sign in to comment.