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.