Vagrant AWS Provider: Difference between revisions
Jump to navigation
Jump to search
(2 intermediate revisions by the same user not shown) | |||
Line 16: | Line 16: | ||
vagrant plugin install vagrant-aws | vagrant plugin install vagrant-aws | ||
vagrant box add dummy https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box | vagrant box add dummy https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box | ||
=Vagrantfile Example= | |||
This is an example. More details about Vagrantfile syntax in: {{Internal|Vagrantfile|Vagrantfile}} | |||
<syntaxhighlight lang='ruby'> | |||
# frozen_string_literal: true | |||
# | |||
# Configuration | |||
# | |||
# | |||
# It is assumed that the environment was already configured with AWS authentication (.aws/credentials or AWS | |||
# environment variables). The VM will be created in the configured account/region. | |||
# | |||
ENVIRONMENT_NAME = "infra-playground" | |||
BASTION_HOST = '1.2.3.4' | |||
AWS_KEYPAIR = 'infra-playground' | |||
SSH_PRIVATE_KEY = "~/.ssh/#{AWS_KEYPAIR}.pem" | |||
SSH_CONFIG_FILE = "#{ENV['HOME']}/.ssh/dev/infra-worker" | |||
# | |||
# This is required by AWS CLI as part of instance provisioning call. It must the ID of the private subnet | |||
# the instance will be attached to. If using environments, this subnet should be the default private subnet | |||
# of the environment. | |||
# | |||
SUBNET_ID = 'subnet-000000000000000' | |||
# | |||
# This is required by AWS CLI as part of instance provisioning call. It must the ID of the security | |||
# group that will protect the access to the instance. Access must be configuring depending on the instance | |||
# requirements. At minimum, it should allow inbound ssh access. | |||
# | |||
SECURITY_GROUP_ID = 'sg-000000000000000' | |||
# | |||
# The AMI of the infra-worker image created by Packer | |||
# | |||
AMI_ID = ENV['AMI_ID'] || 'ami-0000000000000000' | |||
INSTANCE_TYPE = 'm5.4xlarge' | |||
VOLUME_SIZE_GB = 50 | |||
# | |||
# Install vagrant plugin | |||
# | |||
# @param: plugin type: Array[String] desc: The desired plugin to install | |||
def ensure_plugins(plugins) | |||
logger = Vagrant::UI::Colored.new | |||
result = false | |||
plugins.each do |p| | |||
pm = Vagrant::Plugin::Manager.new( | |||
Vagrant::Plugin::Manager.user_plugins_file | |||
) | |||
plugin_hash = pm.installed_plugins | |||
next if plugin_hash.key?(p) | |||
result = true | |||
logger.warn("Installing plugin #{p}") | |||
pm.install_plugin(p) | |||
end | |||
if result | |||
logger.warn('Re-run vagrant up now that plugins are installed') | |||
exit | |||
end | |||
end | |||
def aws_config(name) | |||
value = `aws configure get #{name}`.strip | |||
raise ArgumentError, "aws #{name} config must be set; use 'aws configure set #{name} <value>'" if value.empty? | |||
value | |||
end | |||
def username | |||
ENV['USER'] || 'anonymous' | |||
end | |||
def hostname | |||
"infra-worker-#{username}" | |||
end | |||
# | |||
# Create and configure the AWS instance(s) | |||
# | |||
Vagrant.configure('2') do |config| | |||
ensure_plugins(%w[vagrant-aws]) | |||
config.vm.define :infra_worker do |t| | |||
end | |||
config.vm.hostname = hostname | |||
# | |||
# Use dummy AWS box | |||
# | |||
config.vm.box = 'dummy' | |||
config.vm.synced_folder '.', '/vagrant', disabled: true | |||
# | |||
# Specify AWS provider configuration | |||
# | |||
config.vm.provider 'aws' do |aws, override| | |||
# | |||
# Specify SSH keypair to use, which should match SSH_PRIVATE_KEY | |||
# | |||
aws.keypair_name = AWS_KEYPAIR | |||
aws.instance_type = INSTANCE_TYPE | |||
aws.associate_public_ip = false | |||
aws.elastic_ip = false | |||
# | |||
# Launch configuration | |||
# | |||
aws.ami = AMI_ID | |||
aws.subnet_id = SUBNET_ID | |||
aws.security_groups = [SECURITY_GROUP_ID] | |||
aws.block_device_mapping = [{ 'DeviceName' => '/dev/xvda', 'Ebs.VolumeSize' => VOLUME_SIZE_GB }] | |||
aws.tags = { | |||
'Name' => hostname, | |||
'Created by' => username, | |||
'Environment' => ENVIRONMENT_NAME | |||
} | |||
# | |||
# Specify username and private key path | |||
# | |||
config.ssh.forward_agent = true | |||
override.ssh.username = 'ec2-user' | |||
override.ssh.private_key_path = SSH_PRIVATE_KEY | |||
override.ssh.proxy_command = "ssh -o ExitOnForwardFailure=yes -W %h:%p -i #{override.ssh.private_key_path} %r@#{BASTION_HOST}" | |||
end | |||
config.trigger.after [:up] do |t| | |||
t.info = "Writing ssh config to #{SSH_CONFIG_FILE}" | |||
t.run = { path: '../_common_tools_and_config/bin/configure-ssh-access', args: [SSH_CONFIG_FILE.to_s] } | |||
end | |||
end | |||
</syntaxhighlight> | |||
Companion ssh configuration script <code>configure-ssh-access'</code> | |||
<syntaxhighlight lang='bash'> | |||
#!/usr/bin/env bash | |||
function usage() { | |||
cat << EOF | |||
Write the output of "vagrant ssh-config" to the configuration file specified as first argument. | |||
This script is invoked as part of the "vagrant up" sequence. Various Vagrantfiles that mention | |||
it have the path to it hardcoded. | |||
EOF | |||
} | |||
function main() { | |||
local ssh_config_file=$1 | |||
[[ -z ${ssh_config_file} ]] && { echo "a ssh configuration file must be specified" 1>&2; exit 1; } | |||
mkdir -p $(dirname ${ssh_config_file}) | |||
# | |||
# Ruby won't allow for "-" in host name so we convert it here. "Host a_b" will be converted to "Host a-b". | |||
# | |||
vagrant ssh-config | sed -e 's/^\(Host.*\)_\(.*\)/\1-\2/' > ${ssh_config_file} | |||
} | |||
main "$@" | |||
</syntaxhighlight> | |||
=Configuration= | |||
==Configuring the Instance Profile== | |||
Use <code>iam_instance_profile_arn</code> (the ARN of the [[Amazon_AWS_Security_Concepts#Instance_Profile|IAM instance profile]] to associate with the instance) or <code>iam_instance_profile_name</code> (the name of the [[Amazon_AWS_Security_Concepts#Instance_Profile|IAM instance profile]] to associate with the instance). |
Latest revision as of 21:50, 19 November 2019
External
- https://github.com/mitchellh/vagrant-aws
- https://www.vagrantup.com/docs/plugins/providers.html#example-provider-aws
Internal
Overview
Vagrant AWS Provider is a Vagrant plugin that adds an AWS provider to Vagrant, allowing it to control and provision machines in EC2 and VPC.
Installation
vagrant plugin install vagrant-aws vagrant box add dummy https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box
Vagrantfile Example
This is an example. More details about Vagrantfile syntax in:
# frozen_string_literal: true
#
# Configuration
#
#
# It is assumed that the environment was already configured with AWS authentication (.aws/credentials or AWS
# environment variables). The VM will be created in the configured account/region.
#
ENVIRONMENT_NAME = "infra-playground"
BASTION_HOST = '1.2.3.4'
AWS_KEYPAIR = 'infra-playground'
SSH_PRIVATE_KEY = "~/.ssh/#{AWS_KEYPAIR}.pem"
SSH_CONFIG_FILE = "#{ENV['HOME']}/.ssh/dev/infra-worker"
#
# This is required by AWS CLI as part of instance provisioning call. It must the ID of the private subnet
# the instance will be attached to. If using environments, this subnet should be the default private subnet
# of the environment.
#
SUBNET_ID = 'subnet-000000000000000'
#
# This is required by AWS CLI as part of instance provisioning call. It must the ID of the security
# group that will protect the access to the instance. Access must be configuring depending on the instance
# requirements. At minimum, it should allow inbound ssh access.
#
SECURITY_GROUP_ID = 'sg-000000000000000'
#
# The AMI of the infra-worker image created by Packer
#
AMI_ID = ENV['AMI_ID'] || 'ami-0000000000000000'
INSTANCE_TYPE = 'm5.4xlarge'
VOLUME_SIZE_GB = 50
#
# Install vagrant plugin
#
# @param: plugin type: Array[String] desc: The desired plugin to install
def ensure_plugins(plugins)
logger = Vagrant::UI::Colored.new
result = false
plugins.each do |p|
pm = Vagrant::Plugin::Manager.new(
Vagrant::Plugin::Manager.user_plugins_file
)
plugin_hash = pm.installed_plugins
next if plugin_hash.key?(p)
result = true
logger.warn("Installing plugin #{p}")
pm.install_plugin(p)
end
if result
logger.warn('Re-run vagrant up now that plugins are installed')
exit
end
end
def aws_config(name)
value = `aws configure get #{name}`.strip
raise ArgumentError, "aws #{name} config must be set; use 'aws configure set #{name} <value>'" if value.empty?
value
end
def username
ENV['USER'] || 'anonymous'
end
def hostname
"infra-worker-#{username}"
end
#
# Create and configure the AWS instance(s)
#
Vagrant.configure('2') do |config|
ensure_plugins(%w[vagrant-aws])
config.vm.define :infra_worker do |t|
end
config.vm.hostname = hostname
#
# Use dummy AWS box
#
config.vm.box = 'dummy'
config.vm.synced_folder '.', '/vagrant', disabled: true
#
# Specify AWS provider configuration
#
config.vm.provider 'aws' do |aws, override|
#
# Specify SSH keypair to use, which should match SSH_PRIVATE_KEY
#
aws.keypair_name = AWS_KEYPAIR
aws.instance_type = INSTANCE_TYPE
aws.associate_public_ip = false
aws.elastic_ip = false
#
# Launch configuration
#
aws.ami = AMI_ID
aws.subnet_id = SUBNET_ID
aws.security_groups = [SECURITY_GROUP_ID]
aws.block_device_mapping = [{ 'DeviceName' => '/dev/xvda', 'Ebs.VolumeSize' => VOLUME_SIZE_GB }]
aws.tags = {
'Name' => hostname,
'Created by' => username,
'Environment' => ENVIRONMENT_NAME
}
#
# Specify username and private key path
#
config.ssh.forward_agent = true
override.ssh.username = 'ec2-user'
override.ssh.private_key_path = SSH_PRIVATE_KEY
override.ssh.proxy_command = "ssh -o ExitOnForwardFailure=yes -W %h:%p -i #{override.ssh.private_key_path} %r@#{BASTION_HOST}"
end
config.trigger.after [:up] do |t|
t.info = "Writing ssh config to #{SSH_CONFIG_FILE}"
t.run = { path: '../_common_tools_and_config/bin/configure-ssh-access', args: [SSH_CONFIG_FILE.to_s] }
end
end
Companion ssh configuration script configure-ssh-access'
#!/usr/bin/env bash
function usage() {
cat << EOF
Write the output of "vagrant ssh-config" to the configuration file specified as first argument.
This script is invoked as part of the "vagrant up" sequence. Various Vagrantfiles that mention
it have the path to it hardcoded.
EOF
}
function main() {
local ssh_config_file=$1
[[ -z ${ssh_config_file} ]] && { echo "a ssh configuration file must be specified" 1>&2; exit 1; }
mkdir -p $(dirname ${ssh_config_file})
#
# Ruby won't allow for "-" in host name so we convert it here. "Host a_b" will be converted to "Host a-b".
#
vagrant ssh-config | sed -e 's/^\(Host.*\)_\(.*\)/\1-\2/' > ${ssh_config_file}
}
main "$@"
Configuration
Configuring the Instance Profile
Use iam_instance_profile_arn
(the ARN of the IAM instance profile to associate with the instance) or iam_instance_profile_name
(the name of the IAM instance profile to associate with the instance).