This example application implements a very basic "pet shop" REST service using the Connexion Python library. Compared to hjacobs/connexion-example, this setup focuses more on operational aspects and includes Redis as a persistent storage and Kubernetes deployment manifests.
QUICKSTART: Please follow the steps to deploy to Kubernetes (Minikube).
This example should demonstrate:
- how to map an OpenAPI/Swagger specification to Python code with Connexion
- how to run Connexion with gevent
- how to build a Docker image for Connexion
- how to integrate a simple persistent database (Redis)
- how to set up Kubernetes manifests for deployment and making sure rolling updates do not cause downtime
- how to configure some best practices for production usage
This example is NOT:
- a real world application (unless you need a REST service to store pets)
- a production-ready service
- a best practice setup for a persistent database (Redis has its own issues, but is used here to keep the database part simple)
DISCLAIMER: While trying to show some best practices for production usage, this is still just an example project --- especially the Redis database setup is not highly available (single replica).
This requires Pipenv:
pipenv install --dev
pipenv shell
docker run -d --name connexion-example-redis -p 6379:6379 redis:4-alpine
./app.py
xdg-open http://localhost:8080/ui/
First install and then start Minikube:
minikube start
Build the Docker image:
eval $(minikube docker-env)
docker build -t connexion-example:local-minikube .
Deploy to Kubernetes:
kubectl apply -f deploy/
Wait for pods to come up:
kubectl get pod
Create a pet:
url=$(minikube service connexion-example --url)
curl -X PUT $url/pets/susie -d '{"animal_type": "cat", "name": "Susie", "tags": {"color": "black"}}' -H Content-Type:application/json
Get all pets:
curl $url/pets
Simple load test with Vegeta:
echo "GET $url/pets" | vegeta attack -rate 100 -duration 60s | vegeta report
The output should look something like this (depends on your hardware/VM configuration):
Requests [total, rate] 6000, 100.02
Duration [total, attack, wait] 1m0.034341468s, 59.98999991s, 44.341558ms
Latencies [mean, 50, 95, 99, max] 41.344672ms, 46.279545ms, 52.171431ms, 54.320335ms, 72.515124ms
Bytes In [total, mean] 3156000, 526.00
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:6000
Error Set:
While the setup gracefully handles rolling deployments (try it out by changing a pod label in deploy/deployment.yaml
and doing kubectl apply -f deploy/
),
it cannot handle Redis downtimes without causing HTTP errors. Deleting the Redis pod causes a ~10 seconds unavailability for the REST service:
The above latency cap at 5000ms reflects the configured Redis socket timeout of 5 seconds.