- Added comprehensive course structure with 11 modules - Included theoretical content, practical examples, and tasks - Multi-language code examples (Java, Rust, Node.js, Python) - Detailed analysis of architectural approaches and trade-offs - Complete caching strategies documentation - Architecture examples from real-world systems (Twitter, Netflix, Uber) - Structured navigation and learning path - Ready for educational use
3613 lines
93 KiB
Markdown
3613 lines
93 KiB
Markdown
# Модуль 8: Облачные технологии и миграция
|
|
|
|
## Содержание модуля
|
|
1. [Основы облачных технологий](#основы-облачных-технологий)
|
|
2. [AWS (Amazon Web Services)](#aws-amazon-web-services)
|
|
3. [Azure (Microsoft Azure)](#azure-microsoft-azure)
|
|
4. [GCP (Google Cloud Platform)](#gcp-google-cloud-platform)
|
|
5. [Cloud-Native архитектура](#cloud-native-архитектура)
|
|
6. [Стратегии миграции](#стратегии-миграции)
|
|
7. [Cost Optimization](#cost-optimization)
|
|
|
|
---
|
|
|
|
## Основы облачных технологий
|
|
|
|
### Что такое облачные вычисления
|
|
|
|
**Облачные вычисления** — модель предоставления вычислительных ресурсов через интернет по требованию.
|
|
|
|
### Модели обслуживания
|
|
|
|
#### 1. IaaS (Infrastructure as a Service)
|
|
**Определение:** Предоставление виртуальной инфраструктуры.
|
|
|
|
**Примеры:**
|
|
- AWS EC2
|
|
- Azure Virtual Machines
|
|
- Google Compute Engine
|
|
|
|
**Преимущества:**
|
|
- Полный контроль над инфраструктурой
|
|
- Гибкость в выборе ОС и ПО
|
|
- Масштабируемость
|
|
|
|
**Технический пример - AWS EC2 Infrastructure as Code:**
|
|
|
|
```yaml
|
|
# terraform/main.tf
|
|
terraform {
|
|
required_providers {
|
|
aws = {
|
|
source = "hashicorp/aws"
|
|
version = "~> 5.0"
|
|
}
|
|
}
|
|
}
|
|
|
|
provider "aws" {
|
|
region = var.aws_region
|
|
}
|
|
|
|
# VPC Configuration
|
|
resource "aws_vpc" "main" {
|
|
cidr_block = "10.0.0.0/16"
|
|
enable_dns_hostnames = true
|
|
enable_dns_support = true
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-vpc"
|
|
Environment = var.environment
|
|
}
|
|
}
|
|
|
|
# Internet Gateway
|
|
resource "aws_internet_gateway" "main" {
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-igw"
|
|
}
|
|
}
|
|
|
|
# Public Subnets
|
|
resource "aws_subnet" "public" {
|
|
count = length(var.availability_zones)
|
|
|
|
vpc_id = aws_vpc.main.id
|
|
cidr_block = "10.0.${count.index + 1}.0/24"
|
|
availability_zone = var.availability_zones[count.index]
|
|
map_public_ip_on_launch = true
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-public-subnet-${count.index + 1}"
|
|
Type = "Public"
|
|
}
|
|
}
|
|
|
|
# Private Subnets
|
|
resource "aws_subnet" "private" {
|
|
count = length(var.availability_zones)
|
|
|
|
vpc_id = aws_vpc.main.id
|
|
cidr_block = "10.0.${count.index + 10}.0/24"
|
|
availability_zone = var.availability_zones[count.index]
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-private-subnet-${count.index + 1}"
|
|
Type = "Private"
|
|
}
|
|
}
|
|
|
|
# Security Groups
|
|
resource "aws_security_group" "web" {
|
|
name_prefix = "${var.project_name}-web-"
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
ingress {
|
|
from_port = 80
|
|
to_port = 80
|
|
protocol = "tcp"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
|
|
ingress {
|
|
from_port = 443
|
|
to_port = 443
|
|
protocol = "tcp"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
|
|
ingress {
|
|
from_port = 22
|
|
to_port = 22
|
|
protocol = "tcp"
|
|
cidr_blocks = [var.admin_cidr]
|
|
}
|
|
|
|
egress {
|
|
from_port = 0
|
|
to_port = 0
|
|
protocol = "-1"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-web-sg"
|
|
}
|
|
}
|
|
|
|
resource "aws_security_group" "app" {
|
|
name_prefix = "${var.project_name}-app-"
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
ingress {
|
|
from_port = 8080
|
|
to_port = 8080
|
|
protocol = "tcp"
|
|
security_groups = [aws_security_group.web.id]
|
|
}
|
|
|
|
ingress {
|
|
from_port = 22
|
|
to_port = 22
|
|
protocol = "tcp"
|
|
cidr_blocks = [var.admin_cidr]
|
|
}
|
|
|
|
egress {
|
|
from_port = 0
|
|
to_port = 0
|
|
protocol = "-1"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-app-sg"
|
|
}
|
|
}
|
|
|
|
# Application Load Balancer
|
|
resource "aws_lb" "main" {
|
|
name = "${var.project_name}-alb"
|
|
internal = false
|
|
load_balancer_type = "application"
|
|
security_groups = [aws_security_group.web.id]
|
|
subnets = aws_subnet.public[*].id
|
|
|
|
enable_deletion_protection = false
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-alb"
|
|
}
|
|
}
|
|
|
|
# Target Group
|
|
resource "aws_lb_target_group" "app" {
|
|
name = "${var.project_name}-tg"
|
|
port = 8080
|
|
protocol = "HTTP"
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
health_check {
|
|
enabled = true
|
|
healthy_threshold = 2
|
|
unhealthy_threshold = 2
|
|
timeout = 5
|
|
interval = 30
|
|
path = "/health"
|
|
matcher = "200"
|
|
port = "traffic-port"
|
|
protocol = "HTTP"
|
|
}
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-tg"
|
|
}
|
|
}
|
|
|
|
# Launch Template
|
|
resource "aws_launch_template" "app" {
|
|
name_prefix = "${var.project_name}-"
|
|
image_id = var.ami_id
|
|
instance_type = var.instance_type
|
|
|
|
vpc_security_group_ids = [aws_security_group.app.id]
|
|
|
|
user_data = base64encode(templatefile("${path.module}/user_data.sh", {
|
|
app_name = var.project_name
|
|
environment = var.environment
|
|
}))
|
|
|
|
tag_specifications {
|
|
resource_type = "instance"
|
|
tags = {
|
|
Name = "${var.project_name}-instance"
|
|
Environment = var.environment
|
|
}
|
|
}
|
|
|
|
lifecycle {
|
|
create_before_destroy = true
|
|
}
|
|
}
|
|
|
|
# Auto Scaling Group
|
|
resource "aws_autoscaling_group" "app" {
|
|
name = "${var.project_name}-asg"
|
|
vpc_zone_identifier = aws_subnet.private[*].id
|
|
target_group_arns = [aws_lb_target_group.app.arn]
|
|
health_check_type = "ELB"
|
|
health_check_grace_period = 300
|
|
|
|
min_size = var.min_size
|
|
max_size = var.max_size
|
|
desired_capacity = var.desired_capacity
|
|
|
|
launch_template {
|
|
id = aws_launch_template.app.id
|
|
version = "$Latest"
|
|
}
|
|
|
|
tag {
|
|
key = "Name"
|
|
value = "${var.project_name}-asg"
|
|
propagate_at_launch = false
|
|
}
|
|
|
|
tag {
|
|
key = "Environment"
|
|
value = var.environment
|
|
propagate_at_launch = true
|
|
}
|
|
}
|
|
|
|
# Auto Scaling Policies
|
|
resource "aws_autoscaling_policy" "scale_up" {
|
|
name = "${var.project_name}-scale-up"
|
|
scaling_adjustment = 1
|
|
adjustment_type = "ChangeInCapacity"
|
|
cooldown = 300
|
|
autoscaling_group_name = aws_autoscaling_group.app.name
|
|
}
|
|
|
|
resource "aws_autoscaling_policy" "scale_down" {
|
|
name = "${var.project_name}-scale-down"
|
|
scaling_adjustment = -1
|
|
adjustment_type = "ChangeInCapacity"
|
|
cooldown = 300
|
|
autoscaling_group_name = aws_autoscaling_group.app.name
|
|
}
|
|
|
|
# CloudWatch Alarms
|
|
resource "aws_cloudwatch_metric_alarm" "cpu_high" {
|
|
alarm_name = "${var.project_name}-cpu-high"
|
|
comparison_operator = "GreaterThanThreshold"
|
|
evaluation_periods = "2"
|
|
metric_name = "CPUUtilization"
|
|
namespace = "AWS/EC2"
|
|
period = "300"
|
|
statistic = "Average"
|
|
threshold = "80"
|
|
alarm_description = "This metric monitors ec2 cpu utilization"
|
|
alarm_actions = [aws_autoscaling_policy.scale_up.arn]
|
|
|
|
dimensions = {
|
|
AutoScalingGroupName = aws_autoscaling_group.app.name
|
|
}
|
|
}
|
|
|
|
resource "aws_cloudwatch_metric_alarm" "cpu_low" {
|
|
alarm_name = "${var.project_name}-cpu-low"
|
|
comparison_operator = "LessThanThreshold"
|
|
evaluation_periods = "2"
|
|
metric_name = "CPUUtilization"
|
|
namespace = "AWS/EC2"
|
|
period = "300"
|
|
statistic = "Average"
|
|
threshold = "20"
|
|
alarm_description = "This metric monitors ec2 cpu utilization"
|
|
alarm_actions = [aws_autoscaling_policy.scale_down.arn]
|
|
|
|
dimensions = {
|
|
AutoScalingGroupName = aws_autoscaling_group.app.name
|
|
}
|
|
}
|
|
|
|
# RDS Database
|
|
resource "aws_db_subnet_group" "main" {
|
|
name = "${var.project_name}-db-subnet-group"
|
|
subnet_ids = aws_subnet.private[*].id
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-db-subnet-group"
|
|
}
|
|
}
|
|
|
|
resource "aws_db_instance" "main" {
|
|
identifier = "${var.project_name}-db"
|
|
|
|
engine = "postgres"
|
|
engine_version = "14.7"
|
|
instance_class = var.db_instance_class
|
|
|
|
allocated_storage = 20
|
|
max_allocated_storage = 100
|
|
storage_type = "gp2"
|
|
storage_encrypted = true
|
|
|
|
db_name = var.db_name
|
|
username = var.db_username
|
|
password = var.db_password
|
|
|
|
vpc_security_group_ids = [aws_security_group.db.id]
|
|
db_subnet_group_name = aws_db_subnet_group.main.name
|
|
|
|
backup_retention_period = 7
|
|
backup_window = "03:00-04:00"
|
|
maintenance_window = "sun:04:00-sun:05:00"
|
|
|
|
skip_final_snapshot = var.environment != "production"
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-db"
|
|
Environment = var.environment
|
|
}
|
|
}
|
|
|
|
resource "aws_security_group" "db" {
|
|
name_prefix = "${var.project_name}-db-"
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
ingress {
|
|
from_port = 5432
|
|
to_port = 5432
|
|
protocol = "tcp"
|
|
security_groups = [aws_security_group.app.id]
|
|
}
|
|
|
|
egress {
|
|
from_port = 0
|
|
to_port = 0
|
|
protocol = "-1"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-db-sg"
|
|
}
|
|
}
|
|
```
|
|
|
|
```bash
|
|
# user_data.sh
|
|
#!/bin/bash
|
|
yum update -y
|
|
|
|
# Install Docker
|
|
yum install -y docker
|
|
systemctl start docker
|
|
systemctl enable docker
|
|
usermod -a -G docker ec2-user
|
|
|
|
# Install Docker Compose
|
|
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
|
chmod +x /usr/local/bin/docker-compose
|
|
|
|
# Create application directory
|
|
mkdir -p /opt/${app_name}
|
|
cd /opt/${app_name}
|
|
|
|
# Create docker-compose.yml
|
|
cat > docker-compose.yml << EOF
|
|
version: '3.8'
|
|
services:
|
|
app:
|
|
image: ${app_name}:latest
|
|
ports:
|
|
- "8080:8080"
|
|
environment:
|
|
- SPRING_PROFILES_ACTIVE=${environment}
|
|
- DB_HOST=${db_host}
|
|
- DB_PORT=5432
|
|
- DB_NAME=${db_name}
|
|
- DB_USERNAME=${db_username}
|
|
- DB_PASSWORD=${db_password}
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
|
|
nginx:
|
|
image: nginx:alpine
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
volumes:
|
|
- ./nginx.conf:/etc/nginx/nginx.conf
|
|
depends_on:
|
|
- app
|
|
restart: unless-stopped
|
|
EOF
|
|
|
|
# Start application
|
|
docker-compose up -d
|
|
|
|
# Install CloudWatch agent
|
|
yum install -y amazon-cloudwatch-agent
|
|
cat > /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json << EOF
|
|
{
|
|
"metrics": {
|
|
"namespace": "CWAgent",
|
|
"metrics_collected": {
|
|
"cpu": {
|
|
"measurement": ["cpu_usage_idle", "cpu_usage_iowait", "cpu_usage_user", "cpu_usage_system"],
|
|
"metrics_collection_interval": 60
|
|
},
|
|
"disk": {
|
|
"measurement": ["used_percent"],
|
|
"metrics_collection_interval": 60,
|
|
"resources": ["*"]
|
|
},
|
|
"mem": {
|
|
"measurement": ["mem_used_percent"],
|
|
"metrics_collection_interval": 60
|
|
}
|
|
}
|
|
}
|
|
}
|
|
EOF
|
|
|
|
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
|
|
-a fetch-config \
|
|
-m ec2 \
|
|
-c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json \
|
|
-s
|
|
```
|
|
|
|
```hcl
|
|
# variables.tf
|
|
variable "aws_region" {
|
|
description = "AWS region"
|
|
type = string
|
|
default = "us-west-2"
|
|
}
|
|
|
|
variable "project_name" {
|
|
description = "Name of the project"
|
|
type = string
|
|
}
|
|
|
|
variable "environment" {
|
|
description = "Environment name"
|
|
type = string
|
|
default = "dev"
|
|
}
|
|
|
|
variable "availability_zones" {
|
|
description = "List of availability zones"
|
|
type = list(string)
|
|
default = ["us-west-2a", "us-west-2b", "us-west-2c"]
|
|
}
|
|
|
|
variable "admin_cidr" {
|
|
description = "CIDR block for admin access"
|
|
type = string
|
|
default = "0.0.0.0/0"
|
|
}
|
|
|
|
variable "ami_id" {
|
|
description = "AMI ID for EC2 instances"
|
|
type = string
|
|
default = "ami-0c02fb55956c7d316" # Amazon Linux 2
|
|
}
|
|
|
|
variable "instance_type" {
|
|
description = "EC2 instance type"
|
|
type = string
|
|
default = "t3.medium"
|
|
}
|
|
|
|
variable "min_size" {
|
|
description = "Minimum number of instances"
|
|
type = number
|
|
default = 2
|
|
}
|
|
|
|
variable "max_size" {
|
|
description = "Maximum number of instances"
|
|
type = number
|
|
default = 10
|
|
}
|
|
|
|
variable "desired_capacity" {
|
|
description = "Desired number of instances"
|
|
type = number
|
|
default = 3
|
|
}
|
|
|
|
variable "db_instance_class" {
|
|
description = "RDS instance class"
|
|
type = string
|
|
default = "db.t3.micro"
|
|
}
|
|
|
|
variable "db_name" {
|
|
description = "Database name"
|
|
type = string
|
|
}
|
|
|
|
variable "db_username" {
|
|
description = "Database username"
|
|
type = string
|
|
}
|
|
|
|
variable "db_password" {
|
|
description = "Database password"
|
|
type = string
|
|
sensitive = true
|
|
}
|
|
```
|
|
|
|
#### 2. PaaS (Platform as a Service)
|
|
**Определение:** Предоставление платформы для разработки приложений.
|
|
|
|
**Примеры:**
|
|
- AWS Elastic Beanstalk
|
|
- Azure App Service
|
|
- Google App Engine
|
|
|
|
**Преимущества:**
|
|
- Фокус на разработке приложений
|
|
- Автоматическое управление инфраструктурой
|
|
- Встроенные сервисы
|
|
|
|
**Технический пример - Azure App Service Deployment:**
|
|
|
|
```yaml
|
|
# azure-pipelines.yml
|
|
trigger:
|
|
- main
|
|
|
|
pool:
|
|
vmImage: 'ubuntu-latest'
|
|
|
|
variables:
|
|
azureSubscription: 'your-subscription-id'
|
|
appName: 'your-app-name'
|
|
resourceGroupName: 'your-resource-group'
|
|
location: 'West Europe'
|
|
|
|
stages:
|
|
- stage: Build
|
|
displayName: Build stage
|
|
jobs:
|
|
- job: Build
|
|
displayName: Build
|
|
steps:
|
|
- task: NodeTool@0
|
|
inputs:
|
|
versionSpec: '18.x'
|
|
displayName: 'Install Node.js'
|
|
|
|
- script: |
|
|
npm install
|
|
npm run build
|
|
displayName: 'Install dependencies and build'
|
|
|
|
- task: ArchiveFiles@2
|
|
displayName: 'Archive files'
|
|
inputs:
|
|
rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
|
|
includeRootFolder: false
|
|
archiveType: zip
|
|
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
|
|
replaceExistingArchive: true
|
|
|
|
- upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
|
|
artifact: drop
|
|
|
|
- stage: Deploy
|
|
displayName: Deploy stage
|
|
dependsOn: Build
|
|
condition: succeeded()
|
|
jobs:
|
|
- deployment: Deploy
|
|
displayName: Deploy
|
|
environment: 'production'
|
|
strategy:
|
|
runOnce:
|
|
deploy:
|
|
steps:
|
|
- task: AzureWebApp@1
|
|
displayName: 'Azure Web App Deploy'
|
|
inputs:
|
|
azureSubscription: '$(azureSubscription)'
|
|
appType: 'webApp'
|
|
appName: '$(appName)'
|
|
package: '$(Pipeline.Workspace)/drop/$(Build.BuildId).zip'
|
|
deploymentMethod: 'zipDeploy'
|
|
```
|
|
|
|
```json
|
|
// azure-resources.json
|
|
{
|
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
|
"contentVersion": "1.0.0.0",
|
|
"parameters": {
|
|
"appName": {
|
|
"type": "string",
|
|
"defaultValue": "my-app",
|
|
"metadata": {
|
|
"description": "Name of the App Service"
|
|
}
|
|
},
|
|
"location": {
|
|
"type": "string",
|
|
"defaultValue": "[resourceGroup().location]",
|
|
"metadata": {
|
|
"description": "Location for all resources"
|
|
}
|
|
},
|
|
"sku": {
|
|
"type": "string",
|
|
"defaultValue": "S1",
|
|
"allowedValues": [
|
|
"F1",
|
|
"D1",
|
|
"B1",
|
|
"B2",
|
|
"B3",
|
|
"S1",
|
|
"S2",
|
|
"S3",
|
|
"P1",
|
|
"P2",
|
|
"P3",
|
|
"P4"
|
|
],
|
|
"metadata": {
|
|
"description": "The pricing tier for the hosting plan"
|
|
}
|
|
},
|
|
"nodeVersion": {
|
|
"type": "string",
|
|
"defaultValue": "18-lts",
|
|
"metadata": {
|
|
"description": "The version of Node.js to use"
|
|
}
|
|
}
|
|
},
|
|
"variables": {
|
|
"hostingPlanName": "[concat(parameters('appName'), '-plan')]",
|
|
"applicationInsightsName": "[concat(parameters('appName'), '-ai')]"
|
|
},
|
|
"resources": [
|
|
{
|
|
"type": "Microsoft.Web/serverfarms",
|
|
"apiVersion": "2021-02-01",
|
|
"name": "[variables('hostingPlanName')]",
|
|
"location": "[parameters('location')]",
|
|
"sku": {
|
|
"name": "[parameters('sku')]"
|
|
},
|
|
"kind": "linux",
|
|
"properties": {
|
|
"reserved": true
|
|
}
|
|
},
|
|
{
|
|
"type": "Microsoft.Web/sites",
|
|
"apiVersion": "2021-02-01",
|
|
"name": "[parameters('appName')]",
|
|
"location": "[parameters('location')]",
|
|
"dependsOn": [
|
|
"[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
|
|
],
|
|
"kind": "app,linux",
|
|
"properties": {
|
|
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
|
|
"siteConfig": {
|
|
"linuxFxVersion": "[concat('NODE|', parameters('nodeVersion'))]",
|
|
"appSettings": [
|
|
{
|
|
"name": "WEBSITE_NODE_DEFAULT_VERSION",
|
|
"value": "[parameters('nodeVersion')]"
|
|
},
|
|
{
|
|
"name": "WEBSITE_RUN_FROM_PACKAGE",
|
|
"value": "1"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"type": "Microsoft.Insights/components",
|
|
"apiVersion": "2020-02-02",
|
|
"name": "[variables('applicationInsightsName')]",
|
|
"location": "[parameters('location')]",
|
|
"kind": "web",
|
|
"properties": {
|
|
"Application_Type": "web",
|
|
"Request_Source": "rest"
|
|
}
|
|
}
|
|
],
|
|
"outputs": {
|
|
"appUrl": {
|
|
"type": "string",
|
|
"value": "[concat('https://', reference(resourceId('Microsoft.Web/sites', parameters('appName'))).defaultHostName)]"
|
|
},
|
|
"appServicePlanId": {
|
|
"type": "string",
|
|
"value": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
```javascript
|
|
// app.js - Express.js application for Azure App Service
|
|
const express = require('express');
|
|
const path = require('path');
|
|
const cors = require('cors');
|
|
const helmet = require('helmet');
|
|
const compression = require('compression');
|
|
const rateLimit = require('express-rate-limit');
|
|
|
|
const app = express();
|
|
const PORT = process.env.PORT || 3000;
|
|
|
|
// Security middleware
|
|
app.use(helmet());
|
|
app.use(compression());
|
|
|
|
// Rate limiting
|
|
const limiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
max: 100, // limit each IP to 100 requests per windowMs
|
|
message: 'Too many requests from this IP, please try again later.'
|
|
});
|
|
app.use(limiter);
|
|
|
|
// CORS configuration
|
|
app.use(cors({
|
|
origin: process.env.ALLOWED_ORIGINS?.split(',') || ['http://localhost:3000'],
|
|
credentials: true
|
|
}));
|
|
|
|
// Body parsing middleware
|
|
app.use(express.json({ limit: '10mb' }));
|
|
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
|
|
|
|
// Static files
|
|
app.use(express.static(path.join(__dirname, 'public')));
|
|
|
|
// Health check endpoint
|
|
app.get('/health', (req, res) => {
|
|
res.status(200).json({
|
|
status: 'healthy',
|
|
timestamp: new Date().toISOString(),
|
|
uptime: process.uptime(),
|
|
environment: process.env.NODE_ENV || 'development',
|
|
version: process.env.npm_package_version || '1.0.0'
|
|
});
|
|
});
|
|
|
|
// API routes
|
|
app.use('/api', require('./routes/api'));
|
|
|
|
// Error handling middleware
|
|
app.use((err, req, res, next) => {
|
|
console.error(err.stack);
|
|
res.status(500).json({
|
|
error: 'Something went wrong!',
|
|
message: process.env.NODE_ENV === 'development' ? err.message : 'Internal server error'
|
|
});
|
|
});
|
|
|
|
// 404 handler
|
|
app.use('*', (req, res) => {
|
|
res.status(404).json({
|
|
error: 'Not Found',
|
|
message: 'The requested resource was not found'
|
|
});
|
|
});
|
|
|
|
// Graceful shutdown
|
|
process.on('SIGTERM', () => {
|
|
console.log('SIGTERM received, shutting down gracefully');
|
|
server.close(() => {
|
|
console.log('Process terminated');
|
|
});
|
|
});
|
|
|
|
const server = app.listen(PORT, () => {
|
|
console.log(`Server running on port ${PORT}`);
|
|
console.log(`Environment: ${process.env.NODE_ENV || 'development'}`);
|
|
});
|
|
|
|
module.exports = app;
|
|
```
|
|
|
|
**Дополнительные Node.js примеры для облачных технологий:**
|
|
|
|
**Node.js приложение для AWS Lambda:**
|
|
```typescript
|
|
// lambda/handler.ts
|
|
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
|
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
import { DynamoDBDocumentClient, PutCommand, GetCommand } from '@aws-sdk/lib-dynamodb';
|
|
|
|
const dynamoClient = new DynamoDBClient({ region: process.env.AWS_REGION });
|
|
const docClient = DynamoDBDocumentClient.from(dynamoClient);
|
|
|
|
interface User {
|
|
id: string;
|
|
name: string;
|
|
email: string;
|
|
createdAt: string;
|
|
}
|
|
|
|
export const handler = async (
|
|
event: APIGatewayProxyEvent,
|
|
context: Context
|
|
): Promise<APIGatewayProxyResult> => {
|
|
console.log('Event:', JSON.stringify(event, null, 2));
|
|
console.log('Context:', JSON.stringify(context, null, 2));
|
|
|
|
try {
|
|
const method = event.httpMethod;
|
|
const path = event.path;
|
|
|
|
switch (method) {
|
|
case 'POST':
|
|
if (path === '/users') {
|
|
return await createUser(event);
|
|
}
|
|
break;
|
|
case 'GET':
|
|
if (path.startsWith('/users/')) {
|
|
const userId = path.split('/')[2];
|
|
return await getUser(userId);
|
|
}
|
|
break;
|
|
default:
|
|
return {
|
|
statusCode: 405,
|
|
body: JSON.stringify({ error: 'Method not allowed' })
|
|
};
|
|
}
|
|
|
|
return {
|
|
statusCode: 404,
|
|
body: JSON.stringify({ error: 'Not found' })
|
|
};
|
|
} catch (error) {
|
|
console.error('Error:', error);
|
|
return {
|
|
statusCode: 500,
|
|
body: JSON.stringify({ error: 'Internal server error' })
|
|
};
|
|
}
|
|
};
|
|
|
|
async function createUser(event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> {
|
|
if (!event.body) {
|
|
return {
|
|
statusCode: 400,
|
|
body: JSON.stringify({ error: 'Request body is required' })
|
|
};
|
|
}
|
|
|
|
const userData = JSON.parse(event.body);
|
|
const user: User = {
|
|
id: generateId(),
|
|
name: userData.name,
|
|
email: userData.email,
|
|
createdAt: new Date().toISOString()
|
|
};
|
|
|
|
await docClient.send(new PutCommand({
|
|
TableName: process.env.USERS_TABLE,
|
|
Item: user
|
|
}));
|
|
|
|
return {
|
|
statusCode: 201,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Access-Control-Allow-Origin': '*'
|
|
},
|
|
body: JSON.stringify(user)
|
|
};
|
|
}
|
|
|
|
async function getUser(userId: string): Promise<APIGatewayProxyResult> {
|
|
const result = await docClient.send(new GetCommand({
|
|
TableName: process.env.USERS_TABLE,
|
|
Key: { id: userId }
|
|
}));
|
|
|
|
if (!result.Item) {
|
|
return {
|
|
statusCode: 404,
|
|
body: JSON.stringify({ error: 'User not found' })
|
|
};
|
|
}
|
|
|
|
return {
|
|
statusCode: 200,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Access-Control-Allow-Origin': '*'
|
|
},
|
|
body: JSON.stringify(result.Item)
|
|
};
|
|
}
|
|
|
|
function generateId(): string {
|
|
return Math.random().toString(36).substr(2, 9);
|
|
}
|
|
```
|
|
|
|
**Node.js приложение для Google Cloud Functions:**
|
|
```typescript
|
|
// functions/index.ts
|
|
import { Request, Response } from 'express';
|
|
import { Storage } from '@google-cloud/storage';
|
|
import { Firestore } from '@google-cloud/firestore';
|
|
|
|
const storage = new Storage();
|
|
const firestore = new Firestore();
|
|
|
|
interface FileUploadRequest extends Request {
|
|
file?: Express.Multer.File;
|
|
}
|
|
|
|
export const uploadFile = async (req: FileUploadRequest, res: Response): Promise<void> => {
|
|
try {
|
|
if (!req.file) {
|
|
res.status(400).json({ error: 'No file uploaded' });
|
|
return;
|
|
}
|
|
|
|
const bucketName = process.env.BUCKET_NAME;
|
|
const fileName = `${Date.now()}-${req.file.originalname}`;
|
|
|
|
// Upload to Google Cloud Storage
|
|
const bucket = storage.bucket(bucketName!);
|
|
const file = bucket.file(fileName);
|
|
|
|
await file.save(req.file.buffer, {
|
|
metadata: {
|
|
contentType: req.file.mimetype,
|
|
metadata: {
|
|
originalName: req.file.originalname,
|
|
uploadedBy: req.body.userId || 'anonymous'
|
|
}
|
|
}
|
|
});
|
|
|
|
// Save metadata to Firestore
|
|
const fileMetadata = {
|
|
fileName,
|
|
originalName: req.file.originalname,
|
|
size: req.file.size,
|
|
contentType: req.file.mimetype,
|
|
uploadedAt: new Date(),
|
|
uploadedBy: req.body.userId || 'anonymous',
|
|
downloadUrl: `https://storage.googleapis.com/${bucketName}/${fileName}`
|
|
};
|
|
|
|
await firestore.collection('files').add(fileMetadata);
|
|
|
|
res.status(200).json({
|
|
message: 'File uploaded successfully',
|
|
file: fileMetadata
|
|
});
|
|
} catch (error) {
|
|
console.error('Upload error:', error);
|
|
res.status(500).json({ error: 'Upload failed' });
|
|
}
|
|
};
|
|
|
|
export const getFiles = async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const userId = req.query.userId as string;
|
|
let query = firestore.collection('files').orderBy('uploadedAt', 'desc');
|
|
|
|
if (userId) {
|
|
query = query.where('uploadedBy', '==', userId);
|
|
}
|
|
|
|
const snapshot = await query.limit(50).get();
|
|
const files = snapshot.docs.map(doc => ({
|
|
id: doc.id,
|
|
...doc.data()
|
|
}));
|
|
|
|
res.status(200).json({ files });
|
|
} catch (error) {
|
|
console.error('Get files error:', error);
|
|
res.status(500).json({ error: 'Failed to retrieve files' });
|
|
}
|
|
};
|
|
```
|
|
|
|
**Node.js приложение для Azure Functions:**
|
|
```typescript
|
|
// azure-functions/index.ts
|
|
import { AzureFunction, Context, HttpRequest } from '@azure/functions';
|
|
import { CosmosClient } from '@azure/cosmos';
|
|
|
|
const cosmosClient = new CosmosClient({
|
|
endpoint: process.env.COSMOS_DB_ENDPOINT!,
|
|
key: process.env.COSMOS_DB_KEY!
|
|
});
|
|
|
|
const database = cosmosClient.database(process.env.COSMOS_DB_NAME!);
|
|
const container = database.container('orders');
|
|
|
|
interface Order {
|
|
id: string;
|
|
userId: string;
|
|
items: OrderItem[];
|
|
total: number;
|
|
status: string;
|
|
createdAt: string;
|
|
}
|
|
|
|
interface OrderItem {
|
|
productId: string;
|
|
quantity: number;
|
|
price: number;
|
|
}
|
|
|
|
export const httpTrigger: AzureFunction = async (
|
|
context: Context,
|
|
req: HttpRequest
|
|
): Promise<void> => {
|
|
context.log('HTTP trigger function processed a request.');
|
|
|
|
try {
|
|
const method = req.method;
|
|
const orderId = req.params.id;
|
|
|
|
switch (method) {
|
|
case 'POST':
|
|
await createOrder(context, req);
|
|
break;
|
|
case 'GET':
|
|
if (orderId) {
|
|
await getOrder(context, orderId);
|
|
} else {
|
|
await getOrders(context, req);
|
|
}
|
|
break;
|
|
case 'PUT':
|
|
await updateOrder(context, orderId, req);
|
|
break;
|
|
default:
|
|
context.res = {
|
|
status: 405,
|
|
body: { error: 'Method not allowed' }
|
|
};
|
|
}
|
|
} catch (error) {
|
|
context.log.error('Error:', error);
|
|
context.res = {
|
|
status: 500,
|
|
body: { error: 'Internal server error' }
|
|
};
|
|
}
|
|
};
|
|
|
|
async function createOrder(context: Context, req: HttpRequest): Promise<void> {
|
|
const orderData = req.body;
|
|
|
|
const order: Order = {
|
|
id: generateId(),
|
|
userId: orderData.userId,
|
|
items: orderData.items,
|
|
total: orderData.items.reduce((sum: number, item: OrderItem) => sum + (item.price * item.quantity), 0),
|
|
status: 'pending',
|
|
createdAt: new Date().toISOString()
|
|
};
|
|
|
|
await container.items.create(order);
|
|
|
|
context.res = {
|
|
status: 201,
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: order
|
|
};
|
|
}
|
|
|
|
async function getOrder(context: Context, orderId: string): Promise<void> {
|
|
const { resource: order } = await container.item(orderId, orderId).read();
|
|
|
|
if (!order) {
|
|
context.res = {
|
|
status: 404,
|
|
body: { error: 'Order not found' }
|
|
};
|
|
return;
|
|
}
|
|
|
|
context.res = {
|
|
status: 200,
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: order
|
|
};
|
|
}
|
|
|
|
async function getOrders(context: Context, req: HttpRequest): Promise<void> {
|
|
const userId = req.query.userId;
|
|
let query = 'SELECT * FROM c';
|
|
|
|
if (userId) {
|
|
query += ` WHERE c.userId = "${userId}"`;
|
|
}
|
|
|
|
query += ' ORDER BY c.createdAt DESC';
|
|
|
|
const { resources: orders } = await container.items.query(query).fetchAll();
|
|
|
|
context.res = {
|
|
status: 200,
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: { orders }
|
|
};
|
|
}
|
|
|
|
async function updateOrder(context: Context, orderId: string, req: HttpRequest): Promise<void> {
|
|
const { resource: existingOrder } = await container.item(orderId, orderId).read();
|
|
|
|
if (!existingOrder) {
|
|
context.res = {
|
|
status: 404,
|
|
body: { error: 'Order not found' }
|
|
};
|
|
return;
|
|
}
|
|
|
|
const updatedOrder = {
|
|
...existingOrder,
|
|
...req.body,
|
|
updatedAt: new Date().toISOString()
|
|
};
|
|
|
|
await container.item(orderId, orderId).replace(updatedOrder);
|
|
|
|
context.res = {
|
|
status: 200,
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: updatedOrder
|
|
};
|
|
}
|
|
|
|
function generateId(): string {
|
|
return Math.random().toString(36).substr(2, 9);
|
|
}
|
|
```
|
|
|
|
**Terraform для Node.js приложения на AWS:**
|
|
```hcl
|
|
# terraform/main.tf
|
|
terraform {
|
|
required_providers {
|
|
aws = {
|
|
source = "hashicorp/aws"
|
|
version = "~> 5.0"
|
|
}
|
|
}
|
|
}
|
|
|
|
provider "aws" {
|
|
region = var.aws_region
|
|
}
|
|
|
|
# VPC
|
|
resource "aws_vpc" "main" {
|
|
cidr_block = "10.0.0.0/16"
|
|
enable_dns_hostnames = true
|
|
enable_dns_support = true
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-vpc"
|
|
}
|
|
}
|
|
|
|
# Internet Gateway
|
|
resource "aws_internet_gateway" "main" {
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-igw"
|
|
}
|
|
}
|
|
|
|
# Public Subnets
|
|
resource "aws_subnet" "public" {
|
|
count = 2
|
|
vpc_id = aws_vpc.main.id
|
|
cidr_block = "10.0.${count.index + 1}.0/24"
|
|
availability_zone = data.aws_availability_zones.available.names[count.index]
|
|
|
|
map_public_ip_on_launch = true
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-public-subnet-${count.index + 1}"
|
|
}
|
|
}
|
|
|
|
# Private Subnets
|
|
resource "aws_subnet" "private" {
|
|
count = 2
|
|
vpc_id = aws_vpc.main.id
|
|
cidr_block = "10.0.${count.index + 10}.0/24"
|
|
availability_zone = data.aws_availability_zones.available.names[count.index]
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-private-subnet-${count.index + 1}"
|
|
}
|
|
}
|
|
|
|
# Application Load Balancer
|
|
resource "aws_lb" "main" {
|
|
name = "${var.project_name}-alb"
|
|
internal = false
|
|
load_balancer_type = "application"
|
|
security_groups = [aws_security_group.alb.id]
|
|
subnets = aws_subnet.public[*].id
|
|
|
|
enable_deletion_protection = false
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-alb"
|
|
}
|
|
}
|
|
|
|
# ALB Target Group
|
|
resource "aws_lb_target_group" "app" {
|
|
name = "${var.project_name}-tg"
|
|
port = 3000
|
|
protocol = "HTTP"
|
|
vpc_id = aws_vpc.main.id
|
|
|
|
health_check {
|
|
enabled = true
|
|
healthy_threshold = 2
|
|
interval = 30
|
|
matcher = "200"
|
|
path = "/health"
|
|
port = "traffic-port"
|
|
protocol = "HTTP"
|
|
timeout = 5
|
|
unhealthy_threshold = 2
|
|
}
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-tg"
|
|
}
|
|
}
|
|
|
|
# ECS Cluster
|
|
resource "aws_ecs_cluster" "main" {
|
|
name = "${var.project_name}-cluster"
|
|
|
|
setting {
|
|
name = "containerInsights"
|
|
value = "enabled"
|
|
}
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-cluster"
|
|
}
|
|
}
|
|
|
|
# ECS Task Definition
|
|
resource "aws_ecs_task_definition" "app" {
|
|
family = "${var.project_name}-app"
|
|
network_mode = "awsvpc"
|
|
requires_compatibilities = ["FARGATE"]
|
|
cpu = 256
|
|
memory = 512
|
|
execution_role_arn = aws_iam_role.ecs_execution_role.arn
|
|
task_role_arn = aws_iam_role.ecs_task_role.arn
|
|
|
|
container_definitions = jsonencode([
|
|
{
|
|
name = "${var.project_name}-app"
|
|
image = "${var.aws_account_id}.dkr.ecr.${var.aws_region}.amazonaws.com/${var.project_name}:latest"
|
|
|
|
portMappings = [
|
|
{
|
|
containerPort = 3000
|
|
protocol = "tcp"
|
|
}
|
|
]
|
|
|
|
environment = [
|
|
{
|
|
name = "NODE_ENV"
|
|
value = "production"
|
|
},
|
|
{
|
|
name = "PORT"
|
|
value = "3000"
|
|
}
|
|
]
|
|
|
|
secrets = [
|
|
{
|
|
name = "DATABASE_URL"
|
|
valueFrom = aws_secretsmanager_secret.database_url.arn
|
|
}
|
|
]
|
|
|
|
logConfiguration = {
|
|
logDriver = "awslogs"
|
|
options = {
|
|
awslogs-group = aws_cloudwatch_log_group.app.name
|
|
awslogs-region = var.aws_region
|
|
awslogs-stream-prefix = "ecs"
|
|
}
|
|
}
|
|
}
|
|
])
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-task-definition"
|
|
}
|
|
}
|
|
|
|
# ECS Service
|
|
resource "aws_ecs_service" "app" {
|
|
name = "${var.project_name}-service"
|
|
cluster = aws_ecs_cluster.main.id
|
|
task_definition = aws_ecs_task_definition.app.arn
|
|
desired_count = 2
|
|
launch_type = "FARGATE"
|
|
|
|
network_configuration {
|
|
security_groups = [aws_security_group.ecs_tasks.id]
|
|
subnets = aws_subnet.private[*].id
|
|
assign_public_ip = false
|
|
}
|
|
|
|
load_balancer {
|
|
target_group_arn = aws_lb_target_group.app.arn
|
|
container_name = "${var.project_name}-app"
|
|
container_port = 3000
|
|
}
|
|
|
|
depends_on = [aws_lb_listener.app]
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-service"
|
|
}
|
|
}
|
|
|
|
# RDS PostgreSQL
|
|
resource "aws_db_instance" "main" {
|
|
identifier = "${var.project_name}-db"
|
|
|
|
engine = "postgres"
|
|
engine_version = "15.4"
|
|
instance_class = "db.t3.micro"
|
|
|
|
allocated_storage = 20
|
|
max_allocated_storage = 100
|
|
storage_type = "gp2"
|
|
storage_encrypted = true
|
|
|
|
db_name = var.database_name
|
|
username = var.database_username
|
|
password = var.database_password
|
|
|
|
vpc_security_group_ids = [aws_security_group.rds.id]
|
|
db_subnet_group_name = aws_db_subnet_group.main.name
|
|
|
|
backup_retention_period = 7
|
|
backup_window = "03:00-04:00"
|
|
maintenance_window = "sun:04:00-sun:05:00"
|
|
|
|
skip_final_snapshot = true
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-db"
|
|
}
|
|
}
|
|
|
|
# CloudWatch Log Group
|
|
resource "aws_cloudwatch_log_group" "app" {
|
|
name = "/ecs/${var.project_name}"
|
|
retention_in_days = 30
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-log-group"
|
|
}
|
|
}
|
|
|
|
# Secrets Manager
|
|
resource "aws_secretsmanager_secret" "database_url" {
|
|
name = "${var.project_name}-database-url"
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-database-url"
|
|
}
|
|
}
|
|
|
|
resource "aws_secretsmanager_secret_version" "database_url" {
|
|
secret_id = aws_secretsmanager_secret.database_url.id
|
|
secret_string = "postgresql://${var.database_username}:${var.database_password}@${aws_db_instance.main.endpoint}/${var.database_name}"
|
|
}
|
|
```
|
|
|
|
```yaml
|
|
# docker-compose.yml for local development
|
|
version: '3.8'
|
|
|
|
services:
|
|
app:
|
|
build: .
|
|
ports:
|
|
- "3000:3000"
|
|
environment:
|
|
- NODE_ENV=development
|
|
- PORT=3000
|
|
- ALLOWED_ORIGINS=http://localhost:3000,http://localhost:3001
|
|
volumes:
|
|
- .:/app
|
|
- /app/node_modules
|
|
depends_on:
|
|
- redis
|
|
- postgres
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
ports:
|
|
- "6379:6379"
|
|
volumes:
|
|
- redis_data:/data
|
|
|
|
postgres:
|
|
image: postgres:15-alpine
|
|
environment:
|
|
- POSTGRES_DB=myapp
|
|
- POSTGRES_USER=myapp
|
|
- POSTGRES_PASSWORD=myapp
|
|
ports:
|
|
- "5432:5432"
|
|
volumes:
|
|
- postgres_data:/var/lib/postgresql/data
|
|
|
|
volumes:
|
|
redis_data:
|
|
postgres_data:
|
|
```
|
|
|
|
```dockerfile
|
|
# Dockerfile
|
|
FROM node:18-alpine AS builder
|
|
|
|
WORKDIR /app
|
|
|
|
# Copy package files
|
|
COPY package*.json ./
|
|
|
|
# Install dependencies
|
|
RUN npm ci --only=production && npm cache clean --force
|
|
|
|
# Copy source code
|
|
COPY . .
|
|
|
|
# Build application
|
|
RUN npm run build
|
|
|
|
# Production stage
|
|
FROM node:18-alpine AS production
|
|
|
|
WORKDIR /app
|
|
|
|
# Create non-root user
|
|
RUN addgroup -g 1001 -S nodejs
|
|
RUN adduser -S nextjs -u 1001
|
|
|
|
# Copy built application
|
|
COPY --from=builder --chown=nextjs:nodejs /app .
|
|
|
|
# Switch to non-root user
|
|
USER nextjs
|
|
|
|
# Expose port
|
|
EXPOSE 3000
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
CMD node healthcheck.js
|
|
|
|
# Start application
|
|
CMD ["npm", "start"]
|
|
```
|
|
|
|
```javascript
|
|
// healthcheck.js
|
|
const http = require('http');
|
|
|
|
const options = {
|
|
hostname: 'localhost',
|
|
port: process.env.PORT || 3000,
|
|
path: '/health',
|
|
method: 'GET',
|
|
timeout: 2000
|
|
};
|
|
|
|
const req = http.request(options, (res) => {
|
|
if (res.statusCode === 200) {
|
|
process.exit(0);
|
|
} else {
|
|
process.exit(1);
|
|
}
|
|
});
|
|
|
|
req.on('error', () => {
|
|
process.exit(1);
|
|
});
|
|
|
|
req.on('timeout', () => {
|
|
req.destroy();
|
|
process.exit(1);
|
|
});
|
|
|
|
req.end();
|
|
```
|
|
|
|
#### 3. SaaS (Software as a Service)
|
|
**Определение:** Предоставление готового программного обеспечения.
|
|
|
|
**Примеры:**
|
|
- Salesforce
|
|
- Microsoft Office 365
|
|
- Google Workspace
|
|
|
|
**Преимущества:**
|
|
- Готовое решение
|
|
- Нет необходимости в разработке
|
|
- Автоматические обновления
|
|
|
|
### Модели развертывания
|
|
|
|
#### 1. Public Cloud
|
|
**Определение:** Облачные ресурсы, доступные публично.
|
|
|
|
**Характеристики:**
|
|
- Общие ресурсы
|
|
- Оплата по использованию
|
|
- Высокая масштабируемость
|
|
|
|
#### 2. Private Cloud
|
|
**Определение:** Облачные ресурсы для одной организации.
|
|
|
|
**Характеристики:**
|
|
- Изолированные ресурсы
|
|
- Высокий уровень безопасности
|
|
- Полный контроль
|
|
|
|
#### 3. Hybrid Cloud
|
|
**Определение:** Комбинация публичного и приватного облака.
|
|
|
|
**Характеристики:**
|
|
- Гибкость в выборе
|
|
- Оптимизация затрат
|
|
- Сложность управления
|
|
|
|
#### 4. Multi-Cloud
|
|
**Определение:** Использование нескольких облачных провайдеров.
|
|
|
|
**Характеристики:**
|
|
- Избежание vendor lock-in
|
|
- Оптимизация по сервисам
|
|
- Высокая сложность
|
|
|
|
---
|
|
|
|
## AWS (Amazon Web Services)
|
|
|
|
### Основные сервисы AWS
|
|
|
|
#### 1. Compute Services
|
|
|
|
**EC2 (Elastic Compute Cloud)**
|
|
- Виртуальные серверы в облаке
|
|
- Различные типы инстансов (t3, m5, c5, r5, etc.)
|
|
- Автомасштабирование с Auto Scaling Groups
|
|
- Spot Instances для экономии
|
|
|
|
```yaml
|
|
# EC2 Instance Configuration
|
|
Resources:
|
|
WebServerInstance:
|
|
Type: AWS::EC2::Instance
|
|
Properties:
|
|
ImageId: ami-0c02fb55956c7d316 # Amazon Linux 2
|
|
InstanceType: t3.micro
|
|
KeyName: my-key-pair
|
|
SecurityGroupIds:
|
|
- !Ref WebServerSecurityGroup
|
|
UserData:
|
|
Fn::Base64: !Sub |
|
|
#!/bin/bash
|
|
yum update -y
|
|
yum install -y docker
|
|
systemctl start docker
|
|
systemctl enable docker
|
|
usermod -a -G docker ec2-user
|
|
docker run -d -p 80:80 nginx
|
|
Tags:
|
|
- Key: Name
|
|
Value: WebServer
|
|
- Key: Environment
|
|
Value: Production
|
|
```
|
|
|
|
**Lambda (Serverless Computing)**
|
|
- Выполнение кода без управления серверами
|
|
- Оплата только за время выполнения
|
|
- Автоматическое масштабирование
|
|
- Интеграция с другими AWS сервисами
|
|
|
|
```python
|
|
# Lambda Function Example
|
|
import json
|
|
import boto3
|
|
|
|
def lambda_handler(event, context):
|
|
"""
|
|
AWS Lambda function для обработки заказов
|
|
"""
|
|
# Получение данных из события
|
|
order_data = event.get('order', {})
|
|
|
|
# Валидация данных
|
|
if not validate_order(order_data):
|
|
return {
|
|
'statusCode': 400,
|
|
'body': json.dumps({'error': 'Invalid order data'})
|
|
}
|
|
|
|
# Обработка заказа
|
|
order_id = process_order(order_data)
|
|
|
|
# Отправка уведомления через SNS
|
|
sns = boto3.client('sns')
|
|
sns.publish(
|
|
TopicArn='arn:aws:sns:us-east-1:123456789012:order-notifications',
|
|
Message=f'Order {order_id} has been processed',
|
|
Subject='Order Processed'
|
|
)
|
|
|
|
return {
|
|
'statusCode': 200,
|
|
'body': json.dumps({
|
|
'orderId': order_id,
|
|
'status': 'processed'
|
|
})
|
|
}
|
|
|
|
def validate_order(order_data):
|
|
"""Валидация данных заказа"""
|
|
required_fields = ['customerId', 'items', 'total']
|
|
return all(field in order_data for field in required_fields)
|
|
|
|
def process_order(order_data):
|
|
"""Обработка заказа"""
|
|
# Логика обработки заказа
|
|
return f"ORD-{order_data.get('customerId')}-{int(time.time())}"
|
|
```
|
|
|
|
**Elastic Beanstalk**
|
|
- Платформа для развертывания приложений
|
|
- Автоматическое управление инфраструктурой
|
|
- Поддержка различных языков и фреймворков
|
|
|
|
```yaml
|
|
# Elastic Beanstalk Configuration
|
|
Resources:
|
|
WebAppEnvironment:
|
|
Type: AWS::ElasticBeanstalk::Environment
|
|
Properties:
|
|
ApplicationName: !Ref WebApplication
|
|
EnvironmentName: !Sub "${AWS::StackName}-env"
|
|
SolutionStackName: "64bit Amazon Linux 2 v3.4.0 running Docker"
|
|
VersionLabel: !Ref ApplicationVersion
|
|
OptionSettings:
|
|
- Namespace: aws:autoscaling:launchconfiguration
|
|
OptionName: InstanceType
|
|
Value: t3.micro
|
|
- Namespace: aws:autoscaling:asg
|
|
OptionName: MinSize
|
|
Value: "1"
|
|
- Namespace: aws:autoscaling:asg
|
|
OptionName: MaxSize
|
|
Value: "3"
|
|
```
|
|
|
|
#### 2. Storage Services
|
|
```yaml
|
|
# S3 Bucket Configuration
|
|
Resources:
|
|
MyBucket:
|
|
Type: AWS::S3::Bucket
|
|
Properties:
|
|
BucketName: my-app-bucket
|
|
VersioningConfiguration:
|
|
Status: Enabled
|
|
PublicAccessBlockConfiguration:
|
|
BlockPublicAcls: true
|
|
BlockPublicPolicy: true
|
|
IgnorePublicAcls: true
|
|
RestrictPublicBuckets: true
|
|
```
|
|
|
|
#### 3. Database Services
|
|
```yaml
|
|
# RDS Configuration
|
|
Resources:
|
|
MyDatabase:
|
|
Type: AWS::RDS::DBInstance
|
|
Properties:
|
|
DBInstanceIdentifier: my-database
|
|
DBInstanceClass: db.t3.micro
|
|
Engine: postgres
|
|
EngineVersion: "13.7"
|
|
MasterUsername: admin
|
|
MasterUserPassword: !Ref DatabasePassword
|
|
AllocatedStorage: 20
|
|
StorageType: gp2
|
|
VPCSecurityGroups:
|
|
- !Ref DatabaseSecurityGroup
|
|
```
|
|
|
|
#### 4. Networking Services
|
|
```yaml
|
|
# VPC Configuration
|
|
Resources:
|
|
MyVPC:
|
|
Type: AWS::EC2::VPC
|
|
Properties:
|
|
CidrBlock: 10.0.0.0/16
|
|
EnableDnsHostnames: true
|
|
EnableDnsSupport: true
|
|
Tags:
|
|
- Key: Name
|
|
Value: MyVPC
|
|
|
|
PublicSubnet:
|
|
Type: AWS::EC2::Subnet
|
|
Properties:
|
|
VpcId: !Ref MyVPC
|
|
CidrBlock: 10.0.1.0/24
|
|
AvailabilityZone: !Select [0, !GetAZs '']
|
|
MapPublicIpOnLaunch: true
|
|
```
|
|
|
|
### Лучшие практики AWS
|
|
|
|
#### 1. Security
|
|
```yaml
|
|
# IAM Role Configuration
|
|
Resources:
|
|
EC2Role:
|
|
Type: AWS::IAM::Role
|
|
Properties:
|
|
AssumeRolePolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Principal:
|
|
Service: ec2.amazonaws.com
|
|
Action: sts:AssumeRole
|
|
Policies:
|
|
- PolicyName: S3Access
|
|
PolicyDocument:
|
|
Version: '2012-10-17'
|
|
Statement:
|
|
- Effect: Allow
|
|
Action:
|
|
- s3:GetObject
|
|
- s3:PutObject
|
|
Resource: !Sub '${MyBucket}/*'
|
|
```
|
|
|
|
#### 2. Monitoring
|
|
```yaml
|
|
# CloudWatch Alarms
|
|
Resources:
|
|
HighCPUAlarm:
|
|
Type: AWS::CloudWatch::Alarm
|
|
Properties:
|
|
AlarmName: HighCPUUtilization
|
|
AlarmDescription: Alarm when CPU exceeds 80%
|
|
MetricName: CPUUtilization
|
|
Namespace: AWS/EC2
|
|
Statistic: Average
|
|
Period: 300
|
|
EvaluationPeriods: 2
|
|
Threshold: 80
|
|
ComparisonOperator: GreaterThanThreshold
|
|
Dimensions:
|
|
- Name: InstanceId
|
|
Value: !Ref MyInstance
|
|
```
|
|
|
|
---
|
|
|
|
## Azure (Microsoft Azure)
|
|
|
|
### Основные сервисы Azure
|
|
|
|
#### 1. Compute Services
|
|
```yaml
|
|
# Azure VM Configuration
|
|
apiVersion: 2021-03-01
|
|
type: Microsoft.Compute/virtualMachines
|
|
properties:
|
|
hardwareProfile:
|
|
vmSize: Standard_B1s
|
|
storageProfile:
|
|
imageReference:
|
|
publisher: Canonical
|
|
offer: UbuntuServer
|
|
sku: 18.04-LTS
|
|
version: latest
|
|
osDisk:
|
|
createOption: FromImage
|
|
managedDisk:
|
|
storageAccountType: Standard_LRS
|
|
osProfile:
|
|
computerName: my-vm
|
|
adminUsername: azureuser
|
|
adminPassword: !Ref AdminPassword
|
|
networkProfile:
|
|
networkInterfaces:
|
|
- id: !Ref NetworkInterface
|
|
```
|
|
|
|
#### 2. Storage Services
|
|
```yaml
|
|
# Azure Storage Account
|
|
apiVersion: 2021-02-01
|
|
type: Microsoft.Storage/storageAccounts
|
|
properties:
|
|
sku:
|
|
name: Standard_LRS
|
|
kind: StorageV2
|
|
accessTier: Hot
|
|
supportsHttpsTrafficOnly: true
|
|
minimumTlsVersion: TLS1_2
|
|
allowBlobPublicAccess: false
|
|
```
|
|
|
|
#### 3. Database Services
|
|
```yaml
|
|
# Azure SQL Database
|
|
apiVersion: 2021-02-01
|
|
type: Microsoft.Sql/servers
|
|
properties:
|
|
administratorLogin: admin
|
|
administratorLoginPassword: !Ref AdminPassword
|
|
version: 12.0
|
|
publicNetworkAccess: Disabled
|
|
minimalTlsVersion: 1.2
|
|
```
|
|
|
|
#### 4. Networking Services
|
|
```yaml
|
|
# Azure Virtual Network
|
|
apiVersion: 2021-02-01
|
|
type: Microsoft.Network/virtualNetworks
|
|
properties:
|
|
addressSpace:
|
|
addressPrefixes:
|
|
- 10.0.0.0/16
|
|
subnets:
|
|
- name: default
|
|
properties:
|
|
addressPrefix: 10.0.1.0/24
|
|
```
|
|
|
|
### Лучшие практики Azure
|
|
|
|
#### 1. Resource Groups
|
|
```yaml
|
|
# Resource Group Organization
|
|
Resources:
|
|
ProductionRG:
|
|
Type: Microsoft.Resources/resourceGroups
|
|
Properties:
|
|
location: East US
|
|
tags:
|
|
Environment: Production
|
|
CostCenter: IT
|
|
Owner: Development Team
|
|
|
|
DevelopmentRG:
|
|
Type: Microsoft.Resources/resourceGroups
|
|
Properties:
|
|
location: East US
|
|
tags:
|
|
Environment: Development
|
|
CostCenter: IT
|
|
Owner: Development Team
|
|
```
|
|
|
|
#### 2. Monitoring
|
|
```yaml
|
|
# Azure Monitor Alerts
|
|
Resources:
|
|
HighCPUAlert:
|
|
Type: Microsoft.Insights/metricAlerts
|
|
Properties:
|
|
description: Alert when CPU exceeds 80%
|
|
severity: 2
|
|
enabled: true
|
|
scopes:
|
|
- !Ref VirtualMachine
|
|
criteria:
|
|
metricName: Percentage CPU
|
|
operator: GreaterThan
|
|
threshold: 80
|
|
timeAggregation: Average
|
|
```
|
|
|
|
---
|
|
|
|
## GCP (Google Cloud Platform)
|
|
|
|
### Основные сервисы GCP
|
|
|
|
#### 1. Compute Services
|
|
```yaml
|
|
# GCP VM Instance
|
|
resources:
|
|
- name: my-vm
|
|
type: compute.v1.instance
|
|
properties:
|
|
zone: us-central1-a
|
|
machineType: zones/us-central1-a/machineTypes/e2-micro
|
|
disks:
|
|
- deviceName: boot
|
|
type: PERSISTENT
|
|
boot: true
|
|
autoDelete: true
|
|
initializeParams:
|
|
sourceImage: projects/ubuntu-os-cloud/global/images/family/ubuntu-2004-lts
|
|
networkInterfaces:
|
|
- network: global/networks/default
|
|
accessConfigs:
|
|
- name: External NAT
|
|
type: ONE_TO_ONE_NAT
|
|
```
|
|
|
|
#### 2. Storage Services
|
|
```yaml
|
|
# GCP Cloud Storage Bucket
|
|
resources:
|
|
- name: my-bucket
|
|
type: storage.v1.bucket
|
|
properties:
|
|
location: US
|
|
storageClass: STANDARD
|
|
versioning:
|
|
enabled: true
|
|
lifecycle:
|
|
rule:
|
|
- action:
|
|
type: Delete
|
|
condition:
|
|
age: 365
|
|
```
|
|
|
|
#### 3. Database Services
|
|
```yaml
|
|
# GCP Cloud SQL
|
|
resources:
|
|
- name: my-database
|
|
type: sqladmin.v1beta4.instance
|
|
properties:
|
|
region: us-central1
|
|
settings:
|
|
tier: db-f1-micro
|
|
dataDiskType: PD_SSD
|
|
dataDiskSizeGb: 10
|
|
backupConfiguration:
|
|
enabled: true
|
|
startTime: 03:00
|
|
ipConfiguration:
|
|
ipv4Enabled: true
|
|
authorizedNetworks:
|
|
- value: 0.0.0.0/0
|
|
```
|
|
|
|
#### 4. Networking Services
|
|
```yaml
|
|
# GCP VPC Network
|
|
resources:
|
|
- name: my-vpc
|
|
type: compute.v1.network
|
|
properties:
|
|
autoCreateSubnetworks: false
|
|
routingConfig:
|
|
routingMode: REGIONAL
|
|
|
|
- name: my-subnet
|
|
type: compute.v1.subnetwork
|
|
properties:
|
|
network: $(ref.my-vpc.selfLink)
|
|
ipCidrRange: 10.0.0.0/24
|
|
region: us-central1
|
|
```
|
|
|
|
### Лучшие практики GCP
|
|
|
|
#### 1. IAM
|
|
```yaml
|
|
# GCP IAM Policy
|
|
resources:
|
|
- name: my-iam-policy
|
|
type: gcp-types/cloudresourcemanager-v1:projects.iamPolicyBinding
|
|
properties:
|
|
resource: projects/my-project
|
|
role: roles/storage.objectViewer
|
|
members:
|
|
- user:user@example.com
|
|
- serviceAccount:service@project.iam.gserviceaccount.com
|
|
```
|
|
|
|
#### 2. Monitoring
|
|
```yaml
|
|
# GCP Monitoring Alert
|
|
resources:
|
|
- name: high-cpu-alert
|
|
type: monitoring.v3.alertPolicy
|
|
properties:
|
|
displayName: High CPU Usage
|
|
conditions:
|
|
- displayName: CPU usage is high
|
|
conditionThreshold:
|
|
filter: 'resource.type="gce_instance"'
|
|
comparison: COMPARISON_GREATER_THAN
|
|
thresholdValue: 0.8
|
|
duration: 300s
|
|
alertStrategy:
|
|
autoClose: 1800s
|
|
```
|
|
|
|
---
|
|
|
|
## Cloud-Native архитектура
|
|
|
|
### Принципы Cloud-Native
|
|
|
|
#### 1. 12-Factor App
|
|
```markdown
|
|
# 12-Factor App Principles
|
|
|
|
1. **Codebase** — один код, множество развертываний
|
|
2. **Dependencies** — явно объявлять и изолировать зависимости
|
|
3. **Config** — хранить конфигурацию в переменных окружения
|
|
4. **Backing Services** — рассматривать внешние сервисы как подключенные ресурсы
|
|
5. **Build, Release, Run** — строго разделять этапы сборки и выполнения
|
|
6. **Processes** — выполнять приложение как один или несколько stateless процессов
|
|
7. **Port Binding** — экспортировать сервисы через привязку к порту
|
|
8. **Concurrency** — масштабировать через модель процессов
|
|
9. **Disposability** — максимизировать надежность через быстрый запуск и graceful shutdown
|
|
10. **Dev/Prod Parity** — держать разработку, staging и production максимально похожими
|
|
11. **Logs** — рассматривать логи как потоки событий
|
|
12. **Admin Processes** — выполнять административные задачи как одноразовые процессы
|
|
```
|
|
|
|
#### 2. Microservices Architecture
|
|
```yaml
|
|
# Kubernetes Microservices Deployment
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: user-service
|
|
spec:
|
|
replicas: 3
|
|
selector:
|
|
matchLabels:
|
|
app: user-service
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: user-service
|
|
spec:
|
|
containers:
|
|
- name: user-service
|
|
image: user-service:latest
|
|
ports:
|
|
- containerPort: 8080
|
|
env:
|
|
- name: DATABASE_URL
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: database-secret
|
|
key: url
|
|
- name: REDIS_URL
|
|
valueFrom:
|
|
configMapKeyRef:
|
|
name: redis-config
|
|
key: url
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8080
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 10
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /ready
|
|
port: 8080
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 5
|
|
```
|
|
|
|
#### 3. Container Orchestration
|
|
```yaml
|
|
# Kubernetes Service
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: user-service
|
|
spec:
|
|
selector:
|
|
app: user-service
|
|
ports:
|
|
- protocol: TCP
|
|
port: 80
|
|
targetPort: 8080
|
|
type: ClusterIP
|
|
|
|
---
|
|
# Kubernetes Ingress
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: user-service-ingress
|
|
annotations:
|
|
nginx.ingress.kubernetes.io/rewrite-target: /
|
|
spec:
|
|
rules:
|
|
- host: api.example.com
|
|
http:
|
|
paths:
|
|
- path: /users
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: user-service
|
|
port:
|
|
number: 80
|
|
```
|
|
|
|
### Serverless архитектура
|
|
|
|
#### 1. AWS Lambda
|
|
```python
|
|
import json
|
|
import boto3
|
|
|
|
def lambda_handler(event, context):
|
|
# Обработка события
|
|
user_id = event['pathParameters']['id']
|
|
|
|
# Получение данных пользователя
|
|
dynamodb = boto3.resource('dynamodb')
|
|
table = dynamodb.Table('Users')
|
|
|
|
try:
|
|
response = table.get_item(Key={'id': user_id})
|
|
user = response['Item']
|
|
|
|
return {
|
|
'statusCode': 200,
|
|
'body': json.dumps(user)
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
'statusCode': 500,
|
|
'body': json.dumps({'error': str(e)})
|
|
}
|
|
```
|
|
|
|
#### 2. Azure Functions
|
|
```csharp
|
|
[FunctionName("GetUser")]
|
|
public static async Task<IActionResult> Run(
|
|
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "users/{id}")] HttpRequest req,
|
|
string id,
|
|
ILogger log)
|
|
{
|
|
log.LogInformation($"Getting user with ID: {id}");
|
|
|
|
try
|
|
{
|
|
var user = await userService.GetUserAsync(id);
|
|
|
|
if (user == null)
|
|
{
|
|
return new NotFoundResult();
|
|
}
|
|
|
|
return new OkObjectResult(user);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.LogError(ex, "Error getting user");
|
|
return new StatusCodeResult(500);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 3. Google Cloud Functions
|
|
```javascript
|
|
const { Firestore } = require('@google-cloud/firestore');
|
|
|
|
exports.getUser = async (req, res) => {
|
|
const userId = req.params.id;
|
|
|
|
try {
|
|
const firestore = new Firestore();
|
|
const doc = await firestore.collection('users').doc(userId).get();
|
|
|
|
if (!doc.exists) {
|
|
return res.status(404).json({ error: 'User not found' });
|
|
}
|
|
|
|
res.json(doc.data());
|
|
} catch (error) {
|
|
console.error('Error getting user:', error);
|
|
res.status(500).json({ error: 'Internal server error' });
|
|
}
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## Мультиоблачные и гибридные стратегии
|
|
|
|
### Мультиоблачная архитектура
|
|
|
|
**Мультиоблачная архитектура** — использование нескольких облачных провайдеров для различных сервисов или в качестве резервных копий.
|
|
|
|
#### Преимущества мультиоблачной стратегии
|
|
|
|
1. **Избежание vendor lock-in**
|
|
2. **Лучшие цены** за счет конкуренции
|
|
3. **Географическое распределение**
|
|
4. **Отказоустойчивость**
|
|
5. **Специализированные сервисы**
|
|
|
|
#### Архитектурные паттерны
|
|
|
|
```yaml
|
|
# Multi-Cloud Architecture
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: multi-cloud-config
|
|
data:
|
|
strategy: |
|
|
primary_cloud: "AWS"
|
|
secondary_cloud: "Azure"
|
|
disaster_recovery: "GCP"
|
|
|
|
services:
|
|
- name: "user-service"
|
|
cloud: "AWS"
|
|
region: "us-east-1"
|
|
backup_cloud: "Azure"
|
|
|
|
- name: "payment-service"
|
|
cloud: "Azure"
|
|
region: "eastus"
|
|
backup_cloud: "AWS"
|
|
|
|
- name: "analytics-service"
|
|
cloud: "GCP"
|
|
region: "us-central1"
|
|
backup_cloud: "AWS"
|
|
```
|
|
|
|
#### Реализация мультиоблачной стратегии
|
|
|
|
```python
|
|
# Multi-Cloud Service Manager
|
|
class MultiCloudManager:
|
|
def __init__(self):
|
|
self.aws_client = boto3.client('ec2')
|
|
self.azure_client = get_azure_client()
|
|
self.gcp_client = get_gcp_client()
|
|
|
|
self.cloud_configs = {
|
|
'aws': {
|
|
'client': self.aws_client,
|
|
'regions': ['us-east-1', 'us-west-2', 'eu-west-1'],
|
|
'services': ['ec2', 's3', 'rds', 'lambda']
|
|
},
|
|
'azure': {
|
|
'client': self.azure_client,
|
|
'regions': ['eastus', 'westus2', 'westeurope'],
|
|
'services': ['vm', 'storage', 'sql', 'functions']
|
|
},
|
|
'gcp': {
|
|
'client': self.gcp_client,
|
|
'regions': ['us-central1', 'us-east1', 'europe-west1'],
|
|
'services': ['compute', 'storage', 'sql', 'cloud-functions']
|
|
}
|
|
}
|
|
|
|
def deploy_service(self, service_name, service_config):
|
|
"""Развертывание сервиса в мультиоблачной среде"""
|
|
primary_cloud = service_config.get('primary_cloud', 'aws')
|
|
backup_cloud = service_config.get('backup_cloud')
|
|
|
|
# Развертывание в основном облаке
|
|
primary_result = self._deploy_to_cloud(
|
|
primary_cloud,
|
|
service_name,
|
|
service_config
|
|
)
|
|
|
|
# Развертывание в резервном облаке
|
|
if backup_cloud:
|
|
backup_result = self._deploy_to_cloud(
|
|
backup_cloud,
|
|
service_name,
|
|
service_config
|
|
)
|
|
|
|
return {
|
|
'primary': primary_result,
|
|
'backup': backup_result,
|
|
'status': 'deployed'
|
|
}
|
|
|
|
return primary_result
|
|
|
|
def _deploy_to_cloud(self, cloud_provider, service_name, config):
|
|
"""Развертывание сервиса в конкретном облаке"""
|
|
cloud_config = self.cloud_configs[cloud_provider]
|
|
|
|
if cloud_provider == 'aws':
|
|
return self._deploy_aws_service(service_name, config)
|
|
elif cloud_provider == 'azure':
|
|
return self._deploy_azure_service(service_name, config)
|
|
elif cloud_provider == 'gcp':
|
|
return self._deploy_gcp_service(service_name, config)
|
|
|
|
def _deploy_aws_service(self, service_name, config):
|
|
"""Развертывание в AWS"""
|
|
# Создание EC2 инстанса
|
|
response = self.aws_client.run_instances(
|
|
ImageId=config.get('ami_id'),
|
|
MinCount=1,
|
|
MaxCount=1,
|
|
InstanceType=config.get('instance_type', 't3.micro'),
|
|
SecurityGroupIds=config.get('security_groups', []),
|
|
TagSpecifications=[{
|
|
'ResourceType': 'instance',
|
|
'Tags': [
|
|
{'Key': 'Name', 'Value': service_name},
|
|
{'Key': 'Environment', 'Value': config.get('environment', 'production')}
|
|
]
|
|
}]
|
|
)
|
|
|
|
return {
|
|
'cloud': 'aws',
|
|
'instance_id': response['Instances'][0]['InstanceId'],
|
|
'status': 'running'
|
|
}
|
|
```
|
|
|
|
### Гибридная облачная архитектура
|
|
|
|
**Гибридная облачная архитектура** — комбинация частного облака (on-premises) и публичного облака.
|
|
|
|
#### Архитектурные компоненты
|
|
|
|
```mermaid
|
|
graph TB
|
|
subgraph "On-Premises Data Center"
|
|
A[Private Cloud] --> B[Local Services]
|
|
B --> C[Database]
|
|
B --> D[File Storage]
|
|
end
|
|
|
|
subgraph "Public Cloud"
|
|
E[Cloud Services] --> F[Web Applications]
|
|
E --> G[Analytics]
|
|
E --> H[Backup]
|
|
end
|
|
|
|
subgraph "Hybrid Connectivity"
|
|
I[VPN/ExpressRoute] --> J[Load Balancer]
|
|
J --> K[API Gateway]
|
|
end
|
|
|
|
A <--> I
|
|
E <--> I
|
|
K --> A
|
|
K --> E
|
|
```
|
|
|
|
#### Гибридная интеграция
|
|
|
|
```java
|
|
// Hybrid Cloud Integration Service
|
|
@Service
|
|
public class HybridCloudService {
|
|
|
|
@Autowired
|
|
private OnPremisesService onPremisesService;
|
|
|
|
@Autowired
|
|
private CloudService cloudService;
|
|
|
|
@Value("${hybrid.routing.strategy}")
|
|
private String routingStrategy;
|
|
|
|
public ResponseEntity<String> processRequest(String serviceType, Object request) {
|
|
// Определение стратегии маршрутизации
|
|
CloudProvider provider = determineProvider(serviceType, request);
|
|
|
|
switch (provider) {
|
|
case ON_PREMISES:
|
|
return onPremisesService.process(request);
|
|
case CLOUD:
|
|
return cloudService.process(request);
|
|
case HYBRID:
|
|
return processHybrid(request);
|
|
default:
|
|
throw new IllegalArgumentException("Unknown provider: " + provider);
|
|
}
|
|
}
|
|
|
|
private CloudProvider determineProvider(String serviceType, Object request) {
|
|
// Логика определения провайдера
|
|
if (routingStrategy.equals("data-locality")) {
|
|
return determineByDataLocality(request);
|
|
} else if (routingStrategy.equals("performance")) {
|
|
return determineByPerformance(serviceType);
|
|
} else if (routingStrategy.equals("cost")) {
|
|
return determineByCost(serviceType);
|
|
}
|
|
|
|
return CloudProvider.CLOUD; // По умолчанию
|
|
}
|
|
|
|
private ResponseEntity<String> processHybrid(Object request) {
|
|
// Обработка в гибридном режиме
|
|
// Часть данных обрабатывается локально, часть в облаке
|
|
|
|
// 1. Обработка чувствительных данных локально
|
|
String sensitiveData = extractSensitiveData(request);
|
|
String processedSensitiveData = onPremisesService.processSensitive(sensitiveData);
|
|
|
|
// 2. Обработка остальных данных в облаке
|
|
Object cloudRequest = prepareCloudRequest(request, processedSensitiveData);
|
|
ResponseEntity<String> cloudResponse = cloudService.process(cloudRequest);
|
|
|
|
// 3. Объединение результатов
|
|
return combineResults(processedSensitiveData, cloudResponse);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Стратегии миграции
|
|
|
|
#### 1. Lift and Shift (Rehosting)
|
|
|
|
**Lift and Shift** — перенос приложения в облако без изменений архитектуры.
|
|
|
|
```yaml
|
|
# Lift and Shift Migration Plan
|
|
migration_plan:
|
|
phase_1_assessment:
|
|
- "Inventory current applications"
|
|
- "Identify dependencies"
|
|
- "Assess cloud readiness"
|
|
- "Calculate migration costs"
|
|
|
|
phase_2_preparation:
|
|
- "Set up cloud infrastructure"
|
|
- "Configure networking"
|
|
- "Prepare security policies"
|
|
- "Train team on cloud tools"
|
|
|
|
phase_3_migration:
|
|
- "Migrate non-critical applications first"
|
|
- "Test in cloud environment"
|
|
- "Migrate critical applications"
|
|
- "Validate functionality"
|
|
|
|
phase_4_optimization:
|
|
- "Optimize for cloud-native features"
|
|
- "Implement monitoring"
|
|
- "Fine-tune performance"
|
|
- "Cost optimization"
|
|
```
|
|
|
|
#### 2. Refactoring (Replatforming)
|
|
|
|
**Refactoring** — модификация приложения для использования облачных сервисов.
|
|
|
|
```java
|
|
// Before: On-premises application
|
|
@RestController
|
|
public class LegacyOrderController {
|
|
|
|
@Autowired
|
|
private FileSystemOrderService fileSystemService;
|
|
|
|
@PostMapping("/orders")
|
|
public ResponseEntity<Order> createOrder(@RequestBody Order order) {
|
|
// Сохранение в файловую систему
|
|
fileSystemService.saveOrder(order);
|
|
return ResponseEntity.ok(order);
|
|
}
|
|
}
|
|
|
|
// After: Cloud-native application
|
|
@RestController
|
|
public class CloudOrderController {
|
|
|
|
@Autowired
|
|
private DynamoDBOrderService dynamoDBService;
|
|
|
|
@Autowired
|
|
private S3DocumentService s3Service;
|
|
|
|
@Autowired
|
|
private SNSNotificationService notificationService;
|
|
|
|
@PostMapping("/orders")
|
|
public ResponseEntity<Order> createOrder(@RequestBody Order order) {
|
|
// Сохранение в DynamoDB
|
|
Order savedOrder = dynamoDBService.saveOrder(order);
|
|
|
|
// Сохранение документов в S3
|
|
s3Service.saveOrderDocuments(order);
|
|
|
|
// Отправка уведомления через SNS
|
|
notificationService.sendOrderCreatedNotification(savedOrder);
|
|
|
|
return ResponseEntity.ok(savedOrder);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 3. Re-architecting
|
|
|
|
**Re-architecting** — полная переработка приложения с использованием облачных паттернов.
|
|
|
|
```yaml
|
|
# Re-architecting Strategy
|
|
architecture_transformation:
|
|
from_monolith:
|
|
- "Single application"
|
|
- "Tightly coupled components"
|
|
- "Single database"
|
|
- "Vertical scaling"
|
|
|
|
to_microservices:
|
|
- "Multiple independent services"
|
|
- "Loosely coupled via APIs"
|
|
- "Database per service"
|
|
- "Horizontal scaling"
|
|
|
|
cloud_native_patterns:
|
|
- "Event-driven architecture"
|
|
- "Serverless functions"
|
|
- "Container orchestration"
|
|
- "API Gateway"
|
|
- "Service Mesh"
|
|
```
|
|
|
|
### Управление мультиоблачной средой
|
|
|
|
#### 1. Единая точка управления
|
|
|
|
```python
|
|
# Multi-Cloud Management Dashboard
|
|
class CloudManagementDashboard:
|
|
def __init__(self):
|
|
self.cloud_managers = {
|
|
'aws': AWSManager(),
|
|
'azure': AzureManager(),
|
|
'gcp': GCPManager()
|
|
}
|
|
|
|
def get_unified_metrics(self):
|
|
"""Получение унифицированных метрик со всех облаков"""
|
|
metrics = {}
|
|
|
|
for cloud_name, manager in self.cloud_managers.items():
|
|
metrics[cloud_name] = {
|
|
'cost': manager.get_monthly_cost(),
|
|
'usage': manager.get_resource_usage(),
|
|
'performance': manager.get_performance_metrics(),
|
|
'security': manager.get_security_status()
|
|
}
|
|
|
|
return self.aggregate_metrics(metrics)
|
|
|
|
def optimize_costs(self):
|
|
"""Оптимизация затрат в мультиоблачной среде"""
|
|
recommendations = []
|
|
|
|
for cloud_name, manager in self.cloud_managers.items():
|
|
cloud_recommendations = manager.get_cost_optimization_recommendations()
|
|
recommendations.extend(cloud_recommendations)
|
|
|
|
return self.prioritize_recommendations(recommendations)
|
|
|
|
def disaster_recovery_plan(self):
|
|
"""План аварийного восстановления"""
|
|
return {
|
|
'rto': '4 hours', # Recovery Time Objective
|
|
'rpo': '1 hour', # Recovery Point Objective
|
|
'backup_strategy': 'Cross-cloud replication',
|
|
'failover_procedure': self.get_failover_procedure()
|
|
}
|
|
```
|
|
|
|
#### 2. Безопасность в мультиоблачной среде
|
|
|
|
```yaml
|
|
# Multi-Cloud Security Configuration
|
|
security:
|
|
identity_management:
|
|
primary: "Azure AD"
|
|
federation:
|
|
- "AWS IAM"
|
|
- "GCP IAM"
|
|
|
|
network_security:
|
|
vpn_connections:
|
|
- "AWS VPN Gateway"
|
|
- "Azure VPN Gateway"
|
|
- "GCP Cloud VPN"
|
|
|
|
firewall_rules:
|
|
- "AWS Security Groups"
|
|
- "Azure NSG"
|
|
- "GCP Firewall Rules"
|
|
|
|
data_encryption:
|
|
at_rest:
|
|
- "AWS KMS"
|
|
- "Azure Key Vault"
|
|
- "GCP Cloud KMS"
|
|
|
|
in_transit:
|
|
- "TLS 1.3"
|
|
- "IPSec"
|
|
- "mTLS"
|
|
|
|
compliance:
|
|
standards:
|
|
- "SOC 2"
|
|
- "ISO 27001"
|
|
- "GDPR"
|
|
- "HIPAA"
|
|
```
|
|
|
|
### Сравнение стратегий
|
|
|
|
| Стратегия | Сложность | Время | Стоимость | Риск | Гибкость |
|
|
|-----------|-----------|-------|-----------|------|----------|
|
|
| **Lift and Shift** | Низкая | Быстро | Низкая | Низкий | Низкая |
|
|
| **Refactoring** | Средняя | Средне | Средняя | Средний | Средняя |
|
|
| **Re-architecting** | Высокая | Долго | Высокая | Высокий | Высокая |
|
|
| **Hybrid** | Очень высокая | Очень долго | Очень высокая | Очень высокий | Очень высокая |
|
|
|
|
---
|
|
|
|
## Стратегии миграции
|
|
|
|
### Типы миграции
|
|
|
|
#### 1. Lift and Shift (Rehosting)
|
|
**Определение:** Перенос приложения в облако без изменений.
|
|
|
|
**Преимущества:**
|
|
- Быстрая миграция
|
|
- Минимальные изменения
|
|
- Низкий риск
|
|
|
|
**Недостатки:**
|
|
- Не использует преимущества облака
|
|
- Высокие затраты
|
|
- Ограниченная масштабируемость
|
|
|
|
```yaml
|
|
# Lift and Shift Example
|
|
# Original on-premises application
|
|
# Migrated to AWS EC2
|
|
Resources:
|
|
MyApplication:
|
|
Type: AWS::EC2::Instance
|
|
Properties:
|
|
ImageId: ami-0c02fb55956c7d316
|
|
InstanceType: t3.large
|
|
SecurityGroups:
|
|
- !Ref ApplicationSecurityGroup
|
|
UserData:
|
|
Fn::Base64: !Sub |
|
|
#!/bin/bash
|
|
# Install application dependencies
|
|
yum update -y
|
|
yum install -y java-1.8.0-openjdk
|
|
# Deploy application
|
|
aws s3 cp s3://my-bucket/app.jar /opt/app.jar
|
|
java -jar /opt/app.jar
|
|
```
|
|
|
|
#### 2. Replatforming
|
|
**Определение:** Миграция с минимальными изменениями для использования облачных сервисов.
|
|
|
|
**Преимущества:**
|
|
- Использование облачных сервисов
|
|
- Улучшенная производительность
|
|
- Снижение затрат
|
|
|
|
**Недостатки:**
|
|
- Требует изменений в приложении
|
|
- Средний риск
|
|
- Время на адаптацию
|
|
|
|
```yaml
|
|
# Replatforming Example
|
|
# Migrate from on-premises database to RDS
|
|
Resources:
|
|
MyDatabase:
|
|
Type: AWS::RDS::DBInstance
|
|
Properties:
|
|
DBInstanceIdentifier: my-app-db
|
|
DBInstanceClass: db.t3.micro
|
|
Engine: mysql
|
|
EngineVersion: "8.0"
|
|
MasterUsername: admin
|
|
MasterUserPassword: !Ref DatabasePassword
|
|
AllocatedStorage: 20
|
|
VPCSecurityGroups:
|
|
- !Ref DatabaseSecurityGroup
|
|
|
|
MyApplication:
|
|
Type: AWS::ECS::Service
|
|
Properties:
|
|
ServiceName: my-app-service
|
|
Cluster: !Ref ECSCluster
|
|
TaskDefinition: !Ref TaskDefinition
|
|
DesiredCount: 2
|
|
```
|
|
|
|
#### 3. Refactoring (Re-architecting)
|
|
**Определение:** Полная переработка приложения для облачной архитектуры.
|
|
|
|
**Преимущества:**
|
|
- Максимальное использование облака
|
|
- Высокая масштабируемость
|
|
- Оптимальная производительность
|
|
|
|
**Недостатки:**
|
|
- Высокие затраты
|
|
- Длительное время
|
|
- Высокий риск
|
|
|
|
```yaml
|
|
# Refactoring Example
|
|
# Migrate to microservices architecture
|
|
Resources:
|
|
UserService:
|
|
Type: AWS::ECS::Service
|
|
Properties:
|
|
ServiceName: user-service
|
|
Cluster: !Ref ECSCluster
|
|
TaskDefinition: !Ref UserServiceTaskDefinition
|
|
DesiredCount: 3
|
|
|
|
OrderService:
|
|
Type: AWS::ECS::Service
|
|
Properties:
|
|
ServiceName: order-service
|
|
Cluster: !Ref ECSCluster
|
|
TaskDefinition: !Ref OrderServiceTaskDefinition
|
|
DesiredCount: 3
|
|
|
|
APIGateway:
|
|
Type: AWS::ApiGateway::RestApi
|
|
Properties:
|
|
Name: microservices-api
|
|
Description: API Gateway for microservices
|
|
```
|
|
|
|
### Миграционная стратегия
|
|
|
|
#### 1. Assessment Phase
|
|
```markdown
|
|
# Assessment Checklist
|
|
|
|
## Application Analysis
|
|
- [ ] Inventory all applications
|
|
- [ ] Analyze dependencies
|
|
- [ ] Assess performance requirements
|
|
- [ ] Identify security requirements
|
|
- [ ] Calculate current costs
|
|
|
|
## Infrastructure Analysis
|
|
- [ ] Map network topology
|
|
- [ ] Identify data flows
|
|
- [ ] Assess storage requirements
|
|
- [ ] Analyze backup strategies
|
|
- [ ] Document disaster recovery
|
|
|
|
## Business Analysis
|
|
- [ ] Define migration goals
|
|
- [ ] Identify critical applications
|
|
- [ ] Assess business impact
|
|
- [ ] Plan migration timeline
|
|
- [ ] Allocate resources
|
|
```
|
|
|
|
#### 2. Planning Phase
|
|
```markdown
|
|
# Migration Plan
|
|
|
|
## Phase 1: Foundation (Month 1-2)
|
|
- Set up cloud infrastructure
|
|
- Configure networking
|
|
- Implement security controls
|
|
- Set up monitoring
|
|
|
|
## Phase 2: Pilot Migration (Month 3-4)
|
|
- Migrate non-critical applications
|
|
- Test cloud services
|
|
- Validate performance
|
|
- Train team
|
|
|
|
## Phase 3: Production Migration (Month 5-8)
|
|
- Migrate critical applications
|
|
- Implement disaster recovery
|
|
- Optimize performance
|
|
- Monitor and adjust
|
|
|
|
## Phase 4: Optimization (Month 9-12)
|
|
- Optimize costs
|
|
- Implement automation
|
|
- Enhance security
|
|
- Continuous improvement
|
|
```
|
|
|
|
#### 3. Execution Phase
|
|
```yaml
|
|
# Migration Automation
|
|
Resources:
|
|
MigrationPipeline:
|
|
Type: AWS::CodePipeline::Pipeline
|
|
Properties:
|
|
Name: application-migration-pipeline
|
|
RoleArn: !GetAtt CodePipelineRole.Arn
|
|
Stages:
|
|
- Name: Source
|
|
Actions:
|
|
- Name: SourceAction
|
|
ActionTypeId:
|
|
Category: Source
|
|
Owner: AWS
|
|
Provider: S3
|
|
Version: 1
|
|
Configuration:
|
|
S3Bucket: !Ref SourceBucket
|
|
S3ObjectKey: source.zip
|
|
- Name: Build
|
|
Actions:
|
|
- Name: BuildAction
|
|
ActionTypeId:
|
|
Category: Build
|
|
Owner: AWS
|
|
Provider: CodeBuild
|
|
Version: 1
|
|
Configuration:
|
|
ProjectName: !Ref BuildProject
|
|
- Name: Deploy
|
|
Actions:
|
|
- Name: DeployAction
|
|
ActionTypeId:
|
|
Category: Deploy
|
|
Owner: AWS
|
|
Provider: CloudFormation
|
|
Version: 1
|
|
Configuration:
|
|
StackName: !Ref StackName
|
|
TemplatePath: BuildArtifact::template.yaml
|
|
```
|
|
|
|
---
|
|
|
|
## Экономика облака и калькулятор затрат
|
|
|
|
### Понимание модели оплаты облака
|
|
|
|
#### 1. Pay-as-you-go модель
|
|
|
|
**Принцип:** Оплата только за используемые ресурсы.
|
|
|
|
**Преимущества:**
|
|
- Нет предварительных инвестиций
|
|
- Гибкость в масштабировании
|
|
- Оплата только за фактическое использование
|
|
|
|
**Примеры затрат:**
|
|
```yaml
|
|
# Пример расчета затрат на EC2
|
|
ec2_costs:
|
|
instance_type: "t3.micro"
|
|
hourly_rate: "$0.0104"
|
|
monthly_cost: "$7.49" # 24/7 использование
|
|
annual_cost: "$89.88"
|
|
|
|
# Пример расчета затрат на S3
|
|
s3_costs:
|
|
storage_class: "Standard"
|
|
storage_gb: 100
|
|
monthly_storage: "$2.30"
|
|
requests_per_month: 1000000
|
|
monthly_requests: "$0.40"
|
|
total_monthly: "$2.70"
|
|
```
|
|
|
|
#### 2. Модели ценообразования AWS
|
|
|
|
**On-Demand Instances**
|
|
- Оплата по часам/секундам
|
|
- Без долгосрочных обязательств
|
|
- Максимальная гибкость
|
|
|
|
```python
|
|
# Калькулятор затрат On-Demand
|
|
class OnDemandCostCalculator:
|
|
def __init__(self):
|
|
self.pricing = {
|
|
't3.micro': 0.0104, # USD per hour
|
|
't3.small': 0.0208,
|
|
't3.medium': 0.0416,
|
|
'm5.large': 0.096,
|
|
'c5.large': 0.085
|
|
}
|
|
|
|
def calculate_monthly_cost(self, instance_type, hours_per_month=744):
|
|
"""Расчет месячной стоимости"""
|
|
hourly_rate = self.pricing.get(instance_type, 0)
|
|
return hourly_rate * hours_per_month
|
|
|
|
def calculate_annual_cost(self, instance_type, hours_per_month=744):
|
|
"""Расчет годовой стоимости"""
|
|
monthly_cost = self.calculate_monthly_cost(instance_type, hours_per_month)
|
|
return monthly_cost * 12
|
|
|
|
# Использование
|
|
calculator = OnDemandCostCalculator()
|
|
monthly_cost = calculator.calculate_monthly_cost('t3.medium')
|
|
print(f"Monthly cost for t3.medium: ${monthly_cost:.2f}")
|
|
```
|
|
|
|
**Reserved Instances**
|
|
- Скидка до 75% при предоплате
|
|
- Обязательство на 1-3 года
|
|
- Предсказуемые затраты
|
|
|
|
```python
|
|
# Калькулятор Reserved Instances
|
|
class ReservedInstanceCalculator:
|
|
def __init__(self):
|
|
self.reserved_pricing = {
|
|
't3.medium': {
|
|
'1_year_no_upfront': 0.025,
|
|
'1_year_partial_upfront': 0.020,
|
|
'1_year_all_upfront': 0.015,
|
|
'3_year_no_upfront': 0.018,
|
|
'3_year_partial_upfront': 0.014,
|
|
'3_year_all_upfront': 0.010
|
|
}
|
|
}
|
|
|
|
def calculate_savings(self, instance_type, on_demand_rate, reserved_rate):
|
|
"""Расчет экономии от Reserved Instances"""
|
|
monthly_on_demand = on_demand_rate * 744
|
|
monthly_reserved = reserved_rate * 744
|
|
monthly_savings = monthly_on_demand - monthly_reserved
|
|
annual_savings = monthly_savings * 12
|
|
savings_percentage = (monthly_savings / monthly_on_demand) * 100
|
|
|
|
return {
|
|
'monthly_savings': monthly_savings,
|
|
'annual_savings': annual_savings,
|
|
'savings_percentage': savings_percentage
|
|
}
|
|
|
|
# Использование
|
|
ri_calculator = ReservedInstanceCalculator()
|
|
savings = ri_calculator.calculate_savings(
|
|
't3.medium',
|
|
0.0416, # On-demand rate
|
|
0.015 # 1-year all upfront rate
|
|
)
|
|
print(f"Annual savings: ${savings['annual_savings']:.2f} ({savings['savings_percentage']:.1f}%)")
|
|
```
|
|
|
|
**Spot Instances**
|
|
- До 90% скидка от On-Demand
|
|
- Могут быть прерваны в любой момент
|
|
- Подходят для fault-tolerant workloads
|
|
|
|
```python
|
|
# Калькулятор Spot Instances
|
|
class SpotInstanceCalculator:
|
|
def __init__(self):
|
|
self.spot_pricing = {
|
|
't3.medium': 0.0125, # Примерная цена
|
|
'm5.large': 0.024,
|
|
'c5.large': 0.021
|
|
}
|
|
|
|
def calculate_spot_savings(self, instance_type, on_demand_rate):
|
|
"""Расчет экономии от Spot Instances"""
|
|
spot_rate = self.spot_pricing.get(instance_type, 0)
|
|
monthly_on_demand = on_demand_rate * 744
|
|
monthly_spot = spot_rate * 744
|
|
monthly_savings = monthly_on_demand - monthly_spot
|
|
savings_percentage = (monthly_savings / monthly_on_demand) * 100
|
|
|
|
return {
|
|
'monthly_savings': monthly_savings,
|
|
'savings_percentage': savings_percentage,
|
|
'spot_rate': spot_rate
|
|
}
|
|
|
|
# Использование
|
|
spot_calculator = SpotInstanceCalculator()
|
|
spot_savings = spot_calculator.calculate_spot_savings('t3.medium', 0.0416)
|
|
print(f"Spot savings: {spot_savings['savings_percentage']:.1f}%")
|
|
```
|
|
|
|
#### 3. AWS Cost Calculator
|
|
|
|
**Онлайн калькулятор AWS:**
|
|
- https://calculator.aws/
|
|
- Детальный расчет затрат
|
|
- Сравнение различных конфигураций
|
|
- Экспорт в Excel/PDF
|
|
|
|
**Программный доступ к ценам:**
|
|
|
|
```python
|
|
# AWS Pricing API
|
|
import boto3
|
|
import json
|
|
|
|
class AWSPricingCalculator:
|
|
def __init__(self):
|
|
self.pricing_client = boto3.client('pricing', region_name='us-east-1')
|
|
|
|
def get_ec2_pricing(self, instance_type, region='us-east-1'):
|
|
"""Получение цен на EC2 инстансы"""
|
|
try:
|
|
response = self.pricing_client.get_products(
|
|
ServiceCode='AmazonEC2',
|
|
Filters=[
|
|
{
|
|
'Type': 'TERM_MATCH',
|
|
'Field': 'instanceType',
|
|
'Value': instance_type
|
|
},
|
|
{
|
|
'Type': 'TERM_MATCH',
|
|
'Field': 'location',
|
|
'Value': self.get_region_name(region)
|
|
}
|
|
]
|
|
)
|
|
return response
|
|
except Exception as e:
|
|
print(f"Error getting pricing: {e}")
|
|
return None
|
|
|
|
def get_region_name(self, region_code):
|
|
"""Преобразование кода региона в название"""
|
|
region_mapping = {
|
|
'us-east-1': 'US East (N. Virginia)',
|
|
'us-west-2': 'US West (Oregon)',
|
|
'eu-west-1': 'Europe (Ireland)',
|
|
'ap-southeast-1': 'Asia Pacific (Singapore)'
|
|
}
|
|
return region_mapping.get(region_code, region_code)
|
|
|
|
# Использование
|
|
pricing_calc = AWSPricingCalculator()
|
|
pricing = pricing_calc.get_ec2_pricing('t3.micro')
|
|
```
|
|
|
|
#### 4. Cost Optimization Strategies
|
|
|
|
**Right-Sizing**
|
|
- Выбор подходящего размера инстансов
|
|
- Мониторинг использования ресурсов
|
|
- Автоматическое масштабирование
|
|
|
|
```yaml
|
|
# CloudWatch Metrics для Right-Sizing
|
|
Resources:
|
|
RightSizingAlarm:
|
|
Type: AWS::CloudWatch::Alarm
|
|
Properties:
|
|
AlarmName: LowCPUUtilization
|
|
ComparisonOperator: LessThanThreshold
|
|
EvaluationPeriods: 2
|
|
MetricName: CPUUtilization
|
|
Namespace: AWS/EC2
|
|
Period: 300
|
|
Statistic: Average
|
|
Threshold: 20
|
|
AlarmActions:
|
|
- !Ref SNSNotificationTopic
|
|
Dimensions:
|
|
- Name: InstanceId
|
|
Value: !Ref EC2Instance
|
|
```
|
|
|
|
**Reserved Instances Planning**
|
|
|
|
```python
|
|
# Планировщик Reserved Instances
|
|
class ReservedInstancePlanner:
|
|
def __init__(self):
|
|
self.usage_history = {}
|
|
|
|
def analyze_usage_pattern(self, instance_type, hours_per_month):
|
|
"""Анализ паттернов использования"""
|
|
if hours_per_month >= 744: # 24/7 использование
|
|
return "Full-time usage - consider Reserved Instances"
|
|
elif hours_per_month >= 372: # 12/7 использование
|
|
return "Part-time usage - consider Scheduled Reserved Instances"
|
|
else:
|
|
return "Variable usage - stick with On-Demand"
|
|
|
|
def calculate_break_even(self, on_demand_rate, reserved_rate, upfront_cost=0):
|
|
"""Расчет точки безубыточности"""
|
|
monthly_savings = (on_demand_rate - reserved_rate) * 744
|
|
if upfront_cost > 0:
|
|
months_to_break_even = upfront_cost / monthly_savings
|
|
return months_to_break_even
|
|
return float('inf')
|
|
|
|
# Использование
|
|
planner = ReservedInstancePlanner()
|
|
break_even = planner.calculate_break_even(0.0416, 0.015, 100)
|
|
print(f"Break-even point: {break_even:.1f} months")
|
|
```
|
|
|
|
**Storage Optimization**
|
|
|
|
```yaml
|
|
# S3 Lifecycle Configuration
|
|
Resources:
|
|
S3Bucket:
|
|
Type: AWS::S3::Bucket
|
|
Properties:
|
|
LifecycleConfiguration:
|
|
Rules:
|
|
- Id: TransitionToIA
|
|
Status: Enabled
|
|
Transitions:
|
|
- StorageClass: STANDARD_IA
|
|
TransitionInDays: 30
|
|
- Id: TransitionToGlacier
|
|
Status: Enabled
|
|
Transitions:
|
|
- StorageClass: GLACIER
|
|
TransitionInDays: 90
|
|
- Id: DeleteOldVersions
|
|
Status: Enabled
|
|
NoncurrentVersionTransitions:
|
|
- StorageClass: GLACIER
|
|
TransitionInDays: 30
|
|
NoncurrentVersionExpirationInDays: 90
|
|
```
|
|
|
|
#### 5. Cost Monitoring and Alerting
|
|
|
|
**AWS Cost Explorer**
|
|
- Визуализация затрат
|
|
- Фильтрация по сервисам, регионам, тегам
|
|
- Прогнозирование затрат
|
|
|
|
**Billing Alerts**
|
|
|
|
```yaml
|
|
# CloudWatch Billing Alarm
|
|
Resources:
|
|
BillingAlarm:
|
|
Type: AWS::CloudWatch::Alarm
|
|
Properties:
|
|
AlarmName: MonthlyBillingAlarm
|
|
AlarmDescription: Alert when monthly costs exceed threshold
|
|
MetricName: EstimatedCharges
|
|
Namespace: AWS/Billing
|
|
Statistic: Maximum
|
|
Period: 86400 # 24 hours
|
|
EvaluationPeriods: 1
|
|
Threshold: 100 # $100
|
|
ComparisonOperator: GreaterThanThreshold
|
|
Dimensions:
|
|
- Name: Currency
|
|
Value: USD
|
|
AlarmActions:
|
|
- !Ref SNSNotificationTopic
|
|
```
|
|
|
|
**Cost Allocation Tags**
|
|
|
|
```yaml
|
|
# Tagging Strategy
|
|
Resources:
|
|
EC2Instance:
|
|
Type: AWS::EC2::Instance
|
|
Properties:
|
|
Tags:
|
|
- Key: Environment
|
|
Value: Production
|
|
- Key: Project
|
|
Value: E-commerce
|
|
- Key: Owner
|
|
Value: DevelopmentTeam
|
|
- Key: CostCenter
|
|
Value: IT-001
|
|
- Key: AutoShutdown
|
|
Value: "false"
|
|
```
|
|
|
|
#### 6. Multi-Cloud Cost Comparison
|
|
|
|
**Сравнение облачных провайдеров:**
|
|
|
|
```python
|
|
# Сравнительный калькулятор облачных затрат
|
|
class MultiCloudCostComparator:
|
|
def __init__(self):
|
|
self.pricing = {
|
|
'aws': {
|
|
't3.micro': 0.0104,
|
|
't3.small': 0.0208,
|
|
't3.medium': 0.0416
|
|
},
|
|
'azure': {
|
|
'B1s': 0.0052,
|
|
'B1ms': 0.0104,
|
|
'B2s': 0.0416
|
|
},
|
|
'gcp': {
|
|
'e2-micro': 0.006,
|
|
'e2-small': 0.012,
|
|
'e2-medium': 0.024
|
|
}
|
|
}
|
|
|
|
def compare_costs(self, instance_type, hours=744):
|
|
"""Сравнение затрат между облачными провайдерами"""
|
|
results = {}
|
|
for provider, instances in self.pricing.items():
|
|
if instance_type in instances:
|
|
monthly_cost = instances[instance_type] * hours
|
|
results[provider] = {
|
|
'monthly_cost': monthly_cost,
|
|
'annual_cost': monthly_cost * 12
|
|
}
|
|
return results
|
|
|
|
def find_cheapest(self, instance_type, hours=744):
|
|
"""Поиск самого дешевого варианта"""
|
|
costs = self.compare_costs(instance_type, hours)
|
|
if costs:
|
|
cheapest = min(costs.items(), key=lambda x: x[1]['monthly_cost'])
|
|
return cheapest[0], cheapest[1]
|
|
|
|
# Использование
|
|
comparator = MultiCloudCostComparator()
|
|
cheapest_provider, cost = comparator.find_cheapest('t3.micro')
|
|
print(f"Cheapest provider: {cheapest_provider}, Monthly cost: ${cost['monthly_cost']:.2f}")
|
|
```
|
|
|
|
### Экономические принципы облачных вычислений
|
|
|
|
#### 1. CAPEX vs OPEX
|
|
|
|
**CAPEX (Capital Expenditure) - Капитальные затраты:**
|
|
- Покупка оборудования
|
|
- Предварительные инвестиции
|
|
- Амортизация активов
|
|
|
|
**OPEX (Operational Expenditure) - Операционные затраты:**
|
|
- Оплата по факту использования
|
|
- Переменные затраты
|
|
- Налоговые преимущества
|
|
|
|
#### 2. Total Cost of Ownership (TCO)
|
|
|
|
**Компоненты TCO:**
|
|
- Стоимость инфраструктуры
|
|
- Стоимость персонала
|
|
- Стоимость лицензий
|
|
- Стоимость поддержки
|
|
- Стоимость безопасности
|
|
|
|
```python
|
|
# TCO Calculator
|
|
class TCOCalculator:
|
|
def __init__(self):
|
|
self.components = {
|
|
'infrastructure': 0,
|
|
'personnel': 0,
|
|
'licenses': 0,
|
|
'support': 0,
|
|
'security': 0
|
|
}
|
|
|
|
def calculate_tco(self, years=3):
|
|
"""Расчет TCO за указанный период"""
|
|
total_tco = sum(self.components.values()) * years
|
|
return {
|
|
'total_tco': total_tco,
|
|
'annual_tco': total_tco / years,
|
|
'monthly_tco': total_tco / (years * 12),
|
|
'breakdown': self.components
|
|
}
|
|
|
|
def compare_on_premise_vs_cloud(self, on_premise_tco, cloud_tco):
|
|
"""Сравнение On-Premise vs Cloud"""
|
|
savings = on_premise_tco - cloud_tco
|
|
savings_percentage = (savings / on_premise_tco) * 100
|
|
|
|
return {
|
|
'savings': savings,
|
|
'savings_percentage': savings_percentage,
|
|
'cloud_advantage': savings > 0
|
|
}
|
|
|
|
# Использование
|
|
tco_calc = TCOCalculator()
|
|
tco_calc.components = {
|
|
'infrastructure': 50000,
|
|
'personnel': 120000,
|
|
'licenses': 15000,
|
|
'support': 25000,
|
|
'security': 10000
|
|
}
|
|
|
|
tco_result = tco_calc.calculate_tco(3)
|
|
print(f"3-year TCO: ${tco_result['total_tco']:,.2f}")
|
|
```
|
|
|
|
---
|
|
|
|
## Cost Optimization
|
|
|
|
### Стратегии оптимизации затрат
|
|
|
|
#### 1. Right-Sizing
|
|
```yaml
|
|
# Auto Scaling Configuration
|
|
Resources:
|
|
AutoScalingGroup:
|
|
Type: AWS::AutoScaling::AutoScalingGroup
|
|
Properties:
|
|
MinSize: 2
|
|
MaxSize: 10
|
|
DesiredCapacity: 3
|
|
LaunchTemplate:
|
|
LaunchTemplateId: !Ref LaunchTemplate
|
|
Version: !GetAtt LaunchTemplate.LatestVersionNumber
|
|
TargetGroupARNs:
|
|
- !Ref TargetGroup
|
|
MetricsCollection:
|
|
- Granularity: 1Minute
|
|
Metrics:
|
|
- GroupDesiredCapacity
|
|
- GroupInServiceInstances
|
|
- GroupTotalInstances
|
|
|
|
ScalingPolicy:
|
|
Type: AWS::AutoScaling::ScalingPolicy
|
|
Properties:
|
|
AutoScalingGroupName: !Ref AutoScalingGroup
|
|
PolicyType: TargetTrackingScaling
|
|
TargetTrackingConfiguration:
|
|
TargetValue: 70.0
|
|
PredefinedMetricSpecification:
|
|
PredefinedMetricType: ASGAverageCPUUtilization
|
|
```
|
|
|
|
#### 2. Reserved Instances
|
|
```yaml
|
|
# Reserved Instance Purchase
|
|
Resources:
|
|
ReservedInstance:
|
|
Type: AWS::EC2::ReservedInstances
|
|
Properties:
|
|
InstanceCount: 3
|
|
InstanceType: t3.medium
|
|
OfferingType: All Upfront
|
|
ProductDescription: Linux/UNIX
|
|
ReservedInstancesOfferingId: !Ref ReservedInstancesOffering
|
|
```
|
|
|
|
#### 3. Spot Instances
|
|
```yaml
|
|
# Spot Instance Configuration
|
|
Resources:
|
|
SpotFleet:
|
|
Type: AWS::EC2::SpotFleetRequest
|
|
Properties:
|
|
SpotFleetRequestConfig:
|
|
IamFleetRole: !GetAtt SpotFleetRole.Arn
|
|
TargetCapacity: 5
|
|
LaunchSpecifications:
|
|
- ImageId: ami-0c02fb55956c7d316
|
|
InstanceType: t3.micro
|
|
KeyName: !Ref KeyPair
|
|
SecurityGroups:
|
|
- !Ref SecurityGroup
|
|
UserData:
|
|
Fn::Base64: !Sub |
|
|
#!/bin/bash
|
|
yum update -y
|
|
yum install -y aws-cli
|
|
```
|
|
|
|
### Мониторинг затрат
|
|
|
|
#### 1. Cost Alerts
|
|
```yaml
|
|
# Cost Budget Alert
|
|
Resources:
|
|
CostBudget:
|
|
Type: AWS::Budgets::Budget
|
|
Properties:
|
|
Budget:
|
|
BudgetName: MonthlyCostBudget
|
|
BudgetLimit:
|
|
Amount: 1000
|
|
Unit: USD
|
|
TimeUnit: MONTHLY
|
|
BudgetType: COST
|
|
CostFilters:
|
|
Service:
|
|
- Amazon Elastic Compute Cloud - Compute
|
|
- Amazon Relational Database Service
|
|
NotificationsWithSubscribers:
|
|
- Notification:
|
|
NotificationType: ACTUAL
|
|
ComparisonOperator: GREATER_THAN
|
|
Threshold: 80
|
|
ThresholdType: PERCENTAGE
|
|
Subscribers:
|
|
- SubscriptionType: EMAIL
|
|
Address: admin@example.com
|
|
```
|
|
|
|
#### 2. Cost Analysis
|
|
```python
|
|
import boto3
|
|
from datetime import datetime, timedelta
|
|
|
|
def analyze_costs():
|
|
ce_client = boto3.client('ce')
|
|
|
|
# Get costs for last 30 days
|
|
end_date = datetime.now().strftime('%Y-%m-%d')
|
|
start_date = (datetime.now() - timedelta(days=30)).strftime('%Y-%m-%d')
|
|
|
|
response = ce_client.get_cost_and_usage(
|
|
TimePeriod={
|
|
'Start': start_date,
|
|
'End': end_date
|
|
},
|
|
Granularity='DAILY',
|
|
Metrics=['BlendedCost'],
|
|
GroupBy=[
|
|
{
|
|
'Type': 'DIMENSION',
|
|
'Key': 'SERVICE'
|
|
}
|
|
]
|
|
)
|
|
|
|
# Analyze costs by service
|
|
for result in response['ResultsByTime']:
|
|
for group in result['Groups']:
|
|
service = group['Keys'][0]
|
|
cost = group['Metrics']['BlendedCost']['Amount']
|
|
print(f"{service}: ${cost}")
|
|
|
|
if __name__ == "__main__":
|
|
analyze_costs()
|
|
```
|
|
|
|
---
|
|
|
|
## Практические задания
|
|
|
|
### Задание 1: Cloud Infrastructure
|
|
1. Создайте инфраструктуру в AWS/Azure/GCP
|
|
2. Разверните приложение в облаке
|
|
3. Настройте мониторинг и алерты
|
|
|
|
### Задание 2: Migration Planning
|
|
1. Создайте план миграции для существующего приложения
|
|
2. Оцените затраты и риски
|
|
3. Разработайте стратегию тестирования
|
|
|
|
### Задание 3: Cost Optimization
|
|
1. Проанализируйте текущие затраты
|
|
2. Предложите стратегии оптимизации
|
|
3. Реализуйте автоматическое масштабирование
|
|
|
|
---
|
|
|
|
## Дополнительные ресурсы
|
|
|
|
### Облачные провайдеры
|
|
- **AWS**: Amazon Web Services
|
|
- **Azure**: Microsoft Azure
|
|
- **GCP**: Google Cloud Platform
|
|
- **Alibaba Cloud**: Alibaba Cloud
|
|
- **IBM Cloud**: IBM Cloud
|
|
|
|
### Инструменты
|
|
- **Infrastructure as Code**: Terraform, CloudFormation, ARM Templates
|
|
- **Container Orchestration**: Kubernetes, Docker Swarm
|
|
- **Monitoring**: CloudWatch, Azure Monitor, Stackdriver
|
|
- **Cost Management**: AWS Cost Explorer, Azure Cost Management
|
|
|
|
---
|
|
|
|
## Контрольные вопросы
|
|
|
|
1. Какие модели обслуживания облачных вычислений вы знаете?
|
|
2. В чем разница между IaaS, PaaS и SaaS?
|
|
3. Какие основные сервисы предоставляют AWS, Azure и GCP?
|
|
4. Что такое Cloud-Native архитектура?
|
|
5. Какие стратегии миграции в облако существуют?
|
|
6. Как оптимизировать затраты в облаке?
|
|
7. Что такое 12-Factor App?
|
|
8. Как выбрать подходящую стратегию миграции?
|