Simple demo of how to deploy a basic API on kubernetes. The demo has 3 stages from simpler to more complex deployment strategies.
Basic setup of minikube and docker
- Start vanilla minikube with
bash scripts/minkube_setup.sh
- Point docker-cli to minikube's docker-server
eval $(minikube docker-env)
- Build api with
docker build -t api:v0.1.0 .
insideapi/
folder
Deploy app using vanilla kubernetes
- Create services with
kubectl apply -f deploy/api/networking.yml
- Create deployment with
kubectl apply -f deploy/api/deployment.yml
- Test that the api works with
minikube service api-svc-stable
Introduce Istio for smarter rounting and Ingress.
- Setup istio
- install istio in the cluster with
istioctl install
- Create istio's components with
kubectl apply -f deploy/api/istio.yml
- Open another terminal and run
minikube tunnel
- Get ingress IP with
INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
- Run the consumer with
python scripts/consumer.py -e http://$INGRESS_HOST
Introduce Argo rollouts for Canary deployments
- Cleanup with
kubectl delete deployment api
- Install argo rollouts controller and it's kubectl addon
- Install prometheus for istio
- Create rollout
kubectl apply -f deploy/api/rollout.yml
first time is going to ignore canary and deploy inmediatelly - Modify
api/app.py
- Build new version with
docker build -t api:v0.1.1
insideapi/
folder - Deploy new version with
kubectl argo rollouts set image api-rollout api=api:<NEW_VERSION>
- Watch progress with
kubectl argo rollouts get rollout api-rollout --watch
You can run 2 consumers while rolling the deployment, and set the user to juancarlo
on one of them. There is a special rule on the virtual service that always routes this user to the stable version.
For testing a failed canary add a sleep of 1 second to the API endpoint or an respond with a non 2XX code, build and deploy as described above.
Troubleshoot:
- Wierd 503 certificate errors:
kubectl delete -n istio-system pod istio-ingressgateway-<Tab>