118 lines
7.4 KiB
Markdown
118 lines
7.4 KiB
Markdown
# Exam Submission - Public Cloud Application Deployment
|
||
|
||
## 1. Application Description
|
||
This project is a multi-component web application deployed on a public cloud Kubernetes cluster. It consists of a Node.js frontend/backend that interfaces with a robust MySQL database for data persistence. An additional phpMyAdmin component is included for easy database administration.
|
||
|
||
## 2. Infrastructure & Cloud Resources
|
||
- **Public Cloud Used:** Microsoft Azure
|
||
- **Cloud Services:**
|
||
- **Azure Kubernetes Service (AKS):** The managed Kubernetes platform that orchestrates the containers.
|
||
- **Azure Container Registry (ACR):** The private registry used to store and pull the application's Docker image securely.
|
||
- **Azure Managed Disks (Standard_LRS):** The underlying block storage used by Kubernetes to satisfy the persistent volume claims automatically.
|
||
- **Azure Load Balancer:** Automatically provisioned by the NGINX Ingress controller to expose the application to the internet.
|
||
- **Kubernetes Objects Used:**
|
||
- `Deployment`: Used for the Node.js webapp and phpMyAdmin containers to handle replica management and automatic restarting upon failure.
|
||
- `StatefulSet`: Used for the MySQL database to ensure stable, unique network identifiers and persistent storage binding.
|
||
- `PersistentVolumeClaim`: Dynamically requests storage from Azure.
|
||
- `Service`: Defines logical sets of pods and access policies (ClusterIP or Headless).
|
||
- `Ingress`: Manages external access to the services, utilizing NGINX and TLS.
|
||
- `Secret`: Securely stores the generated database password to prevent hardcoding it in GIT.
|
||
- `ConfigMap`: Stores the `user.sql` initialization script for MySQL.
|
||
- **Databases Used:** MySQL 8.0
|
||
|
||
## 3. Cost Analysis — Azure Container Instances (ACI) Deployment
|
||
|
||
> **Deployment model:** 4 Linux containers running 24/7 in a single ACI container group (`germanywestcentral` region).
|
||
> Prices are based on published Azure pay-as-you-go rates (May 2025). Always verify at [azure.microsoft.com/pricing](https://azure.microsoft.com/en-us/pricing/details/container-instances/).
|
||
|
||
### Container Resource Allocation (from `prepare-app.sh`)
|
||
|
||
| Container | vCPU | Memory (GB) |
|
||
|--------------|------|-------------|
|
||
| `mysql` | 0.5 | 0.8 |
|
||
| `webapp` | 0.5 | 0.5 |
|
||
| `phpmyadmin` | 0.3 | 0.3 |
|
||
| `caddy` | 0.2 | 0.3 |
|
||
| **Total** | **1.5** | **1.9** |
|
||
|
||
### ACI Pricing Rates (Linux, West Europe / Germany region)
|
||
|
||
| Resource | Rate |
|
||
|---|---|
|
||
| vCPU | ~$0.0000125 / vCPU-second |
|
||
| Memory | ~$0.0000013 / GB-second |
|
||
|
||
### Monthly Cost Breakdown (running 24/7 = 2,592,000 seconds/month)
|
||
|
||
| Service | Calculation | Monthly Cost |
|
||
|---|---|---|
|
||
| **ACI — vCPU** | 1.5 vCPU × 2,592,000 s × $0.0000125 | ~$48.60 |
|
||
| **ACI — Memory** | 1.9 GB × 2,592,000 s × $0.0000013 | ~$6.40 |
|
||
| **Azure Container Registry (Basic)** | Flat rate, 10 GB included | ~$10.33 |
|
||
| **Azure Storage (Azure Files, ~1 GB)** | ~$0.06/GB/month | ~$0.06 |
|
||
| **Outbound bandwidth** | ~50 GB/month egress (1000 users/day estimate) | ~$4.50 |
|
||
| **Total** | | **~$69.89 / month** |
|
||
|
||
### Annual Cost Estimate
|
||
|
||
| Scenario | Annual Cost |
|
||
|---|---|
|
||
| Running 24/7 (full year) | **~$839 / year** |
|
||
| Running only during business hours (8h/day, 5 days/week) | **~$210 / year** |
|
||
|
||
|
||
|
||
## 4. File Descriptions
|
||
- `prepare-app.sh`: Main script that creates Azure resources (Resource Group, ACR, AKS), builds/pushes images, sets up ingress/certificates, and applies all manifests.
|
||
- `remove-app.sh`: Cleanup script that safely deletes the entire Azure Resource Group to prevent unwanted charges.
|
||
- `deployment.yaml`: Defines the Node.js web application replica.
|
||
- `statefulset.yaml`: Defines the MySQL database with persistent volume claims.
|
||
- `phpmyadmin.yaml`: Defines the phpMyAdmin interface deployment and service.
|
||
- `ingress.yaml`: Defines routing rules and TLS certificate configuration for HTTPS.
|
||
- `namespace.yaml`: Defines the Kubernetes namespace (`smartbuilding-namespace`).
|
||
- `service.yaml`: Defines the web app service endpoints.
|
||
- `webapp/Dockerfile`: Instructions to build the Node.js container image.
|
||
- `webapp/user.sql`: Database initialization script.
|
||
|
||
## 5. Configuration Description
|
||
The configuration relies entirely on declarative Kubernetes manifests and a `prepare-app.sh` automation script. Secrets are intentionally kept out of the source code. During deployment, a random password is generated and stored securely in a Kubernetes `Secret` (`db-secrets`). The `deployment.yaml` and `statefulset.yaml` inject this secret securely into the containers via environment variables (`MYSQL_ROOT_PASSWORD` and `DB_PASSWORD`), ensuring repeatable and secure deployments. Storage is configured to use Azure's default CSI driver, abstracting the physical disk away from the code.
|
||
|
||
## 6. Accessing the Application
|
||
Once `prepare-app.sh` finishes, it will print the URLs to the terminal.
|
||
To view the applications:
|
||
1. Open a modern web browser.
|
||
2. Navigate to **https://smartbuilding.germanywestcentral.azurecontainer.io/admin** to view the web application.
|
||
3. Navigate to **http://smartbuilding.germanywestcentral.azurecontainer.io:8080** to view phpMyAdmin.
|
||
The HTTPS connection is handled automatically by the Caddy reverse proxy container.
|
||
|
||
## 7. Data Backup Instructions
|
||
To back up the MySQL database running in the StatefulSet without modifying the container:
|
||
```bash
|
||
kubectl exec -it mysql-statefulset-0 -n smartbuilding-namespace -- bash -c 'mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" --all-databases' > backup.sql
|
||
```
|
||
This command streams the complete SQL backup securely from the pod directly to your local machine into a file named `backup.sql`.
|
||
|
||
## 8. Viewing Access Logs
|
||
To view access logs from the internet (e.g., to see who is visiting the application), you can query the NGINX Ingress Controller logs:
|
||
```bash
|
||
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller --tail=100
|
||
```
|
||
This outputs the HTTP requests handled by the public-facing proxy, including IP addresses, timestamps, and requested paths.
|
||
|
||
## 9. Conditions to Run Scripts
|
||
To run `prepare-app.sh` and `remove-app.sh`, your local environment must satisfy these conditions:
|
||
- **Azure CLI (`az`)** is installed.
|
||
- **Docker CLI** is installed and running.
|
||
- **kubectl** is installed.
|
||
- **OpenSSL** is installed (for generating the secure password).
|
||
- You must have an active Azure Subscription (e.g., Azure Student).
|
||
- You must be authenticated to Azure by running `az login` successfully prior to execution.
|
||
|
||
## 10. External Resources & Generative AI Usage
|
||
- **Generative AI Used:** Google Gemini (Antigravity pair programming agent).
|
||
- **Method of Use:**
|
||
- **Resolving Azure student account restrictions:** The TUKE Azure Student subscription imposes quota limits that prevent the creation of standard Virtual Machines and AKS node pools. AI assistance was used to diagnose these conflicts and redesign the deployment to use **Azure Container Instances (ACI)** as a VM-free alternative that is fully supported within the student quota.
|
||
- **Building the HTTPS deployment pipeline:** AI was used to design and implement the `prepare-app.sh` script, specifically the integration of **Caddy** as a reverse proxy for automatic HTTPS certificate generation, and the secure Docker image push flow using temporary ACR OAuth tokens (bypassing the local Docker credential store).
|
||
- **Documentation:** This README was written with AI assistance, including the cost analysis, file descriptions, and configuration explanations.
|
||
|