云平台部署实践
概述
云平台部署是现代应用部署的主流方式,提供了弹性扩展、高可用性和成本优化等优势。本文档详细介绍主流云平台(AWS、Azure、Google Cloud、阿里云、腾讯云)的部署实践,包括基础设施即代码(IaC)、容器服务、无服务器架构等现代云原生部署模式。
云部署架构模式
传统三层架构
┌─────────────────────────────────────────────────────────────┐
│ 负载均衡器 │
│ (ALB/NLB/CLB) │
└─────────────────────┬───────────────────────────────────────┘
│
┌─────────────────────┴───────────────────────────────────────┐
│ Web层 (多AZ) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Web服务器 │ │ Web服务器 │ │ Web服务器 │ │
│ │ (AZ-1) │ │ (AZ-2) │ │ (AZ-3) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────┬───────────────────────────────────────┘
│
┌─────────────────────┴───────────────────────────────────────┐
│ 应用层 (多AZ) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 应用服务器 │ │ 应用服务器 │ │ 应用服务器 │ │
│ │ (AZ-1) │ │ (AZ-2) │ │ (AZ-3) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────┬───────────────────────────────────────┘
│
┌─────────────────────┴───────────────────────────────────────┐
│ 数据层 (主从) │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 主数据库 │ ────────────────► │ 从数据库 │ │
│ │ (AZ-1) │ │ (AZ-2) │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
微服务架构
┌─────────────────────────────────────────────────────────────┐
│ API网关 │
│ (API Gateway/Kong) │
└─────────────────────┬───────────────────────────────────────┘
│
┌─────────────────────┴───────────────────────────────────────┐
│ 微服务集群 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 用户服务 │ │ 订单服务 │ │ 支付服务 │ │
│ │ (Container) │ │ (Container) │ │ (Container) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 商品服务 │ │ 库存服务 │ │ 通知服务 │ │
│ │ (Container) │ │ (Container) │ │ (Container) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────┬───────────────────────────────────────┘
│
┌─────────────────────┴───────────────────────────────────────┐
│ 数据存储层 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 关系数据库 │ │ NoSQL │ │ 缓存 │ │
│ │ (RDS) │ │ (DynamoDB) │ │ (Redis) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
AWS部署实践
EC2部署
1. 实例配置和启动
# 使用AWS CLI创建EC2实例
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--count 1 \
--instance-type t3.medium \
--key-name my-key-pair \
--security-group-ids sg-903004f8 \
--subnet-id subnet-6e7f829e \
--user-data file://user-data.sh
2. 用户数据脚本
#!/bin/bash
# user-data.sh - EC2实例启动脚本
# 更新系统
yum update -y
# 安装Node.js
curl -fsSL https://rpm.nodesource.com/setup_18.x | bash -
yum install -y nodejs
# 安装PM2
npm install -g pm2
# 创建应用目录
mkdir -p /opt/myapp
cd /opt/myapp
# 克隆应用代码
git clone https://github.com/username/myapp.git .
# 安装依赖
npm install --production
# 启动应用
pm2 start ecosystem.config.js
pm2 startup
pm2 save
# 配置Nginx
yum install -y nginx
systemctl start nginx
systemctl enable nginx
# 配置反向代理
cat > /etc/nginx/conf.d/myapp.conf << EOF
server {
listen 80;
server_name _;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_cache_bypass \$http_upgrade;
}
}
EOF
# 重启Nginx
systemctl restart nginx
ECS部署(容器服务)
1. 任务定义
{
"family": "myapp-task",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"containerDefinitions": [
{
"name": "myapp",
"image": "123456789012.dkr.ecr.us-west-2.amazonaws.com/myapp:latest",
"portMappings": [
{
"containerPort": 3000,
"protocol": "tcp"
}
],
"environment": [
{
"name": "NODE_ENV",
"value": "production"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/myapp",
"awslogs-region": "us-west-2",
"awslogs-stream-prefix": "ecs"
}
}
}
]
}
2. 服务配置
# 创建ECS服务
aws ecs create-service \
--cluster myapp-cluster \
--service-name myapp-service \
--task-definition myapp-task:1 \
--desired-count 2 \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-12345,subnet-67890],securityGroups=[sg-12345],assignPublicIp=ENABLED}" \
--load-balancers "targetGroupArn=arn:aws:elasticloadbalancing:us-west-2:123456789012:targetgroup/myapp-tg/1234567890123456,containerName=myapp,containerPort=3000"
Lambda部署(无服务器)
1. Lambda函数代码
// lambda-function.js
const AWS = require('aws-sdk');
exports.handler = async (event, context) => {
console.log('Event:', JSON.stringify(event, null, 2));
try {
// 处理业务逻辑
const result = await processRequest(event);
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({
success: true,
data: result
})
};
} catch (error) {
console.error('Error:', error);
return {
statusCode: 500,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({
success: false,
error: error.message
})
};
}
};
async function processRequest(event) {
// 业务逻辑实现
return { message: 'Hello from Lambda!' };
}
2. SAM模板
# template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Timeout: 30
Runtime: nodejs18.x
Environment:
Variables:
NODE_ENV: production
Resources:
MyAppFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: lambda-function.handler
Events:
Api:
Type: Api
Properties:
Path: /{proxy+}
Method: ANY
Environment:
Variables:
DB_HOST: !Ref DatabaseEndpoint
MyAppApi:
Type: AWS::Serverless::Api
Properties:
StageName: prod
Cors:
AllowMethods: "'*'"
AllowHeaders: "'*'"
AllowOrigin: "'*'"
Outputs:
ApiUrl:
Description: "API Gateway endpoint URL"
Value: !Sub "https://${MyAppApi}.execute-api.${AWS::Region}.amazonaws.com/prod/"
CloudFormation基础设施即代码
# infrastructure.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: 'MyApp Infrastructure'
Parameters:
Environment:
Type: String
Default: production
AllowedValues: [development, staging, production]
InstanceType:
Type: String
Default: t3.medium
AllowedValues: [t3.small, t3.medium, t3.large]
Resources:
# VPC配置
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Sub '${Environment}-vpc'
# 公有子网
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub '${Environment}-public-subnet-1'
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.2.0/24
AvailabilityZone: !Select [1, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub '${Environment}-public-subnet-2'
# 私有子网
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.3.0/24
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Name
Value: !Sub '${Environment}-private-subnet-1'
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.4.0/24
AvailabilityZone: !Select [1, !GetAZs '']
Tags:
- Key: Name
Value: !Sub '${Environment}-private-subnet-2'
# 互联网网关
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub '${Environment}-igw'
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
# 应用负载均衡器
ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub '${Environment}-alb'
Scheme: internet-facing
Type: application
Subnets:
- !Ref PublicSubnet1
- !Ref PublicSubnet2
SecurityGroups:
- !Ref ALBSecurityGroup
# RDS数据库
DatabaseSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Subnet group for RDS database
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
Tags:
- Key: Name
Value: !Sub '${Environment}-db-subnet-group'
Database:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceIdentifier: !Sub '${Environment}-database'
DBInstanceClass: db.t3.micro
Engine: mysql
EngineVersion: '8.0'
MasterUsername: admin
MasterUserPassword: !Ref DatabasePassword
AllocatedStorage: 20
DBSubnetGroupName: !Ref DatabaseSubnetGroup
VPCSecurityGroups:
- !Ref DatabaseSecurityGroup
BackupRetentionPeriod: 7
MultiAZ: true
StorageEncrypted: true
# 安全组
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for Application Load Balancer
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
DatabaseSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for RDS database
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref ApplicationSecurityGroup
Outputs:
VPCId:
Description: VPC ID
Value: !Ref VPC
Export:
Name: !Sub '${Environment}-VPC-ID'
LoadBalancerDNS:
Description: Load Balancer DNS Name
Value: !GetAtt ApplicationLoadBalancer.DNSName
Export:
Name: !Sub '${Environment}-ALB-DNS'
Azure部署实践
App Service部署
1. ARM模板
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appName": {
"type": "string",
"metadata": {
"description": "The name of the web app"
}
},
"sku": {
"type": "string",
"defaultValue": "S1",
"allowedValues": ["F1", "D1", "B1", "B2", "B3", "S1", "S2", "S3"]
}
},
"variables": {
"appServicePlanName": "[concat(parameters('appName'), '-plan')]",
"location": "[resourceGroup().location]"
},
"resources": [
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2020-06-01",
"name": "[variables('appServicePlanName')]",
"location": "[variables('location')]",
"sku": {
"name": "[parameters('sku')]"
},
"properties": {
"reserved": true
},
"kind": "linux"
},
{
"type": "Microsoft.Web/sites",
"apiVersion": "2020-06-01",
"name": "[parameters('appName')]",
"location": "[variables('location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]"
],
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
"siteConfig": {
"linuxFxVersion": "NODE|18-lts",
"appSettings": [
{
"name": "NODE_ENV",
"value": "production"
},
{
"name": "WEBSITE_NODE_DEFAULT_VERSION",
"value": "18.17.0"
}
]
}
}
}
],
"outputs": {
"webAppUrl": {
"type": "string",
"value": "[concat('https://', parameters('appName'), '.azurewebsites.net')]"
}
}
}
2. 部署脚本
#!/bin/bash
# deploy-to-azure.sh
RESOURCE_GROUP="myapp-rg"
APP_NAME="myapp-$(date +%s)"
LOCATION="East US"
# 创建资源组
az group create --name $RESOURCE_GROUP --location "$LOCATION"
# 部署ARM模板
az deployment group create \
--resource-group $RESOURCE_GROUP \
--template-file azuredeploy.json \
--parameters appName=$APP_NAME sku=S1
# 配置部署源
az webapp deployment source config \
--name $APP_NAME \
--resource-group $RESOURCE_GROUP \
--repo-url https://github.com/username/myapp.git \
--branch main \
--manual-integration
echo "应用已部署到: https://$APP_NAME.azurewebsites.net"
Container Instances部署
# docker-compose.yml for Azure Container Instances
version: '3.8'
services:
web:
image: myregistry.azurecr.io/myapp:latest
ports:
- "80:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=${DATABASE_URL}
restart: always
redis:
image: redis:alpine
ports:
- "6379:6379"
restart: always
# 部署到Azure Container Instances
az container create \
--resource-group myapp-rg \
--file docker-compose.yml
Google Cloud Platform部署实践
App Engine部署
1. app.yaml配置
# app.yaml
runtime: nodejs18
env_variables:
NODE_ENV: production
DATABASE_URL: ${DATABASE_URL}
automatic_scaling:
min_instances: 1
max_instances: 10
target_cpu_utilization: 0.6
resources:
cpu: 1
memory_gb: 0.5
disk_size_gb: 10
handlers:
- url: /static
static_dir: public
secure: always
- url: /.*
script: auto
secure: always
2. 部署脚本
#!/bin/bash
# deploy-to-gcp.sh
PROJECT_ID="my-project-id"
SERVICE_NAME="myapp"
# 设置项目
gcloud config set project $PROJECT_ID
# 部署应用
gcloud app deploy app.yaml --service=$SERVICE_NAME --version=v1
# 设置流量
gcloud app services set-traffic $SERVICE_NAME --splits=v1=100
echo "应用已部署到: https://$SERVICE_NAME-dot-$PROJECT_ID.appspot.com"
Cloud Run部署
1. Dockerfile
# Dockerfile for Cloud Run
FROM node:18-alpine
WORKDIR /app
# 复制依赖文件
COPY package*.json ./
# 安装依赖
RUN npm ci --only=production
# 复制应用代码
COPY . .
# 构建应用
RUN npm run build
# 暴露端口
EXPOSE 8080
# 启动应用
CMD ["npm", "start"]
2. 部署脚本
#!/bin/bash
# deploy-to-cloud-run.sh
PROJECT_ID="my-project-id"
SERVICE_NAME="myapp"
REGION="us-central1"
IMAGE_NAME="gcr.io/$PROJECT_ID/$SERVICE_NAME"
# 构建镜像
docker build -t $IMAGE_NAME .
# 推送镜像
docker push $IMAGE_NAME
# 部署到Cloud Run
gcloud run deploy $SERVICE_NAME \
--image $IMAGE_NAME \
--platform managed \
--region $REGION \
--allow-unauthenticated \
--set-env-vars NODE_ENV=production
echo "服务已部署到Cloud Run"
阿里云部署实践
ECS部署
1. 实例创建脚本
#!/bin/bash
# create-ecs-instance.sh
# 配置阿里云CLI
aliyun configure set \
--profile default \
--mode AK \
--region cn-hangzhou \
--access-key-id $ACCESS_KEY_ID \
--access-key-secret $ACCESS_KEY_SECRET
# 创建ECS实例
aliyun ecs RunInstances \
--RegionId cn-hangzhou \
--ImageId ubuntu_20_04_x64_20G_alibase_20210420.vhd \
--InstanceType ecs.t5-lc1m2.small \
--SecurityGroupId sg-bp1fg655nh68xyz9**** \
--VSwitchId vsw-bp1s5fnvk4gn2tws0**** \
--InstanceName myapp-server \
--InternetMaxBandwidthOut 5 \
--UserData $(base64 -w 0 user-data.sh)
2. 用户数据脚本
#!/bin/bash
# user-data.sh
# 更新系统
apt update && apt upgrade -y
# 安装Node.js
curl -fsSL https://deb.nodesource.com/setup_18.x | bash -
apt-get install -y nodejs
# 安装PM2
npm install -g pm2
# 安装Nginx
apt install -y nginx
# 克隆应用
git clone https://github.com/username/myapp.git /opt/myapp
cd /opt/myapp
# 安装依赖并启动
npm install --production
pm2 start ecosystem.config.js
pm2 startup
pm2 save
# 配置Nginx
cat > /etc/nginx/sites-available/myapp << EOF
server {
listen 80;
server_name _;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_cache_bypass \$http_upgrade;
}
}
EOF
ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
nginx -t && systemctl restart nginx
容器服务ACK部署
1. Kubernetes部署文件
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: registry.cn-hangzhou.aliyuncs.com/namespace/myapp:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: "production"
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: LoadBalancer
2. 部署脚本
#!/bin/bash
# deploy-to-ack.sh
CLUSTER_ID="c1234567890abcdef"
REGION="cn-hangzhou"
NAMESPACE="default"
# 配置kubectl
aliyun cs GET /k8s/$CLUSTER_ID/user_config | jq -r '.config' > ~/.kube/config
# 构建并推送镜像
docker build -t registry.cn-hangzhou.aliyuncs.com/namespace/myapp:latest .
docker push registry.cn-hangzhou.aliyuncs.com/namespace/myapp:latest
# 部署应用
kubectl apply -f deployment.yaml -n $NAMESPACE
# 等待部署完成
kubectl rollout status deployment/myapp-deployment -n $NAMESPACE
# 获取服务地址
kubectl get service myapp-service -n $NAMESPACE
腾讯云部署实践
CVM部署
1. 实例创建
#!/bin/bash
# create-cvm-instance.sh
# 配置腾讯云CLI
tccli configure set secretId $SECRET_ID
tccli configure set secretKey $SECRET_KEY
tccli configure set region ap-guangzhou
# 创建CVM实例
tccli cvm RunInstances \
--ImageId img-pi0ii46r \
--InstanceType S5.MEDIUM2 \
--Placement.Zone ap-guangzhou-3 \
--InstanceName myapp-server \
--InternetAccessible.InternetMaxBandwidthOut 5 \
--InternetAccessible.PublicIpAssigned TRUE \
--UserData $(base64 -w 0 user-data.sh)
TKE部署(容器服务)
1. 部署配置
# tke-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: ccr.ccs.tencentyun.com/namespace/myapp:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
---
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 3000
selector:
app: myapp
多云部署策略
Terraform多云配置
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 4.0"
}
}
}
# AWS Provider
provider "aws" {
region = var.aws_region
}
# Azure Provider
provider "azurerm" {
features {}
}
# Google Cloud Provider
provider "google" {
project = var.gcp_project_id
region = var.gcp_region
}
# AWS Resources
resource "aws_instance" "app_server" {
count = var.deploy_to_aws ? 1 : 0
ami = var.aws_ami
instance_type = var.aws_instance_type
tags = {
Name = "myapp-aws"
}
}
# Azure Resources
resource "azurerm_resource_group" "main" {
count = var.deploy_to_azure ? 1 : 0
name = "myapp-rg"
location = var.azure_location
}
resource "azurerm_linux_virtual_machine" "main" {
count = var.deploy_to_azure ? 1 : 0
name = "myapp-vm"
resource_group_name = azurerm_resource_group.main[0].name
location = azurerm_resource_group.main[0].location
size = var.azure_vm_size
# VM configuration...
}
# Google Cloud Resources
resource "google_compute_instance" "app_server" {
count = var.deploy_to_gcp ? 1 : 0
name = "myapp-gcp"
machine_type = var.gcp_machine_type
zone = var.gcp_zone
# Instance configuration...
}
部署脚本
#!/bin/bash
# multi-cloud-deploy.sh
CLOUDS=("aws" "azure" "gcp")
ENVIRONMENT=${1:-production}
for cloud in "${CLOUDS[@]}"; do
echo "部署到 $cloud..."
case $cloud in
"aws")
terraform apply -var="deploy_to_aws=true" -var="deploy_to_azure=false" -var="deploy_to_gcp=false"
;;
"azure")
terraform apply -var="deploy_to_aws=false" -var="deploy_to_azure=true" -var="deploy_to_gcp=false"
;;
"gcp")
terraform apply -var="deploy_to_aws=false" -var="deploy_to_azure=false" -var="deploy_to_gcp=true"
;;
esac
if [ $? -eq 0 ]; then
echo "$cloud 部署成功"
else
echo "$cloud 部署失败"
exit 1
fi
done
echo "多云部署完成"
监控和日志
CloudWatch(AWS)
// cloudwatch-metrics.js
const AWS = require('aws-sdk');
const cloudwatch = new AWS.CloudWatch();
class MetricsCollector {
async putMetric(metricName, value, unit = 'Count') {
const params = {
Namespace: 'MyApp/Performance',
MetricData: [
{
MetricName: metricName,
Value: value,
Unit: unit,
Timestamp: new Date()
}
]
};
try {
await cloudwatch.putMetricData(params).promise();
console.log(`Metric ${metricName} sent to CloudWatch`);
} catch (error) {
console.error('Error sending metric:', error);
}
}
async putCustomMetrics(requestCount, responseTime, errorCount) {
await Promise.all([
this.putMetric('RequestCount', requestCount),
this.putMetric('ResponseTime', responseTime, 'Milliseconds'),
this.putMetric('ErrorCount', errorCount)
]);
}
}
module.exports = MetricsCollector;
Application Insights(Azure)
// azure-monitoring.js
const appInsights = require('applicationinsights');
// 初始化Application Insights
appInsights.setup(process.env.APPINSIGHTS_INSTRUMENTATIONKEY)
.setAutoDependencyCorrelation(true)
.setAutoCollectRequests(true)
.setAutoCollectPerformance(true, true)
.setAutoCollectExceptions(true)
.setAutoCollectDependencies(true)
.setAutoCollectConsole(true)
.setUseDiskRetryCaching(true)
.setSendLiveMetrics(false)
.setDistributedTracingMode(appInsights.DistributedTracingModes.AI)
.start();
const client = appInsights.defaultClient;
class AzureMonitoring {
trackEvent(name, properties = {}) {
client.trackEvent({
name: name,
properties: properties
});
}
trackMetric(name, value) {
client.trackMetric({
name: name,
value: value
});
}
trackException(error) {
client.trackException({
exception: error
});
}
trackRequest(req, res, duration) {
client.trackRequest({
name: `${req.method} ${req.path}`,
url: req.url,
duration: duration,
resultCode: res.statusCode,
success: res.statusCode < 400
});
}
}
module.exports = AzureMonitoring;
成本优化
AWS成本优化
#!/bin/bash
# aws-cost-optimization.sh
# 查找未使用的EBS卷
echo "查找未使用的EBS卷..."
aws ec2 describe-volumes --filters Name=status,Values=available --query 'Volumes[*].[VolumeId,Size,VolumeType]' --output table
# 查找未使用的弹性IP
echo "查找未使用的弹性IP..."
aws ec2 describe-addresses --query 'Addresses[?AssociationId==null].[PublicIp,AllocationId]' --output table
# 查找空闲的负载均衡器
echo "查找空闲的负载均衡器..."
aws elbv2 describe-load-balancers --query 'LoadBalancers[*].[LoadBalancerName,State.Code]' --output table
# 建议使用Spot实例
echo "获取Spot实例价格..."
aws ec2 describe-spot-price-history --instance-types t3.medium --product-descriptions "Linux/UNIX" --max-items 1
自动扩缩容配置
# auto-scaling.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp-deployment
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 50
periodSeconds: 60
安全最佳实践
IAM策略配置
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::myapp-bucket/*"
},
{
"Effect": "Allow",
"Action": [
"rds:DescribeDBInstances",
"rds:Connect"
],
"Resource": "arn:aws:rds:*:*:db:myapp-database"
},
{
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
}
}
}
]
}
网络安全配置
# network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: myapp-network-policy
spec:
podSelector:
matchLabels:
app: myapp
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: nginx
ports:
- protocol: TCP
port: 3000
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- to: []
ports:
- protocol: TCP
port: 443
- protocol: TCP
port: 80
总结
云平台部署提供了强大的弹性和可扩展性,但也需要考虑以下关键要素:
- 选择合适的服务:根据应用特性选择IaaS、PaaS或SaaS服务
- 基础设施即代码:使用Terraform、CloudFormation等工具管理基础设施
- 多云策略:避免供应商锁定,提高可用性
- 成本优化:合理使用资源,实施自动扩缩容
- 安全加固:实施多层安全防护,遵循最小权限原则
- 监控告警:建立完善的监控和日志系统
- 灾难恢复:制定备份和恢复策略
通过遵循这些最佳实践,可以构建稳定、安全、高效的云原生应用部署架构。