A simple web app written in Go that demonstrates how to deploy Redis (using vanilla Kubernetes components) alongside a Knative Service that relies on it. The guestbook application shows a page with a form that allows users to leave a message under a name of their choosing. Names and messages map to keys and values in Redis, so only one message per user is saved at a time.
Although the configuration in this sample is intentionally very simple, Redis can require relatively complex configuration that Knative does not support. Luckily, Knative allows you to mix and match Knative components with vanilla Kubernetes components.
The Redis configuration consists of two parts:
-
Deployment: contains a minimal configuration for a single Redis instance, namedredis-master. -
Service: contains a KubernetesServicethat findsredis-masterby its name and role labels and routes requests to it. TheREDIS_HOSTenvironment variable inguestbook.yamlrefers to the name of theService, also namedredis-master, not the name of theDeployment.
Note: Don't confuse a Kubernetes
Servicewith a KnativeService. A KnativeServicehandles the deployment, scaling, and routing for a workload. A KubernetesServiceroutes requests to an existing deployment.
Deploy this to you Kubernetes cluster using kubectl:
kubectl apply -f redis.yamlAs with the previous lab assignments this too uses the Knative Build and [Serve][knative-serve] components in order to build the Guestbook application from soure and running it in one go.
Create a new file called guestbook.yaml that will represent our Guestbook
applications:
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: guestbook
namespace: default
spec:
runLatest:
configuration:
build:
apiVersion: build.knative.dev/v1alpha1
kind: Build
spec:
serviceAccountName: build-bot
source:
git:
url: https://github.com/evry-bergen/knative-workshop.git
revision: master
template:
name: kaniko
arguments:
- name: DOCKERFILE
value: ./labs/4-guestbook/Dockerfile
- name: IMAGE
value: eu.gcr.io/{PROJECT}/lab-4-guestbook:latest
timeout: 10m
revisionTemplate:
spec:
container:
image: eu.gcr.io/{PROJECT}/lab-4-guestbook:latest
imagePullPolicy: Always
env:
- name: REDIS_HOST
value: redis-masterRemember to replace the
{PROJECT}placeholder with your actual Google Cloud project name.
Simply deploy the Guestbook application by running the following command:
kubectl apply -f guestbook.yamlNote: the following example uses curl to make requests to the application. You
can also use your browser by following the steps in the routing
sample to route requests to / to the
guestbook Service.
To access this service, you need to determine its ingress address:
kubectl get svc istio-ingressgateway -n istio-systemWhen the service is ready, you'll see an IP address in the EXTERNAL-IP field:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.23.247.74 35.203.155.229 80:32380/TCP,443:32390/TCP,32400:32400/TCP 2d
Once the EXTERNAL-IP gets assigned to the cluster, you can run:
# Put the host name into an environment variable.
export SERVICE_HOST=`kubectl get route guestbook -o jsonpath="{.status.domain}"`
# Put the ingress IP into an environment variable.
export SERVICE_IP=`kubectl get svc istio-ingressgateway -n istio-system -o jsonpath="{.status.loadBalancer.ingress[*].ip}"`Now use curl with the service IP as if DNS were properly configured:
curl --header "Host:$SERVICE_HOST" http://${SERVICE_IP}
# [...]
# <form action="/" method="post">
# <div>Name: <input name="name"></div>
# <div>Message: <input name="message"></div>
# <input type="submit">
# </form>
# <ul>
#
# </ul>
# [...]Note that the inputs are named name and message. You can use curl to POST
data to the form as shown below:
curl -X POST -F "name=someone" -F "message=Hello, Knative!" --header "Host:$SERVICE_HOST" http://${SERVICE_IP}
# [...]
# <ul>
# <li><strong>someone</strong>: Hello, Knative!</li>
# </ul>
# [...]curl -X POST -F "name=knative_user" -F "message=I love Knative!" --header "Host:$SERVICE_HOST" http://${SERVICE_IP}
# [...]
# <ul>
# <li><strong>knative_user</strong>: I love Knative!</li>
# <li><strong>someone</strong>: Hello, Knative!</li>
# </ul>
# [...]When you're done, clean up the sample resources:
kubectl delete -f serving/samples/guestbook-redis-go/redis-deployment.yaml
kubectl delete -f serving/samples/guestbook-redis-go/redis-service.yaml
kubectl delete -f serving/samples/guestbook-redis-go/guestbook.yamlFor simplicity, this sample showed a configuration for Redis with a single
server. In practice, that wouldn't scale very well for a real application. See
the Kubernetes example repository
for a more scalable deployment configuration for Redis on Kubernetes. That
example does not include a service that allows other applications to connect to
Redis, but you can use redis-service.yaml since it selects on the same name
and role labels.
Alternatively, you may prefer to use a managed solution from your cloud provider (e.g. Cloud Memorystore). To access services outside of the cluster, you'll have to configure outbound network access.
Whichever way you go, you can use the guestbook container to test your Redis
deployment. Just change the REDIS_HOST environment variable in
guestbook.yaml to the correct host name.
To remove the Guestbook application and Redis service run the following commands:
kubectl delete --filename redis.yaml
kubectl delete --filename guestbook.yamlExcept as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License.