1. 开头:为什么在Ubuntu上装AWS SAM值得折腾
先说结论:如果你正在用Ubuntu做云原生开发,特别是涉及无服务器架构,AWS SAM这套东西迟早绕不开。我最早接触SAM是在一次内部项目迁移里,团队要把一堆Lambda函数从手动打包上传的原始流程里解放出来,当时对比了一圈工具,最后定下来用SAM。坦白讲,刚开始也踩了不少坑,尤其是Ubuntu环境下各种依赖、权限、Python版本的问题轮着来,网上的教程又零零散散,今天是这个版本,明天是那个参数,照着抄都容易翻车。所以这篇我把自己在Ubuntu上完整安装、配置、验证AWS SAM的流程整理出来,尽量把所有关键选择和踩坑点都讲透,你可以当一份可复现的操作手册用。
这篇文章适合谁?一是刚接触AWS无服务器开发、想在本地跑通SAM的入门者;二是已经在用其他工具、想切换到SAM工作流的开发者;三是需要在Ubuntu作为主力开发机或CI构建环境里部署SAM的运维或平台工程师。无论你属于哪一类,只要照着走一遍,大概半小时内能把环境搭好、跑通第一个示例项目。
我会按实际操作的顺序来讲:先解释为什么需要这套工具链,再讲环境准备阶段最容易出问题的地方,然后是安装的完整动作和参数选择,接着用一个小示例项目验证是否装成功,最后是常见问题排查和几个真正省时间的技巧。内容会有点长,但每一段都是实操里会碰到的东西。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心概念与工具链拆解:搞清楚SAM到底是个什么角色
2.1 SAM在AWS无服务器开发里的位置
AWS SAM(Serverless Application Model)本质上是一个开源框架,它把无服务器应用的资源定义用一种简化的语法描述出来,然后底层还是转换成AWS CloudFormation模板来执行部署。换句话说,SAM是站在CloudFormation肩膀上的一个更贴近开发者心智的抽象层。
为什么要多这一层抽象?举个例子:如果你直接写CloudFormation模板来定义一个Lambda函数加一个API Gateway接口,你需要分别写AWS::Lambda::Function、AWS::ApiGateway::RestApi、AWS::ApiGateway::Method,还要手动处理角色权限、策略、映射关系,一个最小的接口可能要上百行YAML。而用SAM,核心定义大概这么几行就够:
yaml复制AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.12
Events:
HelloWorldApi:
Type: Api
Properties:
Path: /hello
Method: get
Transform 声明告诉CloudFormation:这个模板需要用SAM的语义来解析,然后SAM会把简化的 AWS::Serverless::Function 展开成完整的函数、角色、事件源映射等资源。这也是为什么你在SAM模板里永远看不到传统CloudFormation那么多繁琐的IAM角色定义——SAM会自动生成默认的执行角色,当然你也可以显式覆盖。
2.2 SAM CLI的三大核心职责
理解了SAM是什么,再看CLI工具就清楚了。SAM CLI(即sam命令行工具)在本地主要做三件事:
第一,本地构建。sam build 会在一个隔离的环境里处理你的依赖。比如你用Python写的函数,它会读取 requirements.txt,在本地把依赖安装好,和代码一起组织成一个部署包;如果用Node.js,就解析 package.json。
第二,本地运行与调试。sam local start-api 可以在你本机启动一个模拟API Gateway的HTTP服务,点一下浏览器就能调你的Lambda函数;sam local invoke 则直接调用单个函数。这个能力非常实用,很多时候不用把代码部署上云,本地就能完成逻辑验证和联调。
第三,打包与部署。sam package(现在新版也可以直接用 sam deploy 一步完成)会把本地构建产物上传到S3,然后生成或更新CloudFormation堆栈,实现云上部署。
2.3 为什么在Ubuntu上装比Mac稍微麻烦一点
在macOS上装SAM通常一条Homebrew命令就解决了,但Ubuntu上需要你自己处理几个前置环境。我见过很多人在这一步卡住,不是因为SAM本身难装,而是前置的Python、pip、Docker、AWS CLI版本之间出了配合问题。
先说Python。SAM CLI是基于Python实现的,虽然新版CLI已经打包成了独立的二进制文件,对系统Python的依赖已经降低了很多,但部分功能(比如某些构建流程、插件机制)仍然要求系统里有一个可用的Python 3.9到3.12版本。Ubuntu 22.04和24.04自带的Python 3.10或3.12通常是满足要求的,但如果你的系统是旧一点的版本,或者你自己编译过低版本Python,就可能在运行时碰到兼容性问题。
其次是Docker。SAM的本地调试能力,尤其是 sam local start-api 调用容器运行函数,依赖Docker来模拟Lambda的运行环境。如果你没装Docker,SAM本地调试功能基本是残废的。
最后是AWS CLI。SAM本身不负责AWS API调用凭证管理,它需要你预先配置好AWS凭证。最合适的搭配是安装AWS CLI v2,然后用 aws configure 配置凭证,SAM CLI会自动复用这套凭证。如果你的机器上还没有AWS CLI,安装SAM之前最好先把它搞定。
3. 安装前的环境准备:这一步能省掉后面80%的坑
3.1 检查系统基础信息
安装之前,先确认系统版本和架构。不同的Ubuntu版本、不同的CPU架构,对应的安装方式会略有差别。用下面几条命令看一下:
bash复制lsb_release -a
uname -m
python3 --version
在Ubuntu 22.04 LTS或24.04 LTS上,输出一般都会显示 x86_64 架构,Python版本在3.10以上。如果你的系统是ARM架构(比如Apple Silicon云主机、树莓派上的Ubuntu),安装命令会稍有不同,但SAM官方对ARM的支持也不错,只是某些本地构建的依赖包在ARM上可能出现兼容性问题,这个后面再说。
3.2 安装Python包管理工具pip
这一步很关键。虽然系统自带Python,但pip可能需要单独装。如果pip缺失,后面很多东西都装不了。
bash复制sudo apt update
sudo apt install -y python3-pip
装完之后检查一下:
bash复制pip3 --version
如果pip版本过低,建议先升级,否则之后安装某些依赖包时会碰到兼容性报错。
bash复制pip3 install --upgrade pip
3.3 安装AWS CLI v2
AWS CLI建议装v2版本,v1太老了,很多新特性不支持。在Ubuntu上,我推荐直接用官方安装脚本,这种方式最省事,而且不污染系统Python环境:
bash复制curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
装完验证:
bash复制aws --version
你会看到类似 aws-cli/2.x.x Python/3.x.x Linux/5.x.x 的输出。这里提醒一句:如果你用的是ARM架构,需要把下载链接里的 x86_64 改成 aarch64,对应的URL是 https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip。我当初在一台ARM服务器上装CLI就忘了换架构,结果装完一跑直接段错误,排查了很久才发现是下载错了包。
AWS CLI装完后,需要配置凭证:
bash复制aws configure
按提示输入Access Key ID、Secret Access Key、默认区域(比如 ap-northeast-1)、默认输出格式(建议填 json)。如果你是在CI环境或者服务器上,也可以通过环境变量注入凭证:
bash复制export AWS_ACCESS_KEY_ID=你的AK
export AWS_SECRET_ACCESS_KEY=你的SK
export AWS_DEFAULT_REGION=ap-northeast-1
3.4 安装Docker
如果你要用SAM的本地调试功能,Docker是必须的。在Ubuntu上安装Docker,最推荐的是用官方apt仓库,而不是装Ubuntu仓库里那个老版本:
bash复制sudo apt update
sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io
装完还需要把自己加入docker组,否则每次都要sudo:
bash复制sudo usermod -aG docker $USER
newgrp docker
然后验证:
bash复制docker --version
docker run hello-world
这里有一个常见问题:如果docker run报permission denied,大概率是你还没推出重新登录,或者usermod之后没重新加载组权限。执行一下 newgrp docker 再试,还不行就重启一下终端。
3.5 检查系统依赖库
SAM CLI在运行过程中依赖一些动态链接库。Ubuntu桌面版一般没问题,但如果是精简安装的Server版,可能缺少这些库。未雨绸缪,先把常用依赖一次性装上:
bash复制sudo apt install -y build-essential libssl-dev libffi-dev jq
jq 是用来处理JSON输出的,虽然SAM不直接依赖它,但调试云上部署结果时很有用。build-essential 则确保本地构建原生扩展时不会缺编译工具。
4. 安装AWS SAM CLI的完整流程与关键选择
4.1 方式一:官方二进制安装包(最推荐)
现在SAM CLI官方提供预编译的二进制文件,安装过程非常简单,而且不依赖系统Python环境,避免了大量pip相关的兼容性问题。这也是我目前最推荐的方式。
首先去GitHub的aws/aws-sam-cli发布页面下载对应架构的zip包。用命令行的方式操作如下:
bash复制wget https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip
unzip aws-sam-cli-linux-x86_64.zip -d sam-install
sudo ./sam-install/install
ARM架构对应的文件名是 aws-sam-cli-linux-aarch64.zip。安装脚本默认把SAM安装到 /usr/local/bin 目录下,所以可以直接全局使用。
装完确认版本:
bash复制sam --version
正常会输出 SAM CLI, version 1.x.x 这样的信息。
4.2 方式二:pip安装(适合需要特定版本的场景)
如果你确实需要安装某个特定版本,或者你的环境里已经有很多Python项目依赖,想用虚拟环境管理,那么pip方式也有它的用武之地。需要注意的是,我不推荐直接全局用pip装SAM,因为它会把一堆依赖装进系统Python里,容易和其他包冲突。正确做法是创建虚拟环境:
bash复制python3 -m venv sam-venv
source sam-venv/bin/activate
pip install --upgrade aws-sam-cli
装完验证:
bash复制sam --version
这种方式的好处是版本控制灵活,想回退到旧版只需 pip install aws-sam-cli==版本号。坏处是比官方二进制方式要多几步环境操作,而且在虚拟环境里,每次用SAM之前都要记得先activate。如果你只是偶尔用SAM,这种方式会有些烦人。
4.3 方式三:Homebrew(仅限Linuxbrew用户)
如果你之前在Ubuntu上装了Linuxbrew(Linux版Homebrew),那么也能用brew安装:
bash复制brew tap aws/tap
brew install aws-sam-cli
但说实话,在Ubuntu上用brew属于少数派选择,容易碰到路径问题和编译依赖,没必要为了装SAM又引入一个包管理器。如果已经有brew环境且习惯了这种方式,可以试试;如果是新环境,建议直接用官方二进制。
4.4 升级和卸载
SAM CLI的版本更新很频繁,官方二进制方式升级也很方便,直接重新下载最新版zip包,再次运行install脚本即可。它会自动覆盖旧版本,不需要先卸载。我在一个CI镜像里就是这么维护SAM版本的,每次构建时用固定版本号下载安装,保证可重复性。
如果哪天要卸载SAM,官方二进制方式就简单了,直接删掉相关文件:
bash复制sudo rm /usr/local/bin/sam
sudo rm -rf /usr/local/aws-sam-cli
pip方式就执行 pip uninstall aws-sam-cli。
5. 安装完成后的验证:跑通一个真实的项目
5.1 初始化一个示例项目
环境装好后,第一步用sam init创建示例项目。这条命令会拉取官方模板列表,交互式询问一些问题,比如环境类型、运行时、项目名称等:
bash复制sam init
交互过程大致是:
- 选择模板来源:选
1,表示AWS Quick Start Templates。 - 选择运行时:建议选
1(Python 3.12)或者其他你熟悉的运行时。 - 选择项目类型:选
1是Hello World示例。 - 是否使用X-Ray追踪和CloudWatch监控:选
n就行,跟安装验证无关。 - 项目名称:填
sam-test-app之类的名字。
生成的目录结构大概是这样的:
code复制sam-test-app/
├── __init__.py
├── events/
│ └── event.json
├── hello_world/
│ ├── __init__.py
│ ├── app.py
│ └── requirements.txt
├── template.yaml
├── README.md
├── .gitignore
└── tests/
5.2 本地构建与运行验证
进入项目目录,执行构建:
bash复制cd sam-test-app
sam build
这一步SAM会读取template.yaml,解析资源定义,然后用Docker容器把函数依赖打包到 .aws-sam 目录下。第一次构建会拉取Lambda运行时的基础镜像,可能需要一点时间。
构建成功后,试试本地运行API:
bash复制sam local start-api
输出里会有一个本地地址,通常是 http://127.0.0.1:3000。在浏览器里访问 http://127.0.0.1:3000/hello,你应该能看到类似 {"message": "hello world"} 的JSON响应。
这一步是整个验证过程的核心——如果本地API能跑起来,说明SAM CLI主体功能没问题、Docker集成没问题、依赖打包也没问题。
5.3 云上部署验证
如果本地验证通过,再测试云上部署。sam deploy 支持引导式配置,第一次会问你是否创建配置文件:
bash复制sam deploy --guided
按提示操作:
- Stack Name:填
sam-test-app - AWS Region:选择你需要的区域
- Confirm changes before deploy:选
Y或N都行 - Allow SAM CLI IAM role creation:选
Y,让SAM自动创建需要的IAM角色 - Disable rollback:选
N,保持默认
部署完成后,输出里会显示API Gateway endpoint地址,访问一下就能看到和本地一样的结果。这一步验证的是凭证配置、S3桶创建、CloudFormation堆栈操作等流程是否正常。
部署完了如果不想保留资源,记得清理:
bash复制sam delete --stack-name sam-test-app
这条命令会删除堆栈及其关联的资源,避免产生不必要的AWS费用。我在测试环境经常用完就删,反正模板还在,随时可以再部署回来。
6. 常见问题与排查技巧
6.1 Python版本不匹配导致构建失败
现象:sam build 报错说某个依赖需要更高版本的Python,或者干脆提示找不到Python。
原因:SAM在构建Python函数时,会使用本机Python来解释依赖元数据。如果项目里指定的运行时是python3.12,但系统默认Python是3.10,就可能出现问题。
排查思路:
- 确认
python3 --version的系统版本。 - 检查template.yaml里
Runtime属性写的版本。 - 如果有多个Python版本,可以用
SAM_BUILD_MODE或--build-image指定使用哪个版本的构建镜像。
解决方式:强烈推荐让函数运行时和本机Python版本一致。如果必须不一致,就显式指定构建镜像,比如构建Python 3.12函数时:
bash复制sam build --build-image amazon/aws-sam-cli-build-image-python3.12
6.2 Docker权限问题
现象:sam local 系列命令报错,提示无法连接Docker daemon,或者permission denied。
原因:当前用户不在docker用户组,没有权限访问 /var/run/docker.sock。
排查思路:
bash复制id $USER
ls -l /var/run/docker.sock
解决方式:
bash复制sudo usermod -aG docker $USER
newgrp docker
如果再不行,重启docker服务:
bash复制sudo systemctl restart docker
6.3 网络超时或拉取镜像失败
现象:sam build 或 sam local 执行时卡在拉取镜像,或者报网络连接超时。
原因:Docker Hub或AWS ECR的镜像拉取被网络环境限制,或者本机代理设置有问题。
排查思路:
- 先单独执行
docker pull public.ecr.aws/lambda/python:3.12,看能不能手动拉取。 - 检查环境变量里是否有
HTTP_PROXY、HTTPS_PROXY设置。
解决方式:如果默认镜像源慢,可以配置Docker镜像加速器,或者换用SAM中国区专用的镜像地址。在执行构建时也可以通过 --build-image 指定其他镜像源。
6.4 凭证配置错误导致部署失败
现象:sam deploy 报 Unable to locate credentials 或 AccessDenied。
原因:AWS凭证没有正确配置,或者配置的凭证权限不足。
排查思路:
bash复制aws sts get-caller-identity
如果这条命令能返回你的账号信息,说明凭证配置正常。如果报错,重新执行 aws configure。
解决方式:检查使用的AccessKey是否有Lambda、CloudFormation、S3、IAM相关权限。如果是在EC2上运行的,可以直接给实例绑定IAM角色的方式,这样连AccessKey都不用配。
6.5 一个容易忽略的小坑:文件和目录名大小写
现象:本地构建成功,但部署到云上后调用函数报 Unable to import module。
原因:SAM在Linux容器里对文件名大小写是敏感的。如果你在Windows或macOS上开发时创建的Python文件是 App.py,代码里 import app 没问题,但在Linux容器里就找不到 app.py 了。
解决方式:项目目录和文件名统一用全小写加下划线风格。这个坑在本地很难发现,因为本地文件系统可能不区分大小写,到了云端就露馅了。
6.6 问题排查速查表
| 症状 | 可能原因 | 快速处理 |
|---|---|---|
| sam命令找不到 | 安装路径不在PATH中 | 检查/usr/local/bin/sam是否存在 |
| sam --version报错 | 动态库缺失 | sudo apt install -y build-essential libssl-dev libffi-dev |
| sam build卡住 | Docker镜像拉取慢 | 配置镜像加速或换构建镜像 |
| sam local start-api启动后无法访问 | 端口被占用 | 检查3000端口,或用--port指定其他端口 |
| 部署时提示S3桶不存在 | 首次部署未自动创建 | 给SAM配置一个已有的S3桶参数 |
| 调用函数报超时 | 函数默认超时时间3秒 | 在template.yaml里设置Timeout属性 |
7. 进阶建议:几个让我效率翻倍的用法
装好SAM只是第一步,真正把它的价值用起来需要在工作流里做好几个配套选择。这里分享几点个人体会。
第一,把sam build和sam deploy放进CI流水线。 我在GitLab CI里是这样用的:触发条件为打tag时,跑一条流水线,先装SAM CLI(用官方二进制方式),再执行 sam build、sam deploy --no-confirm-changeset --parameter-overrides Stage=prod,一条命令完成整个部署。这比用Jenkins配置一堆AWS插件简单太多了。
第二,用sam sync做快速迭代。 sam sync 这个命令可以在代码变更后只上传变化的部分,不用每次都跑完整的build和CloudFormation更新,开发时特别快。我第一次用的时候都有点意外,原来几十秒的部署,现在几秒就完成了。适合开发阶段频繁改代码的场景。
第三,善用sam local的调试能力。 在本地调试Python函数时,我通常会在代码里加断点,然后配合SAM的本地调用触发。如果你用VS Code,官方还提供了SAM调试扩展,可以直接在IDE里打断点,调试体验非常接近本地开发传统程序。
第四,认真维护template.yaml的分层。 以后项目变大后,模板文件可能几百行。我习惯把公共的Lambda配置用 Globals 段统一声明,把不同环境的差异参数用 Parameters 声明,然后通过 sam deploy --parameter-overrides 传入。这样同一套模板可以部署到dev、test、prod多个环境,不需要复制粘贴多份模板。
第五,花钱的事一定记得清理。 测试环境用完 sam delete 是我的固定动作。云上资源每一分钟都在计费,特别是API Gateway和Lambda本身虽然便宜,但测试不小心触发大规模遍历还是会有点费用。养成用完就清理的习惯,比任何成本优化策略都管用。
我在实际使用中发现,很多人在SAM的安装和入门阶段花的时间其实是最多的,真正用顺手之后反而会感慨这套工具链的完整。Ubuntu上装SAM的关键就是顺序对、版本对、权限对,把CLI、Docker、凭证三个基础打牢,后面怎么折腾都顺。希望这篇能把你的安装之路铺平,让你把精力留给真正有创造性的业务逻辑。
