Google Remote Procedure Call (gRPC) is developed based on the HTTP/2 protocol and the Protocol Buffers serialization mechanism. gRPC supports various programming languages, multiplexing, header compression, and load balancing. Google gRPC greatly improves the communication efficiency between clients and servers. This topic describes how to use an Ingress controller provided by Container Service for Kubernetes (ACK) to access gRPC services.

Background information

gRPC is an open-source, high-performance Remote Procedure Call (RPC) framework provided by Google. gRPC uses Protocol Buffers as its Interface Definition Language (IDL). Protocol Buffers are supported by various programming language. gRPC is developed based on the HTTP/2 protocol and supports multiplexing, header compression, and load balancing. gRPC greatly improves the communication efficiency between clients and servers. Introduction to gRPCIn gRPC, a client application can directly call a method on a server application on a different machine the same as the client application calls a local method. This makes it easier for you to create distributed applications and services. Similar to other RPC frameworks, gRPC defines a service interface to specify the methods that can be called remotely and the return types. On the server side, the server implements the service interface and runs a gRPC server to process client requests.

Prerequisites

Examples of gRPC services

Use the following code to define a gRPC service. Clients can call the SAYHello interface of the helloworld.Greeter service.
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}
For more information about the source code of the gRPC service, see gRPC Hello World.

Descriptions

In the NGINX Ingress controller, gRPC services run only on HTTPS ports. The default HTTPS port for gRPC services is port 443. Therefore, you must configure a domain name and an SSL certificate for the gRPC service in the production environment. In this example, the domain name grpc.example.com and a self-signed SSL certificate are used.

In this example, the version of the ACK cluster is 1.20.4-aliyun and the version of the NGINX Ingress controller is v0.44.0.3-8e83e7dc6-aliyun.

If you already have a gRPC service, proceed to Step 3: Create an Ingress.

Step 1: Apply for an SSL certificate

If you want to use an Ingress to distribute requests to the gRPC service, you must configure an SSL certificate for the gRPC service and use the TLS protocol to communicate with the gRPC service.

You can go to SSL Certificates Service console and purchase an SSL certificate. You can also apply for a free SSL certificate on third-party platforms such as Let's Encrypt.

In this example, a self-signed SSL certificate is generated by using OpenSSL.

  1. Copy the following content to the /tmp/openssl.cnf file:
    [ req ]
    #default_bits           = 2048
    #default_md             = sha256
    #default_keyfile        = privkey.pem
    distinguished_name      = req_distinguished_name
    attributes              = req_attributes
    req_extensions          = v3_req
    
    [ req_distinguished_name ]
    countryName                     = Country Name (2 letter code)
    countryName_min                 = 2
    countryName_max                 = 2
    stateOrProvinceName             = State or Province Name (full name)
    localityName                    = Locality Name (eg, city)
    0.organizationName              = Organization Name (eg, company)
    organizationalUnitName          = Organizational Unit Name (eg, section)
    commonName                      = Common Name (eg, fully qualified host name)
    commonName_max                  = 64
    emailAddress                    = Email Address
    emailAddress_max                = 64
    
    [ req_attributes ]
    challengePassword               = A challenge password
    challengePassword_min           = 4
    challengePassword_max           = 20
    
    [v3_req]
    # Extensions to add to a certificate request
    basicConstraints = CA:FALSE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName = @alt_names
    
    [alt_names]
    DNS.1 = grpc.example.com
  2. Run the following command to generate a certificate signing request:
    openssl req -new -nodes -keyout grpc.key -out grpc.csr -config /tmp/openssl.cnf -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=AlibabaCloud/OU=ContainerService/CN=grpc.example.com"
  3. Run the following command to sign the certificate:
    openssl x509 -req -days 3650 -in grpc.csr -signkey grpc.key -out grpc.crt -extensions v3_req -extfile /tmp/openssl.cnf
    After the command is executed, the certificate file grpc.crt and the private key file grpc.key are generated.
  4. Run the following command to add the TLS Secret named grpc-secret to the cluster.
    You can also add the TLS Secret to the cluster in the ACK console. For more information, see Create a Secret.
    kubectl create secret tls grpc-secret --key grpc.key --cert grpc.crt

Step 2: Create resources for the gRPC service

Create a backend service that uses the gRPC protocol. In this example, the registry.cn-hangzhou.aliyuncs.com/acs-sample/grpc-server image is used to create the gRPC service.

  1. Create a file named grpc.yaml and copy the following content to the file:
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: grpc-service
    spec:
      replicas: 1
      selector:
        matchLabels:
          run: grpc-service
      template:
        metadata:
          labels:
            run: grpc-service
        spec:
          containers:
          - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/grpc-server:latest
            imagePullPolicy: Always
            name: grpc-service
            ports:
            - containerPort: 50051
              protocol: TCP
          restartPolicy: Always
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: grpc-service
    spec:
      ports:
      - port: 50051
        protocol: TCP
        targetPort: 50051
      selector:
        run: grpc-service
      sessionAffinity: None
      type: NodePort
  2. Run the following command to create a Deployment and a Service for gRPC:
    kubectl apply -f grpc.yaml
    Expected output:
    deployment.apps/grpc-service created
    service/grpc-service created
  3. Run the following command to query the pod:
    kubectl get pod
    Expected output:
    NAME                                   READY   STATUS              RESTARTS   AGE
    grpc-service-57884679-2bkbr            1/1     Running             0          98s
    The output indicates that the pod grpc-service-57884679-2bkbr is in the Running state.

Step 3: Create an Ingress

  1. Create a file named grpc-ingress.yaml and copy the following content to the file:
    Notice
    • In the annotation field of the Ingress that is used to deploy the gRPC service, you must add the nginx.ingress.kubernetes.io/backend-protocol annotation and set the value to GRPC.
    • In this example, the domain name grpc.example.com is used. You can modify the domain name as needed.
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: grpc-ingress
      annotations:
        # Note: You must specify the gRPC service as the backend service.
        nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
    spec:
      # The certificate.
      tls:
      - hosts:
        - grpc.example.com
        secretName: grpc-secret
      rules:
      # The domain name of the gRPC service.
      - host: grpc.example.com
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                # The gRPC service.
                name: grpc-service
                port:
                  number: 50051
  2. Run the following command to create the Ingress:
    kubectl apply -f grpc-ingress.yaml
    Expected output:
    ingress.networking.k8s.io/grpc-ingress created

Verify the result

After gRPCurl is installed on your on-premises machine, enter grpcurl <domain name>:443 list to check whether requests are distributed to the backend gRPC service.

In this example, the domain name grpc.example.com and a self-signed certificate are used. Run the following command to check whether requests are distributed to the backend gRPC service:

grpcurl -insecure -authority grpc.example.com <ip_address>:443 list
Note ip_address specifies the external IP address of the Service provisioned for the NGINX Ingress controller. You can run the kubectl get ingress command to query the IP address.
Expected output:
grpc.reflection.v1alpha.ServerReflection
helloworld.Greeter
The output indicates that requests are distributed to the backend gRPC service.

What to do next

For more information about how to perform canary releases for a gRPC service by using an Ingress controller, see Use Ingresses to implement canary releases and blue-green releases.
Notice Due to the grpc_pass limit of NGINX, you cannot configure service-weight for gRPC services.