How to setup GRPC Health Checking for gRPC with Node.js an Bazel?
In your WORKSPACE
file add
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
http_file(
name = "grpc_health_check_bin",
downloaded_file_path = "grpc_health_probe",
urls = ["https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/v0.3.2/grpc_health_probe-linux-amd64"],
)
to download the executable binary.
Option 1: Use the grpc-health-check npm module
Option 2 Implement the Health service yourself
health-checking.proto
file, which currently looks like this:
syntax = "proto3";
package grpc.health.v1;
message HealthCheckRequest {
string service = 1;
}
message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
SERVICE_UNKNOWN = 3; // Used only by the Watch method.
}
ServingStatus status = 1;
}
service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
}
filegroup(
name = "health_checking_proto",
srcs = ["health-checking.proto"],
)
import * as protoLoader from '@grpc/proto-loader'
import * as grpc from '@grpc/grpc-js'
async function main() {
const packageDefinition = await protoLoader.load('health-checking.proto')
const grpcObject = grpc.loadPackageDefinition(packageDefinition)
const {service} = (grpcObject.grpc as any).health.v1.Health
const server = new grpc.Server()
const implementation = {
// status can be on of UNKNOWN, SERVING, NOT_SERVING
Check: (_call: any, callback: any) => callback(null, {status: 'SERVING'}),
}
server.addService(service, implementation)
server.bindAsync('0.0.0.0:9090', grpc.ServerCredentials.createInsecure(), () => server.start())
}
main()
The final BUILD
file might look like this:
load("@npm//@bazel/typescript:index.bzl", "ts_library")
load("@k8s_deploy//:defaults.bzl", "k8s_deploy")
load("@io_bazel_rules_docker//nodejs:image.bzl", "nodejs_image")
package(default_visibility = ["//visibility:public"])
ts_library(
name = "lib",
srcs = glob(include = ["**/*.ts"]),
deps = [
"@npm//@grpc/grpc-js",
"@npm//@grpc/proto-loader",
"@npm//@types/node",
],
)
filegroup(
name = "health_checking_proto",
srcs = ["health-checking.proto"],
)
nodejs_image(
name = "image",
data = [
# nodejs application
":lib",
# health-checking.proto file
":health_checking_proto",
# grpc-health-probe executable binary
"@grpc_health_check_bin//file",
],
entry_point = ":index.ts",
)
k8s_deploy(
name = "k8s",
images = {"k8s:placeholder_name": ":image"},
template = ":k8s.yaml",
)
spec:
containers:
- name: server
image: "[YOUR-DOCKER-IMAGE]"
ports:
- containerPort: 9090
readinessProbe:
exec:
command: ["/app/<path to dir with BUILD file>/image.binary.runfiles/grpc_health_check_bin/file/grpc_health_probe", "-addr=:9090"]
initialDelaySeconds: 5
livenessProbe:
exec:
command: ["/app/<path to dir with BUILD file>/image.binary.runfiles/grpc_health_check_bin/file/grpc_health_probe", "-addr=:9090"]
initialDelaySeconds: 10