|
| 1 | +--- |
| 2 | +name: pgro-status |
| 3 | +description: Check the operational health of a postgres-restore-operator deployment and the replicas/restores it manages. Use when the user asks to "check the replicas", "status check", "is pgro healthy", or similar — anything about pgro operational state in a live cluster. |
| 4 | +--- |
| 5 | + |
| 6 | +# pgro-status |
| 7 | + |
| 8 | +A standard workflow for inspecting a running postgres-restore-operator and its `PostgresPhysicalReplica` / `PostgresPhysicalRestore` resources via `kubectl`. |
| 9 | + |
| 10 | +## Preconditions |
| 11 | + |
| 12 | +- `kubectl` is configured with a context that can see the namespace where pgro is installed (commonly `pgro-system`) and the namespaces holding the replica CRs. |
| 13 | +- If the user's `kubectl` is split across contexts, **confirm the active context first** — pointing at the wrong cluster is the most common reason a check looks "broken" when it isn't. |
| 14 | + |
| 15 | +If the API server is unreachable (timeouts, DNS failures, etc.), report the underlying error and stop; the rest of the workflow won't work. |
| 16 | + |
| 17 | +## Workflow |
| 18 | + |
| 19 | +Run two phases: **overview** (one query per resource kind, single pass) and **per-replica detail** (one targeted block per replica that looks anomalous). |
| 20 | + |
| 21 | +### Phase 1 — overview |
| 22 | + |
| 23 | +```bash |
| 24 | +kubectl get deployment -n pgro-system postgres-restore-operator \ |
| 25 | + -o jsonpath='image: {.spec.template.spec.containers[*].image}{"\n"}' |
| 26 | +kubectl get pods -n pgro-system |
| 27 | +kubectl get postgresphysicalreplicas.pgro.bes.au -A |
| 28 | +kubectl get postgresphysicalrestores.pgro.bes.au -A |
| 29 | +kubectl get pods -A --field-selector=status.phase=Pending --no-headers | wc -l |
| 30 | +``` |
| 31 | + |
| 32 | +Look for: |
| 33 | + |
| 34 | +- Operator image version and pod age. A recent restart means operator logs only cover the post-restart window, which limits debugging. |
| 35 | +- Any replica not in `Ready` phase. |
| 36 | +- Restore objects: each replica should have **exactly one** `Active` restore in steady state. A transient `Pending` / `Restoring` / `Ready` / `Switching` restore is normal during a cycle. More than one `Active` indicates the sweep isn't pruning. |
| 37 | +- Pending pod count > 0 is worth digging into before reporting healthy — could be a scheduling problem (Karpenter, taints, resource pressure). |
| 38 | + |
| 39 | +### Phase 2 — per-replica detail |
| 40 | + |
| 41 | +For each replica that looks off — and whenever a thorough check is requested — fetch the key status fields and conditions: |
| 42 | + |
| 43 | +```bash |
| 44 | +NS=<replica-namespace> |
| 45 | +kubectl get postgresphysicalreplica.pgro.bes.au -n "$NS" replica \ |
| 46 | + -o jsonpath='phase: {.status.phase}{"\n"}currentRestore: {.status.currentRestore}{"\n"}previousRestore: {.status.previousRestore}{"\n"}lastRestoreCompletedAt: {.status.lastRestoreCompletedAt}{"\n"}nextScheduledRestore: {.status.nextScheduledRestore}{"\n"}consecutiveRestoreFailures: {.status.consecutiveRestoreFailures}{"\n"}schemaMigrationPhase: {.status.schemaMigrationPhase}{"\n"}' |
| 47 | +kubectl get postgresphysicalreplica.pgro.bes.au -n "$NS" replica \ |
| 48 | + -o jsonpath='conditions:{"\n"}{range .status.conditions[*]} {.type}: {.status} ({.reason}){"\n"}{end}' |
| 49 | +``` |
| 50 | + |
| 51 | +To enumerate the namespaces holding replicas, list them once with: |
| 52 | + |
| 53 | +```bash |
| 54 | +kubectl get postgresphysicalreplicas.pgro.bes.au -A \ |
| 55 | + -o jsonpath='{range .items[*]}{.metadata.namespace}{"\n"}{end}' |
| 56 | +``` |
| 57 | + |
| 58 | +then iterate. |
| 59 | + |
| 60 | +## Signals to flag |
| 61 | + |
| 62 | +| Signal | What it usually means | |
| 63 | +|---|---| |
| 64 | +| `consecutiveRestoreFailures > 0` | One or more recent failures; check operator logs for failure mode | |
| 65 | +| `consecutiveRestoreFailures` growing across checks | Persistent failure mode — investigate root cause | |
| 66 | +| `lastRestoreCompletedAt` far older than the cron schedule | Either upstream isn't producing new snapshots, or every recent attempt failed | |
| 67 | +| `phase: Restoring` for > 30 min | kopia restore Job pod is slow or stuck; check the Job pod logs | |
| 68 | +| `phase: Switching` for > 30 min | Schema migration likely stuck, or postgres Deployment not coming Ready | |
| 69 | +| `RestoreCreationBlocked: True` | Too-many-restores guardrail tripped — sweep isn't pruning | |
| 70 | +| `RestoreSchedulingSuspended: True` | Legacy condition (older operator versions only — suspension has been removed); means failure backoff is in effect | |
| 71 | +| `SchemaMigrationPartial` events on the replica | Migration succeeded but some statement errors were tolerated; some objects may need regenerating upstream | |
| 72 | + |
| 73 | +## Investigating failures |
| 74 | + |
| 75 | +When `consecutiveRestoreFailures` is non-zero or a restore is stuck, bucket recent failure types from operator logs: |
| 76 | + |
| 77 | +```bash |
| 78 | +kubectl logs -n pgro-system deployment/postgres-restore-operator --tail=800 > /tmp/op.txt |
| 79 | +grep -aE '"level":"(WARN|ERROR)"' /tmp/op.txt \ |
| 80 | + | grep -aoE '"message":"[^"]+"' \ |
| 81 | + | sort | uniq -c | sort -rn | head -10 |
| 82 | +``` |
| 83 | + |
| 84 | +Filter to a specific replica: |
| 85 | + |
| 86 | +```bash |
| 87 | +grep -aE "$NS" /tmp/op.txt \ |
| 88 | + | grep -aoE '"message":"[^"]+"' \ |
| 89 | + | sort | uniq -c | sort -rn | head -10 |
| 90 | +``` |
| 91 | + |
| 92 | +Events for the replica's namespace (Kubernetes default TTL ~1h, so only recent activity): |
| 93 | + |
| 94 | +```bash |
| 95 | +kubectl get events -n "$NS" --sort-by=.lastTimestamp | tail -20 |
| 96 | +``` |
| 97 | + |
| 98 | +For an in-flight kopia restore Job, the pod log shows live progress (download bytes, throughput, ETA): |
| 99 | + |
| 100 | +```bash |
| 101 | +POD=$(kubectl get pods -n "$NS" \ |
| 102 | + -l pgro.bes.au/restore=<restore-name>,job-name -o jsonpath='{.items[0].metadata.name}') |
| 103 | +kubectl logs -n "$NS" "$POD" --tail=20 |
| 104 | +``` |
| 105 | + |
| 106 | +For a postgres Deployment that's not coming Ready after kopia finishes, check init container logs (`fix-locale`, `setup-auth`) and the postgres container itself: |
| 107 | + |
| 108 | +```bash |
| 109 | +DEPLOY=<active-or-switching-restore-name> |
| 110 | +kubectl logs -n "$NS" deployment/"$DEPLOY" -c setup-auth --tail=80 |
| 111 | +kubectl logs -n "$NS" deployment/"$DEPLOY" --tail=80 |
| 112 | +``` |
| 113 | + |
| 114 | +## Reporting back |
| 115 | + |
| 116 | +Keep summaries short and high-signal. A small table covering replica / phase / last-restore-age / failure count is usually enough. Examples of how to phrase: |
| 117 | + |
| 118 | +- "All replicas healthy" — one line, no further detail needed. |
| 119 | +- "X replicas healthy, Y need attention" — followed by a short table only for the Y. |
| 120 | +- For a flagged replica: name it, give the specific anomaly, point to the next step (Job logs / events / etc.). |
| 121 | + |
| 122 | +Do **not** include cluster/site/customer identifiers, real data sizes, or production failure counts in commit messages or PR bodies if working in a public repo — keep operational specifics in the conversation with the user. |
0 commit comments