github.com/projectcontour/contour@v1.28.2/site/content/docs/1.26/guides/grpc.md (about)

     1  ---
     2  title: Configuring ingress to gRPC services with Contour
     3  ---
     4  
     5  ## Example gRPC Service
     6  
     7  The below examples use the [gRPC server][1] used in Contour end to end tests.
     8  The server implements a service `yages.Echo` with two methods `Ping` and `Reverse`.
     9  It also implements the [gRPC health checking service][2] (see [here][3] for more details) and is bundled with the [gRPC health probe][4].
    10  
    11  An example base deployment and service for a gRPC server utilizing plaintext HTTP/2 are provided here:
    12  
    13  ```yaml
    14  ---
    15  apiVersion: apps/v1
    16  kind: Deployment
    17  metadata:
    18    labels:
    19      app.kubernetes.io/name: grpc-echo
    20    name: grpc-echo
    21  spec:
    22    replicas: 2
    23    selector:
    24      matchLabels:
    25        app.kubernetes.io/name: grpc-echo
    26    template:
    27      metadata:
    28        labels:
    29          app.kubernetes.io/name: grpc-echo
    30      spec:
    31        containers:
    32        - name: grpc-echo
    33          image: ghcr.io/projectcontour/yages:v0.1.0
    34          ports:
    35          - name: grpc
    36            containerPort: 9000
    37          readinessProbe:
    38            exec:
    39              command: ["/grpc-health-probe", "-addr=localhost:9000"]
    40  ---
    41  apiVersion: v1
    42  kind: Service
    43  metadata:
    44    labels:
    45      app.kubernetes.io/name: grpc-echo
    46    name: grpc-echo
    47  spec:
    48    selector:
    49      app.kubernetes.io/name: grpc-echo
    50    ports:
    51    - port: 9000
    52      protocol: TCP
    53      targetPort: grpc
    54  ```
    55  
    56  ## HTTPProxy Configuration
    57  
    58  Configuring proxying to a gRPC service with HTTPProxy is as simple as specifying the protocol Envoy uses with the upstream application via the `spec.routes[].services[].protocol` field.
    59  For example, in the resource below, for proxying plaintext gRPC to the `yages` sample app, the protocol is set to `h2c` to denote HTTP/2 over cleartext.
    60  For TLS secured gRPC, the protocol used would be `h2`.
    61  
    62  Route path prefix matching can be used to match a specific gRPC message if required.
    63  
    64  ```yaml
    65  ---
    66  apiVersion: projectcontour.io/v1
    67  kind: HTTPProxy
    68  metadata:
    69    name: my-grpc-service
    70  spec:
    71    virtualhost:
    72      fqdn: my-grpc-service.foo.com 
    73    routes:
    74    - conditions:
    75      - prefix: /yages.Echo/Ping # Matches a specific gRPC method.
    76      services:
    77      - name: grpc-echo
    78        port: 9000
    79        protocol: h2c
    80    - conditions: 
    81      - prefix: / # Matches everything else.
    82      services:
    83      - name: grpc-echo
    84        port: 9000
    85        protocol: h2c
    86  ```
    87  
    88  Using the sample deployment above along with this HTTPProxy example, you can test calling this plaintext gRPC server with the following [grpcurl][5] command:
    89  
    90  ```
    91  grpcurl -plaintext -authority=my-grpc-service.foo.com <load balancer IP and port if needed> yages.Echo/Ping
    92  ```
    93  
    94  If implementing a streaming RPC, it is likely you will need to adjust per-route timeouts to ensure streams are kept alive for the appropriate durations needed.
    95  Relevant timeout fields to adjust include the HTTPProxy `spec.routes[].timeoutPolicy.response` field which defaults to 15s and should be increased as well as the global timeout policy configurations in the Contour configuration file `timeouts.request-timeout` and `timeouts.max-connection-duration`.
    96  
    97  ## Ingress v1 Configuration
    98  
    99  To configure routing for gRPC requests with Ingress v1, you must add an annotation on the upstream Service resource as below.
   100  
   101  ```yaml
   102  ---
   103  apiVersion: v1
   104  kind: Service
   105  metadata:
   106    labels:
   107      app.kubernetes.io/name: grpc-echo
   108    annotations:
   109      projectcontour.io/upstream-protocol.h2c: "9000"
   110    name: grpc-echo
   111  spec:
   112    selector:
   113      app.kubernetes.io/name: grpc-echo
   114    ports:
   115    - port: 9000
   116      protocol: TCP
   117      targetPort: grpc
   118  ```
   119  
   120  The annotation key must follow the form `projectcontour.io/upstream-protocol.{protocol}` where `{protocol}` is `h2c` for plaintext gRPC or `h2` for TLS encrypted gRPC to the upstream application.
   121  The annotation value contains a comma-separated list of port names and/or numbers that must match with the ones defined in the Service definition.
   122  
   123  Using the Service above with the Ingress resource below should achieve the same configuration as with an HTTPProxy.
   124  
   125  ```yaml
   126  ---
   127  apiVersion: networking.k8s.io/v1
   128  kind: Ingress
   129  metadata:
   130    name: my-grpc-service
   131  spec:
   132    rules:
   133    - host: my-grpc-service.foo.com
   134      http:
   135        paths:
   136        - path: /
   137          backend:
   138            service:
   139              name: grpc-echo
   140              port:
   141                number: 9000
   142          pathType: Prefix
   143  ```
   144  
   145  ## Gateway API Configuration
   146  
   147  Gateway API now supports a specific resource [GRPCRoute][6] for routing gRPC requests.
   148  
   149  Configuring GRPCRoute for routing gRPC requests needs to specify parentRefs, hostnames, and routing rules with specific backendRefs. In the below example, route path matching is conducted via method matching rule for declared services and their methods.
   150  
   151  ```yaml
   152  apiVersion: gateway.networking.k8s.io/v1alpha2
   153  kind: GRPCRoute
   154  metadata:
   155    name: yages
   156  spec:
   157    parentRefs:
   158    - namespace: projectcontour
   159      name: contour
   160    hostnames:
   161    - my-grpc-service.foo.com
   162    rules:
   163    - matches:
   164      - method:
   165          service: yages.Echo
   166          method: Ping
   167      - method:
   168          service: grpc.reflection.v1alpha.ServerReflection
   169          method: ServerReflectionInfo
   170      backendRefs:
   171      - name: grpc-echo
   172        port: 9000
   173  ```
   174  Using the sample deployment above along with this GRPCRoute example, you can test calling this plaintext gRPC server with the same grpcurl command:
   175  
   176  ```yaml
   177  grpcurl -plaintext -authority=my-grpc-service.foo.com <load balancer IP and port if needed> yages.Echo/Ping
   178  ```
   179  Note that the second matching method for service of ServerReflection is required by grpcurl command.
   180  
   181  When using GRPCRoute, user should annotate their Service similarly to when using Ingress Configuration, to indicate the protocol to use when connecting to the backend Service, i.e. h2c for HTTP plaintext and h2 for TLS encrypted HTTPS. If it's not specified, Contour will infer the protocol based on the Gateway Listener protocol, h2c for HTTP and h2 for HTTPS.
   182  
   183  
   184  
   185  
   186  ## gRPC-Web
   187  
   188  Contour configures Envoy to automatically convert [gRPC-Web][7] HTTP/1 requests to gRPC over HTTP/2 RPC calls to an upstream service.
   189  This is a convenience addition to make usage of gRPC web application client libraries and the like easier.
   190  
   191  Note that you still must provide configuration of the upstream protocol to have gRPC-Web requests converted to gRPC to the upstream app.
   192  If your upstream application does not in fact support gRPC, you may get a protocol error.
   193  In that case, please see [this issue][8].
   194  
   195  For example, with the example deployment and routing configuration provided above, an example HTTP/1.1 request and response via `curl` looks like:
   196  
   197  ```
   198  curl \
   199    -s -v \
   200    <load balancer IP and port if needed>/yages.Echo/Ping \
   201    -XPOST \
   202    -H 'Host: my-grpc-service.foo.com' \
   203    -H 'Content-Type: application/grpc-web-text' \
   204    -H 'Accept: application/grpc-web-text' \
   205    -d'AAAAAAA='
   206  ```
   207  
   208  This `curl` command sends and receives gRPC messages as base 64 encoded text over HTTP/1.1.
   209  Piping the output to `base64 -d | od -c` we can see the raw text gRPC response:
   210  
   211  ```
   212  0000000  \0  \0  \0  \0 006  \n 004   p   o   n   g 200  \0  \0  \0 036
   213  0000020   g   r   p   c   -   s   t   a   t   u   s   :   0  \r  \n   g
   214  0000040   r   p   c   -   m   e   s   s   a   g   e   :  \r  \n
   215  0000056
   216  ```
   217  
   218  [1]: https://github.com/projectcontour/yages
   219  [2]: https://pkg.go.dev/google.golang.org/grpc/health/grpc_health_v1
   220  [3]: https://github.com/grpc/grpc/blob/master/doc/health-checking.md
   221  [4]: https://github.com/grpc-ecosystem/grpc-health-probe
   222  [5]: https://github.com/fullstorydev/grpcurl
   223  [6]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.GRPCRoute
   224  [7]: https://github.com/grpc/grpc-web
   225  [8]: https://github.com/projectcontour/contour/issues/4290