{"id":33930651,"url":"https://github.com/siutsin/heartbeats","last_synced_at":"2026-05-25T00:05:08.526Z","repository":{"id":287791861,"uuid":"965250028","full_name":"siutsin/heartbeats","owner":"siutsin","description":"A Kubernetes operator that vibes with your HTTP endpoints! 🚀","archived":false,"fork":false,"pushed_at":"2026-04-22T21:03:14.000Z","size":607,"stargazers_count":1,"open_issues_count":4,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-22T23:12:31.852Z","etag":null,"topics":["kubernetes","kubernetes-operator","vibe-coding"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/siutsin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-04-12T18:34:54.000Z","updated_at":"2026-04-22T14:56:08.000Z","dependencies_parsed_at":null,"dependency_job_id":"987d98a1-a93f-4595-9509-cf24f93e9238","html_url":"https://github.com/siutsin/heartbeats","commit_stats":null,"previous_names":["siutsin/heartbeats"],"tags_count":151,"template":false,"template_full_name":null,"purl":"pkg:github/siutsin/heartbeats","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siutsin%2Fheartbeats","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siutsin%2Fheartbeats/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siutsin%2Fheartbeats/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siutsin%2Fheartbeats/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/siutsin","download_url":"https://codeload.github.com/siutsin/heartbeats/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siutsin%2Fheartbeats/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32274992,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"ssl_error","status_checked_at":"2026-04-25T18:29:32.149Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kubernetes","kubernetes-operator","vibe-coding"],"created_at":"2025-12-12T12:03:56.774Z","updated_at":"2026-04-25T20:07:33.695Z","avatar_url":"https://github.com/siutsin.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Heartbeats Operator\n\nA Kubernetes operator that monitors the health of HTTP endpoints by periodically sending requests and tracking their responses.\n\n## Disclaimer\n\n\u003e [!WARNING]\n\u003e AI-GENERATED CODE AHEAD! Every single line of code in this repository is generated.\n\nThis entire repo is the result of me going \"Hey, I wonder if I can vibe-code a Kubernetes operator in a weekend?\"\n\nMe over the weekend:\n\n[![Vibe Coding](https://markdown-videos-api.jorgenkh.no/url?url=https%3A%2F%2Fyoutu.be%2F_2C2CNmK7dQ)](https://youtu.be/_2C2CNmK7dQ)\n\nBuddy-coded with Cursor Pro, 307 premium model requests.\n\n\u003e [!WARNING]\n\u003e Use at your own risk. No guarantees, no warranties, just pure vibes and questionable life choices. 🤪\n\n## Overview\n\nThe Heartbeats Operator provides a custom resource `Heartbeat` that allows you to monitor\nthe health of HTTP endpoints in your Kubernetes cluster. It periodically checks the endpoints\nand updates their status based on HTTP response codes with comprehensive error handling and reporting.\n\n## Features\n\n- **Robust Health Monitoring**: Monitor HTTP endpoints with configurable intervals and retry logic\n- **Flexible Status Code Ranges**: Define custom status code ranges for healthy/unhealthy states\n- **Secure Configuration**: Store endpoint URLs securely in Kubernetes secrets\n- **Real-time Status Updates**: Detailed health information with comprehensive error messages\n- **Configurable Timeouts**: Adjustable timeout and retry settings for different network conditions\n- **Prometheus Metrics**: Built-in metrics integration for monitoring and alerting\n- **Comprehensive Error Handling**: Detailed error messages for troubleshooting\n- **Report Endpoints**: Optional reporting to healthy/unhealthy endpoints for external monitoring systems\n- **Production Ready**: Structured logging, proper error handling, and comprehensive test coverage\n\n## Installation\n\n### Prerequisites\n\n- Kubernetes cluster (v1.16+)\n- kubectl configured to access your cluster\n- cert-manager installed (for webhook certificates)\n\n### Using Helm\n\n```bash\nhelm repo add heartbeats https://siutsin.github.io/heartbeats\nhelm install heartbeats heartbeats/heartbeats-operator\n```\n\n### Manual Installation\n\n1. Install the CRDs:\n\n    ```bash\n    kubectl apply -f config/crd/bases/monitoring.siutsin.com_heartbeats.yaml\n    ```\n\n2. Deploy the operator:\n\n    ```bash\n    kubectl apply -f config/default/\n    ```\n\n## Usage\n\n### Basic Example\n\n1. Create a secret containing your endpoint URLs:\n\n    ```yaml\n    apiVersion: v1\n    kind: Secret\n    metadata:\n      name: heartbeat-endpoints\n    type: Opaque\n    stringData:\n      targetEndpoint: \"https://api.example.com/health\"\n      targetEndpointMethod: \"GET\" # Optional, defaults to GET\n      healthyEndpoint: \"https://httpbin.org/status/200\"\n      healthyEndpointMethod: \"POST\" # Optional, defaults to GET\n      unhealthyEndpoint: \"https://httpbin.org/status/500\"\n      unhealthyEndpointMethod: \"POST\" # Optional, defaults to GET\n    ```\n\n2. Create a Heartbeat resource:\n\n    ```yaml\n    apiVersion: monitoring.siutsin.com/v1alpha1\n    kind: Heartbeat\n    metadata:\n      name: api-health\n    spec:\n      endpointsSecret:\n        name: heartbeat-endpoints\n        targetEndpointKey: targetEndpoint\n        targetEndpointMethodKey: targetEndpointMethod # Optional\n        healthyEndpointKey: healthyEndpoint\n        healthyEndpointMethodKey: healthyEndpointMethod # Optional\n        unhealthyEndpointKey: unhealthyEndpoint\n        unhealthyEndpointMethodKey: unhealthyEndpointMethod # Optional\n      expectedStatusCodeRanges:\n        - min: 200\n          max: 299\n      interval: 30s\n    ```\n\n### Advanced Example with Report Endpoints\n\n```yaml\napiVersion: monitoring.siutsin.com/v1alpha1\nkind: Heartbeat\nmetadata:\n  name: api-health-with-reporting\nspec:\n  endpointsSecret:\n    name: heartbeat-endpoints\n    targetEndpointKey: targetEndpoint\n    targetEndpointMethodKey: targetEndpointMethod # Optional\n    healthyEndpointKey: healthyEndpoint\n    healthyEndpointMethodKey: healthyEndpointMethod # Optional\n    unhealthyEndpointKey: unhealthyEndpoint\n    unhealthyEndpointMethodKey: unhealthyEndpointMethod # Optional\n  expectedStatusCodeRanges:\n    - min: 200\n      max: 299\n    - min: 404\n      max: 404  # Accept 404 as healthy for certain endpoints\n  interval: 30s\n```\n\n### Configuration Options\n\n#### Heartbeat Spec\n\n| Field                    | Type   | Description                                          | Required |\n|--------------------------|--------|------------------------------------------------------|----------|\n| endpointsSecret          | object | Reference to the secret containing endpoint URLs     | Yes      |\n| expectedStatusCodeRanges | array  | Ranges of HTTP status codes considered healthy       | Yes      |\n| interval                 | string | Time between health checks (e.g., \"30s\", \"5m\", \"1h\") | Yes      |\n\n#### EndpointsSecret\n\n| Field                      | Type   | Description                                                                 | Required |\n|----------------------------|--------|-----------------------------------------------------------------------------|----------|\n| name                       | string | Name of the secret                                                          | Yes      |\n| namespace                  | string | Namespace of the secret (defaults to Heartbeat's namespace)                 | No       |\n| targetEndpointKey          | string | Key containing the target endpoint URL                                      | Yes      |\n| targetEndpointMethodKey    | string | Key containing the HTTP method for the target endpoint (e.g., GET, POST)    | No       |\n| healthyEndpointKey         | string | Key containing the healthy endpoint URL for reporting                       | Yes      |\n| healthyEndpointMethodKey   | string | Key containing the HTTP method for the healthy endpoint (e.g., GET, POST)   | No       |\n| unhealthyEndpointKey       | string | Key containing the unhealthy endpoint URL for reporting                     | Yes      |\n| unhealthyEndpointMethodKey | string | Key containing the HTTP method for the unhealthy endpoint (e.g., GET, POST) | No       |\n\n#### StatusCodeRange\n\n| Field | Type    | Description                            | Required |\n|-------|---------|----------------------------------------|----------|\n| min   | integer | Minimum status code in range (100-599) | Yes      |\n| max   | integer | Maximum status code in range (100-599) | Yes      |\n\n### Status Information\n\nThe Heartbeat resource's status includes:\n\n- `healthy`: Boolean indicating if the endpoint is healthy\n- `lastStatus`: Last HTTP status code received\n- `message`: Human-readable status message with detailed error information\n- `lastChecked`: Timestamp of the last health check\n- `reportStatus`: Status of reporting to external endpoints (\"Success\" or \"Failure\")\n\n### Error Messages\n\nThe operator provides detailed error messages for troubleshooting:\n\n- `missing required key`: A required endpoint key is missing from the secret\n- `endpoint is not specified`: An endpoint URL is empty or not provided\n- `failed to check endpoint health`: Network or HTTP errors during health checks\n- `endpoint timed out`: The endpoint took too long to respond\n- `invalid status code range`: Status code range has invalid min/max values\n- `status code is not within expected ranges`: Endpoint returned unexpected status code\n\n## Development\n\n### Development Prerequisites\n\n- Go 1.24+\n- Docker\n- Kind (for local testing)\n- kubectl\n\n### Building and Testing\n\n```bash\n# Run unit tests\nmake test\n\n# Run unit tests with race detection (for CI)\nmake test-ci\n\n# Run e2e tests locally\nmake test-e2e LOCAL=true\n\n# Run e2e tests with race detection (for CI)\nmake test-e2e-ci LOCAL=true\n\n# Build the operator\nmake build\n\n# Build Docker image\nmake docker-build\n```\n\n### Code Quality\n\n```bash\n# Format code\nmake fmt\n\n# Run linter\nmake lint\n\n# Run linter with fixes\nmake lint-fix\n\n# Check markdown files\nmake lint-markdown\n```\n\n### Logging\n\nThe operator uses structured logging via the `logr` interface, integrated with controller-runtime's logger.\nThe `internal/logger` package is generic and only provides helpers for creating loggers with contextual information\n(such as namespace and name).\n\n**No business logic or business-specific logging helpers are present in the logger package.**\n\nAll business-specific logging (such as health check results, reconciliation events, etc.) is performed inline in the\ncontroller and related business logic, using standard log levels and structured key-value pairs.\n\n#### Example Usage\n\n```go\nlog := logger.WithRequest(ctx, \"heartbeat-reconciler\", req.Namespace, req.Name)\nlog.V(1).Info(\"Starting reconciliation\", \"namespace\", req.Namespace, \"name\", req.Name)\nlog.Error(err, \"Failed to fetch resource\", \"namespace\", req.Namespace, \"name\", req.Name)\n```\n\n#### Example Log Output\n\n```json\n{\n  \"time\": \"2025-06-27T21:58:58.917163+01:00\",\n  \"level\": \"INFO\",\n  \"msg\": \"Starting reconciliation\",\n  \"namespace\": \"default\",\n  \"name\": \"api-health\"\n}\n```\n\n#### Log Levels\n\n- **INFO**: General operational information, health check results\n- **ERROR**: Error conditions, failed health checks, configuration issues\n- **DEBUG/V(1)**: Detailed debugging information, HTTP request details\n- **V(2)**: Verbose debugging, internal state information\n\n## Monitoring\n\nThe operator exposes Prometheus metrics at `/metrics`:\n\n- `heartbeat_health_status`: Gauge indicating endpoint health\n  (1 for healthy, 0 for unhealthy)\n- `heartbeat_http_status_code`: Gauge showing the last HTTP status code\n- `heartbeat_check_duration_seconds`: Histogram of health check durations\n\n### Metrics Access\n\nThe metrics endpoint is secured and requires authentication. Access is controlled via RBAC:\n\n```bash\n# Get service account token\nTOKEN=$(kubectl create token heartbeats-operator-controller-manager -n heartbeats-operator-system)\n\n# Access metrics\ncurl -k -H \"Authorization: Bearer $TOKEN\" \\\n  https://heartbeats-operator-controller-manager-metrics-service.heartbeats-operator-system.svc.cluster.local:8443/metrics\n```\n\n## Troubleshooting\n\n### Common Issues\n\n1. **Endpoint Timeout**\n   - Check if the endpoint is accessible from the cluster\n   - Verify network policies allow the connection\n   - Consider increasing the timeout duration\n   - Check logs for detailed timeout information\n\n2. **Invalid Status Code**\n   - Ensure the endpoint returns expected status codes\n   - Verify the status code ranges in the Heartbeat spec\n   - Check the status message for specific error details\n\n3. **Secret Not Found**\n   - Confirm the secret exists in the correct namespace\n   - Verify the secret keys match the Heartbeat configuration\n   - Check for \"missing required key\" error messages\n\n4. **Report Endpoint Failures**\n   - Verify the report endpoints are accessible\n   - Check the `reportStatus` field in the Heartbeat status\n   - Review logs for report endpoint errors\n\n### Debugging\n\n```bash\n# Check Heartbeat status\nkubectl get heartbeat \u003cname\u003e -o yaml\n\n# View operator logs\nkubectl logs -n heartbeats-operator-system deployment/heartbeats-operator-controller-manager\n\n# Check metrics\nkubectl port-forward -n heartbeats-operator-system svc/heartbeats-operator-controller-manager-metrics-service 8443:8443\n```\n\n## Contributing\n\nContributions are welcome! Please see our [Contributing Guide](CONTRIBUTING.md) for details.\n\n### Development Guidelines\n\n- Follow the existing code style and patterns\n- Add comprehensive unit tests for new features\n- Include e2e tests for integration scenarios\n- Use structured logging with appropriate log levels\n- Follow error handling patterns established in the codebase\n\n## License\n\nThis project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiutsin%2Fheartbeats","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsiutsin%2Fheartbeats","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiutsin%2Fheartbeats/lists"}