$yuzu->log();

技術ネタなど。

Vagrantの後継、Ottoを試してみた

f:id:yuzurus:20150930001342p:plain 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/ いけた。 f:id:yuzurus:20150930002003p:plain

本番環境の構築

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/

アクセスしてみる。 f:id:yuzurus:20150930002525p:plain いけた。

まとめ

まだ機能は少ないですが、今後のOttoの発展に期待です。

ISUCON5予選に参加してきました

ISUCON5の予選に参加してきました。

ISUCONとは?

お題となるWebサービスを決められたレギュレーションの中で限界まで高速化を図るチューニングバトル、それがISUCONです。過去の実績も所属している会社も全く関係ない、結果が全てのガチンコバトルです。

メンバーは

今回のお題

「ISUxi」という、どこかで聞いたことのあるような名前の「高負荷に耐えられるSNSコミュニティサイト」 機能としては

  • ログイン、ログアウト
  • プロフィール
  • 友達
  • 記事 (友達限定公開あり)
  • コメント
  • 足あと機能 などなど割りと複雑なもの。

実装言語はRubyPerlPythonPHPJava、Go、Nodeなど様々なものがあり、PHP7を使って挑む気マンマンだったのですが、
スタート当初、運営側のPHPの実装ではベンチマークが期待する動作をせず、急遽使用言語をRubyに変更。
Nodeは準備すら出来なかった模様。Noderってチームは何の言語を選んだのだろう。

環境

  • Ubuntu 15.04
  • Nginx
  • MySQL
  • Google Cloud Platformのn1-highcpu-4 (vCPU x 4、メモリ 3.6 GB)

やったこと

  • New Relic導入
  • Nginxで静的ファイル配信
  • Redisでusersやfrient listをキャッシュ
  • MySQLインデックス貼り貼り
  • Unicorn workerチューニング
  • N + 1問題のクエリが沢山あったのでチューニング
  • MySQLのクエリ最適化

もろもろ
6割ぐらいはMySQLクエリ最適化してた気がします。

感想

8時間ぶっ通しで集中してたのでめちゃくちゃ疲れたけど、普段使ってない技術を使うので勉強になるし、すごく楽しかったです。
主催・共催のLINE、Treasure Data、TREASURE、TECHORUS、Googleの皆様、本当にありがとうございました!

Webコミュニティサイトを運営しているすべての人の読んでもらいたい本

Web Community CGMビジネス”成功請負人”たちの考え方 Webコミュニティでいちばん大切なこと。

Webコミュニティでいちばん大切なこと。 CGMビジネス“成功請負人”たちの考え方

Webコミュニティでいちばん大切なこと。 CGMビジネス“成功請負人”たちの考え方

2008年に出版された本で、nanapiのけんすうさん(当時はロケットスタート)をはじめ、みんなの就活日記の伊藤将雄さん、ループスの斉藤徹さんなど、知る人ぞ知る、CGMコミュニティサイトで実績のある方々が、それぞれの経験を元に運営方法などのノウハウを記述しています。

@tomzohさんがバイブルと仰っていたのでAmazonでポチって読んでみました。

www.hasegawa-tomoki.com

私自身もWebコミュニティサイトを運営しているのですが、この本は本当に素晴らしいと思いました。

サイトを運営しててこういう問題あったなーというあるあるが満載でした。

多少古めかしい話題もありますが、Webコミュニティとは何かをそれぞれ分析し、サービスリリースからグロースまで、運営におけるリスクマネジメント(炎上、荒らし対策)、収益モデルなど、体系的にまとめられいます。

WEBコミュニティのフレームワーク本といったところでしょう。

目次を以下に記します。(敬称略)

1 スタートから成功までの目標とプロセス (早稲田大学大学院/伊藤将雄)

  • 1-1 コミュニティづくりの基本を固める
  • 1-2 設計・開発から、プレオープンまで
  • 1-3 コミュニティを軌道に乗せるには

2 リスクマネジメントの必須項目(株式会社ロケットスタート/古川健介)

  • 2-1 コミュニティサイトに潜むリスクとは
  • 2-2 リスクのある書き込みを減らす
  • 2-3 法的リスクについて

3 ユーザーモチベーションを高める運営術(株式会社セプテーニ・クロスゲート/水波桂)

  • 3-1 管理人はいるか コミュニティをはじめる前に
  • 3-2 コミュニティの育て方
  • 3-3 少しの工夫が大きく刺さる 動的に見せるコツ

4 Webコミュニティにおける収益モデルの考え方(株式会社ドリコムジェネレーティッドメディア/平尾丈)

  • 4-1 Webコミュニティの収益モデル「CREAM」メソッド
  • 4-2 ネット広告による収益の最適化
  • 4-3 ネット広告の変化の兆し

5 ECと集合知の融合。〜ソーシャルコマースの潮流〜(株式会社ループス・コミュニケーションズ/斉藤徹・大迫正治)

  • 5-1 ソーシャルコマースの実態
  • 5-2 ソーシャルコマースの機能
  • 5-3 コマースと連動したコミュニティの運営
  • 5-4 ソーシャルコマース構築の実際
  • 5-5 ソーシャルコマースによる新しい消費行動

6 モバイルコミュニティの可能性(株式会社ゆめみ/片岡俊行)

  • 6-1 モバイルコミュニティの特徴
  • 6-2 モバイルコミュニティの収益化
  • 6-3 モバイルコミュニティの動向・事例

7 コミュニティビジネスの未来(アルカーナ株式会社/原田和英)

付録 ひろゆき氏インタビュー

まとめ

私は普段本は読み終わったら、Amazonマーケットプレイスに流すのですが、 この本は手元において何度も読み返そうと思います。

  1. 自社コミュニティサイトに対しての愛
  2. インターネット&コミュニティサイトについての愛
  3. ユーザへの愛

の3つの愛を心に留め、今後のサイト運営にこの本を役立てていきたいと思います。

清水亮さんの新作『最速の仕事術はプログラマーが知っている』感想

IPA 独立行政法人 情報処理推進機構」から天才プログラマー/スーパークリエイターと認定されている、清水亮さんの新作「最速の仕事術はプログラマーが知っている」を読みました。 ものすごくキャッチーなタイトルですねw

私もプログラマーの端くれなので、清水さんがどんな仕事のこなし方をしているのか、非常に興味がありました。

最速の仕事術はプログラマーが知っている

最速の仕事術はプログラマーが知っている

なぜ今、ビジネスの頂点にプログラマーあがりの人が君臨しているのか?

スティーブ・ジョブズはこんな言葉を残しています。

「アメリカ人は全員コンピュータのプログラミングを学ぶべきだと思うね。

なぜなら、コンピュータ言語を学ぶことによって考え方を学ぶことが出来るからだ。」

ビル・ゲイツMicrosoftラリー・ペイジGoogle

ジェフ・ベゾスAmazonマーク・ザッカーバーグFacebook

といった経営者は、みんなプログラマー出身者。

プログラミングから学べる思考法こそ、彼らのビジネススピードの原動力なのです。

KISS(Keep It Simple, Stupid!)原則 = 「シンプルにしておけ、この間抜け!」

DRY(Don't Repeat Yourself.)原則 = 「同じことは書くな」

YAGNI(You Ain't Gonna Need It)原則 =「必要になってからつくれ」

プログラマーの世界には、こうしたムダを削ぎ落とすための数々の原則や仕組みがあります。

本書ではそこから導き出される実践的な仕事術を、

国家認定天才プログラマーであり、経営者でもある著者が伝授します。

この本はプログラマの効率化とライフハックを関連付けていて、プログラマーなら当たり前の原則である、KISS原則、DRY原則YAGNI原則を軸に仕事術が語られていました。

印象に残ったポイントをまとめてみます。

  1. DRY原則に基づき、よく使う表現はすべて、辞書登録してメールは5秒で送る。

  2. 長文にWordは使わずテキストエディタを使う。Markdown記法を使えばキレイな文章が仕上がる。

  3. プレゼン資料は直前に書け。アイディアをカタチにするときに、その時の最先端の話題をフォローしておくかおかないかだけで、できあがったプレゼン資料の効果はまったく異なる。

  4. エジソンは手抜きの天才だった。怠けるために考える。くだらない仕事はすべて機械にやらせた。

  5. インターネットに公開されている情報は情報受信者のためではなく、発信者のために作られている。

  6. ハッカーの道とは、持続的な改善と反復を積み重ねていくこと。ハッカーとは、物語は常に向上できる余地があり、完璧なものは何もない。と信じている人のこと。

  7. プログラマーの職業的美点は、他のどの職業人よりも自分が無能であることに自覚的であること。

  8. 匿名チャットで経営会議すれば、権力者も自分のアイディアを、仕事をよく知る人たちに同じ目線で共有できるし、平社員やアルバイトでも社員と対等に話ができる。

  9. リーダーは働いたら負け。NEETであれ。

本書内で登場する、「プログラマー的な考え方」は、合理的に仕事をこなす上で、非常に納得できるものが多く、面白い本です。

PHPの名前空間( namespace )のセパレーターがバックスラッシュ"\"になった理由

PHP名前空間(namespace)の区切り文字はバックスラッシュ"\"が採用されています。 最初はエスケープに見えてすごく違和感でした。

気になって調べてみるとバックスラッシュが採用されるIRCログを発見しました。 それによると理由は以下の5つだそうです。

  1. セパレータとしての入力のし易さ
  2. typo-vulnerabilitytypo時にエラーや警告なく意図しない動作に繋がらない)
  3. 構文解析のし易さ
  4. IDE互換性
  5. 文字数

ナルホドネ!!

パーフェクトPHP

パーフェクトPHP

Vagrant で作った仮想マシンから Box ファイルを作る方法

Vagrantで作った仮想環境を他人の環境でもまるまる使えるようにする方法です。

そんなのDocker使えばいいじゃんって言われそうですが、Vagrant使っているけどDockerは習得していないという人のために。

$ vagrant --version                                                            
Vagrant 1.7.2

NICマッピングを削除

# ホスト
$ vagrant ssh

# 仮想
$ sudo ln -s -f /dev/null /etc/udev/rules.d/70-persistent-net.rules
$ exit

# ホスト
$ vagrant halt

boxファイル作成

$ vagrant package
$ ls
package.box

boxファイルができました。

作成したboxファイルをインポート

作成したboxファイルを渡してあげて以下のコマンドを実行してください。

$ vagrant box add hogeos package.box
$ vagrant init hogeos
$ vagrant up

これで環境をまるっと移すことができます。

実践 Vagrant

実践 Vagrant

【池上彰】世界で起きている大問題を包括的に知ることが出来るオススメ本

ニュース解説番組にひっぱりだこな池上彰さん。

そんな池上彰さんの新作、「知らないと恥をかく世界の大問題6 〜21世紀の曲がり角。世界はどこへ向かうのか?〜」を読みました。

池上彰さんの世界情勢の分析を分かりやすく教えてくれる「知らないと恥をかく世界の大問題」シリーズは全部で6作目になりました。

  1. 大国アメリカの野望と世界への責任
  2. ヨーロッパ、衝突の現場から
  3. イスラムの台頭
  4. 人類共通の問題に立ち向かえるのか?
  5. 戦後70年を迎える東アジアの未来志向
  6. 突き進む安倍政権が目指すもの

内容は上記になっています。

特に、

  1. 現在の原油安の理由が、アメリカ、サウジアラビア、イラン、ベネズエラ、シリア、キューバなど経済から宗教が複雑に絡み合いもたらされていること。
  2. イスラム国がどうして生まれてきたのか

の二点が非常にわかりやすく解説されており、勉強になりました。

イスラム国やオバマ大統領後のアメリカ、アベノミクス集団的自衛権、沖縄の基地問題憲法改正、等、知識としては決して先鋭的なものではありませんが、このぐらい知っておけば「世界情勢に疎い人」とは思われないでしょう。

過去の失敗を二度と繰り返さないこと。そのために歴史を学ぶ必要があるのだと思います。『知らないと恥をかく世界の大問題』という題名のシリーズは、多くの読者の支持を得て、ついに6冊目となりました。空港の書店に並べられ、国際線の機内で海外に出かける予習として読んでいる人をよく見かけます。ありがたいことです。5冊目から6冊目までの間に、世界は大きく変わりました。そんな変化の確認のためにも、この本がお役に立つことを願っています。

と本書にかかれている通り、国際線の機内で読む分量としては非常に調度良いです。
是非海外へ向かう前に空港でこの本を手にとってみてください。