Skip to content

Commit 89c6b54

Browse files
averikitschknative-prow-robot
authored andcommitted
[samples] R sample with R server (#1777)
* draft * R plumber sample * update Readme
1 parent 499af88 commit 89c6b54

File tree

6 files changed

+232
-3
lines changed

6 files changed

+232
-3
lines changed

community/samples/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ something isn't working, lend a helping hand and fix it in a PR.
1212

1313
Knative Serving sample apps.
1414

15-
| Sample Name | Description | Language(s) |
16-
| ----------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17-
| Hello World | A quick introduction to Knative Serving that highlights how to deploy an app. | [Clojure](./serving/helloworld-clojure/README.md), [Dart](./serving/helloworld-dart/README.md), [Elixir](./serving/helloworld-elixir/README.md), [Haskell](./serving/helloworld-haskell/README.md), [Java - Micronaut](./serving/helloworld-java-micronaut/README.md), [Java - Quarkus](./serving/helloworld-java-quarkus/README.md), [Rust](./serving/helloworld-rust/README.md), [Swift](./serving/helloworld-swift/README.md), [Vertx](./serving/helloworld-vertx/README.md) |
15+
| Sample Name | Description | Language(s) |
16+
| ----------- | ----------- | ----------- |
17+
| Hello World | A quick introduction to Knative Serving that highlights how to deploy an app. | [Clojure](./serving/helloworld-clojure/README.md), [Dart](./serving/helloworld-dart/README.md), [Elixir](./serving/helloworld-elixir/README.md), [Haskell](./serving/helloworld-haskell/README.md), [Java - Micronaut](./serving/helloworld-java-micronaut/README.md), [Java - Quarkus](./serving/helloworld-java-quarkus/README.md), [R - Go Server](./serving/helloworld-r/README.md), [R](./serving/hellowolrd-rserver/README.md), [Rust](./serving/helloworld-rust/README.md), [Swift](./serving/helloworld-swift/README.md), [Vertx](./serving/helloworld-vertx/README.md) |
1818

1919

2020
#### Eventing and Eventing Resources samples
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# The official R base image
2+
# https://hub.docker.com/_/r-base
3+
FROM r-base:3.6.0
4+
5+
# Copy local code to the container image.
6+
WORKDIR /usr/src/app
7+
COPY . .
8+
9+
# Install R packages
10+
RUN Rscript -e "install.packages('plumber', repos='http://cran.us.r-project.org/')"
11+
12+
# Run the web service on container startup.
13+
CMD ["Rscript", "server.R"]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#' HelloWorld function
2+
#' @get /
3+
#' @html
4+
function() {
5+
TARGET <- Sys.getenv("TARGET", "World")
6+
7+
message = paste("Hello ", TARGET, "!", sep = "")
8+
print(message)
9+
}
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
---
2+
title: "Hello World - R server"
3+
linkTitle: "R server"
4+
weight: 1
5+
type: "docs"
6+
---
7+
8+
A simple web app created with R package, [plumber](https://www.rplumber.io).
9+
plumber creates a REST API by adding annotations to your R code. The R script
10+
reads an environment variable `TARGET` and prints `Hello ${TARGET}!`. If the
11+
`TARGET` environment variable is not specified, the script uses `World`.
12+
13+
Follow the steps below to create the sample code and then deploy the app to your
14+
cluster. You can also download a working copy of the sample, by running the
15+
following commands:
16+
17+
```shell
18+
git clone -b "{{< branch >}}" https://github.com/knative/docs knative-docs
19+
cd knative-docs/docs/serving/samples/hello-world/helloworld-r
20+
```
21+
22+
## Before you begin
23+
24+
- A Kubernetes cluster with Knative installed. Follow the
25+
[installation instructions](../../../../install/README.md) if you need to
26+
create one.
27+
- [Docker](https://www.docker.com) installed and running on your local machine,
28+
and a Docker Hub account configured (we'll use it for a container registry).
29+
30+
## Recreating the sample code
31+
32+
1. Create a new file named `HelloWorld.R` and paste the following script:
33+
34+
```R
35+
#' HelloWorld function
36+
#' @get /
37+
#' @html
38+
function() {
39+
TARGET <- Sys.getenv("TARGET", "World")
40+
41+
message = paste("Hello ", TARGET, "!", sep = "")
42+
print(message)
43+
}
44+
```
45+
46+
This file defines the endpoint `/`, using plumber annotations.
47+
48+
1. Create a new file named `server.R` and paste the following code:
49+
50+
```R
51+
library(plumber) # https://www.rplumber.io/
52+
53+
# Translate the HelloWorld file into a Plumber API
54+
r <- plumb("HelloWorld.R")
55+
# Get the PORT env var
56+
PORT <- strtoi(Sys.getenv("PORT", 8080))
57+
# Run the API
58+
r$run(port=PORT, host="0.0.0.0")
59+
```
60+
61+
1. Create a new file named `Dockerfile` and paste the following code:
62+
63+
```docker
64+
# The official R base image
65+
# https://hub.docker.com/_/r-base
66+
FROM r-base:3.6.0
67+
68+
# Copy local code to the container image.
69+
WORKDIR /usr/src/app
70+
COPY . .
71+
72+
# Install R packages
73+
RUN Rscript -e "install.packages('plumber', repos='http://cran.us.r-project.org/')"
74+
75+
# Run the web service on container startup.
76+
CMD ["Rscript", "server.R"]
77+
```
78+
79+
80+
1. Create a new file, `service.yaml` and copy the following service definition
81+
into the file. Make sure to replace `{username}` with your Docker Hub
82+
username.
83+
84+
```yaml
85+
apiVersion: serving.knative.dev/v1alpha1
86+
kind: Service
87+
metadata:
88+
name: helloworld-rserver
89+
namespace: default
90+
spec:
91+
template:
92+
spec:
93+
containers:
94+
- image: docker.io/{username}/helloworld-rserver
95+
env:
96+
- name: TARGET
97+
value: "R Server Sample v1"
98+
```
99+
100+
## Building and deploying the sample
101+
102+
Once you have recreated the sample code files (or used the files in the sample
103+
folder) you're ready to build and deploy the sample app.
104+
105+
1. Use Docker to build the sample code into a container. To build and push with
106+
Docker Hub, run these commands replacing `{username}` with your Docker Hub
107+
username:
108+
109+
```shell
110+
# Build the container on your local machine
111+
docker build -t {username}/helloworld-rserver .
112+
113+
# Push the container to docker registry
114+
docker push {username}/helloworld-rserver
115+
```
116+
117+
1. After the build has completed and the container is pushed to docker hub, you
118+
can deploy the app into your cluster. Ensure that the container image value
119+
in `service.yaml` matches the container you built in the previous step. Apply
120+
the configuration using `kubectl`:
121+
122+
```shell
123+
kubectl apply --filename service.yaml
124+
```
125+
126+
1. Now that your service is created, Knative performs the following steps:
127+
128+
- Create a new immutable revision for this version of the app.
129+
- Network programming to create a route, ingress, service, and load balance
130+
for your app.
131+
- Automatically scale your pods up and down (including to zero active pods).
132+
133+
1. Run the following command to find the external IP address for your service.
134+
The ingress IP for your cluster is returned. If you just created your
135+
cluster, you might need to wait and rerun the command until your service gets
136+
asssigned an external IP address.
137+
138+
```shell
139+
kubectl get svc knative-ingressgateway --namespace istio-system
140+
```
141+
142+
Example:
143+
144+
```shell
145+
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
146+
knative-ingressgateway LoadBalancer 10.23.247.74 35.203.155.229 80:32380/TCP,443:32390/TCP,32400:32400/TCP 2d
147+
148+
```
149+
150+
1. Run the following command to find the domain URL for your service:
151+
152+
```shell
153+
kubectl get ksvc helloworld-r --output=custom-columns=NAME:.metadata.name,URL:.status.url
154+
```
155+
156+
Example:
157+
158+
```shell
159+
NAME URL
160+
helloworld-r http://helloworld-r.default.example.com
161+
```
162+
163+
1. Test your app by sending it a request. Use the following `curl` command with
164+
the domain URL `helloworld-rserver.default.example.com` and `EXTERNAL-IP`
165+
address that you retrieved in the previous steps:
166+
167+
```shell
168+
curl -H "Host: helloworld-rserver.default.example.com" http://{EXTERNAL_IP_ADDRESS}
169+
```
170+
171+
Example:
172+
173+
```shell
174+
curl -H "Host: helloworld-rserver.default.example.com" http://35.203.155.229
175+
[1] "Hello R Sample v1!"
176+
```
177+
178+
> Note: Add `-v` option to get more detail if the `curl` command failed.
179+
180+
## Removing the sample app deployment
181+
182+
To remove the sample app from your cluster, delete the service record:
183+
184+
```shell
185+
kubectl delete --filename service.yaml
186+
```
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
library(plumber) # https://www.rplumber.io/
2+
3+
# Translate the HelloWorld file into a Plumber API
4+
r <- plumb("HelloWorld.R")
5+
# Get the PORT env var
6+
PORT <- strtoi(Sys.getenv("PORT", 8080))
7+
# Run the API
8+
r$run(port=PORT, host="0.0.0.0")
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: serving.knative.dev/v1alpha1
2+
kind: Service
3+
metadata:
4+
name: helloworld-rserver
5+
namespace: default
6+
spec:
7+
template:
8+
spec:
9+
containers:
10+
- image: docker.io/{username}/helloworld-rserver
11+
env:
12+
- name: TARGET
13+
value: "R Server Sample v1"

0 commit comments

Comments
 (0)