AWS CLI自动化:从手动操作到企业级脚本开发实战
引言:你还在手动执行AWS操作吗?
在DevOps实践中,AWS资源的管理往往陷入重复手动操作的泥潭:每天执行20+条CLI命令、复制粘贴凭证信息、在多个账号间切换导致配置混乱、脚本版本混乱难以追溯。据AWS DevOps调查报告显示,73%的故障源于手动操作失误,而自动化程度高的团队问题解决效率提升4.2倍。本文将系统讲解AWS CLI自动化脚本开发,从环境搭建到企业级流程编排,帮你彻底摆脱重复劳动,构建可复用的云资源管理工具链。
读完本文你将获得:
- 3套企业级自动化脚本模板(ECR镜像管理/S3批量操作/EC2资源巡检)
- 5个核心场景的故障排查流程图
- 10个提升脚本健壮性的关键技巧
- 完整的CI/CD集成方案与权限最小化实践
- 可直接复用的命令速查表与最佳实践清单
一、AWS CLI核心原理与环境配置
1.1 什么是AWS CLI?
AWS Command Line Interface(CLI,命令行界面)是AWS提供的统一工具,允许通过命令行交互方式管理所有AWS服务。与控制台操作相比,CLI支持脚本化执行,是实现基础设施即代码(IaC)和自动化运维的核心工具。
1.2 架构与工作流程
1.3 安装与配置实战
1.3.1 多系统安装命令
| 操作系统 | 安装命令 | 验证命令 |
|---|---|---|
| Linux | curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && unzip awscliv2.zip && sudo ./aws/install | aws --version |
| macOS | brew install awscli | aws --version |
| Windows | msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi | aws --version |
1.3.2 配置文件深度解析
AWS CLI配置文件位于~/.aws/目录,包含两个核心文件:
credentials文件(存储访问凭证):
[default]
aws_access_key_id = AKIAEXAMPLE
aws_secret_access_key = example+secret
[dev]
aws_access_key_id = AKIADEV
aws_secret_access_key = dev+secret
[prod]
role_arn = arn:aws:iam::123456789012:role/AdminRole
source_profile = dev
config文件(存储区域、输出格式等):
[default]
region = us-east-1
output = json
[profile dev]
region = ap-southeast-1
output = table
[profile prod]
region = eu-west-1
output = yaml
1.3.3 多账号切换技巧
# 临时切换账号(当前终端有效)
export AWS_PROFILE=dev
# 命令级别指定账号
aws s3 ls --profile prod
# 通过环境变量覆盖配置
AWS_ACCESS_KEY_ID=AKIAEXAMPLE AWS_SECRET_ACCESS_KEY=example+secret aws ec2 describe-instances
二、核心服务自动化脚本开发
2.1 ECR镜像全生命周期管理
2.1.1 完整操作脚本
#!/bin/bash
set -eo pipefail
# 配置参数
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REGION="ap-southeast-1"
REPO_NAME="my-app-images"
IMAGE_TAG="v1.2.3"
LOCAL_IMAGE="my-app:latest"
# 创建ECR仓库
echo "创建ECR仓库..."
aws ecr create-repository \
--repository-name $REPO_NAME \
--region $REGION \
--image-scanning-configuration scanOnPush=true
# 登录ECR
echo "登录ECR..."
aws ecr get-login-password --region $REGION | docker login \
--username AWS \
--password-stdin $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com
# 构建并标记镜像
echo "构建镜像..."
docker build -t $LOCAL_IMAGE .
docker tag $LOCAL_IMAGE $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO_NAME:$IMAGE_TAG
docker tag $LOCAL_IMAGE $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO_NAME:latest
# 推送镜像
echo "推送镜像..."
docker push $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO_NAME:$IMAGE_TAG
docker push $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO_NAME:latest
# 清理过期镜像(保留最近5个)
echo "清理过期镜像..."
aws ecr list-images \
--repository-name $REPO_NAME \
--region $REGION \
--filter "tagStatus=ANY" \
--query 'imageIds[5:].imageTag' \
--output text | xargs -I {} aws ecr batch-delete-image \
--repository-name $REPO_NAME \
--region $REGION \
--image-ids imageTag={}
echo "操作完成!镜像URI: $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO_NAME:$IMAGE_TAG"
2.1.2 脚本解析与优化
2.2 S3对象存储自动化管理
2.2.1 跨区域备份脚本
#!/bin/bash
set -e
# 配置
SOURCE_BUCKET="my-source-bucket"
DEST_BUCKET="my-dest-bucket"
DEST_REGION="eu-west-1"
LOG_FILE="/var/log/s3_sync.log"
DATE=$(date +%Y-%m-%d-%H-%M)
# 记录开始时间
echo "[$DATE] 开始S3跨区域同步" >> $LOG_FILE
# 同步文件(排除日志和临时文件)
aws s3 sync s3://$SOURCE_BUCKET s3://$DEST_BUCKET \
--region $DEST_REGION \
--exclude "*.log" \
--exclude "tmp/*" \
--delete \
--quiet \
>> $LOG_FILE 2>&1
# 验证同步结果
if [ $? -eq 0 ]; then
echo "[$DATE] 同步成功" >> $LOG_FILE
# 生成同步报告
aws s3 ls s3://$DEST_BUCKET --recursive --region $DEST_REGION | wc -l > /tmp/sync_count.txt
echo "[$DATE] 同步文件总数: $(cat /tmp/sync_count.txt)" >> $LOG_FILE
# 发送成功通知到SNS
aws sns publish \
--topic-arn arn:aws:sns:$DEST_REGION:123456789012:s3-sync-notifications \
--message "S3同步成功: $(cat /tmp/sync_count.txt)个文件" \
--subject "S3 Sync Success"
else
echo "[$DATE] 同步失败" >> $LOG_FILE
# 发送失败通知
aws sns publish \
--topic-arn arn:aws:sns:$DEST_REGION:123456789012:s3-sync-notifications \
--message "S3同步失败,请查看日志: $LOG_FILE" \
--subject "S3 Sync Failed"
exit 1
fi
2.3 EC2实例自动化运维
2.3.1 实例状态检查与自动修复
#!/bin/bash
set -e
# 配置
INSTANCE_ID="i-0123456789abcdef0"
REGION="ap-southeast-1"
ALARM_NAME="EC2-Auto-Recovery-Alarm"
# 检查实例状态
STATUS=$(aws ec2 describe-instance-status \
--instance-ids $INSTANCE_ID \
--region $REGION \
--query "InstanceStatuses[0].InstanceStatus.Status" \
--output text)
# 检查系统状态
SYSTEM_STATUS=$(aws ec2 describe-instance-status \
--instance-ids $INSTANCE_ID \
--region $REGION \
--query "InstanceStatuses[0].SystemStatus.Status" \
--output text)
# 如果状态异常,触发自动恢复
if [ "$STATUS" != "ok" ] || [ "$SYSTEM_STATUS" != "ok" ]; then
echo "实例状态异常: STATUS=$STATUS, SYSTEM_STATUS=$SYSTEM_STATUS"
# 创建CloudWatch告警触发恢复
aws cloudwatch put-metric-alarm \
--alarm-name $ALARM_NAME \
--metric-name StatusCheckFailed_System \
--namespace AWS/EC2 \
--statistic Maximum \
--period 60 \
--evaluation-periods 2 \
--threshold 1 \
--comparison-operator GreaterThanOrEqualToThreshold \
--dimensions Name=InstanceId,Value=$INSTANCE_ID \
--region $REGION \
--alarm-actions arn:aws:automate:$REGION:ec2:recover
# 发送告警通知
aws sns publish \
--topic-arn arn:aws:sns:$REGION:123456789012:ec2-alerts \
--message "EC2实例$INSTANCE_ID状态异常,已触发自动恢复" \
--subject "EC2 Instance Recovery Triggered"
else
echo "实例状态正常"
fi
三、CI/CD流水线集成实践
3.1 AWS CodeBuild自动化构建流程
3.1.1 buildspec.yml完整配置
version: 0.2
env:
variables:
AWS_DEFAULT_REGION: "ap-southeast-1"
ECR_REPO_NAME: "my-app"
parameter-store:
DOCKERFILE_PATH: "/myapp/build/dockerfile-path"
phases:
install:
runtime-versions:
python: 3.11
docker: 20
pre_build:
commands:
- echo "获取代码提交哈希..."
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- IMAGE_TAG=${COMMIT_HASH:=latest}
- echo "登录ECR..."
- aws ecr get-login-password | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
- echo "检查Dockerfile..."
- if [ ! -f $DOCKERFILE_PATH ]; then echo "Dockerfile不存在"; exit 1; fi
build:
commands:
- echo "构建镜像..."
- docker build -f $DOCKERFILE_PATH -t $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$ECR_REPO_NAME:$IMAGE_TAG .
- echo "运行单元测试..."
- docker run --rm $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$ECR_REPO_NAME:$IMAGE_TAG pytest
post_build:
commands:
- echo "推送镜像..."
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$ECR_REPO_NAME:$IMAGE_TAG
- echo "生成部署配置..."
- echo "{\"imageUri\":\"$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$ECR_REPO_NAME:$IMAGE_TAG\"}" > imageDefinition.json
- echo "通知部署系统..."
- aws sns publish --topic-arn arn:aws:sns:$AWS_DEFAULT_REGION:$AWS_ACCOUNT_ID:build-notifications --message "镜像推送完成: $IMAGE_TAG"
artifacts:
files:
- imageDefinition.json
- appspec.yml
- taskdef.json
discard-paths: yes
cache:
paths:
- /root/.cache/pip/**/*
- /var/lib/docker/**/*
3.2 与GitHub Actions集成
# .github/workflows/deploy.yml
name: Deploy to ECS
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v3
- name: 配置AWS凭证
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-southeast-1
- name: 登录ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: 构建推送镜像
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: my-app
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
- name: 更新ECS服务
run: |
aws ecs update-service --cluster my-cluster --service my-service --force-new-deployment
四、高级自动化技巧与最佳实践
4.1 脚本健壮性提升策略
4.1.1 错误处理机制
#!/bin/bash
# 错误处理函数
error_exit() {
echo "$1" 1>&2
# 清理临时文件
if [ -d "/tmp/myapp" ]; then
rm -rf /tmp/myapp
fi
exit 1
}
# 启用错误捕获
set -eo pipefail
# 示例:使用错误处理
aws s3 cp localfile.txt s3://mybucket/ || error_exit "文件上传失败"
# 条件检查
if ! aws ec2 describe-instances --instance-ids i-123456; then
error_exit "无法查询实例信息"
fi
4.1.2 日志管理最佳实践
#!/bin/bash
LOG_FILE="/var/log/aws_automation.log"
MAX_LOG_SIZE=10485760 # 10MB
# 日志轮转
if [ -f "$LOG_FILE" ] && [ $(stat -c%s "$LOG_FILE") -ge $MAX_LOG_SIZE ]; then
mv "$LOG_FILE" "$LOG_FILE.old"
gzip "$LOG_FILE.old"
touch "$LOG_FILE"
fi
# 带时间戳的日志函数
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
# 使用示例
log "开始执行备份任务"
aws s3 sync ...
log "备份完成"
4.2 安全最佳实践
4.2.1 IAM权限最小化原则
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
],
"Condition": {
"StringEquals": {
"aws:RequestedRegion": "ap-southeast-1"
},
"DateLessThan": {
"aws:CurrentTime": "2024-12-31T23:59:59Z"
}
}
}
]
}
4.2.2 凭证安全管理
# 错误示例:硬编码凭证
aws configure set aws_access_key_id AKIAEXAMPLE
aws configure set aws_secret_access_key SECRET
# 正确做法:使用IAM角色
# 1. 为EC2实例附加IAM角色
# 2. 无需配置凭证,CLI自动获取临时凭证
# 本地开发:使用aws-vault
aws-vault add my-profile
aws-vault exec my-profile -- aws s3 ls
五、企业级自动化案例分析
5.1 多环境部署自动化脚本
#!/bin/bash
set -e
# 环境参数
ENV=$1
APP_NAME="myapp"
VERSION=$2
# 验证输入
if [ -z "$ENV" ] || [ -z "$VERSION" ]; then
echo "用法: $0 <环境> <版本号>"
echo "示例: $0 staging 1.2.3"
exit 1
fi
# 加载环境配置
case $ENV in
dev)
INSTANCE_COUNT=2
CLUSTER="dev-cluster"
NAMESPACE="development"
;;
staging)
INSTANCE_COUNT=3
CLUSTER="staging-cluster"
NAMESPACE="staging"
;;
prod)
INSTANCE_COUNT=10
CLUSTER="prod-cluster"
NAMESPACE="production"
# 生产环境需要确认
read -p "确定要部署到生产环境吗? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "部署取消"
exit 0
fi
;;
*)
echo "不支持的环境: $ENV"
exit 1
;;
esac
# 主部署流程
echo "开始部署$APP_NAME:$VERSION到$ENV环境..."
# 1. 更新Kubernetes部署文件
sed -i "s|IMAGE_TAG|$VERSION|g" k8s/deployment.yaml
sed -i "s|REPLICAS|$INSTANCE_COUNT|g" k8s/deployment.yaml
# 2. 应用部署
kubectl apply -f k8s/deployment.yaml -n $NAMESPACE
# 3. 等待部署完成
kubectl rollout status deployment/$APP_NAME -n $NAMESPACE
# 4. 运行健康检查
if ! kubectl exec -n $NAMESPACE deployment/$APP_NAME -- curl -s http://localhost/health | grep "OK"; then
echo "健康检查失败,回滚部署..."
kubectl rollout undo deployment/$APP_NAME -n $NAMESPACE
exit 1
fi
echo "部署成功: $APP_NAME:$VERSION 已部署到$ENV环境"
# 5. 记录部署信息到CloudWatch Logs
aws logs put-log-events \
--log-group-name "/deployments/$APP_NAME" \
--log-stream-name "$ENV" \
--log-events "[{\"timestamp\":$(date +%s%3N),\"message\":\"部署成功: $VERSION ($(date))\"}]"
5.2 基础设施巡检自动化
#!/bin/bash
set -e
# 配置
REPORT_FILE="/tmp/infrastructure-report-$(date +%Y%m%d).md"
REGIONS=("ap-southeast-1" "us-east-1" "eu-west-1")
# 生成报告
echo "# AWS基础设施巡检报告 $(date +%Y-%m-%d)" > $REPORT_FILE
echo "" >> $REPORT_FILE
# 检查每个区域
for region in "${REGIONS[@]}"; do
echo "## 区域: $region" >> $REPORT_FILE
# 1. EC2实例检查
echo "### EC2实例状态" >> $REPORT_FILE
echo "| 实例ID | 状态 | 类型 | 监控 |" >> $REPORT_FILE
echo "|--------|------|------|------|" >> $REPORT_FILE
aws ec2 describe-instances --region $region --query "Reservations[].Instances[].{ID:InstanceId,State:State.Name,Type:InstanceType,Monitoring:Monitoring.State}" --output text | \
while read -r ID State Type Monitoring; do
echo "| $ID | $State | $Type | $Monitoring |" >> $REPORT_FILE
done
# 2. S3存储检查
echo "### S3存储使用" >> $REPORT_FILE
echo "| 桶名称 | 大小(GB) | 版本控制 | 加密 |" >> $REPORT_FILE
echo "|--------|----------|----------|------|" >> $REPORT_FILE
aws s3 ls --region $region | awk '{print $3}' | \
while read -r bucket; do
size=$(aws s3 ls --summarize --human-readable --recursive s3://$bucket --region $region | grep "Total Size" | awk '{print $3 " " $4}')
versioning=$(aws s3api get-bucket-versioning --bucket $bucket --region $region --query "Status" --output text || echo "未启用")
encryption=$(aws s3api get-bucket-encryption --bucket $bucket --region $region --query "ServerSideEncryptionConfiguration.Rules[0].ApplyServerSideEncryptionByDefault.SSEAlgorithm" --output text || echo "未加密")
echo "| $bucket | $size | $versioning | $encryption |" >> $REPORT_FILE
done
echo "" >> $REPORT_FILE
done
# 上传报告到S3
aws s3 cp $REPORT_FILE s3://my-reports/infrastructure/
# 发送通知
aws sns publish \
--topic-arn arn:aws:sns:ap-southeast-1:123456789012:infra-reports \
--message "基础设施巡检报告已生成: https://my-reports.s3.amazonaws.com/infrastructure/$(basename $REPORT_FILE)" \
--subject "AWS基础设施巡检报告 $(date +%Y-%m-%d)"
echo "巡检完成,报告已上传"
六、AWS CLI命令速查表与学习资源
6.1 常用服务命令参考
| 服务 | 常用命令 | 描述 |
|---|---|---|
| EC2 | aws ec2 start-instances --instance-ids i-123 | 启动实例 |
aws ec2 describe-instances --filters "Name=tag:Environment,Values=prod" | 筛选实例 | |
aws ec2 create-image --instance-id i-123 --name "MyImage" | 创建AMI | |
| S3 | aws s3 sync localdir s3://mybucket/ --delete | 同步目录 |
aws s3 presign s3://mybucket/file.txt --expires-in 3600 | 生成临时URL | |
aws s3api get-bucket-policy --bucket mybucket | 获取桶策略 | |
| ECR | aws ecr get-login-password | docker login ... | ECR登录 |
aws ecr describe-images --repository-name myrepo | 列出镜像 | |
aws ecr batch-delete-image --repository-name myrepo --image-ids ... | 删除镜像 | |
| Lambda | aws lambda invoke --function-name myfunc output.json | 调用函数 |
aws lambda update-function-code --function-name myfunc --zip-file fileb://code.zip | 更新代码 | |
| CloudWatch | aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name CPUUtilization ... | 获取指标 |
aws cloudwatch put-metric-alarm ... | 创建告警 |
6.2 学习路径与进阶资源
-
官方文档
-
工具链扩展
- AWS CLI v2自动补全:
complete -C '/usr/local/bin/aws_completer' aws - AWS SAM CLI: 用于无服务器应用开发
- Terraform: 与AWS CLI结合实现基础设施即代码
- AWS CLI v2自动补全:
-
社区资源
- AWS CLI示例库
- AWS Shell: 增强型CLI交互环境
总结与展望
AWS CLI自动化是DevOps工程师提升效率的核心技能,通过本文介绍的技术和实践,你可以构建从简单任务到企业级流程的完整自动化解决方案。关键要点包括:
- 基础先行:掌握AWS CLI配置、多账号管理和核心命令
- 场景驱动:针对EC2、S3、ECR等核心服务开发专用脚本
- 安全第一:遵循IAM最小权限原则,避免硬编码凭证
- 持续优化:通过错误处理、日志管理和参数化提升脚本质量
- 生态集成:与CI/CD工具、监控系统和IaC工具形成闭环
随着云原生技术的发展,AWS CLI将继续与AWS SDK、CloudFormation、Terraform等工具深度融合,成为云资源管理的统一入口。建议关注AWS CLI v2的新特性,如交互式命令行、自动补全和增强的输出格式,持续优化你的自动化工作流。
行动步骤:
- 收藏本文作为速查手册
- 选择一个日常任务进行自动化改造
- 为你的脚本添加错误处理和日志记录
- 在团队中分享最佳实践
- 关注AWS官方文档的更新
记住,自动化不是一次性任务,而是持续改进的过程。从最小可行脚本开始,逐步构建你的企业级自动化工具链!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



