Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/crds/kollectclusterscope.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ The namespaced [`KollectScope`](kollectscope.md) sample
([`config/samples/kollect_v1alpha1_kollectscope_team-a.yaml`](https://github.com/platformrelay/kollect/blob/main/config/samples/kollect_v1alpha1_kollectscope_team-a.yaml))
shows the same fields scoped to a single namespace.

## Enforcement

The ceiling is checked twice ([ADR-0207](../adr/0207-target-collection-filtering.md)):

| Stage | Object | Checks | On violation |
| --- | --- | --- | --- |
| Admission | [`KollectClusterTarget`](kollectclustertarget.md) | `allowedGVKs` (profile `targetGVK` and `resourceRules`), `allowedNamespaces`, `deniedNamespaces`, `allowedStaticRefNamespaces` | Create/update rejected |
| Reconcile | `KollectClusterTarget` | `allowedGVKs`, `allowedStaticRefNamespaces` | Informers unregistered; `Degraded=True` with `ScopeGVKDenied` or `ScopeNamespaceDenied` |
| Reconcile | [`KollectClusterInventory`](kollectclusterinventory.md) | `sinkRefs`, `allowedStaticRefNamespaces` on sink refs | `Degraded=True` with `ScopeSinkDenied` or `SinkNamespaceDenied` |

Reconcile is the backstop for objects admitted before the ceiling existed or was tightened, and for
targets created while `profileRef` did not yet resolve — a missing profile makes the profile
`targetGVK` unknowable at admission time. `allowedNamespaces` and `deniedNamespaces` additionally cap
`status.effectiveNamespaces` at collect time, so a selector that matches a denied namespace filters it
out rather than degrading the target.

## See also

- [KollectScope](kollectscope.md) — namespaced ceiling
Expand Down
9 changes: 9 additions & 0 deletions docs/crds/kollectclustertarget.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,14 @@ kubectl describe kctgt platform-argo-applications
| --- | --- | --- |
| `Suspended` | `spec.suspend: true` | Set `suspend: false` |
| `ProfileNotFound` | No `KollectProfile` in `profileRef.namespace` | Create the `KollectProfile` in the referenced namespace |
| `ScopeGVKDenied` | Profile `targetGVK` or a `resourceRules` GVK is outside [`KollectClusterScope`](kollectclusterscope.md) `allowedGVKs` | Add the GVK to `allowedGVKs`, or point `profileRef` at a permitted profile |
| `ScopeNamespaceDenied` | `profileRef.namespace` is outside `allowedStaticRefNamespaces` ([ADR-0208](../adr/0208-cluster-static-refs-via-namespace.md)) | Move the profile into a permitted namespace, or extend the allowlist |
| `InformerRegistrationFailed` | Dynamic client / GVK error | Verify CRD installed; check operator logs |

Scope violations unregister the target's informers before degrading, so collection stops. Admission
rejects these cases up front; reconcile repeats the check as backstop for objects admitted before the
ceiling existed or before `profileRef` resolved ([ADR-0207](../adr/0207-target-collection-filtering.md)).

## RBAC

| Actor | Verbs | Resource | Notes |
Expand All @@ -124,7 +130,10 @@ Cluster-scoped resources require elevated RBAC — restrict to platform SRE role
| Admission denied | Missing `profileRef.name` | Set the profile name |
| Admission denied | Missing `profileRef.namespace` | Set the profile namespace — required on cluster kinds (ADR-0208) |
| Admission denied | Missing `namespaceSelector` | Add explicit label selector |
| Admission denied | `includedNamespaces` outside the `KollectClusterScope` ceiling, or a denied namespace — checked even when `profileRef` does not resolve yet | Align `includedNamespaces` with the ceiling, or widen `allowedNamespaces` |
| Admission denied | `profileRef.namespace` outside `allowedStaticRefNamespaces` | Move the profile, or extend the allowlist |
| No collection | Empty `namespaceSelector` match or RBAC denied | Label namespaces; extend operator ClusterRole for target GVK |
| `ScopeGVKDenied` after upgrade | Ceiling was tightened after the target was admitted; reconcile now enforces `allowedGVKs` | Widen `allowedGVKs` or retire the target — see [Upgrading](../operator-manual/upgrading.md#cluster-scope-gvk-enforcement-after-v0180) |
| `ProfileNotFound` | No `KollectProfile` in `profileRef.namespace` | Create the profile in the referenced namespace |
| `Degraded` / `Forbidden` | SAR denies list in scoped NS | Grant operator read on target GVK in workload namespaces |

Expand Down
5 changes: 3 additions & 2 deletions docs/operator-manual/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ or namespace** in a `*SinkRefs` entry is wrong — fix the reference, not just c
| `SinkNotFound` | Inventory, Target | Typo or wrong namespace in `*SinkRefs` | Match exact sink name in **same namespace** |
| `SinkUnreachable` | Inventory, Target | `ConnectionVerified=False` on sink | Fix Secret, DSN, network; re-probe sink |
| `ScopeSinkDenied` | Inventory | Sink not in `KollectScope` allow-list | Add sink to scope allow-list refs |
| `ScopeGVKDenied` | Target | GVK blocked by scope | Update `KollectScope.spec.allowedGVKs` |
| `ScopeNamespaceDenied` | Target | Workload namespace blocked | Add to `allowedNamespaces` |
| `ScopeGVKDenied` | Target, ClusterTarget | GVK blocked by scope | Update `allowedGVKs` on `KollectScope` (Target) or `KollectClusterScope` (ClusterTarget) |
| `ScopeNamespaceDenied` | Target, ClusterTarget | Workload namespace blocked; on ClusterTarget, `profileRef.namespace` outside `allowedStaticRefNamespaces` | Add to `allowedNamespaces`, or permit the profile namespace |
| `ProfileNotFound` | Target | Missing `KollectProfile` | Apply profile in same namespace as target |
| `PayloadTooLarge` | Inventory | Exceeds `maxExportBytes` | Split targets or trim attributes |
| `ExportTerminal` | Inventory | Non-retryable sink error | Fix sink config; check operator logs |
Expand All @@ -59,6 +59,7 @@ or namespace** in a `*SinkRefs` entry is wrong — fix the reference, not just c

Full per-kind tables: [KollectInventory](../crds/kollectinventory.md#status-conditions),
[KollectTarget](../crds/kollecttarget.md#status-conditions),
[KollectClusterTarget](../crds/kollectclustertarget.md#status-conditions),
[KollectSnapshotSink](../crds/kollectsnapshotsink.md#status).

## Symptom → cause quick reference
Expand Down
32 changes: 32 additions & 0 deletions docs/operator-manual/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,38 @@ bumping versions. Common upgrade touchpoints:
!!! info "Export debouncing"
Debounce interval is per **`KollectInventory.spec.exportMinInterval`** (CRD default **30s**).

### Cluster-scope GVK enforcement (after v0.18.0)

Releases after **v0.18.0** enforce [`KollectClusterScope`](../crds/kollectclusterscope.md)
`allowedGVKs` during reconcile, not only at admission — the backstop
[ADR-0207](../adr/0207-target-collection-filtering.md) always specified.

!!! warning "Existing cluster targets can stop collecting"
A [`KollectClusterTarget`](../crds/kollectclustertarget.md) whose profile `targetGVK` or
`resourceRules` GVK sits outside a non-empty `allowedGVKs` now unregisters its informers and goes
`Degraded=True` / `reason=ScopeGVKDenied` on the first reconcile after upgrade. Targets admitted
**before** the ceiling was created or tightened are the affected set — admission only ran when
they were last written.

Audit before upgrading, on each cluster that has a `KollectClusterScope`:

```sh
kubectl get kollectclusterscopes.kollect.dev -o yaml | grep -A4 allowedGVKs
kubectl get kollectclustertargets.kollect.dev \
-o custom-columns='NAME:.metadata.name,PROFILE:.spec.profileRef.name,PROFILE_NS:.spec.profileRef.namespace'
```

Cross-check each target's profile `targetGVK` (plus any `spec.resourceRules[].gvk`) against
`allowedGVKs`. Remediate by widening `allowedGVKs`, repointing `profileRef`, or retiring the target.
After upgrading, the affected targets are listed by:

```sh
kubectl get kollectclustertargets.kollect.dev -o custom-columns=\
'NAME:.metadata.name,DEGRADED:.status.conditions[?(@.type=="Degraded")].status,REASON:.status.conditions[?(@.type=="Degraded")].reason'
```

Widening the ceiling clears the condition on the next reconcile; nothing needs to be recreated.

## GitOps and CI/CD

For Argo CD, Flux, or similar:
Expand Down
Loading