将什么融入 AWS AMI 以及使用 cloud-init 预置什么?

What to bake into an AWS AMI and what to provision using cloud-init?

我正在使用 AWS Cloudformation 为我的 Web 应用程序设置网络基础设施的众多元素(VPC、安全组、子网、自动缩放组等)。我希望整个过程自动化。我想要单击一个按钮并能够启动整个程序。

我已经成功创建了一个 Cloudformation 模板来设置所有这些网络基础设施。然而,EC2 实例目前启动时没有任何需要的软件。现在我正试图弄清楚如何最好地在他们身上安装该软件。

为此,我使用 Packer.io 创建 AMI。但是有些人反而敦促我使用 Cloud-Init。我应该使用什么启发式来决定将什么融入 AMI and/or 通过 Cloud-Init 配置什么?

例如,我想预配置一个 EC2 实例以允许我 (saqib) 从我自己的笔记本电脑上无需密码登录。因此 EC2 必须有一个用户。该用户必须有一个主目录。在那个主目录中必须有一个包含加密代码的文件 .ssh/known_hosts。我应该将这些目录烘焙到 AMI 中吗?或者我应该使用 cloud-init 来设置它们吗?在这种情况和其他类似情况下我应该如何决定?

决定您应该如何 assemble 服务器、AMI 和基础架构规划的重要因素之一是回答以下问题:在生产中,我需要以多快的速度启动新实例?

这个问题的答案将决定您在 AMI 中烘焙多少与在启动后构建多少。

注意:我的经验是使用 Chef Server,因此我将使用 Chef 术语,但概念对于任何其他配置管理堆栈都是相同的。

一般的经验法则是善待您的 "Infrastructure as Code"。这意味着考虑启动实例的过程,在该机器上创建用户,以及管理 known_hosts 文件和 SSH 密钥的过程,就像您管理应用程序代码一样。能够跟踪源代码中基础架构的更改使管理、重新部署甚至 CI 变得更加容易。

This Chef Introduction 涵盖食谱、食谱、资源等主厨中的术语。它向您展示了如何构建一个简单的 LAMP 堆栈,以及如何使用一个命令轻松地重新启动它。

所以根据你问题中的例子,在较高的层次上我会做以下事情:

  • 使用 Cloudformation 脚本启动基础 Ubuntu Linux AMI(当前为 14.04)。
  • 在实例配置的用户数据部分,引导 Chef 客户端安装过程。
  • 运行 用于创建用户的食谱。
  • 运行 为用户创建 known_hosts 文件的配方

之所以使用像 Chef 这样的工具,是因为您可以将基础架构分解为执行特定功能的小代码块。已经有许多 Cookbook built and available 执行创建服务、安装软件包等的基本构建块。

话虽这么说,但有时为了您的特定领域和要求,您不得不偏离最佳实践。在某些情况下,即使基础架构管理具有所有优势,您仍然需要将项目烘焙到 AMI 中。

假设您的应用程序进行图像处理并且需要使用 ImageMagick。假设您需要从源代码构建 ImageMagick。如果您要通过 Chef Recipes 执行此操作,这可能会将仅编译 ImageMagick 的时间再增加 7 分钟到正常的实例启动时间。如果等待 10-12 分钟对于新实例上线来说太长,那么您可能需要考虑烘焙您自己的 AMI,该 AMI 已经编译并安装了 ImageMagick。

这是一个可以接受的解决方案,但您应该记住,管理您自己的预烘焙 AMI 队列会增加额外的基础架构开销。随着新 AMI 的发布、您扩展到不同的实例类型和不同的 AWS 区域,您将需要更新您的自定义 AMI。

我喜欢将机器配置与环境配置分开。

一般来说,我使用以下内容作为指导:

构建阶段

  • 使用 Packer 之类的工具构建基本机器映像,包括 运行 您的应用程序所需的所有软件。从中创建一个 AMI。
  • 将应用程序安装到创建应用程序映像的基本机器映像上。标记和版本这个工件。不要在此处嵌入特定于环境的内容,例如数据库连接等,因为这会妨碍您轻松地跨不同环境重复使用此 AMI 运行 次。
  • 确保停止所有服务

发布阶段

  • 使用 CFN 之类的工具启动由图像和所需基础设施组成的环境。
  • 使用 Cloud-Init user-data 配置 应用程序环境(数据库连接、日志转发器等)然后启动 applications/services

这种方法提供了最大的灵活性,并清楚地分离了持续交付管道的各种问题。