最近在做 Serverless 相关的工作. 我们前台用 Cloudfront 和 S3 来, 后台用了 API Gateway 和 lambda 来写逻辑. 在其他同事的建议下使用了SAM, 此时, 在 Cloudformation 模板里面需要使用一个名为 Serverless 的宏. 这样可以大量简化模板的编写, 提高模版的可维护性. 缺点是这个宏的代码不由我们控制, 逻辑对于我们而言也是黑箱子. 这个黑箱子不能正常工作时, 我们是完全没有办法的.
首先是被 AWS 官方认证的 bug. 我们在模板里面定义了若干个 DynamoDB 表, 现有另外一个 stack 需要引用这些表里的内容. 正统的做法当然是在定义了表的模板中定义若干个 Output, 把这些 DynamoDB 的属性(比如 Arn)export 出去, 这样其他 Stack 就可以通过 ImportValue 来引用了. 我们加入这些 Output 后更新这个 stack 会报内部错误而不能继续. 我们各种尝试后交给 AWS 客服解决, AWS 工程师进一步将整个 stack 削减到只有一个 DynamoDB 的表, 加入 Output, 同时使用了前述的 Serverless 宏, 这样就能重现我看到的内部错误. 另外, 如果我们通过 Changeset 来更新, 则不会触发问题, 而当我们直接更新模板时, 就会出现问题. 我们目前解决方案是在其他需要使用 Dynamodb 表的模板中将表的 Arn 人肉拼出来, 虽然能工作, 但是毕竟只是 hack.
第二个被 AWS 官方认为不是 bug, 但是我个人认为是 bug. 在使用 API Gateway 时, 一般修改了参数或属性时我们都需要做部署, 在 Cloudformation 中做 API Gateway 的部署时需要加入类型为 Deployment 资源. 在使用宏的情形下, 我们观察到宏有时会自动创建这个资源, 实现自动部署, 所以这个操作我们认为这个宏可以全部搞定, 没多去深究细节. 直到有一天我们通过 API Gateway 调用后台的 lambda 时发现 lambda 根本没被访问到, API Gateway 就直接返回了 502. 打开 API Gateway 的详细日志时发现日志的最后一条报权限错误, 即 API Gateway 没有权限访问这个 lambda. 再仔细一看, API Gateway 试图访问的 lambda 函数根本不是我们当前 stack 中有的函数, 于此, 我们意识到是 Deployment 没有被触发. 咨询 AWS 客服后被答复, 这是期待的行为, 因为模板里函数的 LogicalID 没有变, 所以不会触发 Deployment. 但是写过 Cloudformation 模板的同学都知道, 一个资源的 LogicalID 是很少会改动的. 这个宏自动创建 Deployment 资源的依据是 LogicalID, 未免太过儿戏.
第三个算是无伤大雅的小问题, 不过仍然算是缺陷. Cloudformation 自带的模板校验命令只会校验 yaml/json 语法, 不会做更深一层的检查, 在开发同学屡次改错模板后, 我们希望在测试流程中添加一个靠谱的模板校验步骤, 我们看上了 AWS 的这个开源工具 cfn-python-lint, 结果用这货来跑我们的模板时就报错了, 即使这个模板在线上部署时运行如常, 原因是 AWS 对 SAM 的支持不够完善, GH 上有相关讨论.
结论: 玩 Serverless 的同学们遇到 SAM 这货请绕路. 尤其是 Serverless 这个宏可能是大坑.
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.