<p>How to setup <a href="https://github.com/grpc/grpc/blob/master/doc/health-checking.md" rel="nofollow noreferrer">GRPC Health Checking</a> for gRPC with Node.js an Bazel?</p>

Florian Ludewig
<h3>1. Add the <a href="https://github.com/grpc-ecosystem/grpc-health-probe" rel="noreferrer">grpc-health-probe</a> binary to Bazel</h3>
<p>In your <code>WORKSPACE</code> file add</p>
<pre><code>load(&quot;@bazel_tools//tools/build_defs/repo:http.bzl&quot;, &quot;http_file&quot;)

http_file(
    name = &quot;grpc_health_check_bin&quot;,
    downloaded_file_path = &quot;grpc_health_probe&quot;,
    urls = [&quot;https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/v0.3.2/grpc_health_probe-linux-amd64&quot;],
)
</code></pre>
<p>to download the executable binary.</p>
<h3>2. Implement Service</h3>
<p><strong>Option 1:</strong> Use the <a href="https://github.com/grpc/grpc-node/tree/master/packages/grpc-health-check" rel="noreferrer">grpc-health-check</a> npm module</p>
<ul>
<li>just read the docs :)</li>
</ul>
<p><strong>Option 2</strong> Implement the Health service yourself</p>
<ol>
<li>Go to <a href="https://github.com/grpc/grpc/blob/master/doc/health-checking.md" rel="noreferrer">this</a> page and copy the <code>health-checking.proto</code> file, which currently looks like this:
<pre class="lang-proto prettyprint-override"><code>syntax = &quot;proto3&quot;;

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);
}
</code></pre>
</li>
<li>In your BUILD.bazel file create a filegroup with the proto file, such that we can later add it to the NodeJs image
<pre><code>filegroup(
    name = &quot;health_checking_proto&quot;,
    srcs = [&quot;health-checking.proto&quot;],
)
</code></pre>
</li>
<li>Implement the Health service
<pre><code>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) =&gt; callback(null, {status: 'SERVING'}),
  }
  server.addService(service, implementation)

  server.bindAsync('0.0.0.0:9090', grpc.ServerCredentials.createInsecure(), () =&gt; server.start())
}

main()
</code></pre>
</li>
</ol>
<h3>3. Build and Deploy the NodeJs image with Bazel</h3>
<p>The final <code>BUILD</code> file might look like this:</p>
<pre><code>load(&quot;@npm//@bazel/typescript:index.bzl&quot;, &quot;ts_library&quot;)
load(&quot;@k8s_deploy//:defaults.bzl&quot;, &quot;k8s_deploy&quot;)
load(&quot;@io_bazel_rules_docker//nodejs:image.bzl&quot;, &quot;nodejs_image&quot;)

package(default_visibility = [&quot;//visibility:public&quot;])

ts_library(
    name = &quot;lib&quot;,
    srcs = glob(include = [&quot;**/*.ts&quot;]),
    deps = [
        &quot;@npm//@grpc/grpc-js&quot;,
        &quot;@npm//@grpc/proto-loader&quot;,
        &quot;@npm//@types/node&quot;,
    ],
)

filegroup(
    name = &quot;health_checking_proto&quot;,
    srcs = [&quot;health-checking.proto&quot;],
)

nodejs_image(
    name = &quot;image&quot;,
    data = [
        # nodejs application
        &quot;:lib&quot;,
        # health-checking.proto file
        &quot;:health_checking_proto&quot;,
        # grpc-health-probe executable binary
        &quot;@grpc_health_check_bin//file&quot;,
    ],
    entry_point = &quot;:index.ts&quot;,
)

k8s_deploy(
    name = &quot;k8s&quot;,
    images = {&quot;k8s:placeholder_name&quot;: &quot;:image&quot;},
    template = &quot;:k8s.yaml&quot;,
)
</code></pre>
<h3>4. Add Liveness and Readiness Probes to Kubernetes</h3>
<pre class="lang-yaml prettyprint-override"><code>spec:
  containers:
  - name: server
    image: &quot;[YOUR-DOCKER-IMAGE]&quot;
    ports:
    - containerPort: 9090
    readinessProbe:
      exec:
        command: [&quot;/app/&lt;path to dir with BUILD file&gt;/image.binary.runfiles/grpc_health_check_bin/file/grpc_health_probe&quot;, &quot;-addr=:9090&quot;]
      initialDelaySeconds: 5
    livenessProbe:
      exec:
        command: [&quot;/app/&lt;path to dir with BUILD file&gt;/image.binary.runfiles/grpc_health_check_bin/file/grpc_health_probe&quot;, &quot;-addr=:9090&quot;]
      initialDelaySeconds: 10
</code></pre>
