Skip to content

Commit e9304e5

Browse files
authored
Merge pull request #213 from vdice/docs/key-value-provider-tutorial
docs(topics): add key-value provider tutorial
2 parents 7bb5e5a + 17b3498 commit e9304e5

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
---
2+
title: Using a key value store
3+
description: Connect your Spin App to a key value store
4+
date: 2024-07-29
5+
categories: [Spin Operator]
6+
tags: [Tutorials]
7+
weight: 14
8+
---
9+
10+
Spin applications can utilize a [standardized API for persisting data in a key value store](https://developer.fermyon.com/spin/v2/kv-store-api-guide). The default key value store in Spin is an SQLite database, which is great for quickly utilizing non-relational local storage without any infrastructure set-up. However, this solution may not be preferable for an app running in the context of SpinKube, where apps are often scaled beyond just one replica.
11+
12+
Thankfully, Spin supports configuring an application with an [external key value provider](https://developer.fermyon.com/spin/v2/dynamic-configuration#key-value-store-runtime-configuration). External providers include [Redis](https://redis.io/) or [Valkey](https://valkey.io/) and [Azure Cosmos DB](https://azure.microsoft.com/en-us/products/cosmos-db).
13+
14+
## Prerequisites
15+
16+
To follow along with this tutorial, you'll need:
17+
18+
- A Kubernetes cluster running SpinKube. See the [Installation]({{< relref "install" >}}) guides for more information.
19+
- The [kubectl CLI](https://kubernetes.io/docs/tasks/tools/#kubectl)
20+
- The [spin CLI](https://developer.fermyon.com/spin/v2/install )
21+
22+
## Build and publish the Spin application
23+
24+
For this tutorial, we'll use a [Spin key/value application](https://github.com/fermyon/spin-go-sdk/tree/main/examples/key-value) written with the Go SDK. The application serves a CRUD (Create, Read, Update, Delete) API for managing key/value pairs.
25+
26+
First, clone the repository locally and navigate to the `examples/key-value` directory:
27+
28+
```bash
29+
git clone [email protected]:fermyon/spin-go-sdk.git
30+
cd examples/key-value
31+
```
32+
33+
Now, build and push the application to a registry you have access to. Here we'll use [ttl.sh](https://ttl.sh):
34+
35+
```bash
36+
export IMAGE_NAME=ttl.sh/$(uuidgen):1h
37+
spin build
38+
spin registry push ${IMAGE_NAME}
39+
```
40+
41+
## Configure an external key value provider
42+
43+
Since we have access to a Kubernetes cluster already running SpinKube, we'll choose [Valkey](https://valkey.io/) for our key value provider and install this provider via Bitnami's [Valkey Helm chart](https://github.com/bitnami/charts/tree/main/bitnami/valkey). Valkey is swappable for Redis in Spin, though note we do need to supply a URL using the `redis://` protocol rather than `valkey://`.
44+
45+
```bash
46+
helm install valkey --namespace valkey --create-namespace oci://registry-1.docker.io/bitnamicharts/valkey
47+
```
48+
49+
As mentioned in the notes shown after successful installation, be sure to capture the valkey password for use later:
50+
51+
```bash
52+
export VALKEY_PASSWORD=$(kubectl get secret --namespace valkey valkey -o jsonpath="{.data.valkey-password}" | base64 -d)
53+
```
54+
55+
## Create a Kubernetes Secret for the Valkey URL
56+
57+
The runtime configuration will require the Valkey URL so that it can connect to this provider. As this URL contains the sensitive password string, we will create it as a Secret resource in Kubernetes:
58+
59+
```bash
60+
kubectl create secret generic kv-secret --from-literal=valkey-url="redis://:${VALKEY_PASSWORD}@valkey-master.valkey.svc.cluster.local:6379"
61+
```
62+
63+
## Prepare the SpinApp manifest
64+
65+
You're now ready to assemble the SpinApp custom resource manifest for this application.
66+
67+
- All of the key value config is set under `spec.runtimeConfig.keyValueStores`. See the [keyValueStores reference guide]({{< ref "docs/reference/spin-app#spinappspecruntimeconfigkeyvaluestoresindex" >}}) for more details.
68+
- Here we configure the `default` store to use the `redis` provider type and under `options` supply the Valkey URL (via its Kubernetes secret)
69+
70+
Plug the `$IMAGE_NAME` and `$DB_URL` values into the manifest below and save as `spinapp.yaml`:
71+
72+
```yaml
73+
apiVersion: core.spinoperator.dev/v1alpha1
74+
kind: SpinApp
75+
metadata:
76+
name: kv-app
77+
spec:
78+
image: "$IMAGE_NAME"
79+
replicas: 1
80+
executor: containerd-shim-spin
81+
runtimeConfig:
82+
keyValueStores:
83+
- name: "default"
84+
type: "redis"
85+
options:
86+
- name: "url"
87+
valueFrom:
88+
secretKeyRef:
89+
name: "kv-secret"
90+
key: "valkey-url"
91+
```
92+
93+
## Create the SpinApp
94+
95+
Apply the resource manifest to your Kubernetes cluster:
96+
97+
```bash
98+
kubectl apply -f spinapp.yaml
99+
```
100+
101+
The Spin Operator will handle the creation of the underlying Kubernetes resources on your behalf.
102+
103+
## Test the application
104+
105+
Now you are ready to test the application and verify connectivity and key value storage to the configured provider.
106+
107+
Configure port forwarding from your local machine to the corresponding Kubernetes `Service`:
108+
109+
```bash
110+
kubectl port-forward services/kv-app 8080:80
111+
112+
Forwarding from 127.0.0.1:8080 -> 80
113+
Forwarding from [::1]:8080 -> 80
114+
```
115+
116+
When port forwarding is established, you can send HTTP requests to the application from within an additional terminal session. Here are a few examples to get you started.
117+
118+
Create a `test` key with value `ok!`:
119+
120+
```bash
121+
$ curl -i -X POST -d "ok!" localhost:8080/test
122+
HTTP/1.1 200 OK
123+
content-length: 0
124+
date: Mon, 29 Jul 2024 19:58:14 GMT
125+
```
126+
127+
Get the value for the `test` key:
128+
129+
```bash
130+
$ curl -i -X GET localhost:8080/test
131+
HTTP/1.1 200 OK
132+
content-length: 3
133+
date: Mon, 29 Jul 2024 19:58:39 GMT
134+
135+
ok!
136+
```
137+
138+
Delete the value for the `test` key:
139+
140+
```bash
141+
$ curl -i -X DELETE localhost:8080/test
142+
HTTP/1.1 200 OK
143+
content-length: 0
144+
date: Mon, 29 Jul 2024 19:59:18 GMT
145+
```
146+
147+
Attempt to get the value for the `test` key:
148+
149+
```bash
150+
$ curl -i -X GET localhost:8080/test
151+
HTTP/1.1 500 Internal Server Error
152+
content-type: text/plain; charset=utf-8
153+
x-content-type-options: nosniff
154+
content-length: 12
155+
date: Mon, 29 Jul 2024 19:59:44 GMT
156+
157+
no such key
158+
```

0 commit comments

Comments
 (0)