This project demonstrates how to build, deploy, and monitor a serverless uptime monitoring service on Azure using Pulumi. The architecture is designed to be resilient, scalable, and cost-effective, leveraging Azure's native serverless and monitoring capabilities. The primary goal of this repository is to serve as a hands-on workshop for migrating a monolithic application to a microservices-based architecture on Azure.
This repository contains two refactoring exercises:
- Exercise 01: Refactoring a Monolith - This exercise guides you through breaking down a single Pulumi project into a Shared Services stack and an Uptime Service stack, demonstrating how to manage shared cloud resources effectively.
- Exercise 02: Centralized Configuration with ESC - This exercise shows how to use Pulumi ESC (Environments, Secrets, and Configuration) to manage and share configuration dynamically across multiple services, improving security and maintainability.
The final architecture consists of the following Azure resources, all managed via Pulumi:
- Azure Function App (Consumption Plan): A serverless function that acts as a health check endpoint. It verifies connectivity to a shared storage account.
- Azure Storage Account: Provides a shared storage container used by the uptime service.
- Application Insights: Gathers metrics, logs, and traces from the Function App for monitoring and diagnostics.
- Azure Monitor: Provides dashboards and alerting capabilities based on the four golden signals (Latency, Traffic, Errors, and Saturation).
graph TD;
subgraph "Pulumi Infrastructure as Code"
A[Pulumi Program]
B[Azure Function App]
C[Storage Account]
D[Application Insights]
E[Azure Monitor]
F[Resource Group]
end
subgraph "Uptime Monitoring Service"
G[HTTP Trigger]
end
A --> F
F --> B
F --> C
F --> D
F --> E
B --> C
B --> D
B --> G
- Deployment Automation: The Azure Function is packaged and deployed using the Pulumi Command provider, which correctly handles the required directory structure for Azure Functions. This ensures that deployments are reliable and automated.
- Health Check Logic: The Azure Function, written in Python, is triggered via an HTTP request. It attempts to connect to a provisioned Azure Storage container. A successful connection returns a
200 OK
JSON response, while any failure results in a500 Internal Server Error
. - Monitoring and Alerting: Application Insights and Azure Monitor are configured to track the function's performance, focusing on the four golden signals. Alerts are triggered if the error rate exceeds a predefined threshold, ensuring that any service degradation is promptly addressed.
Throughout this project, we addressed several real-world infrastructure challenges:
- Azure Function Deployment: Solved the common issue of incorrect zip file structures by using the
pulumi-command
provider to ensure theuptime/
subdirectory is correctly packaged. - Serverless Quota Management: Navigated Azure's "Dynamic VM" quota limitations for Consumption Plans, a frequent issue in certain subscriptions or regions.
- Infrastructure Refactoring: Successfully migrated from a monolithic architecture to a microservices-based approach with shared infrastructure, a core concept of the workshop.
- Cloud Migration: Fully migrated the project from AWS to Azure, replacing services like Lambda, S3, and CloudWatch with their Azure equivalents (Azure Functions, Azure Storage, and Azure Monitor).
- Pulumi CLI
- Azure CLI
- Python 3.11+
- Login to Azure:
az login
- Set the Azure Location:
pulumi config set azure-native:location <your-desired-region>
- Deploy the Stack:
pulumi up
This will provision all the necessary Azure resources for the uptime monitoring service.