Running gRPC with Container Apps

4 minute read | By Anthony Salemo

Azure Container Apps is a new offering that runs on top of Kubernetes. A nice feature of this is that it supports gRPC, which uses HTTP/2 as its transport protocol.

With using gRPC comes a few new concepts to be aware of, some that will be covered here.

Configuring

The Transport property

By default when creating a Container App, the transport property is set to Auto - assuming this is not changed explicitly during creation.

Values for transport can be Auto, http and http2. The transport setting for the environment can be checked in the portal in the Overview blade of the Container App like the below:

Overview Blade

As of right now there is no direct way to change this to http2 in the portal. However, methods such as the AZ CLI, ARM, or BICEP, amongst others - can be used by specifying this on or after creation, like below:

In BICEP/ARM

..code..
ingress: {
    external: true
    targetPort: 50051
    // Set transport to http2 for gRPC
    transport: 'http2'
}
..code..

In the Azure CLI:

az containerapp ingress enable --name mycontainerapp --resource-group my-rg --target-port 50051 --type external --transport http2

A successful request will show the transport property with the new value.

Troubleshooting

If invoking a gRPC server while transport is set to Auto or http, for example, you may recieve the following error:

{
  "error": "14 UNAVAILABLE: upstream connect error or disconnect/reset before headers. retried and the latest reset reason: protocol error"
}

If this is seen, double check that transport is set to http2, like in the method described above, or via AZ CLI, such as with this command:

az containerapp ingress show --name mycontainerapp --resource-group my-rg

Reflection

Whos responsibility

Unless explicitly enabled, gRPC servers are inheritly ‘private’ to their callers.

Depending on the gRPC package for the language in use, reflection may or may not be available. Official gRPC reflection supported packages can be found here.

It is entirely up to the developer to implement, or not implement, reflection. This is done through code and is not Azure’s responsibility.

It’s important to note that if reflection is not enabled, then these gRPC servers that have been deployed to Container Apps (or essentially any other environment) will not be able to be invoked unless the proto file is supplied with the client.

If it is enabled, then the proto file or known contract does not need to be supplied with the client calling the gRPC server. This can almost be thought of making the gRPC servers RPC methods ‘public’.

NOTE: Some examples of applications with and without reflection can be found here

TIP: Some languages may not have reflection support through the grpc package. This means other open-sourced packages may need to be used, if desired.

Troubleshooting

If reflection is not enabled, and a client tries to call a gRPC server hosted on Container Apps without a proto file supplied, an error like this may be returned to the client:

Failed to compute set of methods to expose: server does not support the reflection API

In this case, the proto file would need to be supplied from the calling client, or, enable reflection on the gRPC server.

Client testing tools

There are a few client tools, UI or CLI based that can be used which has gRPC supported.

Each tool has it’s own way of creating a gRPC request to test with. When testing from a client tool, you should not add https:// as a prefix to the FQDN. This will likely cause an immediate error - which happens regardless of testing locally or on Azure Container Apps.. This may surface as an error such as:

Could not invoke method - Error: Invalid protocol: https

Rather, do not add any protocol - or, if the tool supports it - grpc:// or grpcs:// can be prefixed for TLS support.