Kubernetes

An Akka gRPC service can be deployed to a Kubernetes cluster just like any other HTTP-based application, but if you want to make sure HTTP/2 is used across the board there are some things to consider.

There are 3 ways to use HTTP/2:

  • HTTP/2 over TLS, using ALPN to detect support for HTTP/2 in the TLS handshake.
  • HTTP/2 over plaintext TCP (‘h2c’), starting with HTTP/1 and using the Upgrade mechanism to negotiate moving to HTTP/2.
  • HTTP/2 over plaintext TCP (‘h2c’), without negotiation. This assumes the client has prior knowledge that the server supports HTTP/2.

A straightforward way to expose a TCP endpoint outside the cluster is to create a Kubernetes Service of type LoadBalancer. Beyond that, Kubernetes supports many types of Ingress Controllers. GCE and NGINX are the most widely known.

LoadBalancer Service

By creating a service of type LoadBalancer you can expose your services using a direct TCP loadbalancer. This means all features supported by the underlying implementation are available.

Using a LoadBalancer as the Ingress has some limitations, for example:

  • you are restricted to 1 service per IP
  • more advanced features such as TLS termination and path-based routing are not available

NGINX Ingress

Of the three ways to use HTTP/2 presented at the beginning of this page, NGINX by default only supports h2c with negotiation via the Upgrade mechanism. Because the Upgrade mechanism is more complicated than the other 2 approaches (“TLS”, and h2c with “prior knowledge”), gRPC client support for h2c with the Upgrade mechanism is not ubiquitous. Also, the loadbalancer will use HTTP/1 rather than HTTP/2 for the connection from the loadbalancer to the service. While this may happen to work it is not optimal.

GCE Ingress

GCE only supports HTTP/2 over TLS. This means you must configure GCE to use HTTPS both on the ‘outside’ and on the ‘inside’, and you will have to make sure your service is exposed over HTTPS internally as well.

To make sure the GCE loadbalancer uses HTTP/2 to connect to your service you must use the cloud.google.com/app-protocols annotation the service:

apiVersion: v1
kind: Service
metadata:
  name: my-service-3
  annotations:
    cloud.google.com/app-protocols: '{"my-grpc-port":"HTTP2"}'
spec:
  type: NodePort
  selector:
    app: metrics
    department: sales
  ports:
  - name: my-grpc-port
    port: 443
    targetPort: 8443

By default the loadbalancer will accept any certificate, so your service can be configured with a self-signed certificate.

The GCE load balancer only routes to pods that pass the health check. The default health check is a request to ‘/’ that expects a 200 OK return value, so it might be helpful to add this to your route.

Google Cloud Endpoints

The Google cloud has a Cloud Endpoints feature that allows exposing a gRPC API in a more ‘controlled’ way: you can configure API key management, authentication, monitoring quote/rate limiting, generate a ‘developer portal’ for your API’s users and much more. You need to provide your .proto definitions when creating the endpoint, and still need to configure your own loadbalancer to expose this proxy to the outside.

Found an error in this documentation? The source code for this page can be found here. Please feel free to edit and contribute a pull request.