gRPC uses the HTTP/2 protocol and supports features such as bidirectional streaming, header compression, and multiplexing to improve network efficiency. This topic shows how to deploy a gRPC application in a Container Service for Kubernetes (ACK) cluster and use a Cloud Native Gateway to route its traffic.
Prerequisites
Step 1: Deploy the gRPC application
For detailed instructions, see Create a stateless workload by using a Deployment.
This example uses the grpcbin application as a sample backend service, which implements multiple gRPC methods. Apply the following resources to your ACK cluster.
In a Kubernetes Service, the name of the port that handles gRPC traffic must include grpc.
apiVersion: apps/v1
kind: Deployment
metadata:
name: grpcbin
spec:
replicas: 1
selector:
matchLabels:
app: grpcbin
template:
metadata:
labels:
app: grpcbin
spec:
serviceAccountName: grpcbin
containers:
- image: docker.io/moul/grpcbin
imagePullPolicy: IfNotPresent
name: grpcbin
ports:
- containerPort: 9000
- containerPort: 9001
resources:
requests:
cpu: '1'
memory: 2Gi
limit:
cpu: '1'
memory: 2Gi
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: grpcbin
---
apiVersion: v1
kind: Service
metadata:
name: grpcbin-grpc
labels:
app: grpcbin
spec:
ports:
- name: grpc
port: 9000
targetPort: 9000
selector:
app: grpcbin
The following code shows the proto definition for this gRPC service.
syntax = "proto3";
package grpcbin;
service GRPCBin {
rpc Index(EmptyMessage) returns (IndexReply) {}
// A method with no parameters that returns an empty response.
rpc Empty(EmptyMessage) returns (EmptyMessage) {}
// Echoes the request parameters in the response.
rpc DummyUnary(DummyMessage) returns (DummyMessage) {}
// A server-streaming call that returns 10 messages.
rpc DummyServerStream(DummyMessage) returns (stream DummyMessage) {}
// A client-streaming call that accepts 10 requests and returns the body of the last one.
rpc DummyClientStream(stream DummyMessage) returns (DummyMessage) {}
// A bidirectional streaming method.
rpc DummyBidirectionalStreamStream(stream DummyMessage) returns (stream DummyMessage) {}
// This method returns a specified gRPC error.
rpc SpecificError(SpecificErrorRequest) returns (EmptyMessage) {}
// This method returns a random error.
rpc RandomError(EmptyMessage) returns (EmptyMessage) {}
// This method returns headers.
rpc HeadersUnary(EmptyMessage) returns (HeadersMessage) {}
// This method returns no response.
rpc NoResponseUnary(EmptyMessage) returns (EmptyMessage) {}
}
message HeadersMessage {
message Values {
repeated string values = 1;
}
map<string, Values> Metadata = 1;
}
message SpecificErrorRequest {
uint32 code = 1;
string reason = 2;
}
message EmptyMessage {}
message DummyMessage {
message Sub {
string f_string = 1;
}
enum Enum {
ENUM_0 = 0;
ENUM_1 = 1;
ENUM_2 = 2;
}
string f_string = 1;
repeated string f_strings = 2;
int32 f_int32 = 3;
repeated int32 f_int32s = 4;
Enum f_enum = 5;
repeated Enum f_enums = 6;
Sub f_sub = 7;
repeated Sub f_subs = 8;
bool f_bool = 9;
repeated bool f_bools = 10;
int64 f_int64 = 11;
repeated int64 f_int64s= 12;
bytes f_bytes = 13;
repeated bytes f_bytess = 14;
float f_float = 15;
repeated float f_floats = 16;
}
message IndexReply {
message Endpoint {
string path = 1;
string description = 2;
}
string description = 1;
repeated Endpoint endpoints = 2;
}
gRPC is built on the HTTP/2 protocol, and its paths follow the format {PackageName}.{ServiceName}/{MethodName}. This allows the Cloud Native Gateway to route requests based on the path. For example, a gRPC call to the Index method of the grpcbin service has a path of grpcbin.GRPCBin/Index.
Step 2: Configure gRPC routing
Add the ACK cluster as a service source for the gateway and then add the grpcbin service.
Add a service source
-
Log on to the MSE console. In the top navigation bar, select a region.
-
In the left-side navigation pane, choose Cloud-native Gateway > Gateways. On the Gateways page, click the ID of the gateway.
-
In the left-side navigation pane, click Routes. Then, click the Source tab.
-
Click Add Source. In the Add Source panel, set Source Type to Container Service, configure the parameters, and then click OK.
Parameter
Description
ACK/ACK Serverless Cluster
Select the cluster where the backend service is located.
NoteWhen you create the gateway, you must select the same Virtual Private Cloud (VPC) as the backend cluster. Then, when you add the service source, the system automatically discovers clusters in that VPC.
Listen to Kubernetes Ingress
-
If you enable this option, the Cloud Native Gateway automatically listens for changes to Ingress resources and applies the domain and route configurations from those resources.
-
If you disable this option, the Cloud Native Gateway stops listening to Ingress resources and invalidates configurations previously applied from those resources. Use this option with caution.
ImportantDomain and route configurations that are manually set in the console have a higher priority than those from Ingress resources.
Ingress Class
Listens for Ingress resources associated with the specified IngressClass.
-
If left empty, the gateway listens to all Ingress resources in the cluster.
-
If you specify a value (only a single value is supported), the gateway listens for Ingress resources whose
classannotation orSpec.IngressClassNamefield matches the specified value. For example, if you set this tonginx, the gateway listens to Ingress resources with an IngressClass ofnginxand also to Ingress resources that are not associated with any IngressClass.
Namespace
Listens for Ingress resources in a specific namespace.
-
If left empty, the gateway listens to Ingress resources in all namespaces in the cluster.
-
If you specify a value (only a single value is supported), the gateway listens to Ingress resources in the specified namespace.
Update Ingress Status
If you enable this option, the system updates the IP address in the
Statusfield of the listened Ingress to the IP address of the Server Load Balancer (SLB) instance associated with the Cloud Native Gateway.NoteThis feature requires gateway version 1.2.9 or later.
Security Group Authorization
A security group is configured for the node pool of the container cluster. To allow components outside the cluster to access services within it, you must open the required service ports in the security group.
You can modify the security group. For more information, see Set security group rules.
-
Add a service
-
Log on to the MSE console, and select a region in the top navigation bar.
-
In the left-side navigation pane, choose Cloud-native Gateway > Gateways. On the Gateways page, click the ID of the gateway.
-
In the left-side navigation pane, click Routes. Then, click the Services tab.
-
Click Create Service, configure the parameters in the panel, and then click OK.
Parameter
Description
Service Sources
Select Container Service.
Namespaces
Select the namespace of the target cluster.
Services
Select the service from the list.
Add a grpcbin route
-
Log on to the MSE console, and select a region in the top navigation bar.
-
In the left-side navigation pane, choose Cloud-native Gateway > Gateways. On the Gateways page, click the ID of the gateway.
-
In the left-side navigation pane, click Routes. Then, click the Routes tab.
-
Click Add Route. On the Add Route page, configure the route parameters, and then click Save and Advertise. For detailed instructions, see Add a route.
Parameter
Description
Route Name
Set to
grpc.Domain Name
Select the default domain *.
Path
Set the match condition to Prefix, and set the path value to
/grpcbin.GRPCBin.NoteThe path format for a gRPC service is {PackageName}.{ServiceName}/{MethodName}. You can configure a prefix-based route based on this format.
Scenario
Set Scenario to Single Service.
Backend Service
Select the target service and the service port.
Verify the results
Use bloomrpc to test the gRPC service. A successful response confirms that the service is available.
You can also use other gRPC clients for testing.
Use BloomRPC to initiate a Unary Call to the grpcbin.GRPCBin.DummyUnary method. Request body example:
{
"f_string": "Hello",
"f_strings": [
"Hello"
],
"f_int32": 10,
"f_int32s": [
10
],
"f_enum": 0,
"f_enums": [
0
],
"f_sub": {
"f_string": "Hello"
},
"f_subs": [
{
"f_string": "Hello"
}
],
"f_bool": true,
"f_bools": [
true
],
"f_int64": 20,
"f_int64s": [
20
],
"f_bytes": {}
}
Server response example (latency: ~0.14s):
{
"f_strings": [
"Hello"
],
"f_int32s": [
10
],
"f_enums": [
"ENUM_0"
],
"f_subs": [
{
"f_string": "Hello"
}
],
"f_bools": [
true
],
"f_int64s": [
"20"
],
"f_bytess": [],
"f_floats": [
1.100000023841858
],
"f_string": "Hello",
"f_int32": 10,
"f_enum": "ENUM_0",
"f_sub": {
"f_string": "Hello"
}
}