Vagrantの後継、Ottoを試してみた
HashiCorpの新プロダクトOttoはVagrantの後継と位置づけられていて、開発環境だけでなく本番環境のデプロイまで視野にいれたコンセプトとなっているようです。
試しに使ってみたので、そのログを以下に記します。
Ottoのインストール
Ottoのダウンロードページからバイナリを落として、~/bin/以下に配置しました。
実際使ってみる
サンプルとしてRackアプリケーションがあるので、それを使ってみます。
前準備
$ git clone https://github.com/hashicorp/otto-getting-started.git $ cd otto-getting-started $ otto compile ~/dev/tmp/otto-getting-started ⮀ master ⮀ 5d18h51m ⮀ otto compile ⮂ ==> Loading Appfile... ==> No Appfile found! Detecting project information... No Appfile was found. If there is no Appfile, Otto will do its best to detect the type of application this is and set reasonable defaults. This is a good way to get started with Otto, but over time we recommend writing a real Appfile since this will allow more complex customizations, the ability to reference dependencies, versioning, and more. ==> Fetching all Appfile dependencies... ==> Compiling... Application: otto-getting-started (ruby) Project: otto-getting-started Infrastructure: aws (simple) Compiling infra... Compiling foundation: consul ==> Compiling main application... ==> Compilation success! This means that Otto is now ready to start a development environment, deploy this application, build the supporting infastructure, and more. See the help for more information. Supporting files to enable Otto to manage your application from development to deployment have been placed in the output directory. These files can be manually inspected to determine what Otto will do.
開発環境の構築
~/dev/tmp/otto-getting-started ⮀ master● ⮀ 5d18h51m ⮀ otto dev ⮂ Would you like Otto to install Vagrant? An older version of vagrant was found installed (1.7.2). Otto requires version 1.7.4 or higher. Otto can install the latest version of vagrant for you (1.7.4). Would you like Otto to update vagrant for you? Please enter 'yes' to continue. Any other value will exit. Enter a value: yes ==> Downloading Vagrant v1.7.4... URL: https://dl.bintray.com/mitchellh/vagrant/vagrant_1.7.4.dmg 85.3 MB/85.3 MB [otto] Attaching Vagrant disk image... [otto] Starting Vagrant installer... Password: installer: Package name is Vagrant installer: Upgrading at base path / installer: The upgrade was successful. [otto] Vagrant installed. Cleaning up... ==> Vagrant installed successfully! ==> Creating local development environment with Vagrant if it doesn't exist... Raw Vagrant output will begin streaming in below. Otto does not create this output. It is mirrored directly from Vagrant while the development environment is being created. Bringing machine 'default' up with 'virtualbox' provider... ==> default: Box 'hashicorp/precise64' could not be found. Attempting to find and install... default: Box Provider: virtualbox default: Box Version: >= 0 ==> default: Loading metadata for box 'hashicorp/precise64' default: URL: https://atlas.hashicorp.com/hashicorp/precise64 ==> default: Adding box 'hashicorp/precise64' (v1.1.0) for provider: virtualbox default: Downloading: https://atlas.hashicorp.com/hashicorp/boxes/precise64/versions/1.1.0/providers/virtualbox.box ==> default: Successfully added box 'hashicorp/precise64' (v1.1.0) for 'virtualbox'! ==> default: Importing base box 'hashicorp/precise64'... ==> default: Matching MAC address for NAT networking... ==> default: Checking if box 'hashicorp/precise64' is up to date... ==> default: Setting the name of the VM: dev_default_1443489702956_86673 ==> default: Clearing any previously set network interfaces... ==> default: Preparing network interfaces based on configuration... default: Adapter 1: nat default: Adapter 2: hostonly ==> default: Forwarding ports... default: 22 => 2222 (adapter 1) ==> default: Booting VM... ==> default: Waiting for machine to boot. This may take a few minutes... default: SSH address: 127.0.0.1:2222 default: SSH username: vagrant default: SSH auth method: private key default: Warning: Connection timeout. Retrying... default: default: Vagrant insecure key detected. Vagrant will automatically replace default: this with a newly generated keypair for better security. default: default: Inserting generated public key within guest... default: Removing insecure key from the guest if it's present... default: Key inserted! Disconnecting and reconnecting using new SSH key... ==> default: Machine booted and ready! ==> default: Checking for guest additions in VM... default: The guest additions on this VM do not match the installed version of default: VirtualBox! In most cases this is fine, but in rare cases it can default: prevent things such as shared folders from working properly. If you see default: shared folder errors, please make sure the guest additions within the default: virtual machine match the version of VirtualBox you have installed on default: your host and reload your VM. default: default: Guest Additions Version: 4.2.0 default: VirtualBox Version: 4.3 ==> default: Configuring and enabling network interfaces... ==> default: Mounting shared folders... default: /vagrant => /Users/yudsuzuk/dev/tmp/otto-getting-started default: /otto/foundation-1 => /Users/yudsuzuk/dev/tmp/otto-getting-started/.otto/compiled/app/foundation-consul/app-dev ==> default: Running provisioner: shell... default: Running: inline script ==> default: stdin: is not a tty ==> default: [otto] Installing Consul... ==> default: [otto] Installing dnsmasq for Consul... ==> default: [otto] Configuring consul service: otto-getting-started ==> default: Running provisioner: shell... default: Running: inline script ==> default: stdin: is not a tty ==> default: [otto] Adding apt repositories and updating... ==> default: [otto] Installing Ruby 2.2 and supporting packages... ==> default: [otto] Installing Bundler... ==> default: [otto] Configuring Git to use SSH instead of HTTP so we can agent-forward private repo auth... ==> Caching SSH credentials from Vagrant... ==> Development environment successfully created! IP address: 172.16.1.244 A development environment has been created for writing a generic Ruby-based app. Ruby is pre-installed. To work on your project, edit files locally on your own machine. The file changes will be synced to the development environment. When you're ready to build your project, run 'otto dev ssh' to enter the development environment. You'll be placed directly into the working directory where you can run 'bundle' and 'ruby' as you normally would. You can access any running web application using the IP above.
SSH接続してRackアプリケーションを起動してみます。
otto dev ssh ⮂ ==> Executing SSH. This may take a few seconds... Welcome to Ubuntu 12.04 LTS (GNU/Linux 3.2.0-23-generic x86_64) * Documentation: https://help.ubuntu.com/ New release '14.04.3 LTS' available. Run 'do-release-upgrade' to upgrade to it. Welcome to your Vagrant-built virtual machine. Last login: Fri Sep 14 06:23:18 2012 from 10.0.2.2 vagrant@precise64:/vagrant$ bundle && rackup --host 0.0.0.0 Fetching gem metadata from https://rubygems.org/.......... Fetching version metadata from https://rubygems.org/.. Installing rack 1.6.4 Installing rack-protection 1.5.3 Installing tilt 2.0.1 Installing sinatra 1.4.6 Using bundler 1.10.6 Bundle complete! 1 Gemfile dependency, 5 gems now installed. Use `bundle show [gemname]` to see where a bundled gem is installed. [2015-09-29 01:24:53] INFO WEBrick 1.3.1 [2015-09-29 01:24:53] INFO ruby 2.2.3 (2015-08-18) [x86_64-linux-gnu] [2015-09-29 01:24:53] INFO WEBrick::HTTPServer#start: pid=7107 port=9292
http://172.16.1.244:9292/ いけた。
本番環境の構築
AWS Access KeyとAWS Secret Keyが必要になるので予め準備しておいてください。
5d19h23m ⮀ otto infra ⮂ ==> Detecting infrastructure credentials for: otto-getting-started (aws) Cached and encrypted infrastructure credentials found. Otto will now ask you for the password to decrypt these credentials. Encrypted Credentials Password Infrastructure credentials are required for this operation. Otto found saved credentials that are password protected. Please enter the password to decrypt these credentials. You may also just hit <enter> and leave the password blank to force Otto to ask for the credentials again. Enter a value: Existing infrastructure credentials were not found! Otto will now ask you for infrastructure credentials. These will be encrypted and saved on disk so this doesn't need to be repeated. IMPORTANT: If you're re-entering new credentials, make sure the credentials are for the same account, otherwise you may lose access to your existing infrastructure Otto set up. AWS Access Key AWS access key used for API calls. Enter a value: AWS Secret Key AWS secret key used for API calls. Enter a value: SSH Public Key Path Path to an SSH public key that will be granted access to EC2 instances Default: ~/.ssh/id_rsa.pub Enter a value: Password for Encrypting Credentials This password will be used to encrypt and save the credentials so they don't need to be repeated multiple times. Enter a value: ==> Building main infrastructure... ==> Executing Terraform to manage infrastructure... Raw Terraform output will begin streaming in below. Otto does not create this output. It is mirrored directly from Terraform while the infrastructure is being created. Terraform may ask for input. For infrastructure provider credentials, be sure to enter the same credentials consistently within the same Otto environment. aws_vpc.main: Creating... cidr_block: "" => "10.0.0.0/16" default_network_acl_id: "" => "<computed>" default_security_group_id: "" => "<computed>" dhcp_options_id: "" => "<computed>" enable_dns_hostnames: "" => "1" enable_dns_support: "" => "1" main_route_table_id: "" => "<computed>" tags.#: "" => "1" tags.Name: "" => "otto" aws_vpc.main: Creation complete aws_key_pair.main: Creating... fingerprint: "" => "<computed>" key_name: "" => "otto-d65180b2" public_key: "" => "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDd5+GHOl+bLg8HLKtPOE0U3ar1YeX5XnuO+3riT73YSFK4OKkqqsngcVB1YUZGCrnreQ0GCi2rVR3L3maqlji2rNKvgZPqkC3tE7JgbN0b2OJhODdHauUFM74eKyEV6hKsw9qJI4LMKEMGgudoKpftQph6of3+A3gS+qd2WZHn8bkhMvYfrEucXXSHl3JMfCJ3kCgIBVYbaS2+6JP116vd65ZbLbR/hYLTWd6qwXkr2TO5YDoJ+UX7VRwnetSnot6ES0+tJcRNYxnNQpvNYpmyV8ZShLUM7UsxZ5R6P3lwO/J8CGvdDeYVzTh1ZFxsIp5r7P1GihsEfzbSMJu1Z1Xl yudsuzuk@yudsuzuk.local\n" aws_internet_gateway.public: Creating... vpc_id: "" => "vpc-d65180b2" aws_subnet.public: Creating... availability_zone: "" => "<computed>" cidr_block: "" => "10.0.2.0/24" map_public_ip_on_launch: "" => "1" tags.#: "" => "1" tags.Name: "" => "public" vpc_id: "" => "vpc-d65180b2" aws_key_pair.main: Creation complete aws_internet_gateway.public: Creation complete aws_route_table.public: Creating... route.#: "" => "1" route.250069329.cidr_block: "" => "0.0.0.0/0" route.250069329.gateway_id: "" => "igw-dcf6c9b9" route.250069329.instance_id: "" => "" route.250069329.network_interface_id: "" => "" route.250069329.vpc_peering_connection_id: "" => "" tags.#: "" => "1" tags.Name: "" => "public" vpc_id: "" => "vpc-d65180b2" aws_subnet.public: Creation complete aws_route_table.public: Creation complete aws_route_table_association.public: Creating... route_table_id: "" => "rtb-405cda24" subnet_id: "" => "subnet-b92032ce" aws_route_table_association.public: Creation complete Apply complete! Resources: 6 added, 0 changed, 0 destroyed. The state of your infrastructure has been saved to the path below. This state is required to modify and destroy your infrastructure, so keep it safe. To inspect the complete state use the `terraform show` command. State path: /var/folders/nc/dg13cwg94xl7sq6rwvbdyy_h0000gn/T/otto-tf126060527/state Outputs: infra_id = d65180b2 key_name = otto-d65180b2 region = us-east-1 subnet_public = subnet-b92032ce vpc_cidr = 10.0.0.0/16 vpc_id = vpc-d65180b2 ==> Terraform execution complete. Saving results... ==> Building infrastructure for foundation: consul Get: file:///Users/yudsuzuk/dev/tmp/otto-getting-started/.otto/compiled/foundation-consul/deploy/module-aws-simple ==> Terraform execution complete. Saving results... module.consul-1.aws_security_group.consul: Creating... description: "" => "Security group for Consul 1" egress.#: "" => "1" egress.482069346.cidr_blocks.#: "" => "1" egress.482069346.cidr_blocks.0: "" => "0.0.0.0/0" egress.482069346.from_port: "" => "0" egress.482069346.protocol: "" => "-1" egress.482069346.security_groups.#: "" => "0" egress.482069346.self: "" => "0" egress.482069346.to_port: "" => "0" ingress.#: "" => "3" ingress.2541437006.cidr_blocks.#: "" => "1" ingress.2541437006.cidr_blocks.0: "" => "0.0.0.0/0" ingress.2541437006.from_port: "" => "22" ingress.2541437006.protocol: "" => "tcp" ingress.2541437006.security_groups.#: "" => "0" ingress.2541437006.self: "" => "0" ingress.2541437006.to_port: "" => "22" ingress.2547406835.cidr_blocks.#: "" => "1" ingress.2547406835.cidr_blocks.0: "" => "10.0.0.0/16" ingress.2547406835.from_port: "" => "1" ingress.2547406835.protocol: "" => "udp" ingress.2547406835.security_groups.#: "" => "0" ingress.2547406835.self: "" => "0" ingress.2547406835.to_port: "" => "65535" ingress.3910776171.cidr_blocks.#: "" => "1" ingress.3910776171.cidr_blocks.0: "" => "10.0.0.0/16" ingress.3910776171.from_port: "" => "1" ingress.3910776171.protocol: "" => "tcp" ingress.3910776171.security_groups.#: "" => "0" ingress.3910776171.self: "" => "0" ingress.3910776171.to_port: "" => "65535" name: "" => "consul 1" owner_id: "" => "<computed>" vpc_id: "" => "vpc-d65180b2" module.consul-1.aws_security_group.consul: Creation complete module.consul-1.aws_instance.consul: Creating... ami: "" => "ami-7f6a1f1a" availability_zone: "" => "<computed>" ebs_block_device.#: "" => "<computed>" ephemeral_block_device.#: "" => "<computed>" instance_type: "" => "t2.micro" key_name: "" => "otto-d65180b2" placement_group: "" => "<computed>" private_dns: "" => "<computed>" private_ip: "" => "10.0.2.6" public_dns: "" => "<computed>" public_ip: "" => "<computed>" root_block_device.#: "" => "<computed>" security_groups.#: "" => "<computed>" source_dest_check: "" => "1" subnet_id: "" => "subnet-b92032ce" tags.#: "" => "1" tags.Name: "" => "consul 1" tenancy: "" => "<computed>" vpc_security_group_ids.#: "" => "1" vpc_security_group_ids.3140300483: "" => "sg-dea141b8" module.consul-1.aws_instance.consul: Provisioning with 'file'... module.consul-1.aws_instance.consul: Provisioning with 'remote-exec'... module.consul-1.aws_instance.consul (remote-exec): Connecting to remote host via SSH... module.consul-1.aws_instance.consul (remote-exec): Host: 54.152.137.196 module.consul-1.aws_instance.consul (remote-exec): User: ubuntu module.consul-1.aws_instance.consul (remote-exec): Password: false module.consul-1.aws_instance.consul (remote-exec): Private key: false module.consul-1.aws_instance.consul (remote-exec): SSH Agent: true module.consul-1.aws_instance.consul (remote-exec): Connected! module.consul-1.aws_instance.consul (remote-exec): consul stop/waiting module.consul-1.aws_instance.consul (remote-exec): consul start/running, process 1356 module.consul-1.aws_instance.consul: Creation complete Apply complete! Resources: 2 added, 0 changed, 0 destroyed. The state of your infrastructure has been saved to the path below. This state is required to modify and destroy your infrastructure, so keep it safe. To inspect the complete state use the `terraform show` command. State path: /var/folders/nc/dg13cwg94xl7sq6rwvbdyy_h0000gn/T/otto-tf738944147/state Outputs: consul_address = 10.0.2.6 ==> Terraform execution complete. Saving results... ==> Infrastructure successfully created! The infrastructure necessary to deploy this application is now available. You can now deploy using `otto deploy`.
AMIイメージをotto buildコマンドからPackerで生成
~/dev/tmp/otto-getting-started ⮀ master● ⮀ 5d19h26m ⮀ otto build ⮂ ==> Detecting infrastructure credentials for: otto-getting-started (aws) Cached and encrypted infrastructure credentials found. Otto will now ask you for the password to decrypt these credentials. Encrypted Credentials Password Infrastructure credentials are required for this operation. Otto found saved credentials that are password protected. Please enter the password to decrypt these credentials. You may also just hit <enter> and leave the password blank to force Otto to ask for the credentials again. Enter a value: Existing infrastructure credentials were not found! Otto will now ask you for infrastructure credentials. These will be encrypted and saved on disk so this doesn't need to be repeated. IMPORTANT: If you're re-entering new credentials, make sure the credentials are for the same account, otherwise you may lose access to your existing infrastructure Otto set up. AWS Access Key AWS access key used for API calls. Enter a value: AWS Secret Key AWS secret key used for API calls. Enter a value: SSH Public Key Path Path to an SSH public key that will be granted access to EC2 instances Default: ~/.ssh/id_rsa.pub Enter a value: Password for Encrypting Credentials This password will be used to encrypt and save the credentials so they don't need to be repeated multiple times. Enter a value: Would you like Otto to install Packer? Otto requires packer to be installed, but it couldn't be found on your system. Otto can install the latest version of packer for you. Otto will install this into its own private data directory so it doesn't conflict with anything else on your system. Would you like Otto to install packer for you? Alternatively, you may install this on your own. If you answer yes, Otto will install packer version 0.8.6. Please enter 'yes' to continue. Any other value will exit. Enter a value: yes ==> Downloading packer v0.8.6... URL: https://dl.bintray.com/mitchellh/packer/packer_0.8.6_darwin_amd64.zip 132 MB/132 MB ==> Unzipping downloaded package... ==> packer installed successfully! ==> Querying infrastructure data for build... ==> Building deployment archive... ==> Building deployment artifact with Packer... Raw Packer output will begin streaming in below. Otto does not create this output. It is mirrored directly from Packer while the build is being run. otto output will be in this color. ==> otto: Prevalidating AMI Name... ==> otto: Inspecting the source AMI... ==> otto: Creating temporary keypair: packer 5609ef7b-f244-8dc1-8fe5-fb60911dd0f9 ==> otto: Creating temporary security group for this instance... ==> otto: Authorizing access to port 22 the temporary security group... ==> otto: Launching a source AWS instance... otto: Instance ID: i-729290d1 ==> otto: Waiting for instance (i-729290d1) to become ready... ==> otto: Waiting for SSH to become available... ==> otto: Connected to SSH! ==> otto: Provisioning with shell script: /var/folders/nc/dg13cwg94xl7sq6rwvbdyy_h0000gn/T/packer-shell137028228 ==> otto: Uploading /Users/yudsuzuk/dev/tmp/otto-getting-started/.otto/compiled/app/foundation-consul/app-build/ => /tmp/otto/foundation-1 ==> otto: Provisioning with shell script: /var/folders/nc/dg13cwg94xl7sq6rwvbdyy_h0000gn/T/packer-shell113570895 otto: [otto] Installing Consul... otto: [otto] Installing dnsmasq for Consul... otto: [otto] Configuring consul service: otto-getting-started ==> otto: Uploading /var/folders/nc/dg13cwg94xl7sq6rwvbdyy_h0000gn/T/otto-slug-053371806 => /tmp/otto-app.tgz ==> otto: Provisioning with shell script: build-ruby.sh otto: [otto] Waiting for cloud-config to complete... otto: [otto] Adding apt repositories and updating... otto: [otto] Installing Ruby, Passenger, Nginx, and other packages... otto: [otto] Installing Bundler... otto: [otto] Extracting app... otto: [otto] Adding application user... otto: [otto] Setting permissions... otto: [otto] Configuring nginx... otto: [otto] Bundle installing the app... otto: Fetching gem metadata from https://rubygems.org/.......... otto: Fetching version metadata from https://rubygems.org/.. otto: Installing rack 1.6.4 otto: Installing rack-protection 1.5.3 otto: Installing tilt 2.0.1 otto: Installing sinatra 1.4.6 otto: Using bundler 1.10.6 otto: Bundle complete! 1 Gemfile dependency, 5 gems now installed. otto: Gems in the groups development and test were not installed. otto: Bundled gems are installed into ./vendor/bundle. otto: [otto] ...done! ==> otto: Stopping the source instance... ==> otto: Waiting for the instance to stop... ==> otto: Creating the AMI: otto-getting-started 1443491707 otto: AMI: ami-af2560ca ==> otto: Waiting for AMI to become ready... ==> otto: Terminating the source AWS instance... ==> otto: Cleaning up any extra volumes... ==> otto: No volumes to clean up, skipping ==> otto: Deleting temporary security group... ==> otto: Deleting temporary keypair... Build 'otto' finished. ==> Builds finished. The artifacts of successful builds are: --> otto: AMIs were created: us-east-1: ami-af2560ca ==> Storing build data in directory... ==> Build success! The build was completed successfully and stored within the directory service, meaning other members of your team don't need to rebuild this same version and can deploy it immediately.
本番環境のデプロイ
otto deploy ⮂ ==> Detecting infrastructure credentials for: otto-getting-started (aws) Cached and encrypted infrastructure credentials found. Otto will now ask you for the password to decrypt these credentials. Encrypted Credentials Password Infrastructure credentials are required for this operation. Otto found saved credentials that are password protected. Please enter the password to decrypt these credentials. You may also just hit <enter> and leave the password blank to force Otto to ask for the credentials again. Enter a value: Existing infrastructure credentials were not found! Otto will now ask you for infrastructure credentials. These will be encrypted and saved on disk so this doesn't need to be repeated. IMPORTANT: If you're re-entering new credentials, make sure the credentials are for the same account, otherwise you may lose access to your existing infrastructure Otto set up. AWS Access Key AWS access key used for API calls. Enter a value: AWS Secret Key AWS secret key used for API calls. Enter a value: SSH Public Key Path Path to an SSH public key that will be granted access to EC2 instances Default: ~/.ssh/id_rsa.pub Enter a value: Password for Encrypting Credentials This password will be used to encrypt and save the credentials so they don't need to be repeated multiple times. Enter a value: aws_security_group.app: Creating... description: "" => "Managed by Terraform" egress.#: "" => "1" egress.482069346.cidr_blocks.#: "" => "1" egress.482069346.cidr_blocks.0: "" => "0.0.0.0/0" egress.482069346.from_port: "" => "0" egress.482069346.protocol: "" => "-1" egress.482069346.security_groups.#: "" => "0" egress.482069346.self: "" => "0" egress.482069346.to_port: "" => "0" ingress.#: "" => "1" ingress.482069346.cidr_blocks.#: "" => "1" ingress.482069346.cidr_blocks.0: "" => "0.0.0.0/0" ingress.482069346.from_port: "" => "0" ingress.482069346.protocol: "" => "-1" ingress.482069346.security_groups.#: "" => "0" ingress.482069346.self: "" => "0" ingress.482069346.to_port: "" => "0" name: "" => "otto-getting-started-d65180b2" owner_id: "" => "<computed>" vpc_id: "" => "vpc-d65180b2" aws_security_group.app: Creation complete aws_instance.app: Creating... ami: "" => "ami-af2560ca" availability_zone: "" => "<computed>" ebs_block_device.#: "" => "<computed>" ephemeral_block_device.#: "" => "<computed>" instance_type: "" => "t2.micro" key_name: "" => "otto-d65180b2" placement_group: "" => "<computed>" private_dns: "" => "<computed>" private_ip: "" => "<computed>" public_dns: "" => "<computed>" public_ip: "" => "<computed>" root_block_device.#: "" => "<computed>" security_groups.#: "" => "<computed>" source_dest_check: "" => "1" subnet_id: "" => "subnet-b92032ce" tags.#: "" => "1" tags.Name: "" => "otto-getting-started" tenancy: "" => "<computed>" vpc_security_group_ids.#: "" => "1" vpc_security_group_ids.3738479127: "" => "sg-45a94923" aws_instance.app: Creation complete Apply complete! Resources: 2 added, 0 changed, 0 destroyed. The state of your infrastructure has been saved to the path below. This state is required to modify and destroy your infrastructure, so keep it safe. To inspect the complete state use the `terraform show` command. State path: /var/folders/nc/dg13cwg94xl7sq6rwvbdyy_h0000gn/T/otto-tf489279237/state Outputs: url = http://ecXXXXXXXXXXXXXXXX.compute-1.amazonaws.com/
アクセスしてみる。 いけた。
まとめ
まだ機能は少ないですが、今後のOttoの発展に期待です。