gRPC with Istio
2023年02月12日
% cd grpc-examples
% ls
Install Go on Linux.
sudo rm -rf /usr/local/go && tar -C /usr/local -xzf go1.20.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
go version
Here is a sample Go code to make a gRPC request to a URL:
In this example, you need to replace
The code establishes a connection to the gRPC server at
Here's an example protobuf file (protos.proto):
The
You can customize this file to define the messages and service methods required for your application.
Clone the GitHub repository.
$ git clone https://github.com/xxx/sc-grpc.git
$ aws ecr create-repository --repository-name grpcdemo --region us-west-2
$ docker tag grpcdemo <111122223333>.dkr.ecr.us-west-2.amazonaws.com/grpcdemo
$ docker login -u AWS -p $(aws ecr get-login-password --region us-west-2) <111122223333>.dkr.ecr.us-west-2.amazonaws.com
$ docker push <111122223333>.dkr.ecr.us-west-2.amazonaws.com/grpcdemo
$ cd ..
$ mkdir grpcclient
$ cd grpcclient/
greeter_client]$ go build
$ vim Dockerfile
$ vim main.go
$ docker build --tag grpcclient --file Dockerfile .
$ aws ecr create-repository --repository-name grpcdemoclient --region us-west-2
$ docker tag grpcclient <111122223333>.dkr.ecr.us-west-2.amazonaws.com/grpcdemoclient
$ docker login -u AWS -p $(aws ecr get-login-password --region us-west-2) <111122223333>.dkr.ecr.us-west-2.amazonaws.com
$ docker push <111122223333>.dkr.ecr.us-west-2.amazonaws.com/grpcdemoclient:latest
创建Virtual Service
grpc_vs.yaml文件内容:
% k apply -f grpc_vs.yaml
创建Destination Rule
grpc_dr.yaml文件内容:
% k apply -f grpc_dr.yaml
创建Service
grpc_svc.yaml文件内容:
% k apply -f grpc_svc.yaml
% kubectl logs -f client-0-59f6fdf7bb-kpq8f -c python
Make sure WAF is not preventing the Uri suffix.
Prerequisites
Install CDK
% npm install aws-cdk-lib
npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated npm WARN deprecated source-map-url@0.4.1: See https://github.com/lydell/source-map-url#deprecated npm WARN deprecated source-map-resolve@0.5.3: See https://github.com/lydell/source-map-resolve#deprecated npm WARN deprecated sane@4.1.0: some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated added 688 packages, and audited 858 packages in 6m 30 packages are looking for funding run `npm fund` for details 5 vulnerabilities (1 low, 4 high) To address issues that do not require attention, run: npm audit fix To address all issues, run: npm audit fix --force Run `npm audit` for details.
% cd grpc-examples
% ls
CODE_OF_CONDUCT.md LICENSE examples go.sum CONTRIBUTING.md README.md go.mod walkthroughs% cd walkthroughs/compute-options
Install Go on Linux.
sudo rm -rf /usr/local/go && tar -C /usr/local -xzf go1.20.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
go version
Here is a sample Go code to make a gRPC request to a URL:
package main
import (
"context"
"fmt"
"log"
"google.golang.org/grpc"
pb "path/to/your/proto/file"
)
const (
address = "localhost:50051"
)
func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
// Create a client for the service.
client := pb.NewYourServiceClient(conn)
// Make a request to the server.
req := &pb.YourRequest{}
res, err := client.MakeRequest(context.Background(), req)
if err != nil {
log.Fatalf("could not make request: %v", err)
}
fmt.Println(res)
}
In this example, you need to replace
path/to/your/proto/file with the path to your protobuf file, and YourService and YourRequest with the names of your gRPC service and request message.The code establishes a connection to the gRPC server at
localhost:50051, creates a client for your service, and makes a request to the server using the MakeRequest method of the client. The response from the server is printed to the console.Here's an example protobuf file (protos.proto):
syntax = "proto3";
package example;
service YourService {
rpc MakeRequest (YourRequest) returns (YourResponse) {}
}
message YourRequest {
string request_field = 1;
}
message YourResponse {
string response_field = 1;
}
In this example, the protobuf file defines a gRPC service named YourService with a single method, MakeRequest, that takes a YourRequest message as input and returns a YourResponse message.The
YourRequest message has a single field, request_field, of type string. The YourResponse message has a single field, response_field, also of type string.You can customize this file to define the messages and service methods required for your application.
Clone the GitHub repository.
$ git clone https://github.com/xxx/sc-grpc.git
$ aws ecr create-repository --repository-name grpcdemo --region us-west-2
{
"repository": {
"repositoryUri": "<111122223333>.dkr.ecr.us-west-2.amazonaws.com/grpcdemo",
"imageScanningConfiguration": {
"scanOnPush": false
},
"encryptionConfiguration": {
"encryptionType": "AES256"
},
"registryId": "<111122223333>",
"imageTagMutability": "MUTABLE",
"repositoryArn": "arn:aws:ecr:us-west-2:<111122223333>:repository/grpcdemo",
"repositoryName": "grpcdemo",
"createdAt": 1676204231.0
}
}
$ docker tag grpcdemo <111122223333>.dkr.ecr.us-west-2.amazonaws.com/grpcdemo
$ docker login -u AWS -p $(aws ecr get-login-password --region us-west-2) <111122223333>.dkr.ecr.us-west-2.amazonaws.com
WARNING! Using --password via the CLI is insecure. Use --password-stdin. WARNING! Your password will be stored unencrypted in /home/ec2-user/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded
$ docker push <111122223333>.dkr.ecr.us-west-2.amazonaws.com/grpcdemo
Using default tag: latest The push refers to repository [<111122223333>.dkr.ecr.us-west-2.amazonaws.com/grpcdemo] efc05b1694d5: Pushed ae1da9abcf46: Pushed latest: digest: sha256:2e3439f76ddcfc026a13dea9eb22e3664470a68365434293a65e3a6d96b9581e size: 739
$ cd ..
$ mkdir grpcclient
$ cd grpcclient/
greeter_client]$ go build
go: downloading google.golang.org/grpc v1.31.1 go: downloading github.com/golang/protobuf v1.4.2 go: downloading google.golang.org/protobuf v1.25.0 go: downloading golang.org/x/net v0.0.0-20200904194848-62affa334b73 go: downloading google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d go: downloading golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f go: downloading golang.org/x/text v0.3.3
$ vim Dockerfile
FROM golang:1.17 as builder RUN CGO_ENABLED=0 go get github.com/aws-samples/grpc-examples/examples/helloworld/greeter_client FROM scratch COPY --from=builder /go/bin/greeter_client /greeter_client CMD ["/greeter_client"]
$ vim main.go
/*
*
* 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.
*
*/
// Package main implements a client for Greeter service.
package main
import (
"context"
"log"
"os"
"time"
pb "github.com/aws-samples/grpc-examples/examples/helloworld/helloworld"
"google.golang.org/grpc"
)
const (
defaultName = "world"
)
var (
address = "grpcdemo.blog.svc.cluster.local:8051"
)
func init() {
if ep, ok := os.LookupEnv("GREETER_ENDPOINT"); ok {
address = ep
}
}
func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
}
$ docker build --tag grpcclient --file Dockerfile .
Sending build context to Docker daemon 4.608kB Step 1/5 : FROM golang:1.17 as builder ---> 742df529b073 Step 2/5 : RUN CGO_ENABLED=0 go get github.com/aws-samples/grpc-examples/examples/helloworld/greeter_client ---> Running in bbffe5865e5b go: downloading github.com/aws-samples/grpc-examples v0.0.0-20220627155707-8da33f5fbe7c go: downloading google.golang.org/grpc v1.31.1 go: downloading github.com/golang/protobuf v1.4.2 go: downloading google.golang.org/protobuf v1.25.0 go: downloading google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d go: downloading golang.org/x/net v0.0.0-20200904194848-62affa334b73 go: downloading golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f go: downloading golang.org/x/text v0.3.3 go get: installing executables with 'go get' in module mode is deprecated. Use 'go install pkg@version' instead. For more information, see https://golang.org/doc/go-get-install-deprecation or run 'go help get' or 'go help install'. Removing intermediate container bbffe5865e5b ---> a97c94dd438f Step 3/5 : FROM scratch ---> Step 4/5 : COPY --from=builder /go/bin/greeter_client /greeter_client ---> 14a2293b22dd Step 5/5 : CMD ["/greeter_client"] ---> Running in 69a6142e7be1 Removing intermediate container 69a6142e7be1 ---> 7e6f4805f17a Successfully built 7e6f4805f17a Successfully tagged grpcclient:latest
$ aws ecr create-repository --repository-name grpcdemoclient --region us-west-2
{
"repository": {
"repositoryUri": "<111122223333>.dkr.ecr.us-west-2.amazonaws.com/grpcdemoclient",
"imageScanningConfiguration": {
"scanOnPush": false
},
"encryptionConfiguration": {
"encryptionType": "AES256"
},
"registryId": "<111122223333>",
"imageTagMutability": "MUTABLE",
"repositoryArn": "arn:aws:ecr:us-west-2:<111122223333>:repository/grpcdemoclient",
"repositoryName": "grpcdemoclient",
"createdAt": 1676212221.0
}
}
$ docker tag grpcclient <111122223333>.dkr.ecr.us-west-2.amazonaws.com/grpcdemoclient
$ docker login -u AWS -p $(aws ecr get-login-password --region us-west-2) <111122223333>.dkr.ecr.us-west-2.amazonaws.com
WARNING! Using --password via the CLI is insecure. Use --password-stdin. WARNING! Your password will be stored unencrypted in /home/ec2-user/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded
$ docker push <111122223333>.dkr.ecr.us-west-2.amazonaws.com/grpcdemoclient:latest
The push refers to repository [<111122223333>.dkr.ecr.us-west-2.amazonaws.com/grpcdemoclient] 0a375004c404: Pushed latest: digest: sha256:fce32c53e1b8c4f3f6afe2302a97fadd1a238064129071fd46c6ca9a4c01154e size: 528
创建Virtual Service
grpc_vs.yaml文件内容:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: grpc
namespace: blog
spec:
hosts:
- tianzhui.cloud
http:
- match:
- port: 50051
route:
- destination:
host: backend.blog.svc.cluster.local
subset: v0
weight: 50
- destination:
host: backend.blog.svc.cluster.local
subset: v1
weight: 50
% k apply -f grpc_vs.yaml
virtualservice.networking.istio.io/grpc created
创建Destination Rule
grpc_dr.yaml文件内容:
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: backend
namespace: blog
spec:
host: backend.blog.svc.cluster.local
subsets:
- labels:
version: "0"
name: v0
- labels:
version: "1"
name: v1
% k apply -f grpc_dr.yaml
destinationrule.networking.istio.io/backend created
创建Service
grpc_svc.yaml文件内容:
apiVersion: v1
kind: Service
metadata:
labels:
app: backend
service: backend
name: backend
namespace: blog
spec:
ports:
- port: 50051
protocol: TCP
targetPort: 9090
selector:
app: backend
type: ClusterIP
% k apply -f grpc_svc.yaml
service/backend created
% kubectl logs -f client-0-59f6fdf7bb-kpq8f -c python
... ------------------------------------------------------------- Name Kana Asumi, Age: 35 Name Ayane Sakura, Age: 25 Name Aoi Yuuki, Age: 26 Name Yukari Tamura, Age: 42 Name Kana Hanazawa, Age: 29 Name Yuka Iguchi, Age: 30 Name Yoko Hikasa, Age: 33 ------------------------------------------------------------- Name Kana Asumi, Age: 35 Name Ayane Sakura, Age: 25 Name Aoi Yuuki, Age: 26 Name Yukari Tamura, Age: 42 Name Kana Hanazawa, Age: 29 Name Yuka Iguchi, Age: 30 Name Yoko Hikasa, Age: 33 ------------------------------------------------------------- ...
Make sure WAF is not preventing the Uri suffix.