Tech Trier Blog

エンジニアとして「好奇心」のおもくまま、いろいろやったり調べたりするブログです。

【otto dev】 Ottoを試して理解する(その3)

otto dev を実行すると、以下のことを完全に自動でやってくれます。

  • 開発環境の起動とプロビジョニング
    • base boxをダウンロード
    • 必要なインストールを行う
      • 紹介された例だと、Rubyと5つのgem
    • VMのIP設定を行い、再起動

ログはこんな感じ。

otto dev
==> Creating development environment layers...
    Otto uses layers to speed up building development environments.
    Each layer only needs to be built once. We've detected that the
    layers below aren't created yet. These will be built this time.
    Future development envirionments will use the cached versions
    to be much, much faster.
==> Creating layer: consul
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Preparing master VM for linked clones...
    default: This is a one time operation. Once the master VM is prepared,
    default: it will be used as a base for linked clones, making the creation
    default: of new VMs take milliseconds on a modern system.
==> default: Importing base box 'hashicorp/precise64'...
==> default: Cloning VM...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: consul_default_1452961743420_68343
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2200 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2200
    default: SSH username: vagrant
    default: SSH auth method: private key
    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: 5.0
==> default: Mounting shared folders...
    default: /otto/foundation-layer-consul => C:/Users/u1bell/otto/FistTry/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: Running provisioner: file...
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: stdin: is not a tty
==> default: Running provisioner: file...
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: stdin: is not a tty
==> 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: Attempting graceful shutdown of VM...
==> Creating layer: ruby2.2
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Cloning VM...
==> default: Setting the name of the VM: ruby22_default_1452962008313_90766
==> default: Clearing any previously set forwarded ports...
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2200 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2200
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Remote connection disconnect. Retrying...
==> 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: 5.0
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: stdin: is not a tty
==> default: Running provisioner: file...
==> default: Running provisioner: shell...
==> default: [otto] Setting locale to en_US.UTF-8...
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: [otto] Updating apt...
==> default: [otto] Installing supporting packages...
==> default: [otto] Installing Ruby 2.2. This can take a few minutes...
==> default: [otto] Installing Bundler...
==> default: [otto] Configuring Git to use SSH instead of HTTP so we can agent-forward private repo auth...
==> default: Attempting graceful shutdown of VM...
==> Creating local development environment with Vagrant if it doesn't exist...
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Cloning VM...
==> default: Setting the name of the VM: dev_default_1452962774521_16824
==> default: Clearing any previously set forwarded ports...
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> 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 (guest) => 2200 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2200
    default: SSH username: vagrant
    default: SSH auth method: private 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: 5.0
==> default: Configuring and enabling network interfaces...
==> default: Mounting shared folders...
    default: /vagrant => C:/Users/u1bell/otto/FistTry/otto-getting-started
    default: /otto/foundation-1 => C:/Users/u1bell/otto/FistTry/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] Configuring consul service: otto-getting-started
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: stdin: is not a tty
==> default: Running provisioner: file...
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: stdin: is not a tty
==> default: Running provisioner: file...
==> default: Running provisioner: shell...
==> default: [otto] Bundling gem dependencies...
==> default: Fetching gem metadata from https://rubygems.org/
==> default: Fetching version metadata from https://rubygems.org/
==> default: Installing rack 1.6.4
==> default: Installing tilt 2.0.1
==> default: Using bundler 1.11.2
==> default: Installing rack-protection 1.5.3
==> default: Installing sinatra 1.4.6
==> default: Bundle complete! 1 Gemfile dependency, 5 gems now installed.
==> default: Use `bundle show [gemname]` to see where a bundled gem is installed.
==> Caching SSH credentials from Vagrant...
==> Development environment successfully created!
    IP address: x.x.x.x

    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.

指定されたIPに、TeraTermでログイン。(Portは22です。)

bundle && rackup --host 0.0.0.0

ブラウザで指定されたIP:9292にアクセスしてみます。

f:id:u1bell:20160117182656p:plain

おお、Vagrantfileを一切書かず、yumやgemコマンドを一回も打ったり書いたりせずに、アプリが起動できる開発環境が整いました!

自動生成されたVagrantfileをのぞいてみた

  # ScriptPacks
  dir = "/otto/scriptpacks"
  config.vm.provision "shell", inline: "sudo rm -rf #{dir}; sudo mkdir -p #{dir}; sudo chmod 0777 #{dir}"
  config.vm.provision "file", source: 'C:\Users\u1bell\otto\FistTry\otto-getting-started\.otto\compiled\app\scriptpacks\STDLIB.tar.gz',   destination: "#{dir}/STDLIB.tar.gz"
  config.vm.provision "shell", inline: "cd #{dir}; sudo mkdir STDLIB; sudo tar xzf STDLIB.tar.gz -C STDLIB"

  config.vm.provision "file", source: 'C:\Users\u1bell\otto\FistTry\otto-getting-started\.otto\compiled\app\scriptpacks\RUBY.tar.gz',    destination: "#{dir}/RUBY.tar.gz"
  config.vm.provision "shell", inline: "cd #{dir}; sudo mkdir RUBY; sudo tar xzf RUBY.tar.gz -C RUBY"

Provisioningを行うスクリプトが、ScriptPacksというアーカイブの形で用意されているようです。 アプリケーションのソースコードを自動解析し、必要なScriptPacksを抽出してVagrantfileに追記してくれるということでしょう。 Rubyのインストール一つとっても、素でコンパイルしたり、rbenvを使ったり、古くてよければyumを使ったりといろいろ手段がありますが、ここではhashicorpがベストプラクティスと考える方法が選択されることになります。

【Ottoのビルド】 Ottoを試して理解する(その2)

前回、Windows10でのOtto(0.2)によるProvisionに失敗しましたが、GitHub上のブランチではすでに解決済みであることを確認しました。 なので、修正済みバイナリを自分でビルドしてみたいと思います。

やりたいこと

Github上のOtto Bug Fix Branchをビルドし、WindowsでProvisionを成功させる。 OttoのビルドはCentOS 7.1 (VM)上で行う。 OttoはGoで書かれているので、VM上にGoの環境を整える。

ビルド環境

VMの準備

VM用のフォルダをHost上で準備し、初期化します(HostOS)。

vagrant init

Vagrantfileのポイント

Vagrangfileをこんな感じで修正しました。

  • Box
  config.vm.box = "bento/centos-7.1"

* Provisioning(Shellscript)

  config.vm.provision "shell", inline: <<-SHELL
    sudo yum -y install git
    sudo yum -y install zip
    sudo yum -y install gcc
    cd /usr/local/src
    wget https://storage.googleapis.com/golang/go1.5.3.linux-amd64.tar.gz
    tar -C /usr/local -xzf go1.5.3.linux-amd64.tar.gz
    grep -q /usr/local/go/bin /home/vagrant/.bashrc || echo 'export PATH=$PATH:/usr/local/go/bin' >> /home/vagrant/.bashrc
    grep -q /home/vagrant/work/bin /home/vagrant/.bashrc || echo 'export PATH=$PATH:/home/vagrant/work/bin' >> /home/vagrant/.bashrc
    grep -q GOPATH /home/vagrant/.bashrc || echo 'GOPATH=/home/vagrant/work' >> /home/vagrant/.bashrc
    grep -q GOROOT_BOOTSTRAP /home/vagrant/.bashrc || echo 'GOROOT_BOOTSTRAP=/home/vagrant/go1.4' >> /home/vagrant/.bashrc
  SHELL

Vagrantfileの準備ができたら、さっそく起動!

vagrant up

Go 1.4のダウンロードやビルドは、この後マニュアルでやりました。

Goの環境変数設定

Getting Started - The Go Programming Language

  • GOROOT: デフォルト(usr/local/go)以外の場所にインストールするときに設定必要
  • GOROOT_BOOTSTRAP: GoをビルドするためのGo1.4の置き場。今回はhome下に設定。
  • GOPATH: Goのワーキングディレクトリ

なお、/usr/local/go/bin/home/vagrant/work/binにパスを通しています。 /usr/local/go/binはGoのパス、/home/vagrant/work/binは依存するGo Package Binaryへのパスです。

VMへのSSH接続

Windowsではsshコマンドがないので、そのままではvagrant sshコマンドが利用できません。 いろいろ解決手段はありますが、ここではTeraTermを使ってssh接続しています。

なお、vagrant upデフォルトのユーザ名およびパスワードは、vagrantになっています。

Goのクロスコンパイル事前準備

ロスコンパイルとは、Linux上でWindowsのバイナリをコンパイルしたりすることです。 Goはクロスコンパイルに対応していますが、準備が必要です。

Go1.5をコンパイルするのにGo1.4が必要!

qiita.com

を参考に、以下のことをやります。

まずはGo1.4をhome下でビルドする。

cd ~
git clone -b release-branch.go1.4 https://go.googlesource.com/go $HOME/go1.4
cd $HOME/go1.4/src
./make.bash

次に、GOROOT_BOOTSTRAPを設定(Vagrangfileで設定済み)し、Windowsでのクロスコンパイル向けビルドを行う。

$ export GOROOT_BOOTSTRAP=/home/vagrant/go1.4
$ cd $(go env GOROOT)
$ sudo -E GOOS=windows GOARCH=amd64 ./make.bash

最後にこのメッセージがでたら成功です。

---
Installed Go for windows/amd64 in /usr/local/go
Installed commands in /usr/local/go/bin

ただし、Ottoのクロスコンパイルに関しては、この作業が不要だったかもしれません。 上記クロスコンパイル準備していない32bit Windowsやその他のプラットフォームのバイナリもコンパイル可能でした。

Ottoのコンパイル

ここまできたら、Ottoをコンパイルすることができます。

github.com

本家のガイドに従いつつ、やっていきましょう。

ディレクトリ作成

$GOPATH/src/github.com/hashicorp

を作成し、cdします。 今回、GOPATHは/home/vagrant/workにしました。

git clone

本来ならこうです。

git clone https://github.com/castaneai/otto.git

今回は、Windows用修正ブランチをビルドするので、こうします。 (このブランチは、masterにマージされ、そのうちなくなるかもしれません。)

git clone -b fix-fails-provisioning-on-windows https://github.com/castaneai/otto.git

Build!!

make updatedeps

で、依存するパッケージのアップデートを行います。 その後、

make bin

うまくいけば、こんな感じです。

$ make bin
find . -type f -name '.DS_Store' -delete
go generate ./...
==> Getting dependencies...
==> Removing old directory...
==> Building...
Number of parallel builds: 1

-->   windows/amd64: github.com/hashicorp/otto
-->       linux/386: github.com/hashicorp/otto
-->     linux/amd64: github.com/hashicorp/otto
-->       linux/arm: github.com/hashicorp/otto
-->      darwin/386: github.com/hashicorp/otto
-->    darwin/amd64: github.com/hashicorp/otto
-->     windows/386: github.com/hashicorp/otto
==> Packaging...
--> windows_amd64
  adding: otto.exe (deflated 73%)
--> linux_386
  adding: otto (deflated 69%)
--> linux_amd64
  adding: otto (deflated 73%)
--> linux_arm
  adding: otto (deflated 70%)
--> darwin_386
  adding: otto (deflated 69%)
--> darwin_amd64
  adding: otto (deflated 73%)
--> windows_386
  adding: otto.exe (deflated 70%)

==> Results:
total 20M

pkg下にバイナリができているので、HostOSとのシェアフォルダにコピーします。

cp pkg/windows_amd64.zip /vagrant/

これで、Vagrantfileがあるフォルダにwindows_amd64.zipがコピーされます。

ようやく、WindowsでOttoによるProvisioningができます! 今日はここまで!

【otto compile】 Ottoを試して理解する(その1)

Ottoは、Vagrantを開発したHashi corpの次世代ツールです。

Otto by HashiCorp

主な特徴を調べて、トライしてみました。

Ottoとは

アプリケーションの開発環境を整え、開発し、セキュリティの設定を行い、アプリケーションをクラウドにデプロイするまでの一連の作業を、ベストプラクティスに基づいて自動化するツールです。現在、複数ツールを使って行われる作業を、Otto一つに集約することができます。 Vagrantと並行して開発を進めていくようです。

主な特徴

  • 開発環境の自動化:Ottoは開発中のアプリケーションのタイプを検出し、そのアプリケーションに最適化された開発環境を設定なし(または最小限の設定)で立ち上げます。

  • Micro servicesに最適:Ottoはソフトウェア間の依存関係やバージョンを自動的に理解して、その依存関係をどんな環境にもデプロイし、設定することができます。

Micro servicesとは、単一機能のサービスが連携してアプリケーションを構成する手法。Unixの理念に根付いています。

33rd Degree - Conference for Java Masters - Micro services - Java, the Unix Way

  • デプロイ:Ottoは開発中のアプリがmicroservicesでも、モノリシックなタイプでも、うまいことデプロイするやり方を知っています。

  • Docker:OttoはDockerを使ってアプリケーションを自動的にコンテナ化することができます。

  • ツール:開発環境構築にはVagrantを、サーバー起動にはTerraformを、サーバ設定にはConsulを使います。これらツールのインストールと管理はOttoが自動で行います。

Ottoを試してみる

試したOS: Windows 10 (64bit)

事前準備

トライアルにgitを使う必要があるので、git for windowsをインストールしておきます。

また、WindowsではVagrantの自動インストールに対応していないようです。 otto実行中にこのメッセージを見ることになります。 事前に、VagrantVirtualBoxをインストールしておくのが良いです。

Ottoのダウンロードとインストール

Download Otto - Otto by HashiCorp

2016/1/16現在のバージョンは0.2です。 ダウンロードしたバイナリを、パスの通った場所に置く必要があります。

Windows10での環境変数設定

ちなみに、環境変数の設定方法は、 windows + xを押した後に、

コントロールパネル - コントロールパネルの検索窓に環境変数と入力 - システム環境変数の編集を選択

PATHで設定されているパス一覧がとっても見やすいのは、Windows10の良いところです。

インストールの確認

コマンドプロンプトを開き、 ottoと入力してみましょう。

C:\Users\u1bell>otto
usage: otto [--version] [--help] <command> [<args>]

Available commands are:
    build      Build the deployable artifact for the app
    compile    Prepares your project for being run
    deploy     Deploy the application
    dev        Start and manage a development environment
    infra      Builds the infrastructure for the Appfile
    status     Status of the stages of this application
    version    Prints the Otto version

試してみる

https://www.ottoproject.io/intro/getting-started/dev.html の内容に沿って、試してみます。

$ git clone https://github.com/hashicorp/otto-getting-started.git
$ cd otto-getting-started
$ otto compile
$ otto dev

実際にやってみると、

otto-getting-started>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...
==> Detecting Ruby version to use...
    No desired Ruby version found! Will use the default: 2.2
==> Compilation success!
    This means that Otto is now ready to start a development environment,
    deploy this application, build the supporting infrastructure, 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.

Rubyを使ったプロジェクトであることを、自動検出したようです。 指定がないので、Ruby2.2を使うよ、と言っています。

なお、Vagrantが未インストールだと、Vagrantをインストールしますか?と聞いてきます。 yesと答えましたが、このOSではVagrantの自動インストールに対応していません、マニュアルでお願いします、とのことでした。 この辺は、windowsのつらいところですね。。

ともあれ、compileは無事成功しました。

otto devに失敗。。

Windowsでのotto devに失敗しました。

==> Creating layer: consul
Bringing machine 'default' up with 'virtualbox' provider...
There are errors in the configuration of this machine. Please fix
the following errors and try again:

File provisioner:
* File upload source file C:/Users/Suzuki/.otto.d/global-data/vagrant-layered/layers/consul/UsersSuzukiottoFistTryotto-getting-started.ottompiledpp criptpacksSTDLIB.tar.gz must exist
* File upload source file C:/Users/Suzuki/.otto.d/global-data/vagrant-layered/layers/consul/UsersSuzukiottoFistTryotto-getting-started.ottompiledpp criptpacksRUBY.tar.gz must exist


Error building dev environment: Error building dev environment layers: Error executing Vagrant: exit status 1

The error messages from Vagrant are usually very informative.
Please read it carefully and fix any issues it mentions. If
the message isn't clear, please report this to the Otto project.

なにやら、otto compileで生成したはずのファイルが見つけられないようです。 ここに書いてあるのと同じことが起きています。 github.com

どうやら、自動生成するvagrantファイルでWindowsのファイルパスに含まれるバックスラッシュがエスケープ文字と認識されちゃう、というありがちなミスのようで、GitHub上ではすでに修正されているようです。

fix hashicorp/otto#391 · castaneai/otto@a960d1f · GitHub

Rubyのダブルクォーテーション(エスケープ文字が有効)とシングルクォーテーション(エスケープ文字無効)の使いどころを間違えるという、私もよくやるミスですね。 なんだか親近感がわきます。またVersion 0.2ですし、こういうのを楽しめなくちゃ好きものとは言えません。

仕方ありません。Github上のottoをコンパイルしてみますか。。 修正は、まだfix-fails-provisioning-on-windowsというブランチにあるようです。

git clone -b fix-fails-provisioning-on-windows ht
tps://github.com/castaneai/otto.git

今日はここまで!

bento project : Vagrantで安心して使えるBase box

数年前にvagrantを使い始めた時から、いろいろ変化がありました。

  • bento boxのホストが変わっていました。
  • vagrant initで作成されるVagrant fileが、だいぶすっきりしていました。

bento projectとは

安心して使えるVagrantのboxを提供しています。 chef softwareが、内部テストに使っているものだそうです。

github.com

Githubを見ると、インストールされているVirualBoxのguest addition versionがわかって便利です。 (Guest Additionのupdateで何回かはまったことがあるので。。)

https://atlas.hashicorp.com/bento ホストはここですね。

Vagrantfileでの指定方法

めちゃめちゃシンプルです。 CentOS 7.2であれば、

  config.vm.box = "bento/centos-7.2"

Communityが作成したbox

Discover Vagrant Boxes | Atlas by HashiCorp

ここから探せます。 商用サービスとして、自分で作成したboxを置くこともできます。