-
-
Notifications
You must be signed in to change notification settings - Fork 634
[codex] Document node renderer health probes #3241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 75 commits
497a18a
37d2ffc
9e8ad39
585f916
2784693
27795d8
0a8bb35
a1df2bc
b0235c8
a6499ed
1454d3e
84c7a3d
1ebe204
0a1c3bc
f43269d
0464273
372da23
402ebcd
db58028
eee5047
42334e6
423d336
b7169ce
6f84b4e
97511ba
0c75acf
18a0cb2
c3ce264
3ffbf7c
cd54398
d03d191
b7547a6
b414b71
5d26c67
e9849c2
c4f1645
950e22c
c064a19
c9b53e5
2cfebbb
0d17e5b
dbd13cb
faab393
0c7b507
ae3764e
9ffa0bf
4e3b683
f39a8c0
8edb703
4548bf1
449931e
9065b1f
cfd9a8d
f138857
6d19040
1050661
5e22ec5
eca7b83
5ad9e6f
549863b
120183c
f49df1e
ae73c7e
6ff4f43
e48a3ca
7ebde39
3e68181
dc34dc9
7c29f56
29a62fa
e740956
5c0fa3e
bc201b3
25fde2e
f9ea8c9
fa38423
f037560
d03f3df
e8a88a5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -129,6 +129,91 @@ end | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Recommendation:** Start with a single container. Move to sidecar containers if you need per-process memory/CPU visibility (e.g., to diagnose OOM restarts). Separate workloads are rarely justified unless you have a specific need for independent scaling at high replica counts. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Control Plane Deployment Shapes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| For Control Plane deployments, choose the probe target based on where the node renderer runs. Control Plane configures | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| probes per container. Renderer probe targets below mean `tcpSocket` or h2c-aware `exec` probes, not HTTP/1.1 `httpGet` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| probes directly against the renderer. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [Control Plane Flow](https://github.com/shakacode/control-plane-flow)'s default `rails` template models Rails as a | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| single-container standard workload. If you follow that template and run the renderer inside the Rails container, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| configure the Rails workload's probes rather than looking for a separate node-renderer container. If you split the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| renderer into its own container or workload, add renderer-specific probes there. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### Same Rails Container Or Process Supervisor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Set the Rails `renderer_url` to `http://localhost:3800`. The renderer can keep the default `localhost` host binding. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Probe the `rails` container's Rails health endpoint, such as `/up` on port `3000` in Rails 7.1+ or a custom endpoint in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| earlier Rails versions. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| When Rails and the renderer share one container, use one combined Rails health endpoint if you need to check both | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This advice is correct but abstract — users familiar with Kubernetes probes but not Rails may not know how to implement "a short TCP connection check" inside a Rails health endpoint. A minimal example would make this actionable: # config/initializers/health_check.rb (Rails 7.1+ with built-in /up)
# Override or supplement /up with a renderer liveness check
Rails.application.routes.draw do
get "/up", to: proc { |env|
begin
TCPSocket.new("localhost", 3800).close
[200, {}, ["OK"]]
rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT
[503, {}, ["renderer unavailable"]]
end
}
endOr at minimum, link to the Rails health controller docs so readers know where to hook this in. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processes. For example, make the Rails readiness endpoint perform a short TCP connection check to `localhost:3800` and | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return `503` if the renderer is unreachable. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Because this guide covers React on Rails Pro's Node Renderer, the Rails endpoint below reads the same | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `ReactOnRailsPro.configuration.renderer_url` value used for SSR requests rather than requiring a second port environment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| variable. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `config/routes.rb`: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```ruby | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Override Rails 7.1+'s built-in /up route to add the renderer TCP check. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If a Rails app already defines a custom
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| get "up", to: "health#show" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `app/controllers/health_controller.rb`: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing a comment explaining why this inherits from
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```ruby | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Ruby stdlib; loaded explicitly for the URI/Socket readiness check. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| require "socket" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Placing Consider either:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| require "uri" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Inherits from ActionController::Base (not ApplicationController) to avoid | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # app-level authentication callbacks on unauthenticated probe requests. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class HealthController < ActionController::Base | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def show | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Opens and immediately closes; raises if the renderer port is unreachable. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # A successful TCP connection means the h2c listener is bound, not that | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # cluster workers are ready. Pair with the startup probe to shield liveness. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # In this same-container topology, Rails and the renderer share a network namespace. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Probe localhost even if other deployment shapes use a service host. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # connect_timeout is supported by the Ruby versions in this guide's prerequisites. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| renderer_port = URI.parse(ReactOnRailsPro.configuration.renderer_url).port | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Pro-only class in OSS docs. Suggestion — use an env var or hardcoded default instead:
Suggested change
If this entire section is intentionally Pro-only, add a callout at the top of the "Same Rails Container" subsection noting that
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Silent wrong-port bug when
Consider either validating the port or falling back explicitly:
Suggested change
Or more pragmatically: renderer_uri = URI.parse(ReactOnRailsPro.configuration.renderer_url)
renderer_port = renderer_uri.port if renderer_uri.to_s.match?(/:\d+/)
renderer_port ||= 3800 # fall back to renderer defaultAt minimum, a prose note alongside this snippet warning that |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Socket.tcp("localhost", renderer_port, connect_timeout: 1) {} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The TCP target is hardcoded to A short inline comment would prevent this confusion:
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The hardcoded Worth adding a brief inline callout (or a blockquote below the snippet) like:
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The empty block
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| head :ok | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rescue SocketError, SystemCallError, URI::Error, TypeError | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Add a nil guard before the URI parse, or widen the rescue:
Suggested change
Or, more defensively, guard the nil case explicitly: renderer_url = ReactOnRailsPro.configuration.renderer_url
raise ArgumentError, "renderer_url not configured" if renderer_url.nil?Either approach prevents an unhandled exception from masking a misconfiguration as a 500. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| head :service_unavailable | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### Separate Container In The Same Workload | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Keep the Rails `renderer_url` as `http://localhost:3800`. Use `0.0.0.0` for the renderer `host` when you rely on | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `tcpSocket` probes; `localhost` is fine for `exec`-only probes. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Add h2c-aware `exec` probes against `localhost:3800` or `tcpSocket` probes on the renderer port. For `tcpSocket`, bind the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| renderer to `0.0.0.0` because Kubernetes and platform TCP probes originate from outside the container and connect to the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pod or workload IP, not container-local loopback. `exec` probes run a command inside the container, so `localhost` works | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| there. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This section (and "Separate Node-Renderer Workload" below) gives correct prose guidance but no YAML example, whereas the Kubernetes sidecar section earlier in the file provides a full manifest. A brief callout that the same |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Probe YAML:** For Control Plane readiness and liveness fields, reuse the individual `exec` or `tcpSocket` probe blocks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > from [Kubernetes Sidecar Manifest](#kubernetes-sidecar-manifest). Attach them to the node-renderer container in this | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > workload instead of to a separate Kubernetes pod spec. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### Separate Node-Renderer Workload | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Set the Rails `renderer_url` to `http://<WORKLOAD_NAME>.<GVC_NAME>.cpln.local:3800`, use `0.0.0.0` for the renderer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `host`, and add `tcpSocket` or h2c-aware `exec` probes to the node-renderer workload container. Expose the renderer port | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| internally, not publicly, unless required. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Use the same Control Plane probe fields as the same-workload case, but attach them to the separate node-renderer workload | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| container. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Replace `<WORKLOAD_NAME>` with the renderer workload name and `<GVC_NAME>` with your Control Plane Global Virtual Cloud | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name. Use your actual renderer port if it is not `3800`; see Control Plane's | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [service-to-service endpoint format](https://docs.controlplane.com/guides/service-to-service). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Dockerfile Example | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Why the renderer entry point lives in a dedicated `renderer/` directory:** Production Docker builds commonly strip JavaScript sources after the client bundles are built, since the Rails app no longer needs them at runtime. Keeping the renderer entry point in its own top-level directory (separate from `client/`) makes it trivial to exclude from that cleanup — the Node Renderer process still needs its entry file and dependencies at runtime. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -208,14 +293,18 @@ services: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| RENDERER_HOST: '0.0.0.0' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NODE_OPTIONS: '--max-old-space-size=512' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| healthcheck: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment references Kubernetes probe values to explain the Docker Compose value, which creates a cross-context dependency. Readers of this file in isolation have to mentally connect the two systems. Consider making the comment self-contained:
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| test: ['CMD', 'curl', '-sf', '--http2-prior-knowledge', 'http://localhost:3800/info'] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # --max-time 2 leaves a 1 s buffer below the 3 s orchestrator timeout so curl exits | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # cleanly with a non-zero code rather than being killed mid-request. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| test: ['CMD', 'curl', '-sf', '--max-time', '2', '--http2-prior-knowledge', 'http://localhost:3800/info'] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
justin808 marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interval: 5s | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeout: 3s | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| retries: 5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| start_period: 10s | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Note:** In Docker Compose, the containers do not share a network namespace (unlike Kubernetes sidecars), so the renderer must bind to `0.0.0.0` and Rails must connect via the service name (`renderer`). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > The Compose example uses `--max-time 2` with `timeout: 3s` for fast local feedback; the Kubernetes examples use | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > `--max-time 3` with `timeoutSeconds: 5` to allow more scheduler and node-load jitter. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Host Binding for Container Environments | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -388,7 +477,20 @@ During container startup, you may see `ERR_STREAM_PREMATURE_CLOSE` errors from F | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **Mitigation:** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 1. **Health check endpoint** — The Node Renderer exposes a built-in `/info` endpoint that returns the node version and renderer version. Because the renderer uses cleartext HTTP/2, Kubernetes `httpGet` probes (HTTP/1.1) are incompatible with this listener. Use a TCP probe, an `exec` probe (for example with `curl --http2-prior-knowledge`, which requires curl with HTTP/2 support in your container image), or a dedicated HTTP/1.1 sidecar/port for probes. For a custom `/health` route with more granular checks, use the `configureFastify()` option (see [JS Configuration: Custom Fastify Configuration](./js-configuration.md#custom-fastify-configuration)). Configure your container orchestrator to wait for it before routing traffic. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > [!NOTE] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Probe command notes:** `exec` probes require curl with HTTP/2 support in your image. Verify with | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > `curl --version | grep -i http2`; if unavailable, use `tcpSocket` as a fallback. Set curl `--max-time` shorter than the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > orchestrator timeout so curl returns a clean non-zero exit code before Kubernetes terminates the probe process. These | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > examples use `--max-time 3` with `timeoutSeconds: 5`, leaving a 2-second buffer. Readiness and liveness omit | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > `initialDelaySeconds` because Kubernetes 1.20+ (startup probe GA) defers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > them until the startup probe succeeds. If you skip the startup probe or run an older cluster without startup probe | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > support, add an appropriate `initialDelaySeconds`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This callout uses a plain
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Security:** `/info` is unauthenticated even when `password` is configured. Keep the renderer on `localhost` or | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > private networking if exposing node and renderer version details is a concern; see | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > [Built-in Endpoints](./js-configuration.md#built-in-endpoints). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The security note is buried inside the "Probe command notes" callout alongside the curl/HTTP2 and Consider separating it into its own > **Security:** `/info` is unauthenticated even when `password` is configured. Keep the renderer
> on `localhost` or private networking if exposing node/renderer version details is a concern;
> see [Built-in Endpoints](./js-configuration.md#built-in-endpoints).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Placing the Consider moving these two callouts after item 4 (or at the end of the section) so the numbered list flows directly under "Mitigation:". This is non-blocking but would improve scannability for operators copy-pasting the probe YAML. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 1. **Health check endpoint** — The Node Renderer exposes a built-in `/info` endpoint that returns the node version and renderer version. Because the renderer uses cleartext HTTP/2, Kubernetes `httpGet` probes (HTTP/1.1) are incompatible with this listener. Use a TCP probe, an `exec` probe with an h2c-aware client such as `curl --http2-prior-knowledge`, or a dedicated HTTP/1.1 sidecar/port for probes. For a custom `/health` route with more granular checks, use the `configureFastify()` option (see [JS Configuration: Adding a Health Check Endpoint](./js-configuration.md#adding-a-health-check-endpoint)). Configure your container orchestrator to wait for it before routing traffic. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Suggest adding a brief security note here, e.g.:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 2. **Startup probe** — Configure a startup probe with a generous `initialDelaySeconds`: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```yaml | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| startupProbe: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -397,30 +499,79 @@ During container startup, you may see `ERR_STREAM_PREMATURE_CLOSE` errors from F | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| initialDelaySeconds: 10 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| periodSeconds: 5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| failureThreshold: 6 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeoutSeconds: 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 3. **Readiness probe** — Ensure traffic is only routed to the renderer when it's ready to accept requests. Prefer an `exec` probe with an h2c-aware client for application-level readiness. Use `tcpSocket` only as a minimal fallback that confirms the port is accepting connections: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```yaml | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| readinessProbe: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exec: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - curl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - -sf | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - --max-time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - '3' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - --http2-prior-knowledge | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - http://localhost:3800/info | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
justin808 marked this conversation as resolved.
justin808 marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeoutSeconds: 5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| periodSeconds: 5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| failureThreshold: 3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Note:** The `exec` probe requires curl with HTTP/2 support in your image. Verify with `curl --version | grep HTTP2`. If curl is unavailable, use `tcpSocket` as a fallback. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 4. **Liveness probe** — Ensure the renderer is restarted if it becomes unresponsive: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Notes:** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > - The YAML uses `/info` so it works before custom Fastify routes exist. Replace `/info` with `/health` after | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > registering that route via `configureFastify` if readiness should wait for renderer-specific warm-up checks. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > - Before upgrading an existing readiness probe, keep curl's `--max-time` lower than `timeoutSeconds`. If switching | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > from `tcpSocket` to `exec`, verify curl HTTP/2 support in the image first. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > - See the probe command notes above for curl HTTP/2 support, `--max-time`, loaded-node buffers, and | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > `initialDelaySeconds` guidance. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Readiness fallback option:** If curl lacks HTTP/2 support in your image, replace that `readinessProbe` with this | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > `tcpSocket` block. This checks port reachability, not application-level readiness: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > ```yaml | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > readinessProbe: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > tcpSocket: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > port: 3800 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > # TCP handshakes should complete quickly; exec/H2 uses timeoutSeconds: 5. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > timeoutSeconds: 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > periodSeconds: 5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > failureThreshold: 3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 4. **Liveness probe** — Ensure the renderer is restarted if it becomes unresponsive. The probe below changes the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The upgrade warning ("verify curl HTTP/2 support first") is important but easy to miss when reading quickly. This sentence is in the surrounding prose, but the YAML immediately follows with the > **Before upgrading:** Run `curl --version | grep -i http2` inside your container image. If HTTP/2 support is absent, use the `tcpSocket` fallback shown below instead of this `exec` block.This mirrors the pattern already used in the Kubernetes Sidecar Manifest section (line ~568) and makes the prerequisite impossible to miss. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| liveness check from `tcpSocket` to `exec`; if you are upgrading an existing deployment, verify curl HTTP/2 support | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| first: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Before upgrading:** Run `curl --version | grep -i http2` inside your container image. If HTTP/2 support is absent, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > use the `tcpSocket` fallback shown below instead of this `exec` block. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```yaml | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
justin808 marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| livenessProbe: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tcpSocket: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| port: 3800 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Omit initialDelaySeconds only if the startupProbe above is configured. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Requires curl with HTTP/2 support (verify: curl --version | grep -i http2). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # If unavailable, replace this exec probe with a tcpSocket probe on port 3800. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exec: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - curl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - -sf | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - --max-time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - '3' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - --http2-prior-knowledge | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - http://localhost:3800/info | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeoutSeconds: 5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| periodSeconds: 10 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| failureThreshold: 3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Notes:** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > - Use `/info` by default. Only substitute `/health` for liveness if that route avoids external dependency checks and | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > readiness gates. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > - See the probe command notes above for curl HTTP/2 support, `--max-time`, loaded-node buffers, and | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > `initialDelaySeconds` guidance. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### OOM Tracking | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Distinguish between Rails and Node Renderer OOM kills by checking container-level exit codes: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -451,6 +602,26 @@ In production, `logLevel: 'warn'` is sufficient unless actively debugging. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| A complete pod spec for the sidecar pattern: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > [!WARNING] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > The `exec` liveness probe in this copy-paste manifest requires curl with HTTP/2 support. Run | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > `curl --version | grep -i http2` in your container image before replacing an existing `tcpSocket` probe. If curl lacks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > HTTP/2 support, keep `tcpSocket` or add HTTP/2-capable curl support. If you cannot verify curl before rollout, use the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > `tcpSocket` fallback block below and upgrade to `exec` later. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Liveness fallback option:** The manifest below uses `exec` (preferred). If curl lacks HTTP/2 support in your image, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > replace the manifest's `livenessProbe` with this `tcpSocket` block before applying it: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > ```yaml | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > livenessProbe: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > # Omit initialDelaySeconds only if the startupProbe above is configured. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > tcpSocket: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > port: 3800 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > # TCP handshakes should complete quickly; exec/H2 uses timeoutSeconds: 5. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > timeoutSeconds: 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > periodSeconds: 10 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > failureThreshold: 3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```yaml | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| apiVersion: apps/v1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| kind: Deployment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -513,23 +684,42 @@ spec: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| initialDelaySeconds: 10 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| periodSeconds: 5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| failureThreshold: 6 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeoutSeconds: 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| readinessProbe: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Omit initialDelaySeconds only if the startupProbe above is configured. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The phrasing "Omit … only if" reads as a restriction (when it is safe to leave it out) rather than a trigger (when it is required). Readers who skip the startup probe may not notice they need to add
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exec: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - curl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - -sf | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - --max-time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - '3' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - --http2-prior-knowledge | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - http://localhost:3800/info | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
justin808 marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeoutSeconds: 5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| periodSeconds: 5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| failureThreshold: 3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The liveness probe block below (line 660) has a
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| livenessProbe: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This switches the liveness probe from a passive Consider adding a one-line callout here (before the YAML block) like:
The in-YAML comment is easy to miss for users who skim to the code block.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The liveness probe switches from Suggested addition directly above
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Users who copy-paste from a previous version of this manifest won't know this changed from
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tcpSocket: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| port: 3800 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # UPGRADE WARNING: verify curl HTTP/2 support before replacing an existing tcpSocket probe. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Requires curl with HTTP/2 support (verify: curl --version | grep -i http2). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # If unavailable, replace this exec probe with a tcpSocket probe on port 3800. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Omit initialDelaySeconds only if the startupProbe above is configured. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same phrasing issue as the readiness probe comment above — "Omit … only if" reads as a restriction rather than a trigger. Suggest the same rewording:
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exec: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The manifest now ships A user who Consider keeping If the current order is intentional (i.e., new deployments should prefer |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - curl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - -sf | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - --max-time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - '3' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - --http2-prior-knowledge | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - http://localhost:3800/info | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeoutSeconds: 5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The 1-second margin between Consider
Suggested change
(No change needed here — just flagging the |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| periodSeconds: 10 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| failureThreshold: 3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
714
to
723
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The liveness probe was silently changed from a zero-dependency Consider adding a YAML comment directly in the manifest so the requirement is visible at copy time:
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Breaking change for copy-paste users — suggest a commented-out fallback in the YAML. The manifest now shows Consider adding the fallback as commented-out lines directly in the spec, e.g.: livenessProbe:
# Omit initialDelaySeconds only if the startupProbe above is configured.
# Requires curl with HTTP/2 support (verify: curl --version | grep -i http2).
# If unavailable, uncomment the tcpSocket block below instead:
# tcpSocket:
# port: 3800
exec:
command:
- curl
- -sf
- --max-time
- '4'
- --http2-prior-knowledge
- http://localhost:3800/info
timeoutSeconds: 5
periodSeconds: 10
failureThreshold: 3This keeps the "safe default" (exec) as the active config while making the fallback a one-line uncomment rather than a from-memory rewrite, significantly reducing the risk of misapplication.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The # --- tcpSocket fallback (if curl lacks HTTP/2 support) ---
# livenessProbe:
# tcpSocket:
# port: 3800
# timeoutSeconds: 1
# periodSeconds: 10
# failureThreshold: 3This keeps both options visible in the one artifact users are most likely to copy. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Readiness endpoint:** The manifest uses `/info` for copy-paste safety because that endpoint is built in. Replace | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This "Readiness endpoint" callout is formatted as a |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > `/info` with `/health` in the readiness probe after registering that route via `configureFastify` if readiness should | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > wait for renderer-specific warm-up checks. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > **Note:** Both containers use the same Docker image, ensuring the React on Rails gem and Node Renderer package versions are always aligned. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Troubleshooting | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The heading mentions "Process Supervisor" (Foreman, Overmind, Honcho) but the body and code example only cover the single-Rails-container case. A reader using a process supervisor to co-locate Rails and the renderer in the same container will have the same
localhostnetwork topology, but the heading implies broader coverage that the section doesn't deliver.Suggest narrowing the heading:
And adding a sentence in the body: "If you use a process supervisor such as Foreman or Overmind inside the same container, the network topology is identical — both processes share
localhost."