日記

日々のことと、Python/Django/PHP/Laravel/nodejs などソフトウェア開発のことを書き綴ります

Otto 入門記 その2

前回で、開発環境の構築とアプリケーションのビルドとデプロイが出来たので続いては、本番インフラの構築です。

教材は、このあたり

ottoproject.io

Infrastructure

Otto はインフラ構築も自動的に行います。

Otto で標準サポートされているのは、AWS 上でのインフラ構築で AWS のアクセスキーが必要になります。(当然、今回の操作もアクセスキーが必要なので、free tier など利用して旨いことやってください)

Otto は EC2 インスタンス作成や、実行環境の構築を開発環境と同様にコマンドをいくつか実行することで完了します。

では早速、試していきます。

$ otto infra
==> Detecting infrastructure credentials for: otto-getting-started (aws)
    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: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

AWS Secret Key
  AWS secret key used for API calls.

  Enter a value: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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: 
==> Loading key into SSH Agent
    The key you provided (~/.ssh/id_rsa.pub) was not found in your SSH Agent.
    However, Otto found a private key here: /Users/takeshi/.ssh/id_rsa
    Automatically running 'ssh-add /Users/takeshi/.ssh/id_rsa'.
    If your SSH key has a passphrase, you will be prompted for it.

Identity added: /Users/takeshi/.ssh/id_rsa (/Users/takeshi/.ssh/id_rsa)

    A private key was found and loaded. Otto will now check
    the SSH Agent again and continue if the correct key is loaded
==> Building main infrastructure...
Would you like Otto to install Terraform?
  Otto requires terraform to be installed, but it couldn't be found on your
  system. Otto can install the latest version of terraform 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 terraform
  for you? Alternatively, you may install this on your own.
  
  If you answer yes, Otto will install terraform version 0.6.4.
  
  Please enter 'yes' to continue. Any other value will exit.

  Enter a value: yes

==> Downloading terraform v0.6.4...
    URL: https://dl.bintray.com/mitchellh/terraform/terraform_0.6.4_darwin_amd64.zip

    85.2 MB/85.2 MB
==> Unzipping downloaded package...
==> terraform installed successfully!
==> 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"
Error applying plan:

1 error(s) occurred:

* aws_vpc.main: Error creating VPC: UnauthorizedOperation: You are not authorized to perform this operation.
    status code: 403, request id: 

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

==> Terraform execution complete. Saving results...
Error occurred: Error reading Terraform outputs: Error running Terraform: Error running Terraform: exit status 1

In this case, Otto is unable to consider the infrastructure ready.
Otto won't lose your infrastructure information. You may just need
to run `otto infra` again and it may work. If this problem persists,
please see the error message and consult the community for help.

途中、 Teraform をインストールするか聞かれ、インストールが進み、最後にエラーで止まりました。新規に用意した AWS アクセスキーにパーミッションを割り当てが足りなかったようです。

面倒なので Admin Access に設定して、もう一度 "otto infra" を実行します。2度目の実行時は AWS アクセスキーの入力は求められず、前回の起動で設定したパスワードを入力することでローカルに保存された AWS アクセスキーが使用されます。

$ 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: 
==> 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_internet_gateway.public: Creating...
  vpc_id: "" => "vpc-896fceed"
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-896fceed"
aws_key_pair.main: Creating...
  fingerprint: "" => "<computed>"
  key_name:    "" => "otto-896fceed"
  public_key:  "" => "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQma2PpDiPOJq40cIz84KCsgJv+O1r2ZeWwZEqLEXeRyll/wa7dnQ4vs9IO+3xfGNxAc79kHs0jFzW5dAfNbT84AVqu/4gcYbK5en/oEUp5+arwc3T4r9HXymb03EIHwkHyxUxZcyEMlMnox6opdmM7vneq4mm9HlkUvdeoouQumDcNsRzn8fSYwVBbEOPkDtWjncW38c9hR0rT/hzqImD1nKusIw9pbL52mYOif0b+8rBf00ZXLYNRH94YSdc1wygj+XcO6x53wm8PzTj1e0+c0vlxMdSfXVZYAHqLbmQK64UIayb4WfnH2xdVBntsi9jvYORhMwxhj/pJ0LXYx6H takeshi@tnamao-mba11.local"
aws_key_pair.main: Creation complete
aws_internet_gateway.public: Creation complete
aws_route_table.public: Creating...
  route.#:                                    "" => "1"
  route.2963673264.cidr_block:                "" => "0.0.0.0/0"
  route.2963673264.gateway_id:                "" => "igw-317d7e54"
  route.2963673264.instance_id:               "" => ""
  route.2963673264.network_interface_id:      "" => ""
  route.2963673264.vpc_peering_connection_id: "" => ""
  tags.#:                                     "" => "1"
  tags.Name:                                  "" => "public"
  vpc_id:                                     "" => "vpc-896fceed"
aws_subnet.public: Creation complete
aws_route_table.public: Creation complete
aws_route_table_association.public: Creating...
  route_table_id: "" => "rtb-f740d093"
  subnet_id:      "" => "subnet-a8d1e9f1"
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/jp/6zbvy6s9199gj7m5xz1pppr00000gn/T/otto-tf842843737/state

Outputs:

  infra_id      = 896fceed
  key_name      = otto-896fceed
  region        = us-east-1
  subnet_public = subnet-a8d1e9f1
  vpc_cidr      = 10.0.0.0/16
  vpc_id        = vpc-896fceed

==> Terraform execution complete. Saving results...
==> Building infrastructure for foundation: consul
Get: file:///Users/takeshi/workspace/otto/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-896fceed"
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-896fceed"
  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-a8d1e9f1"
  tags.#:                            "" => "1"
  tags.Name:                         "" => "consul 1"
  tenancy:                           "" => "<computed>"
  vpc_security_group_ids.#:          "" => "1"
  vpc_security_group_ids.3069585911: "" => "sg-16c80770"
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.164.211.136
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 1337
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/jp/6zbvy6s9199gj7m5xz1pppr00000gn/T/otto-tf614505629/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`.

これで "otto infra" の実行が正常に終わり、 AWS Management Console を見ると t2.micro で、タグに consul 1 という設定がされたインスタンスが起動していました。

この状態で "otto status" を実行すると

$ otto status
==> App Info
    Application:    otto-getting-started (ruby)
    Project:        otto-getting-started
    Infrastructure: aws (simple)
==> Component Status
    Dev environment: CREATED
    Infra:           READY
    Build:           NOT BUILT
    Deploy:          NOT DEPLOYED

このように表示されました。Infra が READY になってますね。続いて、build します。(compile ではない)

Build

$ 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: 
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 5620a4b9-67c9-12b7-fe52-1cf5c2f7d1e1
==> 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-c123b67e
==> otto: Waiting for instance (i-c123b67e) to become ready...
==> otto: Waiting for SSH to become available...
==> otto: Connected to SSH!
==> otto: Provisioning with shell script: /var/folders/jp/6zbvy6s9199gj7m5xz1pppr00000gn/T/packer-shell778391504
==> otto: Uploading /Users/takeshi/workspace/otto/otto-getting-started/.otto/compiled/app/foundation-consul/app-build/ => /tmp/otto/foundation-1
==> otto: Provisioning with shell script: /var/folders/jp/6zbvy6s9199gj7m5xz1pppr00000gn/T/packer-shell478490164
    otto: [otto] Installing Consul...
    otto: [otto] Installing dnsmasq for Consul...
    otto: [otto] Configuring consul service: otto-getting-started
==> otto: Uploading /var/folders/jp/6zbvy6s9199gj7m5xz1pppr00000gn/T/otto-slug-177473237 => /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 1444979897
    otto: AMI: ami-8fadfaea
==> 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-8fadfaea
==> 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 status" で状態を見ると

$ otto status
==> App Info
    Application:    otto-getting-started (ruby)
    Project:        otto-getting-started
    Infrastructure: aws (simple)
==> Component Status
    Dev environment: CREATED
    Infra:           READY
    Build:           BUILD READY
    Deploy:          NOT DEPLOYED

Build が BUILD READY となりました。

Deploy

$ 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: 
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-896fceed"
  owner_id:                            "" => "<computed>"
  vpc_id:                              "" => "vpc-896fceed"
aws_security_group.app: Creation complete
aws_instance.app: Creating...
  ami:                               "" => "ami-8fadfaea"
  availability_zone:                 "" => "<computed>"
  ebs_block_device.#:                "" => "<computed>"
  ephemeral_block_device.#:          "" => "<computed>"
  instance_type:                     "" => "t2.micro"
  key_name:                          "" => "otto-896fceed"
  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-a8d1e9f1"
  tags.#:                            "" => "1"
  tags.Name:                         "" => "otto-getting-started"
  tenancy:                           "" => "<computed>"
  vpc_security_group_ids.#:          "" => "1"
  vpc_security_group_ids.2626755095: "" => "sg-50e92636"
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/jp/6zbvy6s9199gj7m5xz1pppr00000gn/T/otto-tf478560123/state

Outputs:

  url = http://ec2-52-91-236-101.compute-1.amazonaws.com/

これで実行が完了。t2.micro のサーバが新たに起動して、ローカルの仮想マシンで動かしていたものと同じアプリケーションが動作してます。

下記のように

$ otto deploy info
url = http://ec2-52-91-236-101.compute-1.amazonaws.com/

"otto deploy info" とコマンドを実行することで、接続先の URL を知ることができます。

また同様に "otto status" を実行すると

$ otto status
==> App Info
    Application:    otto-getting-started (ruby)
    Project:        otto-getting-started
    Infrastructure: aws (simple)
==> Component Status
    Dev environment: CREATED
    Infra:           READY
    Build:           BUILD READY
    Deploy:          DEPLOYED

Deploy も DEPLOYED に変わった!\(^o^)/

Teardown

インスタンス起動しっぱなしだと、どんどん課金されていくので、インスタンスを停止したいですよね。

止めるときは以下のように順々にやっていくらしい。

$ otto deploy destroy
$ otto infra destroy
$ otto dev destroy

まとめて書かれちゃっていたので、書いてますが 恐らく最後のコマンドは、AWS 側ではなくローカルの開発環境の破棄ですね…。早速試す。

$ otto deploy destroy
Do you really want to destroy?
  Otto will delete all resources associated with the deploy.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes 

==> 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: 
aws_security_group.app: Refreshing state... (ID: sg-50e92636)
aws_instance.app: Refreshing state... (ID: i-0fea1cac)
aws_instance.app: Destroying...
aws_instance.app: Destruction complete
aws_security_group.app: Destroying...
aws_security_group.app: Destruction complete

Apply complete! Resources: 0 added, 0 changed, 2 destroyed.

インスタンスとセキュリティグループが破棄されました。AWS Management Console 上でもインスタンスが1個 terminated になりました。

"otto status" を確認すると

$ otto status
==> App Info
    Application:    otto-getting-started (ruby)
    Project:        otto-getting-started
    Infrastructure: aws (simple)
==> Component Status
    Dev environment: CREATED
    Infra:           READY
    Build:           BUILD READY
    Deploy:          NOT DEPLOYED

Deploy が NOT DEPLOYED に戻りました。続いて infra を破棄

$ otto infra destroy
Do you really want to destroy?
  Otto will delete all your managed infrastructure.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

==> 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: 
==> Destroying infrastructure for foundation: consul
Get: file:///Users/takeshi/workspace/otto/otto-getting-started/.otto/compiled/foundation-consul/deploy/module-aws-simple

==> Terraform execution complete. Saving results...
module.consul-1.aws_security_group.consul: Refreshing state... (ID: sg-16c80770)
module.consul-1.aws_instance.consul: Refreshing state... (ID: i-6d9f69ce)
aws_instance.consul: Destroying...
aws_instance.consul: Destruction complete
aws_security_group.consul: Destroying...
aws_security_group.consul: Destruction complete

Apply complete! Resources: 0 added, 0 changed, 2 destroyed.

==> Terraform execution complete. Saving results...
==> Destroying 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: Refreshing state... (ID: vpc-896fceed)
aws_subnet.public: Refreshing state... (ID: subnet-a8d1e9f1)
aws_internet_gateway.public: Refreshing state... (ID: igw-317d7e54)
aws_key_pair.main: Refreshing state... (ID: otto-896fceed)
aws_route_table.public: Refreshing state... (ID: rtb-f740d093)
aws_route_table_association.public: Refreshing state... (ID: rtbassoc-b3a88ad7)
aws_key_pair.main: Destroying...
aws_route_table_association.public: Destroying...
aws_route_table_association.public: Destruction complete
aws_route_table.public: Destroying...
aws_subnet.public: Destroying...
aws_key_pair.main: Destruction complete
aws_route_table.public: Destruction complete
aws_internet_gateway.public: Destroying...
aws_subnet.public: Destruction complete
aws_internet_gateway.public: Destruction complete
aws_vpc.main: Destroying...
aws_vpc.main: Destruction complete

Apply complete! Resources: 0 added, 0 changed, 6 destroyed.

==> Terraform execution complete. Saving results...
==> Infrastructure successfully destroyed!
    The infrastructure necessary to run this application and
    all other applications in this project has been destroyed.

AWS Management Console を見ると consul 1 で登録されていた t2.micro のインスタンスも terminated となって、課金的には一安心。ちなみに、EBS もインスタンスの破棄と同時に削除されます。ログを残したりなどは、ローカルではなく別の手段をとる必要があって、きっとそれも otto way として何か用意されてるんでしょうね。

一応 "otto status" で状態を確認

$ otto status
==> App Info
    Application:    otto-getting-started (ruby)
    Project:        otto-getting-started
    Infrastructure: aws (simple)
==> Component Status
    Dev environment: CREATED
    Infra:           NOT CREATED
    Build:           BUILD READY
    Deploy:          NOT DEPLOYED

Infra が NOT CREATED に戻りました。 Build のみが BUILD READY になってます。

続いて

$ otto dev destroy
==> Destroying the local development environment...
==> default: Destroying VM and associated drives...
==> default: Running cleanup tasks for 'shell' provisioner...
==> default: Running cleanup tasks for 'shell' provisioner...


==> Deleting development environment metadata...
==> Development environment has been destroyed!

これで開発環境も破棄できたはず…はず!

$ otto status
==> App Info
    Application:    otto-getting-started (ruby)
    Project:        otto-getting-started
    Infrastructure: aws (simple)
==> Component Status
    Dev environment: NOT CREATED
    Infra:           NOT CREATED
    Build:           BUILD READY
    Deploy:          NOT DEPLOYED

"Dev environment: NOT CREATED" に戻った\(^o^)/\(^o^)/\(^o^)/

前回の記事と合わせて、これで一通り開発環境の構築から、AWS (本番インフラ) にデプロイするところまで試すことができました。

tnamao.hatenablog.com

所感

Otto を使ってみての感想は、Otto で想定されたインフラを用意してデプロイするのは非常に簡単に行えました。

小さいシステムでは正直オーバースペックに感じる部分はありますが、2013 年に日本国内では Immutable Infrastucture という言葉が生まれ、ここまで便利にそれが出来るようになってきたんだなぁ、と実感しました。

ただ、Otto は Otto のやり方に従わないと行けない部分は多いので、既存の既にあるサービスのインフラを Otto に無理に合わせるのはなかなか難しいし、既にそれが巧く運用できている場合はメリットが薄い気がします。ただ、サーバの role が複数あり管理に困っている場合には、保証はないけど otto way に乗っかっておくと幸せになれるかもしれません。

また、 otto infra と otto build、 otto deploy は AWS アクセスキーが必要で課金されてしまうので、潜在的に敷居の高さがあるのもネックだなぁと。(今回は以前もらったクレジットがあったのでお手軽でしたけど)

どうも ruby のアプリだと自分の中でリアリティがない(ruby弱者なので…)から、node.js に置き換える感じで、次回からは document の内容を試していけたら良いなと思ってます。そう巧く行くのか謎ですが。

ちなみにチキンなので、アクセスキーは使い終わったら速攻で Inactive に切り替えましたとさ…。あと、えもい文章は苦手ー、書けない。