Skip to content

Commit 91ed4b0

Browse files
committed
update
1 parent 1034e67 commit 91ed4b0

File tree

14 files changed

+189
-103
lines changed

14 files changed

+189
-103
lines changed

README.md

+59-21
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Kubernetes deployment strategies (Azure Edition)
22

33
> In Kubernetes there are a few different ways to release an application, you have
4-
to carefully choose the right strategy to make your infrastructure resilient.
4+
to carefully choose the right strategy to make Microsoft Azure infrastructure resilient.
55

66
- [ ] [recreate](recreate/): terminate the old version and release the new one
77
- [x] Application Gateway Ingress Controller
@@ -25,6 +25,9 @@ to carefully choose the right strategy to make your infrastructure resilient.
2525
response.
2626
- [x] Azure Load Balancer + Istio service mesh
2727

28+
29+
## Deployment strategy Decision Diagram
30+
2831
![deployment strategy decision diagram](decision-diagram.png)
2932

3033
Before experimenting, checkout the following resources:
@@ -36,17 +39,28 @@ Before experimenting, checkout the following resources:
3639
- [Canary deployment using Istio and Helm](https://github.com/etiennetremel/istio-cross-namespace-canary-release-demo)
3740
- [Automated rollback of Helm releases based on logs or metrics](https://container-solutions.com/automated-rollback-helm-releases-based-logs-metrics/)
3841

42+
## Azure Kubernetes Service (AKS) Deployment Strategy Support Matrix
43+
44+
| Strategy | Use AGIC | Use Istio Service Mesh? | Note |
45+
|:-----------:|:-----------------:|:-----------------------:|:----------------------------------------------------------------:|
46+
| Recreate | Yes | Yes | Regardless of whether the Ingress Controller is selected or not. |
47+
| Ramped | Yes | Yes | Regardless of whether the Ingress Controller is selected or not. |
48+
| Blue/Green | Yes | Yes | Regardless of whether the Ingress Controller is selected or not. |
49+
| Canary | Yes, but manually | Yes | Ingress controller is required to work in conjunction. |
50+
| A/B Testing | No | Yes | Ingress controller is required to work in conjunction. |
51+
| Shadow | No | Yes | Ingress controller is required to work in conjunction. |
52+
3953
## Getting started
4054

55+
### 1. Deploy Azure Kubernetes Service and other resources
56+
4157
These examples were created and tested on
4258

4359
- Azure Kubernetes Service v1.26.3
44-
- Azure Service Mesh (Istio Service Mesh) v1.17
45-
- Azure Application Gateway Ingress Controller (AGIC) Standard v2
46-
- Azure Monitor managed service for Prometheus
47-
- Azure Monitor managed service for Grafana v9.4.10 (5e7d575327)
48-
49-
## Deploy Azure Kubernetes Service and other resources
60+
- [Azure Service Mesh (a.k.a Istio Service Mesh)][2] v1.17
61+
- [Azure Application Gateway Ingress Controller (AGIC)][3] Standard v2
62+
- [Azure Monitor managed service for Prometheus][1]
63+
- [Azure Managed Grafana][4] v9.4.10 (5e7d575327)
5064

5165
```bash
5266
$ cd ./deploy
@@ -55,37 +69,44 @@ $ kubectl apply -f ama-metrics-prometheus-config.yml
5569
$ kubectl apply -f ama-metrics-settings-configmap.yml
5670
```
5771

58-
## Import Grafana dashboard in Azure Managed Grafana
72+
### 2. Import existing Grafana dashboard in Azure Managed Grafana
5973

6074
![](./images/azure-managed-grafana.png)
6175

62-
Create a dashboard with a Time series or import the [JSON export](grafana-dashboard.json). Use the following query:
76+
Create a dashboard with a Time series or import the [JSON export](grafana-dashboard.json).
6377

64-
```
78+
Use the following query:
79+
80+
```yaml
6581
sum(rate(http_requests_total{app="my-app"}[2m])) by (version)
6682
```
6783

6884
![](./images/prometheus-query.png)
6985

70-
Since we installed Prometheus with default settings, it is using the default scrape
71-
interval of `1m` so the range cannot be lower than that.
86+
Since we installed [Azure Managed Prometheus][1] with cutomized settings, it is using the short scrape
87+
interval of `10s` so the range cannot be lower than that.
7288

7389
To have a better overview of the version, add `{{version}}` in the legend field.
7490

75-
## Curl script
91+
## Test script
92+
93+
### Usage
7694

77-
### Before you begin
95+
This is a Python script that makes HTTP requests to a web link specified by the provided `AGIC-PUBLIC-IP` address. The script uses the requests library to send GET requests to the specified URL. It has error handling mechanisms to handle different types of exceptions that might occur during the request.
7896

7997
```bash
98+
# Install colorama for colorized output if not already installed
8099
pip3 install colorama
81-
```
82-
83-
### Usage
84100

85-
This is a Python script that makes HTTP requests to a web link specified by the provided AIGC-PUBLIC-IP address. The script uses the requests library to send GET requests to the specified URL. It has error handling mechanisms to handle different types of exceptions that might occur during the request.
101+
# Run the script
102+
# Example:
103+
# ./curl.py x.x.x.x
104+
./curl.py $AGIC-PUBLIC-IP
86105

87-
```bash
88-
./curl.py AIGC-PUBLIC-IP
106+
# Run the script with a custom header
107+
# Example:
108+
# ./curl.py x.x.x.x test.aks.aliez.tw
109+
./curl.py $AGIC-PUBLIC-IP $HEADER_HOST
89110
```
90111

91112
The script continues to run indefinitely, making periodic requests to the web link and monitoring for errors.
@@ -127,4 +148,21 @@ Based on [Troubleshoot collection of Prometheus metrics in Azure Monitor](https:
127148
kubectl port-forward ama-metrics-* -n kube-system 9090
128149
```
129150

130-
![Port Forward prometheus](./images/port-forward-prometheus.png)
151+
![Port Forward prometheus](./images/port-forward-prometheus.png)
152+
153+
154+
### Minimizing Downtime During Deployments with Azure Application Gateway Ingress Controller
155+
156+
Strong recommendation to read [Minimizing Downtime During Deployments](https://azure.github.io/application-gateway-kubernetes-ingress/how-tos/minimize-downtime-during-deployments/)
157+
158+
1. Regarding the `spec.terminationGracePeriodSeconds` parameter, please refer to [ramped/app-v1.yaml#30][5]
159+
2. Regarding the `spec.containers[0].lifecycle.preStop` parameter, please refer to [ramped/app-v1.yaml#L53-L56][6]
160+
3. Add connection draining annotation to the Ingress read by AGIC to allow for in-flight connections to complete, please refer to [ramped/app-v1.yaml#L65-L66][7]
161+
162+
[1]: https://learn.microsoft.com/en-Us/azure/azure-monitor/essentials/prometheus-metrics-overview
163+
[2]: https://learn.microsoft.com/en-us/azure/aks/istio-about
164+
[3]: https://learn.microsoft.com/en-us/azure/application-gateway/ingress-controller-overview
165+
[4]: https://learn.microsoft.com/en-us/azure/managed-grafana/
166+
[5]: https://github.com/pichuang/k8s-deployment-strategies-azure-edition/blob/master/ramped/app-v1.yaml#L30
167+
[6]: https://github.com/pichuang/k8s-deployment-strategies-azure-edition/blob/master/ramped/app-v1.yaml#L53-L56
168+
[7]: https://github.com/pichuang/k8s-deployment-strategies-azure-edition/blob/master/ramped/app-v1.yaml#L65-L66

ab-testing/README.md

+9-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# A/B testing using Istio
1+
# A/B testing using Istio service mesh
22

33
> Version B is released to a subset of users under specific condition.
44
@@ -16,20 +16,19 @@ roll-out the version that converts the most.
1616
Here is a list of conditions that can be used to distribute traffic amongst the
1717
versions:
1818

19-
- Weight
20-
- Cookie value
19+
- [Weight](https://istio.io/latest/docs/reference/config/networking/virtual-service/#RouteDestination)
20+
- [Headers](https://istio.io/latest/docs/reference/config/networking/virtual-service/#Headers)
2121
- Query parameters
2222
- Geolocalisation
2323
- Technology support: browser version, screen size, operating system, etc.
2424
- Language
2525

2626
## Steps to follow
2727

28-
1. version 1 is serving HTTP traffic using Istio
29-
1. deploy version 2
30-
1. wait until all instances are ready
31-
1. update Istio VirtualService with 90% traffic targetting version 1 and 10%
32-
traffic targetting version 2
28+
1. version 1 is serving HTTP traffic using Istio service mesh
29+
2. deploy version 2
30+
3. wait until all instances are ready
31+
4. update Istio VirtualService with 80% traffic targetting version 1 and 20% traffic targetting version 2
3332

3433
## In practice
3534

@@ -54,15 +53,11 @@ To automatically install sidecar to any new pods, annotate your namespaces:
5453

5554
```yaml
5655
# The default istio-injection=enabled labeling doesn't work. Explicit versioning (istio.io/rev=asm-1-17) is required.
57-
kubectl label namespace/ns-canary-istio istio.io/rev=asm-1-17
56+
kubectl label namespace/ns-ab-testing istio.io/rev=asm-1-17
5857
```
5958

6059
### Deploy both applications
6160

62-
Back to the a/b testing directory from this repo, deploy both applications using
63-
the istioctl command to inject the Istio sidecar container which is used to
64-
proxy requests:
65-
6661
```bash
6762
$ kubectl apply -f app-v1.yaml -f app-v2.yaml
6863
namespace/ns-ab-testing created
@@ -73,8 +68,7 @@ deployment.apps/deployment-my-app-v2 created
7368
service/my-app-v2 created
7469
```
7570

76-
Expose both services via the Istio Gateway and create a VirtualService to match
77-
requests to the my-app-v1 service:
71+
Expose both services via the Istio Gateway and create a VirtualService to match requests to the my-app-v1 service:
7872

7973
```bash
8074
$ kubectl apply -f ./gateway.yaml -f ./virtualservice-wildcard.yaml

blue-green/multiple-services/README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ Ingress controller, this example would also work with the
1212
## Steps to follow
1313

1414
1. service a and b are serving traffic
15-
1. deploy new version of both services
16-
1. wait for all services to be ready
17-
1. switch incoming traffic from version 1 to version 2
18-
1. shutdown version 1
15+
2. deploy new version of both services
16+
3. wait for all services to be ready
17+
4. switch incoming traffic from version 1 to version 2
18+
5. shutdown version 1
1919

2020
## In practice
2121

22-
```
22+
```bash
2323
# Deploy version 1 of application a and b and the ingress
2424
$ kubectl apply -f app-a-v1.yaml -f app-b-v1.yaml -f ingress-v1.yaml
2525
namespace/ns-bluegreen created

blue-green/single-service/README.md

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
Blue/green deployment to release a single service
2-
=================================================
1+
# Blue/green deployment to release a single service
32

43
> In this example, we release a new version of a single service using the
54
blue/green deployment strategy.
65

76
## Steps to follow
87

98
1. version 1 is serving traffic
10-
1. deploy version 2
11-
1. wait until version 2 is ready
12-
1. switch incoming traffic from version 1 to version 2
13-
1. shutdown version 1
9+
2. deploy version 2
10+
3. wait until version 2 is ready
11+
4. switch incoming traffic from version 1 to version 2
12+
5. shutdown version 1
1413

1514
## In practice
1615

@@ -23,8 +22,7 @@ ingress.networking.k8s.io/ingress-bluegreen created
2322
service/svc-my-app created
2423

2524
# Test if the deployment was successful
26-
$ export AGIC-PUBLIC-IP="apgw.aks.aliez.tw"
27-
$ curl.py $AGIC-PUBLIC-IP
25+
$ ./curl.py apgw.aks.aliez.tw
2826
Host: deployment-my-app-v1-657c65694c-jg4hn, Version: v1.0.0
2927
Host: deployment-my-app-v1-657c65694c-s77mq, Version: v1.0.0
3028
Host: deployment-my-app-v1-657c65694c-62w74, Version: v1.0.0
@@ -35,7 +33,7 @@ Host: deployment-my-app-v1-657c65694c-jg4hn, Version: v1.0.0
3533

3634
# To see the deployment in action, open a new terminal and run the following
3735
command:
38-
$ watch kubectl get po
36+
$ watch kubectl get pod -n ns-bluegreen
3937
NAME READY STATUS RESTARTS AGE
4038
deployment-my-app-v1-657c65694c-62w74 1/1 Running 0 2m27s
4139
deployment-my-app-v1-657c65694c-jg4hn 1/1 Running 0 2m27s
@@ -84,6 +82,10 @@ service/svc-my-app patched
8482
$ kubectl delete deployment/deployment-my-app-v1 -n ns-bluegreen
8583
```
8684

85+
### Screen Shot
86+
87+
![ScreenShot Bluegreen](screenshot-bluegreen.png)
88+
8789
### Cleanup
8890

8991
```bash
Loading

canary/README.md

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
Canary deployment
2-
=================
1+
# Canary deployment
32

43
> Version B is released to a subset of users, then proceed to a full rollout.
54
@@ -17,13 +16,10 @@ platform.
1716
adjusting the number of replicas or if you use Nginx as Ingress controller you
1817
can define fine grained traffic splitting via Ingress annotations.**
1918

20-
- [NodePort](NodePort/)
21-
- [nginx-ingress](nginx-ingress/)
19+
- [Application Gateway Ingress Controller](application-gateway-ingress-controller/)
20+
- [Istio service mesh add-on](istio-service-mesh-addon/)
2221

23-
*If you use Helm to deploy applications, the following repository demonstrate
24-
how to make a [canary deployment using Istio and
25-
Helm](https://github.com/etiennetremel/istio-cross-namespace-canary-release-demo).*
2622

2723
## Limitation
2824

29-
- Application Gateway Ingress Controller doesn't support Canary deployment.
25+
- Application Gateway Ingress Controller doesn't support Traffic Shifting.

canary/application-gateway-ingress-controller/README.md

+21-21
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1-
Canary deployment using Kubernetes native functionnalities
2-
==========================================================
1+
# Canary deployment using Kubernetes native functionnalities and Azure Application Gateway Ingress Controller
32

4-
> In the following example we apply the poor man's canary using Kubernetes
5-
native features (replicas). If you want a finer grained control over traffic
6-
shifting, check the [nginx-ingress](../nginx-ingress) example which use
7-
[Nginx](http://nginx.org/) to split traffic or the [a/b testing](../../ab-testing)
8-
example which shift traffic using [Istio](https://istio.io).
3+
> In the following example we apply the `poor man's` canary using Kubernetes
4+
native features (replicas) and Azure Application Gateway Ingress Controller.
5+
6+
If you want a finer grained control over traffic shifting, you can use...
7+
8+
- `nginx-ingress ingress controller` which use [Nginx](http://nginx.org/) to split traffic.
9+
- [`Istio Ingress Gateways`](../istio-service-mesh-addon) which use [Istio](https://istio.io) to split traffic.
10+
- [a/b testing](../../ab-testing) which shift traffic using [Istio](https://istio.io).
911

1012
## Steps to follow
1113

1214
1. 10 replicas of version 1 is serving traffic
13-
1. deploy 1 replicas version 2 (meaning ~10% of traffic)
14-
1. wait enought time to confirm that version 2 is stable and not throwing
15-
unexpected errors
16-
1. scale up version 2 replicas to 10
17-
1. wait until all instances are ready
18-
1. shutdown version 1
15+
2. deploy 1 replicas version 2 (meaning ~10% of traffic)
16+
3. wait enought time to confirm that version 2 is stable and not throwing unexpected errors
17+
4. scale up version 2 replicas to 10
18+
5. wait until all instances are ready
19+
6. shutdown version 1
1920

2021
## In practice
2122

@@ -50,14 +51,13 @@ deployment-my-app-v1-657c65694c-rsckt 1/1 Running 0 68s
5051
deployment-my-app-v1-657c65694c-vdvd8 1/1 Running 0 68s
5152

5253
# Then deploy version 2 of the application and scale down version 1 to 9 replicas at same time
53-
version 2 to 1 replicas (meaning ~10% of traffic) + version 1 to 9 replicas (meaning ~90% of traffic)
54+
# version 2 to 1 replicas (meaning ~10% of traffic) + version 1 to 9 replicas (meaning ~90% of traffic)
5455
$ kubectl apply -f app-v2.yaml
5556
deployment.apps/deployment-my-app-v2 created
5657

57-
$ kubectl scale --replicas=9 deployment/deployment-my-app-v1 -n ns-canry
58+
$ kubectl scale --replicas=9 deployment/deployment-my-app-v1 -n ns-canary
5859
deployment.apps/deployment-my-app-v1 scaled
5960

60-
6161
# Only one pod with the new version should be running.
6262
# You can test if the second deployment was successful
6363
$ ./curl.py apgw.aks.aliez.tw
@@ -82,14 +82,14 @@ $ kubectl scale --replicas=5 deployment/deployment-my-app-v1 -n ns-canary
8282
# version 2 to 10 replicas (meaning 100% of traffic) + version 1 to 0 replicas (meaning ~0% of traffic)
8383
$ kubectl scale --replicas=10 deployment/deployment-my-app-v2 -n ns-canary
8484
$ kubectl scale --replicas=0 deployment/deployment-my-app-v1 -n ns-canary
85-
86-
# Then, when all pods are running, you can safely delete the old deployment
87-
$ kubectl delete deployment/deployment-my-app-v1 -n ns-canary
88-
$ kubectl delete deployment/deployment-my-app-v2 -n ns-canary
8985
```
9086

87+
### Screen Shot
88+
89+
![Screenshot canary-50-50](screenshot-canary-50-50.png)
90+
9191
### Cleanup
9292

9393
```bash
94-
$ kubectl delete all -l app=my-app -n ns-canary
94+
$ kubectl delete -f .
9595
```
Loading

canary/istio-service-mesh-addon/README.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Canary deployment using Istio service mesh
22

3-
> In the following example, we will use the Istio service mesh to control
3+
> In the following example, we will use the Istio service mesh provied by Azure to control
44
traffic distribution for a canary deployment using an example application
55
This is very similar to the Istio A/B testing example, however instead of
66
serving a specific subset of clients based on headers, we are simply dividing
@@ -50,8 +50,6 @@ kubectl label namespace/ns-canary-istio istio.io/rev=asm-1-17
5050

5151
Deploy all of the yaml files in this directory
5252

53-
TODO: Split files and apply/verify seperately
54-
5553
```bash
5654
$ kubectl apply -f app-v1.yaml -f app-v2.yaml -f hpa.yaml -f istio.yaml
5755
namespace/ns-canary-istio configured

0 commit comments

Comments
 (0)