Skip to content
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

Provide an unprotected healthcheck endpoint for K8S #4168

Open
winston0410 opened this issue Jul 10, 2024 · 6 comments
Open

Provide an unprotected healthcheck endpoint for K8S #4168

winston0410 opened this issue Jul 10, 2024 · 6 comments

Comments

@winston0410
Copy link

Is your feature request related to a problem? Please describe.
At the moment there is no unprotected healthcheck endpoint provided by Browserless. Even though a healthcheck mechanism is provided by browserless, it is not K8S native and not fault-tolerant.

For example, if we use this health check feature and create two browserless instance, and one is overloaded(instance A), since the healthcheck result is only known to browserless, K8S might still send traffic to instance A. Whereas if there is an unprotected healthcheck endpoint, and we can use that on readinessProbe, K8S will know instance A is not ready, and route the request to instance B.

Describe the solution you'd like
An unprotected healthcheck endpoint, /health that would return 200 if the headless browser is up. Otherwise return 503. Do not check for CPU/Memory resource inside the route, as those requirement will be handled natively else where(For K8S it will be resources limit. Similar feature is provided in docker-compose and other orchestration platform)

Describe alternatives you've considered
That is the most K8S native way

Additional context
Add any other context or screenshots about the feature request here.

@moltar
Copy link

moltar commented Aug 14, 2024

It's also worth considering what goes into a health report. I think simply running a web server is not enough. IMO, it should account for the overall health. Maybe resource usage is not important for K8S, but not all systems run on K8S.

In my opinion, a healthy service can deliver on its promise. In the case of Browserless, this means providing a browser instance that can perform browser actions promptly (defined by SLA = config values). Thus, any deviation from that would qualify the instance as "not healthy".

@joelgriffith
Copy link
Collaborator

@moltar it'd be interesting to see how that's instrumented in K8s. What you're describing sounds like a passive health check and not a discreet health-check API? Just making sure I understand correctly.

@moltar
Copy link

moltar commented Aug 14, 2024

The idea of a health endpoint is simple, IMO, and it works the same way anywhere:

A pre-defined, well-known endpoint (conventionally named /healthz). This endpoint returns:

  • a "good" HTTP status, generally 200, but can be any 2xx in theory or even any status as long as it's known and documented when the service is healthy.
  • a "bad" HTTP status, generally 503, but can be any 4xx or 5xx or even any status as long as it's known and documented when the service is not healthy.

What is considered healthy and not healthy is entirely application-specific and can be anything!

Typically, a database connection check is done, and some other resource checks, such as the amount of RAM left, etc.

The main idea behind health checks is that it is designed to take unhealthy servers (aka instances, pods, tasks) out of rotation and replace them with healthy ones, or at least not serve them more requests (in the hope it will recover). This is also often used for service upgrade rollouts, where you roll out gradually, and once the service passes all health checks, it is swapped out (blue/green).

So, in the case of Browserless, the health endpoint should return an unhealthy status when it cannot deliver on its promise, i.e., it cannot fulfill requests in time, which is mainly about the queue size and/or RAM/CPU.

@kaerbr
Copy link

kaerbr commented Oct 10, 2024

There is a /active route which might be the route you are searching for!? (:
I am using ghcr.io/browserless/chromium:v2.21.1.

From the logs (startup):

  browserless.io:limiter:info  Concurrency: 3 queue: 10 timeout: 120000ms +0ms
  browserless.io:index:info
---------------------------------------------------------
| browserless.io
| To read documentation and more, load in your browser:
|
| OpenAPI: http://0.0.0.0:3000/docs
| Full Documentation: https://docs.browserless.io/
| Debbuger: http://0.0.0.0:3000/debugger/?token=xxx
---------------------------------------------------------


█▓▒
████▒
████▒
████▒   ▒██▓▒
████▒   ▒████
████▒   ▒████
████▒   ▒████
████▒   ▒████
████▒   ▒████
████▒   ▒██████▓▒
████▒   ▒██████████▒
████▒   ▒██████▓████
████▒   ▒█▓▓▒  ▒████
████▒          ▒████
████▒       ▒▓██████
████▒   ▒▓████████▓▒
████▓▓████████▓▒
██████████▓▒
  ▓███▓▒

 +0ms
  browserless.io:index:info  Running as user "blessuser" +1ms
  browserless.io:index:info  Starting import of HTTP Routes +0ms
  browserless.io:index:info  Starting import of WebSocket Routes +120ms
  browserless.io:router:trace  Registering HTTP POST /content?(/),/chromium/content?(/) +0ms
  browserless.io:router:trace  Registering HTTP POST /download?(/),/chromium/download?(/) +0ms
  browserless.io:router:trace  Registering HTTP POST /function?(/),/chromium/function?(/) +0ms
  browserless.io:router:trace  Registering HTTP GET /json/list?(/) +0ms
  browserless.io:router:trace  Registering HTTP PUT /json/new?(/) +1ms
  browserless.io:router:trace  Registering HTTP GET /json/protocol?(/) +0ms
  browserless.io:router:trace  Registering HTTP GET /json/version?(/) +0ms
  browserless.io:router:trace  Registering HTTP POST /pdf?(/),/chromium/pdf?(/) +0ms
  browserless.io:router:trace  Registering HTTP POST /performance?(/),/chromium/performance?(/) +0ms
  browserless.io:router:trace  Registering HTTP POST /scrape?(/),/chromium/scrape?(/) +0ms
  browserless.io:router:trace  Registering HTTP POST /screenshot?(/),/chromium/screenshot?(/) +0ms
  browserless.io:router:trace  Registering HTTP GET /active?(/) +1ms
  browserless.io:router:trace  Registering HTTP GET /config?(/) +0ms
  browserless.io:router:trace  Registering HTTP GET /metrics/total?(/) +0ms
  browserless.io:router:trace  Registering HTTP GET /metrics?(/) +0ms
  browserless.io:router:trace  Registering HTTP GET /pressure?(/) +0ms
  browserless.io:router:trace  Registering HTTP GET /sessions?(/) +0ms
  browserless.io:router:trace  Registering HTTP GET / +1ms
  browserless.io:router:trace  Registering WebSocket "/devtools/browser/*" +0ms
  browserless.io:router:trace  Registering WebSocket "?(/),/chromium?(/)" +0ms
  browserless.io:router:trace  Registering WebSocket "/devtools/page/*" +0ms
  browserless.io:router:trace  Registering WebSocket "/playwright/chromium?(/),/chromium/playwright?(/)" +0ms
  browserless.io:index:info  Imported and validated all route files, starting up server. +18ms
  browserless.io:server:info  Server instantiated with host "0.0.0.0" on port "3000 +0ms
  browserless.io:server:info  HTTP Server is starting +2ms
  browserless.io:server:info  HTTP Server is listening on http://0.0.0.0:3000
Use http://0.0.0.0:3000 for API and connect calls +3ms
  browserless.io:index:info  Starting metrics collection. +7ms

from http://localhost:3000/docs#tag/Management-REST-APIs/paths/~1active/get :
grafik

-->

livenessProbe:
  httpGet:
    path: /active
    port: 3000
readinessProbe:
  httpGet:
    path: /active
    port: 3000

@Mickael-van-der-Beek
Copy link

@kaerbr I think the route is fine, I believe that @winston0410 's issue with it is that a token is required because the route requires authentication.

This is usually not ideal for healthcheck routes that are called by infrastructure services like Docker, load balancers, K8s, etc. because there is usually no way to obfuscate the token in the configuration.

@kaerbr
Copy link

kaerbr commented Nov 5, 2024

Ah I see.
In my local homelab scenario i did not set the env variable TOKEN so I am able to check the /active without any credetials.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants