Steampipe 这名字玩云的同学应该不陌生,但真正把它用顺手的人并不多。它能把你的云账号变成一张巨大的数据库表,直接用 SQL 查 AWS 资源,不用写一堆脚本去调 API。这篇文章我会把整套环境从零搭起来,包括 AWS CLI 的安装配置,以及 Steampipe 的部署、插件接入和几条实用的查询,整个过程都是我在真实环境里跑过的,照着做基本不会翻车。
1. 整体思路与设计拆解
1.1 Steampipe 到底解决什么问题
日常排查云资源的时候,最烦的就是“查个东西要翻半天控制台”。比如你想统计所有没打标签的 EC2 实例,或者找出所有暴露到公网的安全组,在控制台里得一层层点菜单、导出表格、再写脚本过滤。而 Steampipe 的思路很直接:把云厂商的 API 封装成一张张数据库表,然后用 PostgreSQL 语法去查。
它底层是一个 PostgreSQL 实例,通过外部数据包装器把云资源映射成表。你执行select * from aws_s3_bucket的时候,它实际调用了 AWS 的 ListBuckets API,再把返回的 JSON 转成表格行。这个设计有两个明显的好处:一是你不需要提前同步数据,查到的永远是最新状态;二是可以跨资源类型做关联查询,比如把 EC2 实例和它挂的卷、安全组、标签一次性关联出来。
1.2 为什么还要带上 AWS CLI
初次接触 Steampipe 的人很容易忽略一件事:它查 AWS 资源时,需要一套能正常工作的凭证机制。Steampipe 本身支持通过环境变量、配置文件传入凭证,但在实际部署时,大部分人还要顺手装一下 AWS CLI,用它来管理凭证、测试连通性、排查权限问题。
还有一层原因:AWS CLI 的凭证配置文件(~/.aws/credentials和~/.aws/config)是 Steampipe 默认读取的凭证来源之一。也就是说,你只要把 CLI 的凭证配好,Steampipe 装完插件就能直接用,不用重复配置第二遍。与其说这是“附带”,不如说这是整套环境里必须打通的一环。所以我会先把 CLI 装好、配好,再装 Steampipe,这样后面排查问题会省很多事。
2. 环境准备与基础工具安装
动手之前先说一下我的参考环境:一台 Linux 服务器(Ubuntu 22.04 LTS),有 sudo 权限,能访问外网。如果你用的是 CentOS、macOS 或者 WSL,思路完全一样,只是包管理命令稍有差别。建议装之前先确认 Python 版本不低于 3.9,虽然 Steampipe 是 Go 写的二进制,但它的部分插件依赖系统证书和网络环境,干净的 Python 环境能避免一些不必要的麻烦。
2.1 安装 AWS CLI v2
AWS CLI 现在官方主推 v2,不再推荐 v1。v2 是独立打包的二进制,不需要依赖系统里的 Python,升级也方便。安装步骤如下:
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install装完之后验证一下:
aws --version正常会输出类似aws-cli/2.15.x Python/3.11.x Linux/5.15.0这样的信息。如果提示找不到命令,多半是安装路径没加进 PATH。默认安装位置是/usr/local/bin/aws,检查一下这个路径是否存在,或者在~/.bashrc里加上export PATH=/usr/local/bin:$PATH。
如果你在 macOS 上操作,可以用brew install awscli;Windows 则直接下载官方安装包。但无论哪个平台,验证方式都一样。
2.2 配置访问密钥
AWS CLI 本身只是个客户端,真正干活的是它背后调用的 API,所以必须配置一组有权限的访问密钥。这里给一个最小化 IAM 策略示例,只允许读取 EC2 和 S3 的信息:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:Describe*", "s3:List*", "s3:Get*" ], "Resource": "*" } ] }配置凭证时我建议用aws configure交互式命令,它会引导你输入 Access Key ID、Secret Access Key、默认区域和输出格式:
aws configure配置内容会写入~/.aws/credentials和~/.aws/config。如果你有多个账号,可以用aws configure --profile dev创建命名配置文件,后续通过--profile dev参数切换。这一点对后面 Steampipe 多账号接入特别有用,建议提前把命名规范定好。
注意:Secret Access Key 只在创建时显示一次,丢了只能重新生成。另外不建议把密钥写在代码或配置文件里提交到代码仓库,宁可花两分钟配置环境变量或使用 IAM Role,也不要留下安全隐患。
2.3 验证 CLI 连通性
配置完成后,先跑一条简单的命令确认链路是通的:
aws sts get-caller-identity如果返回了类似Account、UserId、Arn的 JSON,说明凭证有效,网络也正常。这一步很关键,因为 Steampipe 查不到数据时,八成就是卡在这一层。
3. Steampipe 的安装与初始配置
3.1 下载并安装 Steampipe
Steampipe 官方提供了一键安装脚本,也支持手动下载二进制。一键脚本适合快速部署,手动方式则适合在离线环境或需要固定版本的场景下使用。我这边直接用了官方脚本:
sudo /bin/sh -c "$(curl -fsSL https://steampipe.io/install/steampipe.sh)"脚本会把二进制放到/usr/local/bin,同时创建配置目录。安装完验证:
steampipe --version看到版本号之后,还需要初始化配置目录。Steampipe 的配置默认放在~/.steampipe,里面包含config和plugins两个子目录。config目录存放连接配置,plugins目录存放你安装的插件二进制。第一次运行steampipe query时它会自动初始化,也可以手动执行:
steampipe plugin list这条命令会创建默认目录结构,并列出已安装的插件(初始为空)。
3.2 安装 AWS 插件
Steampipe 本身只是一个查询引擎,具体要查哪朵云,需要装对应的插件。装 AWS 插件的命令很简单:
steampipe plugin install aws插件会被下载到~/.steampipe/plugins/,每个插件是一个独立的二进制文件,通过grpc与主进程通信。装完后可以用steampipe plugin list确认状态,正常情况下会看到aws和它的版本号。
这里多说一句:Steampipe 的插件机制让“查云资源”这件事变得非常模块化。今天你用它查 AWS,明天想查 GitHub 或者 Okta,直接装对应插件就行,不用改动任何查询逻辑。这也是它比自建脚本方案更耐用的原因。
3.3 插件连接配置的多账号玩法
AWS 插件安装好后,默认会读取你前面配置的默认凭证(环境变量或~/.aws/credentials)。如果你只有一个账号,到这里就可以直接开查了。但真实环境里,一个公司往往有多个账号,开发、测试、生产分开,这时候就需要在 Steampipe 里配置多个连接。
打开~/.steampipe/config/aws.spc,你可以看到默认连接定义。按下面的格式添加多个连接:
connection "aws_dev" { plugin = "aws" regions = ["us-east-1", "ap-southeast-1"] access_key = "AKIA...DEV" secret_key = "xxxx" } connection "aws_prod" { plugin = "aws" regions = ["us-east-1"] access_key = "AKIA...PROD" secret_key = "xxxx" }配置好之后,查询时需要指定连接名作为表名的前缀,比如select * from aws_dev.aws_s3_bucket。这样一条命令就能跨账号查资源,不用来回切换配置文件。多账号场景下,Steampipe 的体验比 AWS 控制台好太多。
4. 核心实操:用 SQL 查询 AWS 资源
4.1 进入交互式查询终端
配置全部就绪后,运行steampipe query就会进入一个类似 psql 的交互式终端。你可以在这里执行 SQL,也可以输出表格、JSON、CSV 等格式。先跑一条最简单的命令试试水:
select title, region, account_id from aws_s3_bucket order by title;如果你前面配置没问题,这里会列出当前账号下所有 S3 桶的名称、所属区域和账号 ID。第一次执行会稍慢,因为插件要建立 API 连接并拉取数据,之后同一会话中的查询会快一些。
4.2 几条场景化的查询示例
直接列几条我平时高频使用的查询,都是从实际排查中提炼出来的。
统计所有未打标签的 EC2 实例:
select instance_id, instance_type, region, launch_time from aws_ec2_instance where tags is null order by launch_time desc;找出所有关联了公网 IP 的实例:
select instance_id, public_ip_address, instance_state, vpc_id from aws_ec2_instance where public_ip_address is not null;列出 S3 桶的加密状态和版本控制状态:
select title, region, server_side_encryption_configuration, versioning_enabled from aws_s3_bucket;跨表关联查询——找出所有没有对应快照的 EC2 卷:
select i.instance_id, v.volume_id, v.size from aws_ec2_instance as i join aws_ebs_volume as v on i.instance_id = v.attachments[0].instance_id where v.snapshot_id is null;最后一条涉及的attachments[0]是 Postgres 数组字段的访问方式。Steampipe 把 AWS API 返回的嵌套 JSON 映射成了 Postgres 的 jsonb 或数组类型,所以你可以直接用 SQL 语法深入到嵌套字段,这也是它强大的地方之一。
4.3 非交互式输出与脚本化使用
交互式终端适合边查边看,但在自动化场景里,你更需要的是非交互式输出。Steampipe 支持直接执行 SQL 并指定输出格式:
steampipe query "select title, region from aws_s3_bucket" --output json加上--output csv就能输出成 CSV,配合定时任务跑巡检再合适不过。比如把未打标签的实例输出成文件:
steampipe query "select instance_id, instance_type from aws_ec2_instance where tags is null" --output csv > untagged_instances.csv这一步在做资源配置合规审计时特别好用。你可以在定时任务里加一行:
0 2 * * * steampipe query "select * from aws_iam_user where password_last_used > interval '90 days'" --output csv > /var/reports/iam_users_90d.csv每天凌晨自动生成报告,再配合现有告警通道推送,比手工翻控制台高效一个量级。
5. 常见问题与排查技巧实录
这套环境我在多台机器上装过,也帮同事排查过不少问题,下面这些是出现频率最高的坑。
5.1 访问被拒绝
执行查询时报AccessDenied是最常见的。先说结论:这事十有八九是 IAM 权限不够,而不是 Steampipe 的问题。Steampipe 的每个表都会调用对应的 API 操作,比如查aws_s3_bucket至少需要s3:ListAllMyBuckets,查aws_iam_user需要iam:ListUsers。
排查思路:
aws iam list-users如果 CLI 也报权限错误,那就是 IAM 策略的问题,回到 AWS 控制台调整策略后再试。如果 CLI 能过但 Steampipe 不行,检查一下 Steampipe 进程拿到的凭证是不是你想要的那一份。在 shell 里执行:
env | grep AWS看有没有历史遗留的AWS_ACCESS_KEY_ID、AWS_PROFILE环境变量覆盖了你的默认配置。我遇到过好几次,明明改了~/.aws/credentials,但 shell 里残留的变量还在“劫持”凭证,导致 Steampipe 读到的还是旧账号。
5.2 查询超慢
Steampipe 查数据是实时调 API,不是本地缓存,所以一个table scan慢是正常的。比如aws_s3_bucket在全区域查询时,插件会对每个区域调用一次 ListBuckets,如果你的配置里 regions 写了一大串,耗时自然翻倍。
优化手段有几个:
- 在连接配置里只列你真正关心的区域,不要图省事写
["*"] - 查询时尽量在 SQL 里带 where 条件,比如通过
where region = 'us-east-1'提前过滤 - 大结果集用
limit控制输出,先看结构再考虑全量导出
另外提醒一句:Steampipe 的第一次查询会比较慢,是因为它要建立到 AWS 的 API 连接池。同一个交互会话里后续查询会明显变快,这是正常的,不用慌。
5.3 插件版本冲突
Steampipe 升级之后,旧插件可能不兼容。现象通常是执行查询时报plugin not found或connection is not available。解决办法很直接:更新插件。
steampipe plugin update aws如果还不行,就把插件卸载重装:
steampipe plugin uninstall aws steampipe plugin install aws日常使用中建议定期执行steampipe plugin update --all,保持插件版本跟主程序匹配。Steampipe 更新频率不算低,主程序和插件版本错开一两个版本就可能出幺蛾子。
5.4 输出格式的坑
用--output json时,如果你的 SQL 查出了嵌套字段(比如 tags 是 jsonb 类型),JSON 输出里会包含多层嵌套结构,这跟你在交互终端看到的扁平表格不太一样。写脚本解析时务必先跑一条小查询确认输出结构,别想当然地按jq '.rows[0].tags'去取,层级可能比你预期的深。
经验之谈:把复杂查询写成
.sql文件,用steampipe query query.sql的方式执行,比在命令行里拼一长串 SQL 靠谱得多。既方便复用,也方便版本管理。
6. 从能用走向好用的一点建议
走到这一步,Steampipe 已经从“能查”变成了“好用”的状态。但说实话,想让它真正在团队或项目里发挥价值,还有几件事值得做。
第一,把常用的审计类查询沉淀成 SQL 文件,放到一个统一目录里做版本管理。不要每次临时敲,时间一长你会发现自己总在重复造轮子。第二,结合定时任务生成定期报告,把未打标签资源、公网暴露端口、闲置卷这些高风险项做成报表。第三,在多账号场景下,把连接配置按照账号维度命名好,比如aws_prod、aws_staging,别用默认的aws,不然查的时候根本分不清数据来自哪个环境。
我在实际使用中还有一个小习惯:给 Steampipe 单独建一个查询用户,不直接拿 root 跑。虽然 Steampipe 主要依赖本地配置,不存在远程 SQL 注入的问题,但保持规范总没有坏处。另外,如果你用 Steampipe 做 CI/CD 里的资源校验,可以考虑直接调用它的 Go SDK 或者用steampipe query --output json的稳定输出接口来对接现有流程,比封装 AWS SDK 省力得多。
这套东西跑起来之后,你会明显感觉到之前很多需要“翻控制台 + 手写脚本 + 拼表格”的活儿,现在一句话就搞定了,而且查询结果天然就是结构化数据,直接喂给报表工具也行,接到告警规则里也没问题。这就是 Steampipe 真正的价值所在。