Skip to content

Commit 185cd42

Browse files
h4x3rotabclaude
andcommitted
fix(consul-postgres-ha): wire SERVICES_JSON to coordinator env
Found during live verification on 2026-05-14: coord-0's config-entry writer only emitted `proxy-defaults/global` and quit, leaving the cluster with no per-service `service-resolver` entries or intentions. Replicas downstream saw "server closed the connection unexpectedly" on every pg_basebackup attempt — Envoy's postgres-master upstream had no resolver, so EDS returned empty, and the listener closed connections on accept. Root cause: `local.services_json` was only set in `phala_app.worker` env, not `phala_app.coordinator`. Coord-0's `mesh-sidecar/entrypoint.sh` reads `SERVICES_JSON` to drive the service-resolver + intentions writer (entrypoint.sh:384, 409, 424), and an empty/unset value made every jq pipeline iterate over no rows. Symptom verified by counting emitted "Config entry written:" lines: 1 (only proxy-defaults) BEFORE the fix, 6 (proxy-defaults + service-resolver/{demo,postgres-master,postgres-replica} + service-intentions/{demo,webdemo}) AFTER applying it. Two-file change: add `SERVICES_JSON = local.services_json` to `phala_app.coordinator`'s env block, and the matching `SERVICES_JSON=${SERVICES_JSON}` env line in `compose/coordinator.yaml`. A residual issue remains downstream (the standalone connect-proxies that the platform sidecar registers fail their service-http-checks watch with "service '' not in agent state", and replicas still can't pg_basebackup with this fix alone — probably needs DestinationServiceID set on the Pattern-B connect-proxy registration); filing as a separate punch-list item. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 48b1b0d commit 185cd42

2 files changed

Lines changed: 15 additions & 2 deletions

File tree

consul-postgres-ha/cluster-example/cluster.tf

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,11 @@ resource "phala_app" "coordinator" {
274274
docker_compose = file("${path.module}/../compose/coordinator.yaml")
275275

276276
env = {
277-
CLUSTER_NAME = var.cluster_name
278-
PEERS_JSON = local.peers_json
277+
CLUSTER_NAME = var.cluster_name
278+
PEERS_JSON = local.peers_json
279+
# Coord-0's config-entry writer needs SERVICES_JSON to emit the
280+
# per-service service-resolver + intentions entries on bringup.
281+
SERVICES_JSON = local.services_json
279282
COORDINATOR_ORDINAL = tostring(each.value)
280283
BOOTSTRAP_EXPECT = tostring(var.coordinator_replicas)
281284
COORDINATOR_VIPS = local.coordinator_vips

consul-postgres-ha/compose/coordinator.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ services:
4141
- ROLE=coordinator
4242
- CLUSTER_NAME=${CLUSTER_NAME}
4343
- PEERS_JSON=${PEERS_JSON}
44+
# SERVICES_JSON is the same content workers see — same shape, same
45+
# source-of-truth (local.services in cluster.tf). Coordinators
46+
# don't run Envoy sidecars, but coord-0 needs the service list so
47+
# its config-entry writer can emit per-service service-resolver
48+
# entries + intentions on cluster bringup. Without this, the
49+
# config-entry writer only writes proxy-defaults/global and the
50+
# whole Connect routing layer ends up with no resolvers, which
51+
# manifests downstream as replicas' pg_basebackup connections
52+
# closing on accept (empty EDS endpoint set).
53+
- SERVICES_JSON=${SERVICES_JSON}
4454
# COORDINATOR_ORDINAL is per-CVM (0..N-1); makes bootstrap-secrets
4555
# write the right /run/instance/info.json without needing Consul
4656
# KV (which itself runs on the coordinators — chicken-and-egg).

0 commit comments

Comments
 (0)