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

🚀 [Feature] Middleware to support Kubernetes probes #2457

Closed
3 tasks done
x80486 opened this issue May 12, 2023 · 11 comments · Fixed by #2509
Closed
3 tasks done

🚀 [Feature] Middleware to support Kubernetes probes #2457

x80486 opened this issue May 12, 2023 · 11 comments · Fixed by #2509

Comments

@x80486
Copy link

x80486 commented May 12, 2023

Feature Description

Applications deployed on Kubernetes should provide information about their internal state with Container Probes.

Fiber could make use of a middleware to automatically manage the application availability state, so when deploying in Kubernetes (or any other environment) there is a built-in option for gathering the "liveness" and "readiness" information.

This could be as simple as implementing the aforementioned probes, but it can plug as well in the application's lifecycle; for instance, refusing traffic automatically when starting. etc. — but that could be phased out, if relevant, into another unit of work.

Additional Context (optional)

No response

Code Snippet (optional)

No response

Checklist:

  • I agree to follow Fiber's Code of Conduct.
  • I have checked for existing issues that describe my suggestion prior to opening this one.
  • I understand that improperly formatted feature requests may be closed without explanation.
@welcome
Copy link

welcome bot commented May 12, 2023

Thanks for opening your first issue here! 🎉 Be sure to follow the issue template! If you need help or want to chat with us, join us on Discord https://gofiber.io/discord

@ReneWerner87
Copy link
Member

middlewares that are in the core are not technology specific

you can implement a health check like this

image
image

@x80486
Copy link
Author

x80486 commented May 12, 2023

I understand this might not be part of the "core" middlewares, but what you are describing is a health-check endpoint, something like what go-chi provides by default — if included.

Liveness and readiness fulfill two different scenarios — they shouldn't be mixed up, and their implementation is not as simple as one endpoint for both returning an HTTP 200 (OK).

While this ticket is oriented towards a particular technology, the concepts are general enough to be used in almost any containerized environment.

@leonklingele
Copy link
Member

Agreeing with @x80486. Let's reopen this.

@leonklingele leonklingele reopened this May 12, 2023
@leonklingele
Copy link
Member

leonklingele commented May 12, 2023

@x80486 what do you think of a new readyness middleware which can be configured as follows:

type Config struct {
	// IsLive returns true when the application is running, false otherwise.
	IsLive func(c fiber.Ctx) bool

	// IsReady returns true when the application is running and ready to serve requests, false otherwise.
	IsReady func(c fiber.Ctx) bool
}

Exemplary instance:

// Init fiber and other services

app := fiber.New()

db := database.New(database.Config{ … })
fs := filesystem.New(filesystem.Config{ … })

app.Use(readiness.New(readiness.Config{
	IsLive: func(c fiber.Ctx) bool { return true },

	IsReady: func(c fiber.Ctx) bool {
		return db.Ready() && fs.Ready() && …
	},
}))

@ReneWerner87
Copy link
Member

how would this middleware look like ?
what added value does it bring instead of registering a route for the action which happens in the handler and is very specific?

don't see this middleware currently in the core, if so then maybe in the contribution packet, but i don't see a big added value there currently, because the checks inside will take up most of the code.

all the middleware could do is to register this code which is injected from outside on a certain route
but this is also very easy to do with the board means of fiber

Liveness and readiness fulfill two different scenarios — they shouldn't be mixed up, and their implementation is not as simple as one endpoint for both returning an HTTP 200 (OK).

by the way, i am aware of the difference between readiness and liveness probe and the above example was just to show how you can easily accomplish such a thing with the board tools
in the above example, there is also no database or similar dependency in the microservice that needs to be tested

@ReneWerner87
Copy link
Member

by the way this middleware only provides a health check
https://github.com/go-chi/chi/blob/c9e87efe9691a63d6a89de8bbd16b04fe4d6640e/middleware/heartbeat.go#L16-L18

code which i could provide with 3 lines in the example above

@gaby
Copy link
Member

gaby commented May 12, 2023

Would adding a heartbeat middleware that by default returns 200 like the one from go-chi, but still allow the dev to override with a custom config the function work?

@x80486
Copy link
Author

x80486 commented May 13, 2023

Fiber is a "web framework". That means it's predictable to have certain functionality that toolkits and libraries won't. Since Kubernetes is the preferred orchestration tool for deploying containers, providing something like this by default will satisfy the need of most users who are looking to implement this — regardless of how easy is to implement. On the other hand, there is limit on the amount of stuff anything can have, and if owners feel this shouldn't be part of Fiber it's understandable, because I don't know the framework as well as they do.

Moreover, I understand @ReneWerner87's concern and probably this wouldn't fit in the main set, but on the contributions one.

At the same time, @leonklingele wrote something that's more or less what users will be looking for. Basically, the implementation for liveness could be provided out of the box — and it shouldn't need to be changed because it's straightforward. The difficult one would be readiness because it involves more "moving parts" that only the application in question should be able to implement correctly. Nevertheless, again, what @leonklingele wrote provides a guidance/framework everyone can look at and customize, while having a default implementation.

@leonklingele
Copy link
Member

leonklingele commented May 13, 2023

Instead of making it a middleware, we could as well introduce those two new fields in the fiber.Config struct. It's not middleware functionality, after all..

package fiber

type Config struct {
	// …

	// IsLive should return true when the application is running, false otherwise.
	IsLive func(c fiber.Ctx) bool
	IsLiveEndpoint string // Defaults to /livez

	// IsReady should return true when the application is running and ready to serve requests, false otherwise.
	IsReady func(c fiber.Ctx) bool
	IsReadyEndpoint string // Defaults to /readyz

	// …
}

(IsLive could be made optional as it solely depends on fiber's HTTP server running state)

Not really required to have it in the fiber stdlib, but definitely a nice-to-have as quite commonly used when working with Kubernetes, Docker or Docker Compose.

EDIT: Having this, we could also easily add support for systemd's sd_notify using this code: https://github.com/coreos/go-systemd/blob/main/daemon/sdnotify.go

@luk3skyw4lker
Copy link
Contributor

Is someone working on this or was it already implemented? I would like to take a stab

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

Successfully merging a pull request may close this issue.

5 participants