如何從官方 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 }}"}

就是這樣,不要忘記在測試之後刪除你的資源,或者為什麼不建立一個角色來刪除正在執行的例項:-)