### 管理 Amazon 的 EC2 实例
> The most amazing achievement of the computer software industry is its continuing cancellation of the steady and staggering gains made by the computer hardware industry.
>
> — Henry Petroski
如果你觉得你的电脑近年来变得比较慢,这可能是正确的。 对于大多数应用程序而言,你已不必将所有的计算能力(computing power) 全部挤进你办公桌下的一个米色盒子里。 为了解决这个问题,计算能力已经成为一种可以在网上购买的商品。
亚马逊不只是卖书了:他们也卖首饰、摩托车、叶鼓风机,以及对我们当前目的有用的计算能力。 你可以用信用卡签约使用 **Amazon Web Services**,并根据你的需要创建众多的服务器实例, 每个服务器基于小时计费。如果你只是想试水,可以运行一个免费最长一年的微型实例。 如果你正在寻找将你的一部分基础设施迁移到公共云的方案,这是一个不错的实验方式。
本处方将向你展示一个使用 Puppet 创建并自动供应一个 **EC2** 实例的简单方法。 尽管还可以使用更强大的方式实现,包括使用 MCollective,但作为教学目的, 我们将只做最低限度的必要的工作:让一个实例运行起来并应用 Puppet 配置清单。 一旦你获得了基本思路,你就可以以此作为基础加入你自己的改良和改进。
#### 准备工作
你需要一个 **Amazon Web Services**(**AWS**)账号。如果还没有,请到 [http://aws-portal.amazon.com/gp/aws/developer/subscription/index.html?productCode=AmazonEC2](http://aws-portal.amazon.com/gp/aws/developer/subscription/index.html?productCode=AmazonEC2) 注册。
你需要 AWS 访问的 key ID,这个秘密访问 Key 对应于你的 AWS 账号。你可以在这个页面找到它: [http://aws-portal.amazon.com/gp/aws/developer/account/index.html?action=access-key](http://aws-portal.amazon.com/gp/aws/developer/account/index.html?action=access-key) 。
你还需要访问 EC2 实例的 SSH 密钥对。为此,你需要如下步骤:
1. 在 [https://console.aws.amazon.com/ec2/home](https://console.aws.amazon.com/ec2/home) 登录 AWS 管理控制台。
2. 选择 **Amazon EC2 标签**,在导航部分的标题 **Network & Security** 上单击 **Key Pairs**。
3. 单击 **Create key pair**,当提示出现后下载 keypair 文件。将此文件保存到一个安全的地方, 并使用如下命令为它设置模式为 0600 的权限:
```
# chmod 600 bitfield.pem
```
#### 操作步骤
1. 创建 fog 模块:
```
# mkdir /etc/puppet/modules/fog
# mkdir /etc/puppet/modules/fog/manifests
# mkdir /etc/puppet/modules/fog/files
```
2. 使用如下内容创建 /etc/puppet/modules/fog/manifests/init.pp 文件:
```
class fog {
package { "fog":
ensure => installed,
provider => gem,
}
file { "/usr/local/etc/fog_credentials":
source => "puppet:///modules/fog/fog_credentials",
}
file { "/usr/local/bin/boot-ec2":
source => "puppet:///modules/fog/boot-ec2.rb",
mode => "755",
}
file { "/usr/local/bin/bootstrap-ec2":
source => "puppet:///modules/fog/bootstrap-ec2.sh",
mode => "755",
}
}
```
3. 使用如下内容创建 /etc/puppet/modules/fog/files/boot-ec2.rb 文件 (修改 :private_key_path 参数指向你自己的 AWS 私钥文件):
```
#!/usr/bin/ruby
require 'rubygems'
require 'fog'
HOSTNAME = 'devbox'
@server = ''
Fog.credentials_path = '/usr/local/etc/fog_credentials'
def command( cmdline )
puts "Running command: #{cmdline}"
res = @server.ssh( "sudo #{cmdline}" )[0]
puts res.stdout
puts res.stderr
end
def create()
puts "Bootstrapping instance..."
connection = Fog::Compute.new( { :provider => 'AWS' } )
@server = connection.servers.bootstrap( :key_name =>
'bitfield',
:private_key_path =>
'~/bitfield.pem',
:username => 'ubuntu')
@server.wait_for { ready? }
@server.reload
puts "Instance name: #{@server.dns_name}"
puts "Setting hostname..."
@server.ssh( "sudo hostname #{HOSTNAME}" )
end
def copy_bootstrap_files()
puts "Copying bootstrap files..."
@server.scp( "puppet.tar.gz", "/tmp" )
@server.scp( "/usr/local/bin/bootstrap-ec2", "/tmp" )
end
def bootstrap()
puts "Bootstrapping..."
command( "sudo sh /tmp/bootstrap-ec2" )
end
create()
copy_bootstrap_files()
bootstrap()
```
4. 使用如下内容创建 /etc/puppet/modules/fog/files/bootstrap-ec2.sh 文件:
```
#!/bin/bash
apt-get update
apt-get -y install puppet
apt-get -y install git-core
cd /root
tar xzf /tmp/puppet.tar.gz
puppet --modulepath=/root/puppet/modules \
/root/puppet/manifests/site.pp
```
5. 使用如下内容创建 /etc/puppet/modules/fog/files/fog_credentials 文件 (使用你自己的 AWS 凭证替换相应的值):
```
:default:
:aws_access_key_id: AKIAI5RGMC3QRPO3AJWR
:aws_secret_access_key: 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
```
6. 添加如下的节点声明,此节点将会应用 EC2 实例:
```
node devbox {
file { "/etc/motd":
content => "Puppet power!\n",
}
}
```
7. 添加如下代码到一个节点:
```
include fog
```
8. 运行 Puppet:
```
# puppet agent --test
info: Retrieving plugin
info: Caching catalog for cookbook.bitfieldconsulting.com
info: Applying configuration version '1313160844'
notice: /Stage[main]/Fog/Package[fog]/ensure: ensure changed
'purged' to 'present'
notice: /Stage[main]/Fog/File[/usr/local/bin/bootstrap-ec2]/
ensure: defined content as '{md5}5bc2ffb3b5aa94b33b17d419625ecbab'
notice: /Stage[main]/Fog/File[/usr/local/bin/boot-ec2]/ensure:
defined content as '{md5}dadc835c6e52c89cb928d60db7677713'
notice: /Stage[main]/Fog/File[/usr/local/etc/fog_credentials]/
ensure: defined content as '{md5}3b140aedac170bbfcc2837077e03bb93'
notice: Finished catalog run in 1.67 seconds
```
9. 在你的工作目录中,为分发 EC2 实例创建一个 Puppet 的 tar 包。 最简单的方法是对你现有的 Puppet 仓库(对于 git 的裸仓库需要先检出)执行 tar 命令:
```
# cd /etc
# tar czf /tmp/puppet.tar.gz --exclude .git puppet
# cd -
# mv /tmp/puppet.tar.gz .
```
10. 运行 boot-ec2 脚本:
```
# boot-ec2
Bootstrapping instance...
Instance name: ec2-107-20-59-174.compute-1.amazonaws.com
Setting hostname...
Copying bootstrap files...
Bootstrapping...
Running command: sudo sh /tmp/bootstrap.sh
sudo: unable to resolve host devbox
sudo: unable to resolve host devbox
...
notice: //Node[devbox]/File[/etc/motd]/content: defined content as
'unknown checksum'
```
11. 登录到该实例检查你的配置清单已被正确应用:
```
# ssh -i bitfield.pem ubuntu@ec2-107-20-59-174.compute-1.amazonaws.com
Puppet power!
ubuntu@devbox:~$
```
12. 你已经得到了一个由 Puppet 管理控制的云服务器! 如果想要创建十个实例,运行此脚本十次即可。 不要忘记使用完毕之后,要在 AWS 管理控制台关闭这些实例(按使用时间付费的哦!)。
#### 工作原理
**Fog** 是一个用于管理云资源的 Ruby 库,包括 EC2 和其他一些供应商(如 Rackspace)。 尽管你可以使用 Amazon 自己提供的 ec2-tools 脚本启动和管理 EC2 实例, 但使用 Fog 可以轻而易举地将你的实例迁移到另一个供应商, 而且还不需要你为运行 ec2-tools 而安装 Java 以及其他依赖的软件。 对于创建 EC2 基础设施的这两种方法来说,我可以自信的说我更喜欢用 Fog, 尽管事实上它几乎没有文档(而 Amazon 却有很多)。
在 boot-ec2 脚本中,我们用自己的凭证使用 Fog 创建了一个新的 EC2 实例, 并为其传输了一份 Puppet 配置清单的拷贝。 然后我们复制 bootstrap-ec2 脚本,它用于安装 Puppet 以及应用程序的配置清单。
对于本例而言,配置清单相当简单:
```
file { "/etc/motd":
content => "Puppet power!\n",
}
```
你可以轻松地修改它,比如,与你的生产应用服务器同名。 这对于快速部署位于物理负载平衡器之后的大量应用程序服务器来说是一个好方法, 例如,处理突然飙升的需求。另外,你也可以使用 EC2 实例作为测试服务器或临时服务器 (这完全取决于你自己的需求)。
#### 更多用法
除了你的信用卡强加给你的限制之外,此处的脚本没有对你能部署的 EC2 实例数量做任何限制。 所以你可以尝试修改此处所示的脚本,启用一个由命令行参数设置的实例数量。
你或许想要创建不同类型的实例,例如:Web 服务器、人工队列服务器(queue worker servers)等。 你可以修改启动脚本,携带一个参数指定要启动的实例类型。
此处显示的脚本有一个重要的限制,就是它以 tar 包形式提供了一个包含你的 Puppet 配置清单快照的实例。 显然,当你在 Puppetmaster 上修改你的 Puppet 配置清单后,EC2 实例不受影响,即更改不会被应用到 EC2 实例。 基于简单的目的,本处方中的例子仅仅使用 Puppet 构建了初始的服务器,它没有运行 Puppet 守护进程也没与 Puppetmaster 服务器联系。
这对于短生存期或仅为指定目的而运行的 EC2 实例往往还是不错的。 如果你需要运行长生存期的服务器,或者需要通过 Puppet 更新 EC2 实例服务器, 就应该修改脚本使实例能与你的 Puppetmaster 服务器取得联系。 要解决的是证书签名问题,例如你可以对证书进行预签名并伴随 bootstrap 脚本一同部署到 EC2 实例。 另外一种方法是,在脚本中通过 SSH 或 MCollective 登录 Puppetmaster 服务器并对实例的证书请求进行签名。 这两种证书签名的机制或简单或复杂,随你选择。
你可能还想使用其他的云服务提供商,例如 Rackspace 或 Linode。 为此,你需要对脚本做轻微地修改。 请参考 Fog 文档获取相关的详细信息,网址为 [http://fog.io](http://fog.io) 。
> ![注记](https://box.kancloud.cn/2016-05-12_5733eec619643.png)
> 你也可以使用 Puppet 新的云供应商扩展(Cloud Provisioner extension)来管理 EC2 实例; 要获取相关的详细信息请参考 Puppet Labs 的 [http://docs.puppetlabs.com/guides/cloud_pack_getting_started.html](http://docs.puppetlabs.com/guides/cloud_pack_getting_started.html) 页面。
#### 参见本书
* 本章的 [使用 Vagrant 管理虚拟机](#ch08sec07) 一节
- Puppet 2.7 Cookbook 中文版
- 中文翻译版
- 译者序
- 项目缘起
- 翻译方法
- 社区链接
- 社区建议
- 贡献者
- 原书版权页
- 关于作者
- 前言
- 本书内容
- 阅读前提
- 适用读者
- 格式约定
- 读者反馈
- 客户支持
- 下载案例代码
- 勘误表
- Puppet 基础设施
- 使用版本控制
- 使用提交钩子
- 使用 Rake 部署变更
- 配置 Puppet 的文件服务器
- 从 cron 运行 Puppet
- 使用自动签名
- 预签名证书
- 从 Puppet 的 filebucket 检索文件
- 使用 Passenger 扩展 Puppet 的部署规模
- 创建去中心化的分布式 Puppet 架构
- 监控、报告和排错
- 生成报告
- 通过 Email 发送包含特定标签的日志信息
- 创建图形化报告
- 自动生成 HTML 文档
- 绘制依赖关系图
- 测试你的 Puppet 配置清单
- 执行模拟运行
- 检测编译错误
- 理解 Puppet 的错误信息
- 显示命令的输出结果
- 输出调试信息
- 检查配置设置
- 使用标签
- 使用运行阶段
- 使用不同的环境
- Puppet 语言及其写作风格
- 使用 Puppet 社区规范
- 使用模块
- 使用标准的命名规范
- 使用嵌入式 Ruby 代码
- 使用纯 Ruby 代码书写配置清单
- 遍历多个项目
- 书写强大的条件语句
- 在 if 语句中使用正则表达式
- 使用选择器和 case 语句
- 检测字符串中是否包含指定的值
- 使用正则表达式替换
- 书写更优质的配置清单
- 使用资源的数组
- 使用 define 资源
- 指定资源的依赖关系
- 使用节点继承
- 使用类的继承和重载
- 给类传递参数
- 书写可重用的跨平台配置清单
- 获得系统的环境信息
- 导入动态信息
- 从 CSV 文件导入数据
- 给 Shell 命令传递参数
- 使用文件和软件包
- 为配置文件添加配置行
- 使用 Augeas 自动修改配置文件
- 使用配置片段构建配置文件
- 使用 ERB 模板
- 在模板中遍历数组
- 从第三方仓库安装软件包
- 配置 APT 软件仓库
- 配置 GEM 仓库
- 从源码包自动构建软件
- 比较软件包的版本
- 用户和虚拟资源
- 使用虚拟资源
- 使用虚拟资源管理用户
- 管理用户基于密钥的 SSH 访问
- 管理用户的自定义文件
- 有效地分发 cron 任务
- 当文件更新时运行命令
- 使用主机资源
- 为文件资源指定多个源
- 使用文件资源递归地分发整个目录树
- 清理过期的旧文件
- 使用日程表资源
- 资源的审计
- 临时禁用资源
- 管理时区
- 应用程序
- 管理 Apache 服务
- 创建 Apache 虚拟主机
- 创建 Nginx 虚拟主机
- 创建 MySQL 数据库及用户
- 管理 Drupal 站点
- 管理 Rails 应用程序
- 服务器和云基础设施
- 部署 Nagios 监控服务器
- 使用 Heartbeat 构建高可用服务
- 管理 NFS 服务和文件共享
- 使用 HAProxy 为多个 web 服务器实现负载均衡
- 使用 iptables 管理防火墙
- 管理 Amazon 的 EC2 实例
- 使用 Vagrant 管理虚拟机
- 外部工具和 Puppet 生态环境
- 创建 Facter 的自定义 fact
- 在运行 Puppet 之前和之后执行命令
- 从 Shell 会话生成 Puppet 配置清单
- 从运行的系统上生成 Puppet 配置清单
- 使用 Puppet Dashboard
- 使用 Foreman
- 使用 MCollective
- 使用公共模块
- 使用外部节点分类器
- 创建自定义的资源类型
- 创建自定义的提供者