ずいぶん前に Docker Desktop (Docker for Windows) のために Hyper-V を有効にしたため VirtualBox が使えなくなりました。それに伴って Vagrant も使わなくなりました。
最初は Vagrant が使えなくなるのは辛いかな・・と思っていたのですが、開発系の作業は Docker で事足りているし、サーバ系の作業でどうしても Docker では足りないときは KVM (virt-install) とか EC2 にインスタンスを作るなどすればいいので、Vagrant が使えなくなってもそれほど困りませんでした。
ただ、Vagrant でローカルの VirtualBox に環境を作るのと比べると KVM に virt-install でセットアップしたり EC2 インスタンスをマネジメントコンソールや CLI で作るのは作業のステップが多くて煩雑が気もしています。
そこで、EC2 インスタンスをサクサク作ったり消したりできるよう vagrant-aws を試してみました。vagrant-aws なら Hyper-V 有効なままでも問題なく使用できます。
環境は次のとおりです。
- Fedora 31 (WSL)
- Vagrant 2.2.9
- vagrant-aws 0.7.2
クイックスタート
下記の README のクイックスタートの手順の通りに試してみます。
# vagrant をインストール sudo dnf install https://releases.hashicorp.com/vagrant/2.2.9/vagrant_2.2.9_x86_64.rpm # vagrant-aws プラグインをインストール vagrant plugin install vagrant-aws # ダミーのボックスを追加 vagrant box add dummy https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box # Vagrantfile を作成 vim Vagrantfile # プロバイダに aws を指定して開始 vagrant up --provider=aws # ssh で接続 vagrant ssh sv01
がしかし、いくつかハマりどころがありました。
Vagrantfile
Vagrantfile の内容は下記のようになりました。クイックスタートそのままだと面白くないので複数台の環境を作るようにしています。
class Hash def slice(*keep_keys) h = {} keep_keys.each { |key| h[key] = fetch(key) if has_key?(key) } h end unless Hash.method_defined?(:slice) def except(*less_keys) slice(*keys - less_keys) end unless Hash.method_defined?(:except) end Vagrant.configure("2") do |config| config.vm.box = "dummy" ["sv01", "sv02", "sv03"].each {|name| config.vm.define name do |config| config.vm.hostname = name end } config.vm.provider :aws do |aws, override| aws.aws_profile = ENV["AWS_PROFILE"] aws.region = "ap-northeast-1" aws.keypair_name = ENV["AWS_KEYNAME"] aws.instance_type = "t2.micro" aws.associate_public_ip = true aws.region_config "ap-northeast-1" do |region| region.ami = "ami-06ad9296e6cf1e3cf" end override.ssh.username = "ec2-user" override.ssh.private_key_path = "~/.ssh/id_rsa" end config.vm.provision "shell", inline: <<-SHELL set -eux amazon-linux-extras install -y ansible2 SHELL end
VPC やセキュリティグループが指定されていませんが、未指定なら AWS アカウントを作ったときに最初から作成されているデフォルト VPC やセキュリティグループが使用されます。
Undefined HashMap method except
Vagrantfile の先頭に見慣れないものがありますが、これは下記の vagrant-aws のバグに対するワークアラウンドです。
素のままでは、最新の Vagrant で vagrant-aws は動きません。
aws_profile と region
aws.aws_profile
を指定した場合、~/.aws/credentials
に書いているクレデンシャルを使いたいだけだとしても ~/.aws/config
に該当するエントリが必要です。エントリがないと vagrant-aws でヌルポのようなエラーになりました。
また、aws.aws_profile
を指定した場合は Vagrantfile でのリージョンの指定は無視され、~/.aws/config
で指定されたリージョンが優先されます。~/.aws/config
でリージョンが指定されていない場合は us-east-1
になります。
~/.aws/credentials
にクレデンシャルを書きつつ、リージョンは Vagrantfile で指定、みたいにしたかったのですが、出来無さそうです。
さいごに
下記を見るにもう何年もリリースされていないしプルリクも放置されっぱなしのようなので、もうメンテナンスされていないと考えたほうが良いのでしょうか。
よくよく考えてみれば Terraform で十分な気もします。インスタンスを立ち上げてからのプロビジョニングが vagrant の方がやりやすいかと思いましたが、Terraform でも remote-exec でできなくもないし、userdata でもできます。
同じようなことを Terraform でやると次のような感じでしょうか。
variable profile {} variable keyname {} variable private_key {} locals { servers = { sv01 = {} sv02 = {} sv03 = {} } } provider aws { region = "ap-northeast-1" profile = var.profile } data aws_ssm_parameter amazon_linux { name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" } resource aws_instance servers { for_each = local.servers ami = data.aws_ssm_parameter.amazon_linux.value key_name = var.keyname instance_type = "t2.micro" associate_public_ip_address = true # user_data = <<-EOS # #!/bin/bash # set -eux # amazon-linux-extras install -y ansible2 # EOS provisioner "remote-exec" { inline = [ <<-EOS set -eux sudo amazon-linux-extras install -y ansible2 EOS ] connection { type = "ssh" host = self.public_ip user = "ec2-user" private_key = file(var.private_key) } } } output public_ips { value = { for k, v in aws_instance.servers : k => v.public_ip } }
改めて比べてみると・・うーん、やっぱり Terraform でいいかなと思います。