Skip to content

Commit

Permalink
project: Nginx ingress with Istio service mesh on AKS (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
tungbq authored Mar 30, 2024
2 parents 563673a + 43358c7 commit 948da0f
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 14 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@
| 07 | Create free VPN server on AWS | [terraform-free-vpn-on-aws](./projects/terraform-free-vpn-on-aws/) | ✔️ Done |
| 08 | Provision, deploy, monitor application on AKS | [terraform-aks-cluster](./projects/terraform-aks-cluster/) | ✔️ Done |
| 09 | Deploy application on AKS with Istio service mesh | [aks-istio-application](./projects/aks-istio-application/) | ✔️ Done |
| 10 | Nginx ingress with Istio service mesh on AKS | [nginx-with-istio-on-aks](./projects/nginx-with-istio-on-aks/) | ✔️ Done |

### Explore our upcoming projects by visiting [this link](https://github.com/tungbq/devops-project/issues?q=is%3Aissue+is%3Aopen+label%3Aproject)
3 changes: 3 additions & 0 deletions docs/troubleshooting/common_issue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Common issues

- nginx-returns-426: https://stackoverflow.com/questions/69231743/nginx-returns-426
3 changes: 3 additions & 0 deletions docs/troubleshooting/k8s_issue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# How to Debug CrashLoopBackOff in a Container or Pod?
Step 1: Using kubectl describe pod to get Pod details
Step 2: Using kubectl logs to get Pod logs
6 changes: 3 additions & 3 deletions projects/aks-istio-application/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ variable "vm_size" {

```bash
# Change to yours
export CLUSTER="cluster-boss-moth"
export CLUSTER="cluster-golden-sturgeon"
# Change to yours
export RESOURCE_GROUP="rg-just-gar"
export RESOURCE_GROUP="rg-genuine-longhorn"
export DEVOPS_PROJECT_PATH="/mnt/d/CODING/GITHUB/OPEN-SOURCE/my-project/devops-project" # replace by yours
export KUBECONFIG=$DEVOPS_PROJECT_PATH/projects/terraform-aks-cluster/private_k8s_config/azurek8s
kubectl get nodes
Expand Down Expand Up @@ -67,7 +67,7 @@ kubectl label namespace aks-istio-system istio.io/rev=asm-1-20 --overwrite

**NOTE:**

- It will take few minutes to enable istio adon to your cluster
- It will take few minutes (~ 4m) to enable istio adon to your cluster
- The istio will be installed in `aks-istio-system` namespace

## 4-Deploy microservices sample app
Expand Down
52 changes: 41 additions & 11 deletions projects/aks-istio-application/scripts/frontend_load_testing.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,43 @@
#!/bin/bash

PAGE_URL=$1
# To get page, run: `kubectl get svc aks-istio-ingressgateway-external -n aks-istio-ingress`
## Usage: ./frontend_load_testing.sh 1.2.3.4

echo "Testing frontend page workload..."
for i in $(seq 1 1000); do
echo "Try number $i..."
curl -s -o /dev/null "$PAGE_URL"
sleep 1
done
echo "Testing frontend page completed!"
# Set 'set -e' to exit immediately if any command fails
set -e

# Function to display script usage
usage() {
echo "Usage: $0 <page_url> [sleep_time]"
echo "Example: $0 http://example.com 1"
exit 1
}

# Check for required arguments
if [ $# -lt 1 ]; then
usage
fi

# Assign command-line arguments to variables
PAGE_URL="$1"
SLEEP_TIME="${2:-1}" # Default sleep time is 1 second

# Main function to perform load testing
perform_load_testing() {
echo "Testing frontend page workload..."
echo "Sending curl command to $PAGE_URL..."
for ((i = 1; i <= 1000; i++)); do
echo "Try number $i..."
if ! curl -s -o /dev/null "$PAGE_URL"; then
echo "Failed to fetch page: $PAGE_URL"
exit 1
fi
sleep "$SLEEP_TIME"
done
echo "Testing frontend page completed!"
}

# Prompt for sleep time if not provided
if [ -z "$2" ]; then
read -rp "Enter sleep time (default is 1 second): " SLEEP_TIME
fi

# Call the main function
perform_load_testing
103 changes: 103 additions & 0 deletions projects/nginx-with-istio-on-aks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Nginx Ingress with Istio service mesh

## Architecture

- Refer: https://docs.nginx.com/nginx-ingress-controller/tutorials/nginx-ingress-istio/
- Nginx Ingress is implemented as an entry point to an Istio service mesh

## Steps

### 0-Prepare environment

```bash
export DEVOPS_PROJECT_PATH="/mnt/d/CODING/GITHUB/OPEN-SOURCE/my-project/devops-project"
```

### 1-Deploy fresh cluster

- Check [terraform-aks-cluster](../terraform-aks-cluster/)

### 2-Enable istio

- Istio (aks-istio-system ns) and deploy app (default ns)
- Check [aks-istio-application](../aks-istio-application/) - Only step #1->#4 (skip step #5 and later)
- Enable side car enjection for nginx

```bash
kubectl create ns nginx-ingress
# Check current istio version on AKS
az aks show --resource-group ${RESOURCE_GROUP} --name ${CLUSTER} | grep asm
kubectl label namespace nginx-ingress istio.io/rev=asm-1-20 --overwrite

# Check labels
kubectl get namespaces -A --show-labels
```

### 3-Nginx deploy

- Deploy

```bash
kubectl apply -f $DEVOPS_PROJECT_PATH/projects/nginx-with-istio-on-aks/k8s_manifest/nginx_deployment.yaml
```

- Get the external nginx IP

```bash
kubectl get svc | grep nginx
# Check the EXTERNAL-IP
```

- Access
- Open browser then check the webpage `http://<EXTERNAL-IP>`

### 4-Monitor the application with Prometheus & Grafana

- Deploy Prometheus/Grafana, see: [aks-istio-application](../aks-istio-application/) - step #6
- Expose the port with port-forward then visit Grafana to get application insights
- Import the Istio dashboards to Grafana
- Perform load testing to the frontend main page, by running:

```bash
# EXTERNAL_IP get from nginx service
$DEVOPS_PROJECT_PATH/projects/aks-istio-application/scripts/frontend_load_testing.sh "$EXTERNAL_IP" "0.2"

# 0.2 is the sleep time between the curl commands, to do more load, reduce that value like 0.1
```

## 5-Result

Once completed, you could archive the results like below:

- Frontend webpage of the application
![front-end-nginx-based](./assets/front-end-nginx-based.png)

- Grafana Istio Service Dashboard for application insights
![grafana-istio-nginx-frontend-monitor](./assets/grafana-istio-nginx-frontend-monitor.png)

If you could reach to this point, congratulations for your effort! Happy coding!

## 6-Cleanup

- Once done, destroy the cluster to free up resource and avoid upcomming Azure cost ($$$)
- Follow the `Delete AKS resources` section of project [terraform-aks-cluster](../terraform-aks-cluster/)

## Summary

To use Nginx ingress to serve the external request and then forward to the application inside Istio service mesh, we could:

- Enable the service mesh as usual
- Deploy the application as previous project
- (\*)Enable Istio side-car injection feature to the namespace that we deploy the `nginx` service/ingress
- (\*)Create `nginx.conf` file to route the traffic to frontend service
- Deploy nginx as usual, then get the `External-IP` from nginx service
- Visit the `External-IP` page then enjoy the result

The (\*) is the most difference steps in this project

## Document

- https://docs.nginx.com/nginx-ingress-controller/tutorials/nginx-ingress-istio/
- https://platform9.com/learn/v1.0/tutorials/nginix-controller-via-yaml
- https://gist.github.com/petitviolet/d36f33d145d0bbf4b54eb187b79d0244
- https://cloud.google.com/endpoints/docs/openapi/custom-nginx
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# full-setup.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
nginx.conf: |
events {}
http {
server {
listen 80;
location / {
proxy_pass http://frontend.default.svc.cluster.local; # Added http:// protocol prefix
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
}
}
}
---
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress
spec:
selector:
app: nginx-ingress
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer # Expose the service using a LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-ingress
spec:
replicas: 1
selector:
matchLabels:
app: nginx-ingress
template:
metadata:
labels:
app: nginx-ingress
annotations:
traffic.sidecar.istio.io/includeInboundPorts: ""
traffic.sidecar.istio.io/excludeInboundPorts: "80,443"
traffic.sidecar.istio.io/excludeOutboundIPRanges: "10.0.0.1/32"
sidecar.istio.io/inject: "true"
spec:
containers:
- name: nginx
image: nginx:1.25.4
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
readOnly: true
volumes:
- name: nginx-config
configMap:
name: nginx-config

0 comments on commit 948da0f

Please sign in to comment.