This guide provides patterns and examples for deploying the CloudZero Azure Insights integration.
⚠️ Note: Examples below are patterns, not tested configurations. Adjust for your environment. We welcome PRs with tested examples!
For one-time or manual execution:
# Build the image
make build
# Run sync (recommended: use dry-run first)
make dry-run
# If dry-run looks good, run for real
make run-syncThis tool is designed for periodic execution (daily or weekly). Benefits:
- ✅ Runs automatically without manual intervention
- ✅ Can run overnight when 1-2 hour execution time doesn't matter
- ✅ Ensures CloudZero insights stay up-to-date with Azure Advisor
- ✅ Simple and reliable
Common schedule patterns:
- Daily: Run at 2 AM every day
- Weekly: Run at 2 AM every Sunday
- Twice daily: Run at 2 AM and 2 PM
Concept: Use your cloud provider's container scheduling service.
Azure Container Instances - Schedule a container to run periodically:
# General pattern (adjust for your environment)
az container create \
--resource-group <your-rg> \
--name cloudzero-insights \
--image <your-registry>/cloudzero-insights:latest \
--restart-policy Never \
--environment-variables <your-env-vars> \
--schedule "0 2 * * *"AWS ECS Scheduled Tasks - Use EventBridge with ECS tasks:
# EventBridge rule pattern
ScheduleExpression: cron(0 2 * * ? *)
Target: ECS TaskGCP Cloud Run Jobs - Schedule Cloud Run executions:
# General pattern
gcloud run jobs create cloudzero-insights \
--image <your-image> \
--schedule "0 2 * * *"Concept: Use Kubernetes CronJob for scheduled execution.
Key components:
- CronJob with schedule spec (e.g.,
0 2 * * *) - Secrets for credentials (never hardcode)
- Resource limits (tool can use significant CPU/memory during 60-120 min run)
- Job history limits for cleanup
Pattern:
apiVersion: batch/v1
kind: CronJob
metadata:
name: cloudzero-insights
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
restartPolicy: Never
containers:
- name: insights
image: <your-image>
command: ["python", "-m", "app.cli", "sync"]
envFrom:
- secretRef:
name: cloudzero-azure-credentialsMonitoring:
- Check CronJob status:
kubectl get cronjobs - View job history:
kubectl get jobs - View logs:
kubectl logs job/<job-name>
Concept: Traditional cron on a VM running Docker.
Pattern:
# Wrapper script (run-insights.sh)
#!/bin/bash
docker run --rm --env-file /path/to/.env <your-image> python -m app.cli sync
# Crontab entry
0 2 * * * /path/to/run-insights.sh >> /var/log/cz-insights.log 2>&1Best practices:
- Use absolute paths in cron
- Redirect output to log file
- Set proper permissions on .env file
- Consider using
flockto prevent overlapping runs
Expected execution times based on deployment size:
| Azure Insights | CloudZero Insights | Fetch Time | Total Time |
|---|---|---|---|
| 100 | 1,000 | 1-2 min | 2-3 min |
| 1,000 | 10,000 | 10-15 min | 15-20 min |
| 10,000 | 50,000 | 60-90 min | 70-100 min |
Key insight: Execution time scales with the number of existing CloudZero insights, not Azure recommendations.
- First run: Fetches all existing CloudZero insights for duplicate checking (slow)
- Subsequent runs: Same fetch time (checks all insights each time)
- New recommendations: Only new Azure recommendations are uploaded
- Schedule overnight: Run during off-hours when execution time doesn't matter
- Monitor logs: Check for errors or API issues in scheduled runs
- Dry-run testing: Use
--dry-runflag to preview before real execution - Start small: Test with a single subscription before scaling
Symptom: Tool runs for 1-2 hours
Cause: Large number of existing CloudZero insights (50K+)
Solution: This is expected behavior. The tool must fetch all insights to check for duplicates.
Mitigation:
- Schedule during off-hours (overnight)
- Run less frequently if insights don't change often (weekly instead of daily)
Symptom: AADSTS7000222: The provided client secret keys are expired
Solution:
- Create new Azure AD app credentials in Azure Portal
- Update
AZURE_CLIENT_SECRETenvironment variable - Ensure credentials have Reader role on subscriptions
Symptom: Tool completes but no new insights appear in CloudZero
Possible causes:
- All recommendations already exist: Check with
make run-list LIMIT=10 - Dry-run mode: Ensure you're not using
--dry-runflag - API errors: Check logs for CloudZero API errors
Debug:
# Run with dry-run to see what would be uploaded
make dry-run
# Check existing insights
make run-list LIMIT=20Kubernetes: Check CronJob status
kubectl describe cronjob cloudzero-azure-insights
kubectl get jobs --selector=job-name=cloudzero-azure-insightsAzure Container Instances: Check container logs
az container logs --resource-group myResourceGroup --name cloudzero-azure-insightsSymptom: 429 Too Many Requests errors
Solution:
- CloudZero API has rate limits
- Reduce execution frequency (daily instead of hourly)
- Contact CloudZero support if limits are too restrictive
- Use secrets management: Store credentials in Azure Key Vault, K8s Secrets, or AWS Secrets Manager
- Monitor scheduled runs: Set up alerting for failed executions
- Test in non-prod first: Verify with dry-run and small Azure subscriptions
- Keep Docker image updated: Pull latest image regularly for bug fixes
- Review logs regularly: Check for warnings or errors in scheduled runs
- Document your schedule: Record when and how often the tool runs for your team
For issues or questions:
- GitHub Issues: https://github.com/cloudzero/cz-azure-insights/issues
- CloudZero Support: [email protected]