如何从官方 Amazon AMI 启动 EC2 实例修改它并将其存储为新的 AMI

使用 Ansible 配置 AWS EC2 实例时,这是一个非常常见的工作流程。本文假定你对 Ansible 有基本的了解,最重要的是,假设你已正确配置它以连接到 AWS。

正如 Ansible 官方文档所坚持的那样 ,我们将使用四个角色:

1- ami_find 获取我们将启动 EC2 实例的 ami id。

2- ec2_ami_creation 有效启动 EC2 实例。

3- code_deploy 用于修改实例; 这可能是任何事情,所以我们只需将文件传输到目标机器。

4- build_ami 基于运行的 ec2 实例构建我们的新映像。这篇文章假设你处于 Ansible 项目的最高级别:my_ansible_project

第一个角色: ami_find

cd my_ansible_project/roles && ansible-galaxy init ami_find

在这个角色中我们将使用 ec2_ami_find 模块,作为一个例子,我们将搜索一个 Ubuntu 机器并获得它的 ami_id (ami-xxxxxxxx)。现在编辑 my_ansible_project/roles/ami_find/tasks/main.yml 文件:

    name: "ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"
    sort: name
    sort_order: descending
    sort_end: 1
    region: "{{ aws_region }}"
  register: ami_find
- set_fact: ami_ubuntu="{{ ami_find.results[0].ami_id }}"

第二个角色: ec2_ami_creation

在这里,我们将使用我们从第一个角色获得的 ami_id,然后基于它启动我们的新实例:

cd my_ansible_project/roles && ansible-galaxy init ec2_ami_creation

在这个角色中,我们将使用最重要的 ec2_module 来启动我们的实例。现在编辑 my_ansible_project/roles/ec2_ami_creation/tasks/main.yml 文件:

    region: "{{aws_region}}"
  register: vpc
- name: creation of security group of the ec2 instance
  ec2_group:
    name: example
    description: an example EC2 group
    region: "{{ aws_region }}"
    rules:
      - proto: tcp
        from_port: 22
        to_port: 22
        cidr_ip: 0.0.0.0/0
    state: present
  register: ec2_sg

- name: create instance using Ansible
  ec2:
    key_name: "{{ ansible_key }}"
    group: example
    vpc_subnet_id: "{{vpc.subnets[0].id}}"
    instance_type: "{{ instance_type }}"
    ec2_region: "{{ aws_region }}"
    image: "{{ base_image }}"
    assign_public_ip: yes
    wait: yes
  register: ec2

- set_fact: id={{ec2.instances[0].id}}

- name: adding the newly created instance to a temporary group in order to access it later from another play
  add_host: name={{ item.public_ip }} groups=just_created
  with_items: ec2.instances

- name: Wait for SSH to come up
  wait_for: host={{ item.public_dns_name }} port=22 delay=10 timeout=640 state=started
  with_items: ec2.instances

第三个角色: code_deploy

在这里,我们将配置此实例,该实例已添加到名为 just_created 的组中

cd my_ansible_project/roles && ansible-galaxy init code_deploy

在此角色中,我们将使用 template_module 传输文件并在其中写入计算机主机名。现在编辑 my_ansible_project/roles/code_deploy/tasks/main.yml 文件:

然后移动到角色内的模板文件夹:

cd my_ansible_project/roles/templates 并添加一个名为 my_file.txt.j2 的文件,其中包含:

my name is {{ ansible_hostname }}` 

第四个角色: build_ami

我们现在将使用 ec2_ami 模块创建正在运行的实例的映像 。移动到你的项目文件夹并:

 cd my_ansible_project/roles && ansible-galaxy init build_ami

现在编辑 my_ansible_project/roles/build_ami/tasks/main.yml 文件:

    instance_id: "{{ instance_id }}"
    wait: yes
    name: Base_Image

现在,我想你一直想知道如何协调所有这些角色。我对吗?如果是这样,继续阅读。

我们将编写一个由三个剧本组成的剧本:第一部适用于 localhost 将调用我们的前两个角色,第二部分适用于我们的 just_created 组。最后一个角色将适用于 localhost。为什么 localhost?当我们想要管理一些 AWS 资源时,我们使用本地机器,就这么简单。接下来,我们将使用一个 vars 文件,我们将在其中放入变量:ansible_keyaws_region 等…

在项目顶部创建基础架构文件夹,并在其中添加一个名为 aws.yml 的文件:

ansible_key: ansible
instance_type: t2.small

所以在项目的顶部创建 build_base_image.yml 并添加:

     connection: local
     gather_facts: False
     vars_files:
       - infrastructure/aws.yml
     roles:
       - ami_find
       - { role: ec2_creation, base_image: "{{ ami_ubuntu }}"}

   - hosts: just_created
     connection: ssh
     gather_facts: True
     become: yes
     become_method: sudo
     roles:
       - code_deploy

   - hosts: localhost
     connection: local
     gather_facts: False
     vars_files:
       - infrastructure/aws.yml
     roles:
       - { role: new_image, instance_id: "{{ id }}"}

就是这样,不要忘记在测试之后删除你的资源,或者为什么不创建一个角色来删除正在运行的实例:-)