Creating a custom CoreOS AMI from scratch using Ansible - Part 1
Installing CoreOS to disk is easy using the self-contained installation script as described in the CoreOS documentation.
The problem is that you cannot normally target the installation process on the disk the instance is booted from. On AWS, and additional EBS disk can be attached to the instance and used as the target installation device.
This first post will quickly explain how the process can be fully automated using the following tools:
- Ansible a simple IT automation engine
- Ansible Core Modules for Cloud - AWS to manage EC2, EBS and AMI
A second post will soon describe how to customize the installation.
The process is the following:
- Create a helper instance from an existing AMI (Amazon Linux) from the AWS Marketplace
- Attach an 4GB EBS disk to it
- Fetch the self-contained installation script from the github repository
- Run it with the appropriate arguments to install the OSE on the EBS disk
- Create a snapshot of the EBS disk on which CoreOs has been installed
- Terminate the helper instance to avoid costs
- Register an AMI from the snapshot
There are many ways to use Ansible. Here is a simple sequential playbook to illustrate the process. Define your own account-specific parameters and adapt to your region. It currently depends on the following https://github.com/ansible/ansible-modules-core/pull/4075.
---
# Simple CoreOS image creation playbook
- name: Bootstrap image process begins
hosts: localhost
connection: local
gather_facts: False
tasks:
- name: Provision Helper Instance
ec2:
region: "eu-west-1"
zone: "eu-west-1a"
instance_type: "t2.micro"
image: "ami-f9dd458a"
key_name: "{{ key_name }}"
group: "{{ sec_group_name }}"
vpc_subnet_id: "{{ vpc_subnet_id }}"
wait: true
exact_count: 1
count_tag:
Name: "helper"
volumes:
- device_name: "/dev/xvda"
volume_size: 8
delete_on_termination: true
register: ec2
- name: Attach a 4 GB EBS volume to helper instance
ec2_vol:
region: "eu-west-1"
zone: "eu-west-1a"
instance: "{{ item.id }}"
state: present
volume_size: "4"
device_name: "/dev/xvdb"
delete_on_termination: yes
with_items: "{{ ec2.instances }}"
register: ec2_vol_bootdisk
- name: Saving EBS volume id (required later to snapshot it)
local_action: command echo {{ item.volume_id }}
register: ec2_vol_bootdisk_id
with_items: "{{ ec2_vol_bootdisk.results }}"
- name: Wait for cloud-init process to setup SSH keys (could be optimized)
pause: minutes=2
- name: Add helper instance to running instances host group
add_host: hostname={{ item.private_dns_name }} groupname=launched
with_items: "{{ ec2.instances }}"
- name: Triggering installation process on helper instance
hosts: launched
remote_user: "ec2-user"
gather_facts: False
tasks:
- name: Fetching custom installation script on the helper instance
get_url: url=https://raw.githubusercontent.com/coreos/init/master/bin/coreos-install dest=/tmp/install.sh mode=755
- name: Running installation script on helper instance
shell: /tmp/install.sh -d /dev/xvdb >> install.log 2>&1 chdir=/tmp/
become: true
- name: Creating AMI
hosts: localhost
connection: local
gather_facts: False
tasks:
- name: Snapshotting AMI root device on EBS volume '{{ ec2_vol_bootdisk.results.volume_id }}'
ec2_snapshot:
region: "eu-west-1"
volume_id: "{{ item.volume_id }}"
register: snapshot_bootdisk
with_items: "{{ ec2_vol_bootdisk.results }}"
- name: Terminating helper instance '{{ec2.instances }}'
ec2:
region: "eu-west-1"
zone: "eu-west-1a"
instance_ids: "{{ item.id }}"
state: absent
with_items: "{{ ec2.instances }}"
- name: Registering image
ec2_ami:
region: "{{ eu-west-1 }}"
name: "CoreOS latest"
description: "CoreOS - latest"
snapshot_id: "{{ snapshot_bootdisk.results[0].snapshot_id }}"
architecture: "x86_64"
root_device_name: "/dev/xvda"
virtualization_type: "hvm"
sriov_net_support: "simple"
delete_root_volume_on_termination: true
volumes:
- device_name: "/dev/xvda"
snapshot: "{{ snapshot_bootdisk.results[0].snapshot_id }}"
volume_size: "4"
device_type: gp2
delete_on_termination: true
register: ec2_ami
- name: ID of newly AMI created
debug: msg="AMIID={{ ec2_ami.image_id }}"