314 lines
14 KiB
Markdown
314 lines
14 KiB
Markdown
|
|
# Sunbeam Service Discovery Labels
|
||
|
|
|
||
|
|
Migration guide: replacing hardcoded service definitions in `sunbeam-sdk/src/registry/services.rs` with Kubernetes label-based discovery.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 1. Label Convention
|
||
|
|
|
||
|
|
Every Sunbeam-managed service must have labels and annotations on its **primary Kubernetes resource** (Deployment, StatefulSet, DaemonSet, or CNPG Cluster).
|
||
|
|
|
||
|
|
### Labels (required)
|
||
|
|
|
||
|
|
| Label | Value | Purpose |
|
||
|
|
|---|---|---|
|
||
|
|
| `sunbeam.pt/service` | Service name (e.g. `hydra`) | Primary lookup key for the CLI |
|
||
|
|
| `sunbeam.pt/category` | Category slug (e.g. `auth`) | Grouping for `sunbeam status`, `sunbeam restart <category>` |
|
||
|
|
|
||
|
|
### Annotations (conditional)
|
||
|
|
|
||
|
|
| Annotation | Value | When to include |
|
||
|
|
|---|---|---|
|
||
|
|
| `sunbeam.pt/display-name` | Human-readable name (e.g. `"Hydra (OAuth2/OIDC)"`) | Always |
|
||
|
|
| `sunbeam.pt/kv-path` | OpenBao KV v2 secret path (e.g. `hydra`) | Only if the service has secrets in OpenBao |
|
||
|
|
| `sunbeam.pt/db-user` | PostgreSQL username (e.g. `hydra`) | Only if the service has a CNPG database |
|
||
|
|
| `sunbeam.pt/db-name` | PostgreSQL database name (e.g. `hydra_db`) | Only if the service has a CNPG database |
|
||
|
|
| `sunbeam.pt/build-target` | Build target name (e.g. `people`) | Only if the service is built from source |
|
||
|
|
| `sunbeam.pt/depends-on` | Comma-separated service names (e.g. `postgres,openbao`) | Only if the service has dependencies |
|
||
|
|
| `sunbeam.pt/health-check` | One of: `pod-ready`, `cnpg`, `seal-status`, or an HTTP path like `/healthz` | Only if not the default (`pod-ready`). Omit for services with `HealthCheck::None` |
|
||
|
|
|
||
|
|
### Virtual services
|
||
|
|
|
||
|
|
Services with **no workload pods** (e.g. `scaleway-s3`, `longhorn`) should be represented by a ConfigMap carrying the labels and an additional marker:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
apiVersion: v1
|
||
|
|
kind: ConfigMap
|
||
|
|
metadata:
|
||
|
|
name: sunbeam-svc-scaleway-s3
|
||
|
|
namespace: external
|
||
|
|
labels:
|
||
|
|
sunbeam.pt/service: scaleway-s3
|
||
|
|
sunbeam.pt/category: infra
|
||
|
|
sunbeam.pt/virtual: "true"
|
||
|
|
annotations:
|
||
|
|
sunbeam.pt/display-name: "Scaleway S3"
|
||
|
|
sunbeam.pt/kv-path: scaleway-s3
|
||
|
|
data: {}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Multi-deployment services
|
||
|
|
|
||
|
|
When a service spans multiple Deployments (e.g. `messages` has `messages-backend`, `messages-mta-in`, `messages-mta-out`), **all** Deployments get the **same** `sunbeam.pt/service` label. The CLI groups them automatically. Put the full annotations on just one of them (conventionally the primary/backend Deployment) and minimal labels on the rest.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. Complete Service Table
|
||
|
|
|
||
|
|
33 services organized by category. The "K8s Resource" column indicates which object to label.
|
||
|
|
|
||
|
|
### Auth (namespace: `ory`)
|
||
|
|
|
||
|
|
| Service | K8s Resource | Labels | Annotations | Notes |
|
||
|
|
|---|---|---|---|---|
|
||
|
|
| `hydra` | Deployment `hydra` in `ory` | `service: hydra`, `category: auth` | `display-name: "Hydra (OAuth2/OIDC)"`, `kv-path: hydra`, `db-user: hydra`, `db-name: hydra_db`, `depends-on: postgres,openbao` | |
|
||
|
|
| `kratos` | Deployment `kratos` in `ory` | `service: kratos`, `category: auth` | `display-name: "Kratos (Identity)"`, `kv-path: kratos`, `db-user: kratos`, `db-name: kratos_db`, `depends-on: postgres,openbao` | |
|
||
|
|
| `login-ui` | Deployment `login-ui` in `ory` | `service: login-ui`, `category: auth` | `display-name: "Login UI"`, `kv-path: login-ui`, `depends-on: kratos` | |
|
||
|
|
|
||
|
|
### Data (namespace: `data`)
|
||
|
|
|
||
|
|
| Service | K8s Resource | Labels | Annotations | Notes |
|
||
|
|
|---|---|---|---|---|
|
||
|
|
| `postgres` | CNPG Cluster `postgres` in `data` | `service: postgres`, `category: data` | `display-name: "PostgreSQL (CNPG)"`, `health-check: cnpg` | Health check is `cnpg`, not `pod-ready` |
|
||
|
|
| `openbao` | StatefulSet `openbao` in `data` | `service: openbao`, `category: data` | `display-name: "OpenBao (Secrets)"`, `health-check: seal-status` | Health check is `seal-status` |
|
||
|
|
| `valkey` | Deployment `valkey` in `data` | `service: valkey`, `category: data` | `display-name: "Valkey (Cache)"` | |
|
||
|
|
| `opensearch` | Deployment `opensearch` in `data` | `service: opensearch`, `category: data` | `display-name: "OpenSearch"` | |
|
||
|
|
|
||
|
|
### DevTools (namespace: `devtools`)
|
||
|
|
|
||
|
|
| Service | K8s Resource | Labels | Annotations | Notes |
|
||
|
|
|---|---|---|---|---|
|
||
|
|
| `gitea` | Deployment `gitea` in `devtools` | `service: gitea`, `category: devtools` | `display-name: "Gitea (Git Forge)"`, `kv-path: gitea`, `db-user: gitea`, `db-name: gitea_db`, `depends-on: postgres,openbao` | |
|
||
|
|
|
||
|
|
### Platform (namespace: `lasuite`)
|
||
|
|
|
||
|
|
| Service | K8s Resource | Labels | Annotations | Notes |
|
||
|
|
|---|---|---|---|---|
|
||
|
|
| `hive` | Deployment `hive` in `lasuite` | `service: hive`, `category: platform` | `display-name: "Hive (Backend)"`, `kv-path: hive`, `db-user: hive`, `db-name: hive_db`, `depends-on: postgres,openbao` | |
|
||
|
|
| `people-backend` | Deployment `people-backend` in `lasuite` | `service: people-backend`, `category: platform` | `display-name: "People (Backend)"`, `kv-path: people`, `db-user: people`, `db-name: people_db`, `build-target: people`, `depends-on: postgres,openbao` | |
|
||
|
|
| `people-frontend` | Deployment `people-frontend` in `lasuite` | `service: people-frontend`, `category: platform` | `display-name: "People (Frontend)"`, `build-target: people-frontend` | |
|
||
|
|
| `people-celery` | Deployments `people-celery-worker` + `people-celery-beat` in `lasuite` | `service: people-celery`, `category: platform` | `display-name: "People (Workers)"`, `depends-on: people-backend` | Multi-deploy: both Deployments get the same `service` label |
|
||
|
|
| `docs` | Deployment `docs-frontend` in `lasuite` | `service: docs`, `category: platform` | `display-name: "Docs"`, `kv-path: docs`, `db-user: docs`, `db-name: docs_db`, `build-target: docs-frontend`, `depends-on: postgres,openbao` | |
|
||
|
|
| `meet` | Deployment `meet` in `lasuite` | `service: meet`, `category: platform` | `display-name: "Meet"`, `kv-path: meet`, `db-user: meet`, `db-name: meet_db`, `build-target: meet`, `depends-on: postgres,openbao,livekit` | |
|
||
|
|
| `drive` | Deployment `drive` in `lasuite` | `service: drive`, `category: platform` | `display-name: "Drive"`, `kv-path: drive`, `db-user: drive`, `db-name: drive_db`, `depends-on: postgres,openbao` | |
|
||
|
|
| `projects` | Deployment `projects` in `lasuite` | `service: projects`, `category: platform` | `display-name: "Projects"`, `kv-path: projects`, `db-user: projects`, `db-name: projects_db`, `build-target: projects`, `depends-on: postgres,openbao` | |
|
||
|
|
| `calendars` | Deployment `calendars` in `lasuite` | `service: calendars`, `category: platform` | `display-name: "Calendars"`, `kv-path: calendars`, `db-user: calendars`, `db-name: calendars_db`, `build-target: calendars`, `depends-on: postgres,openbao` | |
|
||
|
|
| `kratos-admin` | Deployment `kratos-admin` in `lasuite` | `service: kratos-admin`, `category: platform` | `display-name: "Kratos Admin UI"`, `kv-path: kratos-admin`, `build-target: kratos-admin`, `depends-on: kratos,seaweedfs` | |
|
||
|
|
| `collabora` | Deployment `collabora` in `lasuite` | `service: collabora`, `category: platform` | `display-name: "Collabora (Office)"`, `kv-path: collabora` | |
|
||
|
|
|
||
|
|
### Messaging
|
||
|
|
|
||
|
|
| Service | K8s Resource | Labels | Annotations | Notes |
|
||
|
|
|---|---|---|---|---|
|
||
|
|
| `messages` | Deployments `messages-backend`, `messages-mta-in`, `messages-mta-out` in `lasuite` | `service: messages`, `category: messaging` | `display-name: "Messages (Mail)"`, `kv-path: messages`, `db-user: messages`, `db-name: messages_db`, `build-target: messages`, `depends-on: postgres,openbao` | Multi-deploy: all 3 get the same `service` label |
|
||
|
|
| `tuwunel` | Deployment `tuwunel` in `matrix` | `service: tuwunel`, `category: messaging` | `display-name: "Tuwunel (Matrix)"`, `kv-path: tuwunel`, `build-target: tuwunel`, `depends-on: openbao` | |
|
||
|
|
|
||
|
|
### Media (namespace: `media`)
|
||
|
|
|
||
|
|
| Service | K8s Resource | Labels | Annotations | Notes |
|
||
|
|
|---|---|---|---|---|
|
||
|
|
| `livekit` | Deployment `livekit-server` in `media` | `service: livekit`, `category: media` | `display-name: "LiveKit (WebRTC)"`, `kv-path: livekit`, `depends-on: openbao` | |
|
||
|
|
|
||
|
|
### Storage (namespace: `storage`)
|
||
|
|
|
||
|
|
| Service | K8s Resource | Labels | Annotations | Notes |
|
||
|
|
|---|---|---|---|---|
|
||
|
|
| `seaweedfs` | Deployment `seaweedfs-filer` in `storage` | `service: seaweedfs`, `category: storage` | `display-name: "SeaweedFS (S3)"`, `kv-path: seaweedfs`, `depends-on: openbao` | |
|
||
|
|
|
||
|
|
### Monitoring (namespace: `monitoring`)
|
||
|
|
|
||
|
|
| Service | K8s Resource | Labels | Annotations | Notes |
|
||
|
|
|---|---|---|---|---|
|
||
|
|
| `grafana` | Deployment `grafana` in `monitoring` | `service: grafana`, `category: monitoring` | `display-name: "Grafana"`, `kv-path: grafana`, `depends-on: openbao` | |
|
||
|
|
| `prometheus` | Deployment `prometheus` in `monitoring` | `service: prometheus`, `category: monitoring` | `display-name: "Prometheus"` | No KV, no DB, no deps |
|
||
|
|
| `loki` | Deployment `loki` in `monitoring` | `service: loki`, `category: monitoring` | `display-name: "Loki"` | No KV, no DB, no deps |
|
||
|
|
|
||
|
|
### Infra
|
||
|
|
|
||
|
|
| Service | K8s Resource | Labels | Annotations | Notes |
|
||
|
|
|---|---|---|---|---|
|
||
|
|
| `cilium` | Deployment `cilium-operator` in `kube-system` | `service: cilium`, `category: infra` | `display-name: "Cilium (CNI)"` | No health check (HealthCheck::None) |
|
||
|
|
| `longhorn` | ConfigMap `sunbeam-svc-longhorn` in `longhorn-system` | `service: longhorn`, `category: infra`, `virtual: "true"` | `display-name: "Longhorn (Storage)"` | Virtual: no deployments listed |
|
||
|
|
| `cert-manager` | Deployment `cert-manager` in `cert-manager` | `service: cert-manager`, `category: infra` | `display-name: "cert-manager (TLS)"` | No health check |
|
||
|
|
| `ingress` | Deployment `pingora` in `ingress` | `service: ingress`, `category: infra` | `display-name: "Ingress (Proxy)"`, `depends-on: cert-manager` | No health check |
|
||
|
|
| `vso` | Deployment `vault-secrets-operator` in `vault-secrets-operator` | `service: vso`, `category: infra` | `display-name: "Vault Secrets Operator"`, `depends-on: openbao` | No health check |
|
||
|
|
| `headscale` | Deployment `headscale` in `vpn` | `service: headscale`, `category: infra` | `display-name: "Headscale (VPN)"`, `db-user: headscale`, `db-name: headscale_db`, `depends-on: postgres` | No health check, no KV, but has a DB |
|
||
|
|
| `scaleway-s3` | ConfigMap `sunbeam-svc-scaleway-s3` in `external` | `service: scaleway-s3`, `category: infra`, `virtual: "true"` | `display-name: "Scaleway S3"`, `kv-path: scaleway-s3` | Virtual: external service, no pods |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. Example Patches
|
||
|
|
|
||
|
|
### Example 1: Standard Deployment (hydra)
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# Deployment in namespace: ory
|
||
|
|
apiVersion: apps/v1
|
||
|
|
kind: Deployment
|
||
|
|
metadata:
|
||
|
|
name: hydra
|
||
|
|
namespace: ory
|
||
|
|
labels:
|
||
|
|
sunbeam.pt/service: hydra
|
||
|
|
sunbeam.pt/category: auth
|
||
|
|
annotations:
|
||
|
|
sunbeam.pt/display-name: "Hydra (OAuth2/OIDC)"
|
||
|
|
sunbeam.pt/kv-path: hydra
|
||
|
|
sunbeam.pt/db-user: hydra
|
||
|
|
sunbeam.pt/db-name: hydra_db
|
||
|
|
sunbeam.pt/depends-on: postgres,openbao
|
||
|
|
```
|
||
|
|
|
||
|
|
### Example 2: StatefulSet (openbao)
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# StatefulSet in namespace: data
|
||
|
|
apiVersion: apps/v1
|
||
|
|
kind: StatefulSet
|
||
|
|
metadata:
|
||
|
|
name: openbao
|
||
|
|
namespace: data
|
||
|
|
labels:
|
||
|
|
sunbeam.pt/service: openbao
|
||
|
|
sunbeam.pt/category: data
|
||
|
|
annotations:
|
||
|
|
sunbeam.pt/display-name: "OpenBao (Secrets)"
|
||
|
|
sunbeam.pt/health-check: seal-status
|
||
|
|
```
|
||
|
|
|
||
|
|
### Example 3: CNPG Cluster (postgres)
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# CNPG Cluster in namespace: data
|
||
|
|
apiVersion: postgresql.cnpg.io/v1
|
||
|
|
kind: Cluster
|
||
|
|
metadata:
|
||
|
|
name: postgres
|
||
|
|
namespace: data
|
||
|
|
labels:
|
||
|
|
sunbeam.pt/service: postgres
|
||
|
|
sunbeam.pt/category: data
|
||
|
|
annotations:
|
||
|
|
sunbeam.pt/display-name: "PostgreSQL (CNPG)"
|
||
|
|
sunbeam.pt/health-check: cnpg
|
||
|
|
```
|
||
|
|
|
||
|
|
### Example 4: External service ConfigMap (scaleway-s3)
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# No pods exist for this service; use a ConfigMap placeholder
|
||
|
|
apiVersion: v1
|
||
|
|
kind: ConfigMap
|
||
|
|
metadata:
|
||
|
|
name: sunbeam-svc-scaleway-s3
|
||
|
|
namespace: external
|
||
|
|
labels:
|
||
|
|
sunbeam.pt/service: scaleway-s3
|
||
|
|
sunbeam.pt/category: infra
|
||
|
|
sunbeam.pt/virtual: "true"
|
||
|
|
annotations:
|
||
|
|
sunbeam.pt/display-name: "Scaleway S3"
|
||
|
|
sunbeam.pt/kv-path: scaleway-s3
|
||
|
|
data: {}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Example 5: Multi-deployment service (messages)
|
||
|
|
|
||
|
|
All three Deployments carry the same `sunbeam.pt/service: messages` label. Full annotations go on the primary Deployment; the others only need the labels.
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# Primary Deployment - carries all annotations
|
||
|
|
apiVersion: apps/v1
|
||
|
|
kind: Deployment
|
||
|
|
metadata:
|
||
|
|
name: messages-backend
|
||
|
|
namespace: lasuite
|
||
|
|
labels:
|
||
|
|
sunbeam.pt/service: messages
|
||
|
|
sunbeam.pt/category: messaging
|
||
|
|
annotations:
|
||
|
|
sunbeam.pt/display-name: "Messages (Mail)"
|
||
|
|
sunbeam.pt/kv-path: messages
|
||
|
|
sunbeam.pt/db-user: messages
|
||
|
|
sunbeam.pt/db-name: messages_db
|
||
|
|
sunbeam.pt/build-target: messages
|
||
|
|
sunbeam.pt/depends-on: postgres,openbao
|
||
|
|
---
|
||
|
|
# Secondary Deployment - labels only
|
||
|
|
apiVersion: apps/v1
|
||
|
|
kind: Deployment
|
||
|
|
metadata:
|
||
|
|
name: messages-mta-in
|
||
|
|
namespace: lasuite
|
||
|
|
labels:
|
||
|
|
sunbeam.pt/service: messages
|
||
|
|
sunbeam.pt/category: messaging
|
||
|
|
---
|
||
|
|
# Secondary Deployment - labels only
|
||
|
|
apiVersion: apps/v1
|
||
|
|
kind: Deployment
|
||
|
|
metadata:
|
||
|
|
name: messages-mta-out
|
||
|
|
namespace: lasuite
|
||
|
|
labels:
|
||
|
|
sunbeam.pt/service: messages
|
||
|
|
sunbeam.pt/category: messaging
|
||
|
|
```
|
||
|
|
|
||
|
|
The same pattern applies to `people-celery` (Deployments: `people-celery-worker`, `people-celery-beat`).
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. Verification
|
||
|
|
|
||
|
|
### List all sunbeam-managed services
|
||
|
|
|
||
|
|
```bash
|
||
|
|
kubectl get deploy,sts,cm -A -l sunbeam.pt/service
|
||
|
|
```
|
||
|
|
|
||
|
|
### Check a specific service
|
||
|
|
|
||
|
|
```bash
|
||
|
|
kubectl get deploy -n ory -l sunbeam.pt/service=hydra \
|
||
|
|
-o jsonpath='{.items[0].metadata.annotations}'
|
||
|
|
```
|
||
|
|
|
||
|
|
### List all services in a category
|
||
|
|
|
||
|
|
```bash
|
||
|
|
kubectl get deploy,sts,cm -A -l sunbeam.pt/category=platform
|
||
|
|
```
|
||
|
|
|
||
|
|
### List virtual services only
|
||
|
|
|
||
|
|
```bash
|
||
|
|
kubectl get cm -A -l sunbeam.pt/virtual=true
|
||
|
|
```
|
||
|
|
|
||
|
|
### Verify all 33 services are discoverable
|
||
|
|
|
||
|
|
```bash
|
||
|
|
kubectl get deploy,sts,cm -A -l sunbeam.pt/service \
|
||
|
|
-o jsonpath='{range .items[*]}{.metadata.labels.sunbeam\.pt/service}{"\n"}{end}' \
|
||
|
|
| sort -u | wc -l
|
||
|
|
# Expected: 33
|
||
|
|
```
|
||
|
|
|
||
|
|
### Test with the CLI after labeling
|
||
|
|
|
||
|
|
```bash
|
||
|
|
sunbeam status # Should list all services
|
||
|
|
sunbeam logs hydra # Should find hydra pods via label selector
|
||
|
|
sunbeam restart auth # Should restart all services in the auth category
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Notes
|
||
|
|
|
||
|
|
- The `sunbeam.pt/health-check` annotation defaults to `pod-ready` when omitted. Only set it explicitly for `cnpg`, `seal-status`, or custom HTTP paths.
|
||
|
|
- Services with `HealthCheck::None` in the registry (all Infra services) should **not** have a `health-check` annotation. The CLI treats missing health-check on infra services as "no active health monitoring."
|
||
|
|
- The `sunbeam.pt/virtual` label is only needed on ConfigMap placeholders for services with no workload resources. The two virtual services are `longhorn` and `scaleway-s3`.
|
||
|
|
- Namespace is not encoded as a label/annotation because it is intrinsic to the Kubernetes resource itself.
|