From a1a834f9fb16018790c341a3ac03099d67199bee Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Fri, 30 Aug 2019 10:49:48 -0700 Subject: [PATCH 1/4] samples/grpc-ping-go: align with knative sample and README practices --- docs/serving/samples/grpc-ping-go/Dockerfile | 30 ++++--- docs/serving/samples/grpc-ping-go/README.md | 90 +++++++++++++++---- .../{sample.yaml => service.yaml} | 0 3 files changed, 92 insertions(+), 28 deletions(-) rename docs/serving/samples/grpc-ping-go/{sample.yaml => service.yaml} (100%) diff --git a/docs/serving/samples/grpc-ping-go/Dockerfile b/docs/serving/samples/grpc-ping-go/Dockerfile index 247747affd3..1ece4748685 100644 --- a/docs/serving/samples/grpc-ping-go/Dockerfile +++ b/docs/serving/samples/grpc-ping-go/Dockerfile @@ -12,21 +12,31 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM golang AS builder +# Use the offical Golang image to create a build artifact. +# This is based on Debian and sets the GOPATH to /go. +# https://hub.docker.com/_/golang +FROM golang:1.12 as builder -# Get the dependencies from GitHub +# Retrieve the dependencies. RUN go get google.golang.org/grpc -WORKDIR /go/src/github.com/knative/docs/ -ADD . /go/src/github.com/knative/docs/ +# Copy local code to the container image. +WORKDIR /go/src/github.com/knative/docs/docs/serving/samples/grpc-ping-go +COPY . ./ -RUN CGO_ENABLED=0 go build -tags=grpcping ./docs/serving/samples/grpc-ping-go/ -RUN CGO_ENABLED=0 go build -tags=grpcping ./docs/serving/samples/grpc-ping-go/client +# Build the command inside the container. +# To facilitate gRPC testing, this container includes a client command. +RUN CGO_ENABLED=0 go build -tags=grpcping -o ./ping-server +RUN CGO_ENABLED=0 go build -tags=grpcping -o ./ping-client ./client +# Use a Docker multi-stage build to create a lean production image. +# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds +# https://github.com/GoogleContainerTools/distroless#readme FROM gcr.io/distroless/static -EXPOSE 8080 -COPY --from=builder /go/src/github.com/knative/docs/grpc-ping-go /server -COPY --from=builder /go/src/github.com/knative/docs/client /client +# Copy the binaries to the production image from the builder stage. +COPY --from=builder /go/src/github.com/knative/docs/docs/serving/samples/grpc-ping-go/ping-server /server +COPY --from=builder /go/src/github.com/knative/docs/docs/serving/samples/grpc-ping-go/ping-client /client -ENTRYPOINT ["/server"] +# Run the service on container startup. +CMD ["/server"] diff --git a/docs/serving/samples/grpc-ping-go/README.md b/docs/serving/samples/grpc-ping-go/README.md index 99a01e9418c..98554a986e1 100644 --- a/docs/serving/samples/grpc-ping-go/README.md +++ b/docs/serving/samples/grpc-ping-go/README.md @@ -13,47 +13,101 @@ A simple gRPC server written in Go that you can use for testing. - Install [docker](https://www.docker.com/). -- Download a copy of the code: +- A [Docker Hub account](https://hub.docker.com) to which you can upload the sample's container image. + +## Build and Deploy the sample code + +1. Download a copy of the code: ```shell git clone -b "{{< branch >}}" https://github.com/knative/docs knative-docs cd knative-docs/docs/serving/samples/grpc-ping-go ``` -## Build and run the gRPC server +2. Use Docker to build a container image for this service and push to Docker Hub. -First, build and publish the gRPC server to DockerHub (replacing `{username}`): + Replace `{username}` with your Docker Hub username then run the commands: -```shell -# Build and publish the container, run from the root directory. -docker build \ - --tag "docker.io/{username}/grpc-ping-go" \ - --file=docs/serving/samples/grpc-ping-go/Dockerfile . -docker push "docker.io/{username}/grpc-ping-go" -``` + ```shell + # Build the container on your local machine. + docker build --tag "{username}/grpc-ping-go" . + + # Push the container to docker registry. + docker push "{username}/grpc-ping-go" + ``` + +3. Update the `service.yaml` file in the project to reference the published image from step 1. + + Replace `{username}` in `service.yaml` with your DockerHub username: + + + ```yaml + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + metadata: + name: grpc-ping + namespace: default + spec: + template: + spec: + containers: + - image: docker.io/{username}/grpc-ping-go + ports: + - name: h2c + containerPort: 8080 + ``` + +4. Use `kubectl` to deploy the service. + + ```shell + kubectl apply --filename service.yaml + ``` -Next, replace `{username}` in `sample.yaml` with your DockerHub username, and -apply the yaml. + Response: + + ```shell + service "grpc-ping" created + ``` + +## Exploring + +Once deployed, you can inspect the created resources with `kubectl` commands: ```shell -kubectl apply --filename docs/serving/samples/grpc-ping-go/sample.yaml +# This will show the Knative service that we created: +kubectl get ksvc --output yaml + +# This will show the Route, created by the service: +kubectl get route --output yaml + +# This will show the Configuration, created by the service: +kubectl get configurations --output yaml + +# This will show the Revision, created by the Configuration: +kubectl get revisions --output yaml ``` -## Use the client to stream messages to the gRPC server +## Testing the service + +Testing the gRPC service uses the gRPC client built into the container. 1. Fetch the created ingress hostname and IP. ```shell # Put the ingress IP into an environment variable. - export SERVICE_IP=`kubectl get svc istio-ingressgateway --namespace istio-system --output jsonpath="{.status.loadBalancer.ingress[*].ip}"` + export SERVICE_IP=$(kubectl get svc istio-ingressgateway --namespace istio-system --output jsonpath="{.status.loadBalancer.ingress[*].ip}") ``` -1. Use the client to send message streams to the gRPC server (replacing - `{username}`) +1. Use the containerized client to send message streams to the gRPC server (replacing + `{username}`): ```shell - docker run -ti --entrypoint=/client docker.io/{username}/grpc-ping-go \ + docker run --rm -it {username}/grpc-ping-go \ + /client \ -server_addr="${SERVICE_IP}:80" \ -server_host_override="grpc-ping.default.example.com" \ -insecure ``` + + The arguments after the container tag `{username}/grpc-ping-go` replace the container's default entrypoint which starts the server with a command that starts the gRPC client. + \ No newline at end of file diff --git a/docs/serving/samples/grpc-ping-go/sample.yaml b/docs/serving/samples/grpc-ping-go/service.yaml similarity index 100% rename from docs/serving/samples/grpc-ping-go/sample.yaml rename to docs/serving/samples/grpc-ping-go/service.yaml From 74cb84b4a5b8c447e39227242ab89cb07ba3f9c3 Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Fri, 30 Aug 2019 11:44:36 -0700 Subject: [PATCH 2/4] samples/grpc-ping-go: use 0.0.0.0 instead of localhost inside container --- docs/serving/samples/grpc-ping-go/grpc-ping.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/serving/samples/grpc-ping-go/grpc-ping.go b/docs/serving/samples/grpc-ping-go/grpc-ping.go index bf23fe10f7d..77265b9e01b 100644 --- a/docs/serving/samples/grpc-ping-go/grpc-ping.go +++ b/docs/serving/samples/grpc-ping-go/grpc-ping.go @@ -51,7 +51,7 @@ func (p *pingServer) PingStream(stream ping.PingService_PingStreamServer) error } func main() { - lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port)) + lis, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", port)) if err != nil { log.Fatalf("failed to listen: %v", err) } From 8a096a007721540b8c11a0682cbc23be6a982078 Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Fri, 30 Aug 2019 15:27:41 -0700 Subject: [PATCH 3/4] samples/grpc-ping-go: clarity & context improvements --- docs/serving/samples/grpc-ping-go/README.md | 28 +++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/docs/serving/samples/grpc-ping-go/README.md b/docs/serving/samples/grpc-ping-go/README.md index 98554a986e1..9f626b3342b 100644 --- a/docs/serving/samples/grpc-ping-go/README.md +++ b/docs/serving/samples/grpc-ping-go/README.md @@ -1,11 +1,18 @@ --- -title: "gRPC server - Go" +title: "gRPC Server - Go" #linkTitle: "" weight: 1 type: "docs" --- -A simple gRPC server written in Go that you can use for testing. +A [gRPC](https://grpc.io) server written in Go. + +This sample can be used to try out gRPC, HTTP/2, and custom port configuration +in a knative service. + +The container image is built with two binaries: the server and the client. +This is done for ease of testing and is not a recommended practice +for production containers. ## Prerequisites @@ -38,7 +45,7 @@ A simple gRPC server written in Go that you can use for testing. 3. Update the `service.yaml` file in the project to reference the published image from step 1. - Replace `{username}` in `service.yaml` with your DockerHub username: + Replace `{username}` in `service.yaml` with your Docker Hub user name: ```yaml @@ -89,7 +96,8 @@ kubectl get revisions --output yaml ## Testing the service -Testing the gRPC service uses the gRPC client built into the container. +Testing the gRPC service requires using a gRPC client built from the same +protobuf definition used by the server. 1. Fetch the created ingress hostname and IP. @@ -98,8 +106,13 @@ Testing the gRPC service uses the gRPC client built into the container. export SERVICE_IP=$(kubectl get svc istio-ingressgateway --namespace istio-system --output jsonpath="{.status.loadBalancer.ingress[*].ip}") ``` -1. Use the containerized client to send message streams to the gRPC server (replacing - `{username}`): +1. Use the gRPC client to send message streams to the gRPC server. + + The Dockerfile builds the client binary. To run the client you will use the + same container image deployed for the server with an override to the + entrypoint command to use the client binary instead of the server binary. + + Replace `{username}` with your Docker Hub user name and run the command: ```shell docker run --rm -it {username}/grpc-ping-go \ @@ -109,5 +122,6 @@ Testing the gRPC service uses the gRPC client built into the container. -insecure ``` - The arguments after the container tag `{username}/grpc-ping-go` replace the container's default entrypoint which starts the server with a command that starts the gRPC client. + The arguments after the container tag `{username}/grpc-ping-go` are used + instead of the entrypoint command defined in the Dockerfile `CMD` statement. \ No newline at end of file From 4a8a148addd8e82bdb37c3eee7d6b6c6a82e82c8 Mon Sep 17 00:00:00 2001 From: Adam Ross Date: Tue, 3 Sep 2019 13:18:10 -0700 Subject: [PATCH 4/4] serving/samples: remove unneeded -it flag from grpc-ping testing --- docs/serving/samples/grpc-ping-go/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/serving/samples/grpc-ping-go/README.md b/docs/serving/samples/grpc-ping-go/README.md index 9f626b3342b..c8342b2fedb 100644 --- a/docs/serving/samples/grpc-ping-go/README.md +++ b/docs/serving/samples/grpc-ping-go/README.md @@ -115,7 +115,7 @@ protobuf definition used by the server. Replace `{username}` with your Docker Hub user name and run the command: ```shell - docker run --rm -it {username}/grpc-ping-go \ + docker run --rm {username}/grpc-ping-go \ /client \ -server_addr="${SERVICE_IP}:80" \ -server_host_override="grpc-ping.default.example.com" \ @@ -124,4 +124,4 @@ protobuf definition used by the server. The arguments after the container tag `{username}/grpc-ping-go` are used instead of the entrypoint command defined in the Dockerfile `CMD` statement. - \ No newline at end of file +