All Products
Search
Document Center

Alibaba Cloud Service Mesh:Use the proxyless service mesh feature in gRPC services

Last Updated:Mar 14, 2024

Istio can dynamically configure Envoy sidecar proxies by using a set of discovery API operations that are collectively known as xDS API. This allows you to manage gRPC workloads by using features such as traffic routing and Mutual Transport Layer Security (mTLS) authentication without the need to deploy Envoy sidecar proxies. This topic describes how to use the proxyless service mesh feature in gRPC services.

Prerequisites

Background information

The proxyless service mesh feature enables communications on the data plane without proxies. However, an agent is still required for initialization and communication with the control plane. The agent provides the following features:

  • The agent obtains and rotates the certificates used for communications on the data plane.

  • The agent acts as an xDS proxy to connect to istiod and complete authentication on behalf of applications.

  • The agent generates a bootstrap file at startup in the same way the agent does for Envoy proxies. The bootstrap file instructs the gRPC library on how to connect to istiod, where to find certificates for data plane communication, and what data to send to the control plane.

Usage notes

The proxyless service mesh feature has the following limits:

  • The PERMISSIVE mode is not supported. As a result, plaintext traffic and mTLS traffic are not supported at the same time. If you enable the STRICT mode on the server, you must explicitly specify the ISTIO_MUTUAL mode in mTLS configurations on the client.

  • Requests initiated by calling grpc.Serve(listener) or grpc.Dial("xds://...") may fail before the bootstrap file or xDS proxy is ready. You can set the holdApplicationUntilProxyStarts parameter to true to prevent this issue.

  • The implementation of xDS API in gRPC may not be compatible with Envoy proxies. Specific features may be missing, or some configurations may fail to take effect. Make sure that the Istio configurations apply to your proxyless gRPC services. For more information, see xDS Features in gRPC.

Supported features of the proxyless mode

xDS API in gRPC supports only a limited set of features compared with Envoy proxies. The following table describes the supported features.

Category

Supported feature

Service discovery

A gRPC service can identify other pods registered in the mesh.

Destination rule

  • A gRPC service can route traffic to different groups of instances based on label selectors.

  • The ROUND_ROBIN load balancing policy is supported.

  • The DISABLE and ISTIO_MUTUAL modes of mTLS are supported.

Virtual service

  • Header match and URI match in the format of /ServiceName/RPCName are supported.

  • The destination hosts and subsets can be configured.

  • The traffic weight of destination services can be specified for traffic routing.

Peer authentication

The DISABLE and STRICT modes of mTLS are supported.

Use the proxyless service mesh feature

In this example, a gRPC application named echo that supports the proxyless service mesh feature is used. This section describes how to configure the traffic routing and mTLS features for the echo application without using a sidecar proxy.

Deploy the echo application

  1. Add the inject.istio.io/templates: grpc-agent annotation to the YAML file of the echo application.

    If your application supports the proxyless mode, you can add the inject.istio.io/templates: grpc-agent annotation to the YAML file of the application to enable the proxyless mode. In addition, you need to add the proxy.istio.io/config: '{"holdApplicationUntilProxyStarts": true}' annotation to the YAML file of your gRPC server to ensure that the xDS proxy and bootstrap file are ready before the gRPC server is initialized. By default, ASM automatically adds the annotation to the YAML file of a gRPC server.

    The following sample code shows only a part of the annotations in the YAML file of the echo application. For more information about the full YAML file of the echo application, see grpc-echo.

    template:
      metadata:
        annotations:
          inject.istio.io/templates: grpc-agent
          proxy.istio.io/config: '{"holdApplicationUntilProxyStarts": true}'
        labels:
          app: echo
          version: v1
  2. Connect to the ACK cluster by using kubectl. For more information, see Obtain the kubeconfig file of a cluster and use kubectl to connect to the cluster.

  3. Run the following command to create the echo-grpc namespace:

    kubectl create namespace echo-grpc
  4. Run the following command to add a label to the echo-grpc namespace. This way, sidecar proxy injection is enabled for the echo-grpc namespace.

    In proxyless mode, sidecar proxies are not used. However, you still need to use an agent for communication with the control plane. Therefore, sidecar proxy injection must be enabled for the namespace.

    kubectl label namespace echo-grpc istio-injection=enabled
  5. Run the following command to deploy the echo application:

    kubectl -n echo-grpc apply -f https://alibabacloudservicemesh.oss-cn-beijing.aliyuncs.com/asm-grpc-proxyless/grpc-echo.yaml
  6. Verify that the echo application is deployed.

    1. Run the following command to expose port 17171:

      kubectl -n echo-grpc port-forward $(kubectl -n echo-grpc get pods -l version=v1 -ojsonpath='{.items[0].metadata.name}') 17171 &
    2. Run the following command to access the echo application:

      grpcurl -plaintext -d '{"url": "xds:///echo.echo-grpc.svc.cluster.local:7070", "count": 5}' :17171 proto.EchoTestService/ForwardEcho | jq -r '.output | join("")'  | grep Hostname

      Expected output:

      [0 body] Hostname=echo-v1-f76996c45-h7plh
      [1 body] Hostname=echo-v1-f76996c45-h7plh
      [2 body] Hostname=echo-v2-7d76b7969-ltlkp
      [3 body] Hostname=echo-v2-7d76b7969-ltlkp
      [4 body] Hostname=echo-v1-f76996c45-h7plh

Scenario 1: Use the traffic routing feature

  1. Create a destination rule.

    Create a destination rule to add a subset for each version of the workload.

    1. Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.

    2. On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose Traffic Management Center > DestinationRule. On the page that appears, click Create.

    3. On the Create page, set the Namespace parameter to echo-grpc, enter the name of the destination rule in the Name field, and then set the Host parameter to echo.echo-grpc.svc.cluster.local.

    4. Click the Service Version (Subset) tab. Then, click Add Service Version (Subset). In the Subset 1 section, set the Name parameter to v1. Click Add Label and set the Key parameter to version and the Value parameter to v1.

    5. Click Add Service Version (Subset). In the Subset 2 section, set the Name parameter to v2. Click Add Label and set the Key parameter to version and the Value parameter to v2.

    6. Click Create.

  2. Create a virtual service.

    In this example, a virtual service is created to route 80% of traffic to version v2, and 20% of the traffic to version v1.

    1. Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.

    2. On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose Traffic Management Center > VirtualService. On the page that appears, click Create.

    3. On the Create page, set the Namespace parameter to echo-grpc and enter the name of the virtual service in the Name field.

    4. Click HTTP Route. Then, click Add Route. Enter the name of the routing rule in the Name field, and click Add Route Destination. Set the Host parameter to echo.echo-grpc.svc.cluster.local, the Subset parameter to v1, and the Weight parameter to 20.

    5. Click Add Route Destination. Set the Host parameter to echo.echo-grpc.svc.cluster.local, the Subset parameter to v2, and the Weight parameter to 80.

    6. Click Create.

  3. Run the following command to send ten requests to the echo application:

    grpcurl -plaintext -d '{"url": "xds:///echo.echo-grpc.svc.cluster.local:7070", "count": 10}' :17171 proto.EchoTestService/ForwardEcho | jq -r '.output | join("")'  | grep ServiceVersion

    Expected output:

    [0 body] ServiveVersion=v2
    [0 body] ServiveVersion=v1
    [0 body] ServiveVersion=v2
    [0 body] ServiveVersion=v2
    [0 body] ServiveVersion=v2
    [0 body] ServiveVersion=v2
    [0 body] ServiveVersion=v1
    [0 body] ServiveVersion=v2
    [0 body] ServiveVersion=v2
    [0 body] ServiveVersion=v2

    The preceding result indicates that eight requests are sent to version v2, and two requests are sent to version v1 among the ten requests that are sent to the echo application. This indicates that the traffic routing configuration takes effect.

Scenario 2: Use mTLS authentication

You can enable mTLS authentication to encrypt communications between services.

  1. Create a destination rule.

    Create a destination rule to enable mTLS for the client.

    1. Log on to the ASM console.

    2. In the left-side navigation pane, choose Service Mesh > Mesh Management.

    3. On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column.

    4. On the details page of the ASM instance, choose Traffic Management Center > DestinationRule in the left-side navigation pane. On the DestinationRule page, click Create.

    5. On the Create page, set the Namespace parameter to echo-grpc, enter the name of the destination rule in the Name field, and then set the Host parameter to echo.echo-grpc.svc.cluster.local.

    6. Click Traffic Policy. Then, click Add Policy, turn on Client TLS, and select Istio Mutual from the TLS Mode drop-down list.

    7. Click Create.

  2. Run the following command to access the echo application:

    grpcurl -plaintext -d '{"url": "xds:///echo.echo-grpc.svc.cluster.local:7070"}' :17171 proto.EchoTestService/ForwardEcho | jq -r '.output | join("")'  

    Expected output:

    ERROR:
      Code: Unknown
      Message: 1/1 requests had errors; first error: rpc error: code = Unavaliable desc = all SubConna are in TransientFailure

    The request fails because mTLS is disabled on the server.

  3. Create a peer authentication policy.

    Create a peer authentication policy to enable mTLS on the server.

    1. Log on to the ASM console. In the left-side navigation pane, choose Service Mesh > Mesh Management.

    2. On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose Mesh Security Center > PeerAuthentication. On the page that appears, click Create mTLS Mode.

    3. On the Create mTLS Mode page, set the Namespace parameter to echo-grpc, enter the name of the peer authentication policy in the Name field, and then set the mTLS Mode (Namespace-wide) parameter to STRICT -Strictly Enforce mTLS. Then, click Create.

  4. Run the following command to access the echo application:

    grpcurl -plaintext -d '{"url": "xds:///echo.echo-grpc.svc.cluster.local:7070"}' :17171 proto.EchoTestService/ForwardEcho | jq -r '.output | join("")'

    Expected output:

    [0] grpcecho.Echo(${xds:///echo.echo-grpc.svc.cluster.local:7070 map [] 0 <nil> 5s false })
    [0 body] RequestHeader=x-request-id:0
    [0 body] Host=echo.echo-grpc.svc.cluster.local
    [0 body] RequestHeader=:authorit:echo.echo-grpc.svc.cluster.local:7070
    ........

    The preceding result indicates that the request is successful.

Modify the code of a gRPC service

If your gRPC service does not support the proxyless mode, you must modify the code of the client and server of the gRPC service to enable xDS API support. Then, you can use features of the proxyless mode such as traffic routing.

Important

You can enable xDS API support by modifying application code only for gRPC applications of V1.39.0 and later.

Modify the code of the gRPC client

  1. Modify the code of the gRPC client as shown in the following code snippet. This way, the application can register xDS resolvers and balancers.

    Add the following code to the main package or the package in which grpc.Dial("xds://...") is called:

    import _ "google.golang.org/grpc/xds"
  2. Modify the code of the gRPC client as shown in the following code snippet. This way, a URL that uses the xds:/// scheme must be used to establish a gRPC connection.

    conn, err := grpc.DialContext(ctx, "xds:///foo.ns.svc.cluster.local:7070")
  3. Modify the code of the gRPC client as shown in the following code snippet. This way, a special TransportCredentials option is passed to DialContext to enable mTLS.

    The setting of the FallbackCreds parameter allows a successful connection event if istiod has not sent security configurations.

    import "google.golang.org/grpc/credentials/xds"
    
    ...
    
    creds, err := xds.NewClientCredentials(xds.ClientOptions{
    FallbackCreds: insecure.NewCredentials()
    })
    // handle err
    conn, err := grpc.DialContext(
    ctx,
    "xds:///foo.ns.svc.cluster.local:7070",
    grpc.WithTransportCredentials(creds),
    )

Modify the code of the gRPC server

  1. Modify the code of the gRPC server as shown in the following code snippet. This way, a special constructor is used to create the gRPC server.

    import "google.golang.org/grpc/xds"
    
    ...
    
    server = xds.NewGRPCServer()
    RegisterFooServer(server, &fooServerImpl)
  2. Regenerate the Go code If the Go code generated by your protocol buffer compiler is out of date. This ensures that your code is compatible with the xDS server.

    The following code shows the RegisterFooServer function that is generated:

    func RegisterFooServer(s grpc.ServiceRegistrar, srv FooServer) {
    s.RegisterService(&FooServer_ServiceDesc, srv)
    }
  3. Modify the code of the gRPC server as shown in the following code snippet to enable security support.

    creds, err := xds.NewServerCredentials(xdscreds.ServerOptions{FallbackCreds: insecure.NewCredentials()})
    // handle err
    server = xds.NewGRPCServer(grpc.Creds(creds))