Skip to content

Conversation

@yeldiRium
Copy link
Contributor

@yeldiRium yeldiRium commented May 21, 2025

Description of your changes

This MR adds a ServeOption that lets library users provide a HealthServer which will then be served with the go composition function via a common gRPC server. This allows setting up a kubernetes readiness probe to check whether a go composition function is ready to accept gRPC connections.

I have:

  • Read and followed Crossplane's contribution process.
  • Run make reviewable to ensure this PR is ready for review.

How has this code been tested

I have used this fork in our go function composition and confirmed that the passed in health server is correctly exposed via the gRPC server. I configured a kubernetes grpc liveness-probe, which was successfully called.
Since there are currently no integration or e2e tests in this project, I wasn't sure how/where to add a new test for this behavior.

I've used this minimal example for testing:

package main

import (
	"github.com/crossplane/function-sdk-go"
	functionv1 "github.com/crossplane/function-sdk-go/proto/v1"
	"google.golang.org/grpc/health"
)

type Server struct {
	functionv1.UnimplementedFunctionRunnerServiceServer
}

func main() {
	server := Server{}
	healthServer := health.NewServer()

	function.Serve(
		server,
		function.Listen("tcp", ":8080"),
		function.Insecure(true),
		function.WithHealthServer(healthServer),
	)
}

And deployed it to kubernetes with this manifest:

apiVersion: v1
kind: Pod
metadata:
  name: grpc-health-example
  namespace: default
spec:
  containers:
  - image: grpc-health-example:latest
    livenessProbe:
      grpc:
        port: 8080
    name: package-runtime
    ports:
    - containerPort: 8080
      protocol: TCP

This results in a successful liveness probe.

@yeldiRium yeldiRium marked this pull request as ready for review May 22, 2025 14:24
@yeldiRium
Copy link
Contributor Author

Hi,

we would really like this feature. Is there anything we can do to contribute more to this PR?
I've noticed that the actions are failing due to outdated versions. Is there something we can do to fix that?

Thanks in advance and kind regards,
yeldiR

@jbw976
Copy link
Member

jbw976 commented Jun 21, 2025

The CI failures due to an outdated actions/cache version may have been fixed by #199. Try to rebase your fork/branch on the latest in main and force push, then see if that helps the CI checks run again :)

Copy link
Member

@jbw976 jbw976 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you also update the How has this code been tested with some more details? e.g. show some command outputs to show it working, how you checked, etc. 🙇‍♂️

@yeldiRium
Copy link
Contributor Author

Thanks for taking a look! I rebased my branch and cleaned up the history.
I'll update the description with my tests and usage examples when I get to it at the office next week.

@yeldiRium
Copy link
Contributor Author

hi @jbw976,

I edited the pull request description to include a working example of the health server in production, including a kubernetes manifest with a successful liveness probe.

@negz
Copy link
Member

negz commented Jul 11, 2025

I just saw this PR. It seems useful.

Do users ever need to configure the health server? I see for example https://pkg.go.dev/google.golang.org/grpc/health has Shutdown and Resume methods that I imagine the server might call to indicate health.

I ask because if users would never have to configure the health server, perhaps it should just be silently on by default. Would that work?

@yeldiRium
Copy link
Contributor Author

I get the thought, but unfortunately it would not work that easily.

Users usually want to set the health information that the health server exposes. For example if I have to run some setup code before my server is ready, I first want the health server to report "unready" and after the setup I want it to report "serving".
To set that value, I need to have access to the HealthServer object to call the method SetServingStatus on it.

My example doesn't include this, since the HealthServer by default reports the status "serving".

This could also be done by silently activating the health server and somehow exposing it, so that access to the HealthServer's methods is possible. But I found this solution to be unintrusive with only two lines of setup and also useful for customization.

@negz negz merged commit ca27889 into crossplane:main Jul 15, 2025
9 checks passed
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

Successfully merging this pull request may close these issues.

3 participants