Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deployment testing #268

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
710 changes: 710 additions & 0 deletions figures/a_b_testing.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added figures/a_b_testing_example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2,092 changes: 2,092 additions & 0 deletions figures/canary_deployment.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
570 changes: 570 additions & 0 deletions figures/shadow_testing.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ plugins:
- search
- glightbox
- same-dir
- inline-svg
- git-revision-date-localized:
enable_creation_date: true
- exclude:
Expand Down Expand Up @@ -145,6 +146,7 @@ nav:
- M33 - High Performance Clusters: s10_extra/high_performance_clusters.md
- M34 - Frontend: s10_extra/frontend.md
- M35 - ML deployment: s10_extra/ml_deployment.md
- M36 - Deployment Testing: s7_deployment/deployment_testing.md
# - M35 - Designing Pipelines: s10_extra/design.md
# - M37 - Workflow orchestration: s10_extra/orchestration.md
# - M38 - Kubernetes: s10_extra/kubernetes.md
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pymdown-extensions>=1.1.1
mkdocs-same-dir>=0.1.2
mkdocs-git-revision-date-localized-plugin>=1.2.6
mkdocs-exclude>=1.0.2
mkdocs-plugin-inline-svg>=0.1.0

# Developer stuff
ruff>=0.4.7
Expand Down
189 changes: 189 additions & 0 deletions s7_deployment/deployment_testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
![Logo](../figures/icons/gcp.png){ align=right width="130"}

# Deployment Testing

In the module on [testing of APIs](testing_apis.md) we learned how to write integration tests for our APIs and how to
run loadtests to see how our API behaves under different loads. In this module we are going to learn about a few
different deployment testing strategies that can be used to ensure that our application is working as expected *before*
we deploy it to production. Deployment testing is designed to minimize risk, enhance performance, and ensure a smooth
transition from development to production. Being able to choose and execute the correct deployment testing strategy is
even more important within machine learning projects as we tend to update our models more frequently than traditional
software projects, thus requiring more frequent deployments.

In general we recommend you start out with reading this
[page](https://cloud.google.com/architecture/application-deployment-and-testing-strategies) from GCP on both application
deployment and testing strategies. It is a good read on the different metrics we can use to evaluate our deployment
(down time, rollback duration, etc.) and the different deployment strategies we can use. In the following we are going
to be looking at the three testing methods

* A/B testing
* Canary deployment
* Shadow deployment

## A/B testing

In software development, [A/B testing](https://en.wikipedia.org/wiki/A/B_testing) is a method of comparing two versions
of a web page or application against each other to determine which one performs better. A/B testing is a form of
statistical hypothesis testing with two variants

<figure markdown>
![Image](../figures/a_b_testing_example.png)
<figcaption>
In this case we are randomly A/B testing if the color and style of the `Learn more` button affects the click rate. In
this hypothetical example, the green button has a 20% higher click rate than the blue button and is therefore the
preferred choice for the final design.
<a href="https://en.wikipedia.org/wiki/A/B_testing"> Image credit </a>
</figcaption>
</figure>


Check failure on line 39 in s7_deployment/deployment_testing.md

View workflow job for this annotation

GitHub Actions / Check Markdown formatting

Multiple consecutive blank lines [Expected: 1; Actual: 2]
<figure markdown>
![Image](../figures/a_b_testing.svg)
<figcaption>
<a href="https://cloud.google.com/architecture/application-deployment-and-testing-strategies"> Image credit </a>
</figcaption>
</figure>

[text](https://www.surveymonkey.com/mp/ab-testing-significance-calculator/)


Check failure on line 49 in s7_deployment/deployment_testing.md

View workflow job for this annotation

GitHub Actions / Check Markdown formatting

Multiple consecutive blank lines [Expected: 1; Actual: 2]
Assumed Distribution | Example case | Standard test
-------------------- | ------------ | -------------
Gaussian | Average revenue per user | t-test
Binomial | Click-through rate | Fisher's exact test
Poisson | Number of purchases | Chi-squared test
Multinomial | User preferences | Chi-squared test
Unknown | Time to purchase | Mann-Whitney U test


Check failure on line 58 in s7_deployment/deployment_testing.md

View workflow job for this annotation

GitHub Actions / Check Markdown formatting

Multiple consecutive blank lines [Expected: 1; Actual: 2]
### ❔ Exercises

In the exercises we are going to perform two different kinds of A/B testing. The first one is going to be a simple
A/B test where we are going to test two different versions of the same service. The second

1. There are a multiple ways to implement A/B testing.

```python
from fastapi import FastAPI, Request, HTTPException
import geoip2.database

app = FastAPI()

# Load the GeoLite2 database
reader = geoip2.database.Reader('/path/to/GeoLite2-City.mmdb')

def get_client_ip(request: Request) -> str:
if "X-Forwarded-For" in request.headers:
return request.headers["X-Forwarded-For"].split(",")[0]
if "X-Real-IP" in request.headers:
return request.headers["X-Real-IP"]
return request.client.host

def get_geolocation(ip: str) -> dict:
try:
response = reader.city(ip)
return {
"ip": ip,
"city": response.city.name,
"region": response.subdivisions.most_specific.name,
"country": response.country.name,
"location": {
"latitude": response.location.latitude,
"longitude": response.location.longitude
}
}
except geoip2.errors.AddressNotFoundError:
raise HTTPException(status_code=404, detail="IP address not found in the database")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))

@app.get("/geolocation")
async def geolocation(request: Request):
client_ip = get_client_ip(request)
geolocation_data = get_geolocation(client_ip)
return geolocation_data
```

## Canary deployment

<figure markdown>
![Image](../figures/canary_deployment.svg)
<figcaption>
<a href="https://cloud.google.com/architecture/application-deployment-and-testing-strategies"> Image credit </a>
</figcaption>
</figure>


Check failure on line 116 in s7_deployment/deployment_testing.md

View workflow job for this annotation

GitHub Actions / Check Markdown formatting

Multiple consecutive blank lines [Expected: 1; Actual: 2]
### ❔ Exercises

Follow [these](https://cloud.google.com/architecture/implementing-cloud-run-canary-deployments-git-branches-cloud-build)
instructions to implement a canary deployment using Git branches and Cloud Build.

1. Use the following command

```bash
gcloud run services update-traffic
```

## Shadow deployment

<figure markdown>
![Image](../figures/shadow_testing.svg)
<figcaption>
<a href="https://cloud.google.com/architecture/application-deployment-and-testing-strategies"> Image credit </a>
</figcaption>
</figure>


Check failure on line 137 in s7_deployment/deployment_testing.md

View workflow job for this annotation

GitHub Actions / Check Markdown formatting

Multiple consecutive blank lines [Expected: 1; Actual: 2]
### ❔ Exercises

1. Google Run does not naturally support shadow deployments, because its loadbalancer requires that the traffic adds up
to 100%, and for shadow deployments, it would be 200%. To proper implement this you would need to use a kubernetes
cluster and use a service mesh like Istio. So instead we are going to implement a very simple load balancer ourself.

1. Create a new script called `loadbalancer.py` and add the following code

```python
import random
from fastapi import FastAPI, HTTPException
import requests

app = FastAPI()

services = {
"service1": "http://localhost:8000",
"service2": "http://localhost:8001"
}

@app.get("/shadow")
async def shadow():
service = random.choice(list(services.keys()))
response = requests.get(services[service] + "/shadow")
return {
"service": service,
"response": response.json()
}
```

2. Because the loadbalancer is just a simple Python script lets just deploy it to Cloud Functions instead of Cloud
Run. Create a new Cloud Function and deploy the script.

## 🧠 Knowledge check

1. Try to fill out the following table:

Testing patter | Zero downtime | Real production traffic testing | Releasing to users based on conditions | Rollback duration | Releasing to users based on conditions |

Check failure on line 175 in s7_deployment/deployment_testing.md

View workflow job for this annotation

GitHub Actions / Check Markdown formatting

Table pipe style [Expected: no_leading_or_trailing; Actual: trailing_only; Unexpected trailing pipe]
--------------- | -------------- | -------------------------------- | -------------------------------------- | ----------------- | -------------------------------------- |

Check failure on line 176 in s7_deployment/deployment_testing.md

View workflow job for this annotation

GitHub Actions / Check Markdown formatting

Table pipe style [Expected: no_leading_or_trailing; Actual: trailing_only; Unexpected trailing pipe]
A/B testing | | | | | |

Check failure on line 177 in s7_deployment/deployment_testing.md

View workflow job for this annotation

GitHub Actions / Check Markdown formatting

Table pipe style [Expected: no_leading_or_trailing; Actual: trailing_only; Unexpected trailing pipe]
Canary deployment | | | | | |

Check failure on line 178 in s7_deployment/deployment_testing.md

View workflow job for this annotation

GitHub Actions / Check Markdown formatting

Table pipe style [Expected: no_leading_or_trailing; Actual: trailing_only; Unexpected trailing pipe]
Shadow deployment | | | | | |

Check failure on line 179 in s7_deployment/deployment_testing.md

View workflow job for this annotation

GitHub Actions / Check Markdown formatting

Table pipe style [Expected: no_leading_or_trailing; Actual: trailing_only; Unexpected trailing pipe]

??? success "Solution"

Testing patter | Zero downtime | Real production traffic testing | Releasing to users based on conditions | Rollback duration | Releasing to users based on conditions |
--------------- | -------------- | -------------------------------- | -------------------------------------- | ----------------- | -------------------------------------- |
A/B testing | No | No | Yes | Short | No |
Canary deployment | Yes | Yes | Yes | Short | Yes |
Shadow deployment | Yes | No | Yes | Short | Yes |

This ends the deployment testing module.
Loading