在 EC2 上利用 Ansible 部署 CentOS 映像
我会讨论如何在 ECS2 上利用 Ansible 部署一些 CentOS 实例,这当然是通过一台 CentOS 机器来进行。
首先,你不需在你的管理系统上安装 AWS 工具,这样亦省掉安装 Java 的需要。我们的 CentOS 管理系统需要下列组件:
Ansible 及它所依赖的小量组件。你可在 gettingstarted 找到协助。
- Euca2ools,一套与 Amazon 的 EC2 及 S3 服务沟通的命令行工具。我认为它们是对 Amazon 工具的一种响应,不过它们是用 Python 写成的。除此之外,我们亦需要它针对 Ansible 所需的组件。Euca2ools 已收录在 EPEL,因此安装很简单。
- 一大套从 AWS 网页取得的金钥及凭证码。我不会以这些程序来烦扰,但我会告诉你需要正确地设置那些变量才能顺利地操作。
你已经创建了你的 AWS 帐户,而且取得与 EC2 沟通用的凭证密码。由此点开始,我们需要在指令壳的环境下设置以下变量:
export EC2_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxx" export EC2_SECRET_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" export EC2_URL=https://ec2.amazonaws.com export S3_URL=https://s3.amazonaws.com:443 export AWS_ACCESS_KEY_ID=${EC2_ACCESS_KEY} export AWS_SECRET_ACCESS_KEY=${EC2_SECRET_KEY}
1. Ansible 清单
Ansible 采用一个清单来描述被管理的机器、它们的群组及各机器的特定变量。这个清单缺省位于 /etc/ansible/hosts,但我可通过设置 $ANSIBLE_HOSTS 来更改它的路径。信不信由你,但一个清单档可以短至这样,而这正是我们传给 Ansible 来引导 EC2 实例的清单:
[local] 127.0.0.1
我们或许需要部署在世界另一端的 ECS 实例(至少我有需要)。我们要怎样办?我们如何得悉它们的主机名称?
ec2.py 是一个供 Ansible 用脚本,能枚举可访问的 EC2 实例。要是我执行这个程序,我会得到以下的 JSON 输出,因为我已经有运行中的实例。(你可把实例编号和公共主机名称与先前所见的作个比较。)
{ "i-df75cea0": [ "ec2-54-242-141-105.compute-1.amazonaws.com" ], "key_jp1": [ "ec2-54-242-141-105.compute-1.amazonaws.com" ], "security_group_default": [ "ec2-54-242-141-105.compute-1.amazonaws.com" ], "type_m1_small": [ "ec2-54-242-141-105.compute-1.amazonaws.com" ], "us-east-1": [ "ec2-54-242-141-105.compute-1.amazonaws.com" ], "us-east-1a": [ "ec2-54-242-141-105.compute-1.amazonaws.com" ] }
虽然我们只有一台机器,但它出现于不同群组中。这些群组让我们以 Ansible 进行部署时能针对特定的群组。(注:ec2.py 这个程序把它的输出缓存在设置路径内,因此该清单也许需要一分钟才会刷新。)要是我以特定的主机来呼唤该清单程序,我会取得针对该实例的变量:(我已删减了部份输出)
ec2.py --host ec2-54-242-141-105.compute-1.amazonaws.com { "ec2_architecture": "x86_64", "ec2_dns_name": "ec2-54-242-141-105.compute-1.amazonaws.com", "ec2_hypervisor": "xen", "ec2_id": "i-df75cea0", "ec2_image_id": "ami-8a8932e3", "ec2_instance_type": "m1.small", "ec2_ip_address": "54.242.141.105", "ec2_key_name": "jp1", "ec2_launch_time": "2012-11-18T10:57:20.000Z", "ec2_monitored": false, "ec2_placement": "us-east-1a", "ec2_root_device_type": "ebs", "ec2_security_group_ids": "sg-29652b41", "ec2_security_group_names": "default", "ec2_virtualization_type": "paravirtual" }
你可利用 ec2.py 清单脚本让 Ansible 在 EC2 上与实例沟通。你只需把该执行档安装在 /etc/ansible/hosts 或把 $ANSIBLE_HOSTS 指向该执行档。
它能否 ping?
$ export ANSIBLE_HOSTS=~/ec2.py $ ansible -u root ec2-54-242-141-105.compute-1.amazonaws.com -m ping ec2-54-242-141-105.compute-1.amazonaws.com | success >> { "changed": false, "ping": "pong" }
在这里我可以把主权移交给你,你应该能成功地利用 Ansible 来安装及设置你的 EC2 实例。但我不会就此罢放:让我们进行一些部署。
2. Ansible 在 EC2 上引导一个 CentOS 实例
Ansible 的 ec2 模块 在 EC2 上创建一个实例并选择性地等待该实例进入可用状态。(注:可用状态不等同完成开机 —— 这可能需时数分钟。)创建实例的时候,我要指定用哪对 SSH 金钥(我们为此创建一条名叫 jp1 的金钥)、映像名称、及一些在模块的文档内已描述的参数。我想特别指出一个名为 group 的参数。这就是所谓的 _安全性群组_ ,而据我所知,它指定 AWS 的防火墙。按照缺省值只有 22 号端口(SSH)可进入我的实例,但我正在创建一台网页服务器,因此我(至少)也想用 80 号端口。
要创建一个 EC2 安全性群组,我采用以下指令:
$ euca-add-group -d "Web Servers" webs-a $ euca-authorize -P tcp -p 80-80 -s 0.0.0.0/0 webs-a $ euca-authorize -P tcp -p 22-22 -s 0.0.0.0/0 webs-a
你所指定的安全性群组稍后会在 Ansible 的清单(ec2.py)内显示为一个群组。
--- - hosts: - 127.0.0.1 connection: local gather_facts: False vars: keypair: jp1 instance_type: m1.small security_group: webs-a image: ami-8a8932e3 mail_from: Ansible mail_to: charlie vars_prompt: shortname: "What is the shortname of this host to be?" tasks: - name: Launch new EC2 instance local_action: ec2 keypair=${keypair} group=${security_group} instance_type=${instance_type} image=${image} wait=true register: ec2 # - name: Send e-mail to admins local_action: mail from=${mail_from} to=${mail_to} subject="EC2 instance ${ec2.instances[0].id}" body="EC2 instance ${ec2.instances[0].id} created on ${ec2.instances[0].public_ip}"
你在注册 ec2 模块时所取得的变量,ec2,含有以下数值,我会在寄给官理员的电邮中加入它:
{ "instances" : [ { "public_ip" : "107.22.159.172", "id" : "i-3d1ba042" } ], "changed" : true }
让我在 playbook 上执行 Ansible。留意我采用只含有 localhost 的简便清单,因为这些模块在我的 Ansible 管理机器而非远程上运行。
$ ansible-playbook newinstances.yml What is the shortname of this host to be?: : web31 PLAY [127.0.0.1] ********************* TASK: [Launch new EC2 instance] ********************* changed: [127.0.0.1] TASK: [Send e-mail to admins] ********************* ok: [127.0.0.1] PLAY RECAP ********************* 127.0.0.1 : ok=2 changed=1 unreachable=0 failed=0
再复述一遍:暂时 Ansible 利用本地的模块(即我们的管理机器)遥距地在 EC2 上创建一个 CentOS 实例并发电邮。现在我可采用一些 euca- 工具来查看及查阅现况。
此外:请耐心等待:该 EC2 实例也许要数分钟才能运作起来。还有:我收到邮件:
Date: Sun, 18 Nov 2012 12:51:07 +0100 (CET) From: Ansible@c6.ww.example.com Subject: EC2 instance i-3d1ba042 EC2 instance i-3d1ba042 created on 107.22.159.172
3. Ansible 部署 CentOS 实例
经过数分钟后,我利用 Ansible 来部署刚运作起来的实例。作为示范,我会安装 Apache 网页服务器及一个范本,免得太复杂。
--- - hosts: - security_group_webs-a user: root connection: paramiko gather_facts: false tasks: - name: Install | Apache action: yum pkg=httpd state=installed - name: Machine | Launch Apache service action: service name=httpd state=started enabled=true - name: Machine | Disable firewall (fixme) action: service name=iptables state=stopped enabled=false # - name: Web | Install Web templates action: template src=templates/index.j2 dest=/var/www/html/index.html
Ansible 所触及的主机是用 ec2.py 所枚举的群组来指定的,而我是以 root 来连接,因为我们的 jp1 SSH 金钥是针对该用户植入 EC2 内。当 playbook 已经运行起来,我便可以利用浏览器连接到 ec2-*.compute-1.amazonaws.com 主机或它的公共 IP 地址。
该实例仍在等待我们对它有所行动。我们可告诉 Ansible 今次采用另一份清单,例如:EC2 的清单,然后引导设置的 playbook:
ANSIBLE_HOSTS=~/ec2.py ansible-playbook apache.yml PLAY [security_group_webs-a] ********************* TASK: [Install | Apache] ********************* changed: [ec2-107-22-159-172.compute-1.amazonaws.com] TASK: [Machine | Launch Apache service] ********************* changed: [ec2-107-22-159-172.compute-1.amazonaws.com] TASK: [Machine | Disable firewall (fixme)] ********************* changed: [ec2-107-22-159-172.compute-1.amazonaws.com] TASK: [Web | Install Web templates] ********************* changed: [ec2-107-22-159-172.compute-1.amazonaws.com] PLAY RECAP ********************* ec2-107-22-159-172.compute-1.amazonaws.com : ok=4 changed=4 unreachable=0 failed=0
部署完成,而长驻服务也在运行中。
4. 结论
CentOS 在 EC2 上很棒,利用 Ansible 来部署 CentOS 亦然。我相信做这些事的方法很多,而你也许会采取另一个途径。
Translation of revision 11