Skip to content

Add grpc example #5699

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 59 additions & 27 deletions examples/custom-resources/grpc-upstreams/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,64 @@ grpc** field to an upstream. The protocol defaults to http if left unset.

## Prerequisites

- HTTP/2 must be enabled. See `http2` ConfigMap key in the
[ConfigMap](https://docs.nginx.com/nginx-ingress-controller/configuration/global-configuration/configmap-resource/#listeners)

- VirtualServer and VirtualServerRoute resources for gRPC applications must include TLS termination.

## Example

```yaml
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: grpc-vs
spec:
host: grpc.example.com
tls:
secret: grpc-secret
upstreams:
- name: grpc1
service: grpc-svc
port: 50051
type: grpc
routes:
- path: /helloworld.Greeter
action:
pass: grpc1
1. HTTP/2 must be enabled using the `http2` [ConfigMap key](https://docs.nginx.com/nginx-ingress-controller/configuration/global-configuration/configmap-resource/#listeners).

2. Configure TLS termination for VirtualServer and VirtualServerRoute resources.

3. A working [`grpcurl`](https://github.com/fullstorydev/grpcurl) installation.

4. [Install NGINX Ingress Controller using Manifests](https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-manifests/)

5. Save the public IP address of NGINX Ingress Controller into a shell variable:

```shell
IC_IP=XXX.YYY.ZZZ.III
```

6. Save the HTTPS port of NGINX Ingress Controller into a shell variable:

```shell
IC_HTTPS_PORT=<port number>
```

## Step 1 - Update ConfigMap with `http2: "true"`

```shell
kubectl apply -f nginx-config
```

*grpc-svc* is a service for the gRPC application. The service becomes available at the `/helloworld.Greeter` path. Note
how we used the **type: grpc** field in the Upstream configuration.
## Step 2 - Deploy the Cafe Application

Create the coffee and the tea deployments and services:

```shell
kubectl apply -f greeter-app.yaml
```

## Step 3 - Configure TLS termination and Load balancing

1. Create the secret with the TLS certificate and key:

```shell
kubectl create -f greeter-secret.yaml
```

2. Create the VirtualServer resource:

```shell
kubectl create -f greeter-virtual-server.yaml
```

## Step 4 - Test the Configuration

Access the application using `grpcurl`. Use the `-insecure` flag to turn off certificate verification for the self-signed certificate.

```shell
grpcurl -insecure -proto helloworld.proto -authority greeter.example.com $IC_IP:$IC_HTTPS_PORT helloworld.Greeter/SayHello
```

```shell
{
"message": "Hello"
}
```
32 changes: 32 additions & 0 deletions examples/custom-resources/grpc-upstreams/greeter-app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: grpc
spec:
replicas: 1
selector:
matchLabels:
app: greeter
template:
metadata:
labels:
app: greeter
spec:
containers:
- name: greeter
image: ghcr.io/nginxinc/kic-test-grpc-server:0.2.1
ports:
- containerPort: 50051
---
apiVersion: v1
kind: Service
metadata:
name: grpc-svc
spec:
ports:
- port: 50051
targetPort: 50051
protocol: TCP
name: grpc
selector:
app: greeter
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: greeter-secret
type: kubernetes.io/tls
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVEVENDQXZXZ0F3SUJBZ0lVSHFKaFE1TklPN3ZwSDMwc0JHUXZCZWNxZWlFd0RRWUpLb1pJaHZjTkFRRUwKQlFBd2daVXhDekFKQmdOVkJBWVRBa2xGTVEwd0N3WURWUVFJREFSRGIzSnJNUTB3Q3dZRFZRUUhEQVJEYjNKcgpNUTR3REFZRFZRUUtEQVZPUjBsT1dERU9NQXdHQTFVRUN3d0ZUa2RKVGxneEl6QWhCZ05WQkFNTUduWnBjblIxCllXd3RjMlZ5ZG1WeUxtVjRZVzF3YkdVdVkyOXRNU013SVFZSktvWklodmNOQVFrQkZoUnJkV0psY201bGRHVnoKUUc1bmFXNTRMbU52YlRBZUZ3MHlNekV3TXpFeE5EQXlNRE5hRncweU5ERXdNekF4TkRBeU1ETmFNSUdWTVFzdwpDUVlEVlFRR0V3SkpSVEVOTUFzR0ExVUVDQXdFUTI5eWF6RU5NQXNHQTFVRUJ3d0VRMjl5YXpFT01Bd0dBMVVFCkNnd0ZUa2RKVGxneERqQU1CZ05WQkFzTUJVNUhTVTVZTVNNd0lRWURWUVFEREJwMmFYSjBkV0ZzTFhObGNuWmwKY2k1bGVHRnRjR3hsTG1OdmJURWpNQ0VHQ1NxR1NJYjNEUUVKQVJZVWEzVmlaWEp1WlhSbGMwQnVaMmx1ZUM1agpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQy84ZHlLU3gxdHVCRm44dWErCkd6cllCRUhteDkzL0UycUhhVUdNajNHdkZJalJOQ2Z2eUdnaHFGaGNweVVWWEVtWjhKQmVjV0FzZDFZNHJkaTkKaFhSL0ZneVFMMXZFVjFrR2poYklQMmhPMnc5em9rTDRsWU5tZ3UwdUsvZlJtSU1vNnMveDN0YklvOE9ueGdVSApBQ3lzL2RXVkpnVTA1Y0ZxTCtZY0NFRGxHTGxwWFBsdUxJbkgvQklBN1k1T1VTaXdIYlFjZUQxUlpScitKcXR3CmQxN1BpcGRtZHdQbzMyelR1ZW9CY1ZlNldIaWhIb0JyY2FCanBuUUJWZG9Raks0azJHVUs3cHY2dkttNWZBUnAKUkUycS9RVHlMOEhVeWZqVHoxejQrazZ2R2xCa09rWjhzK0RlSms0SmJYRWhUdzM4YitHaE1pYWczMjFTR2ptbgp6elpMQWdNQkFBR2pVekJSTUIwR0ExVWREZ1FXQkJTYlRyNWhWWTRsd1F3WEx4RjZUMjFZTHF2empEQWZCZ05WCkhTTUVHREFXZ0JTYlRyNWhWWTRsd1F3WEx4RjZUMjFZTHF2empEQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01BMEcKQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNFa2cwZUpiOVRHMkdsU2llQVZObThWQ01abGdXdXd1QzF5UUQ0U0U3ZworL0RoRXMzc0JIamoxS1NSUnE2NHJtVHlOTFJGN3FyTDZJVjNmRmRwRUtNRFVEM0RxR25hbUVzV001K0Z0U1A3CmU2SnVVNkZGV0NxMDk4UHVWczd2WkUwbk5mdTZ4c2twdnNuUlZVQlVsTmhJOE5QK1FXSDBCejRtWGYxd3dRQ1YKUFRsNUFoQ25yZG1JNGNkSVVkWjJpREJscEQwelRFdVNVS1RtRldVaVlzS29xMEVWdTRBZVN1bGdGeTdEc1ZXbQo4Y3o1Smh3dEU3WXlqT3UySGRTNXVGOExBdUVhTDZ4c24xSDcveXhzYThHUVRJUmt6eU41UXF5SllrSlZCU0hnClA1Ri91WHB4ekFsSG1rTThGckd4OEFJVzZKQk8wcDgwd0lYK3JVeDZtdjlkCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQy84ZHlLU3gxdHVCRm4KOHVhK0d6cllCRUhteDkzL0UycUhhVUdNajNHdkZJalJOQ2Z2eUdnaHFGaGNweVVWWEVtWjhKQmVjV0FzZDFZNApyZGk5aFhSL0ZneVFMMXZFVjFrR2poYklQMmhPMnc5em9rTDRsWU5tZ3UwdUsvZlJtSU1vNnMveDN0YklvOE9uCnhnVUhBQ3lzL2RXVkpnVTA1Y0ZxTCtZY0NFRGxHTGxwWFBsdUxJbkgvQklBN1k1T1VTaXdIYlFjZUQxUlpScisKSnF0d2QxN1BpcGRtZHdQbzMyelR1ZW9CY1ZlNldIaWhIb0JyY2FCanBuUUJWZG9Raks0azJHVUs3cHY2dkttNQpmQVJwUkUycS9RVHlMOEhVeWZqVHoxejQrazZ2R2xCa09rWjhzK0RlSms0SmJYRWhUdzM4YitHaE1pYWczMjFTCkdqbW56elpMQWdNQkFBRUNnZ0VBRENYdXhkMUJoR1N6eS94RHlLdG8ydGJRenZPVHVYcjM4VHNOcllEcCtvdnIKcVlYMHN4M2dJcVV6ZG5zVHJlN3Aya2JaOUVoQkJIOXh1R09mQmZFR01hdy92azVwQkp1eCtaSzducnFOOWxPeAovaWtQdGw1TUhlR255T3Q2ZUtHcVIzTFpGMTlQQVEyRnFyN1lmdkZ1dDhJc1VZOXNTKy93cTdEOVk0VWkzNmVkCklCY3BLL2d0eFZFUWRkOFI5NStLSEVXS1ZBQWJkSFRlZTBZblNUZ2VaM2tzTUR4a0ZzT1NOR3ZnYUcxQTI0cGUKMHQzSWpkY21kRVE3ZmJHS1ljaWV6d21kMUFHSE5tSC9pU0s5VlN5OW1xeWFFazgyb2dCRW15UCtmd3FKcnkrNwppTmRZVmR3VXNXdE9rdFNIcWw1TmhZR2VhMDhXb3ZCdzZHdzFrQmRlS1FLQmdRRDluY2QvUVF5dlgzUXRRSU9zCkl5SjcyUXBFVlFidDhhaFBleUcwZGhIUk9RZFpSZnBUUlVJM05kVGU5YVNRczgwZWFKd3hDZWxOVW5MZGl2emQKbnRoZHI2cmtmWXJhOHp0NnMwMnRZZnFKSXFFVTRBenpmazVZOEQ4amlFR3FITUhza3NiS2ZRTzl4U3B5Vkl1MgpMNlhzYVZPK2ZXNk1qWTdVY1NjL1REbHNpUUtCZ1FEQnY3SVQvaEtyN3lrT09HOCtEbWtielV0ZzlDYldyYmhRCldtRWd4NjRMY0FGdGEyaTBNRTJLM3loUks4Vkt1ZHJRVGkwU0lLYzgzOE50c1BLa0gvZThqeDFYRHk3b3V2c04KaGViWEtZN29Gb2xnN2ZEV2VMT3dqR095SzdVQ0VvVW5SRzVDR3FJdmM2RGY1OENicGdGbFpSN2d5VFlxZWI0eQo3V2k5RitvZk13S0JnREppa2l1NTVLZENzM1g2Qnk2L25DNDJwRStIQk9Wb3lTTmhOd1QvSC9NTS9XVEMva1JrCjBnN2Q1dmlVbktrU3o0Rm5Ed0MvRTFhRk5zVEV4QS9UYXZEUjRZV2JXMmE4UStqUWpuSVBzUkpsaXRMMjRCdlAKMEFqalVlZmhQZ3BweEMwWHk5NldqNU80QkFMS3dTYmt1SFlMUnRQbFgzMFU4bmRLTTUzanF0VGhBb0dCQUtybwpnWnJYTGZ0UzdlRm9jT0RKNzNnaDRWTjJLK2lGdDZmU0FnbmJlckVHTFl3ckNtS2dsVlppUWZ0UVpDbmx4cHFuCnkyUkpQNTBZT2hsQjFOaG9ocTFqaFZzdHZwQjNtRXcyaVFuVjFBVHhGR0JYcEhKY2FRM2MyWGpxeXpJM3loTjQKYnRhTERmUlR5RjZhM2JHdmYxM0ZGTGJ2WjRPU2Z2QUhzclBUSzZnM0FvR0FjaU5xVlJYVG9FOFpaVkcxZkhlYwp2YzhPS1FDeXk1dmdtczJ0elZkRE9vM2F5c3hYRnVQUUpxSWNFS2lMb3pMckRHeU9NMmloaFhvaUF5NmFCR0ZyCnNsTng2akFiRXo4VFNsa2J0N21zUTRUZVk2QU4rdDhoZE1sNENTSU9vWHF2VFBnZFYzTkxWOVdibHFmbUpMTXkKTGtITVphTm8rV2p0OHkzR0NTc2lTR2s9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: cafe
spec:
host: greeter.example.com
tls:
secret: greeter-secret
upstreams:
- name: grpc
service: grpc-svc
port: 50051
type: grpc
routes:
- path: "/helloworld.Greeter"
action:
pass: grpc
38 changes: 38 additions & 0 deletions examples/custom-resources/grpc-upstreams/helloworld.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

option go_package = "google.golang.org/grpc/examples/helloworld/helloworld";
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;
}
7 changes: 7 additions & 0 deletions examples/custom-resources/grpc-upstreams/nginx-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-config
namespace: nginx-ingress
data:
http2: "true"