CygwinでAnsibleは卒業

セットアップ中にぶちぶち切れて失敗続きになるわ、local_actionがよく分からない挙動を示すわで嫌になったのでCygwin使うのを止めてしまいましたが、一応色々回避はしたのでメモ。

SSHの接続に失敗する件

  1. 環境変数ANSIBLE_SSH_ARGSを設定する
  2. ansible.cfgに以下を追加する

     [ssh_connection]
     ssh_args = -o ControlMaster=no
    

Vagrant provisionから呼び出すと、ansible-playbookがNot Foundになる件~local_actionが失敗する件

以前の記事で、以下のようなansible-playbook.batをおけば良いと書きましたが、あれだと不十分でした。

    c:\cygwin\bin\python2.7.exe c:\cygwin\bin\ansible-playbook %*

具体的にはlocal_actionを使った時に、実行に必要な一時ディレクトリが存在しないという状態になります。 上記batから呼び出されたansible-playbookでは、次のようなコマンドがきちんと動いていない(ディレクトリを作れない)みたいなんですね。

    sh -c "mkdir -p $HOME/.ansible/tmp/ansible-1380895750.84-137886494894963"

ただし、local_actionでもrawを使用してコマンドを実行した場合は一時ディレクトリは不要らしいので問題ありません。

ですので、きちんとCygwin上のプロセスとして呼び出されるようにしてやる必要があります。

    @echo off
    PATH=C:\cygwin\bin;%PATH%;
    sh -c 'python /bin/ansible-playbook %*'

これで一応、Vagrant provisionが動くようにはなります。

JavaコードからSQLを追い出したい(Spring編)

Javaって複数行文字列が良い感じに書けないので、長いSQLを書こうとすると結構辛いです。 StringBuilderでくっ付けくっ付けしていくとか、どっかで定数定義しておくとか、プロパティファイルに追い出すとか・・・

今SpringBatchを使うお仕事があったので、良い感じにSQLを定義できないかなと考えてました。

続きを読む

続・Windowsでも(略

VagrantでAnsibleを使ってvagrant provisionするときに、Vagrantfileに以下のように書くんですが

config.vm.provision :ansible do |ansible|
  ansible.playbook = "site.yml"
  ansible.inventory_path = "ansible_hosts"
  ansible.extra_vars = { foo:'bar' }
  ansible.verbose = "extra"
end

このextra_varsが曲者で、渡す値が1組なら問題ない(とりあえず意図通り動くという意味で)のですが、値を2組渡すと実行時にエラーになっちゃいます。

config.vm.provision :ansible do |ansible|
  ansible.playbook = "site.yml"
  ansible.inventory_path = "ansible_hosts"
  ansible.extra_vars = { foo:'bar', baz:'zoo' }
  ansible.verbose = "extra"
end

エラー内容はこんな感じ

ERROR: the playbook: baz=zoo could not be found
Ansible failed to complete successfully. Any error output should be
visible above. Please fix these errors and try again.

extra_varsに設定したはずのパラメータがなぜかplaybookとして扱われる模様。 ログに出力された実行したと思われるコマンドを見るとこんな感じ。

c:\cygwin\bin\python2.7.exe c:\cygwin\bin\ansible-playbook --private-key=C:/Users/xxxx/.vagrant.d/insecure_private_key --user=vagrant "--extra-vars="foo=bar  baz=zoo"" --inventory-file=ansible_hosts -vvv site.yml

extra_vars周りが余分な""で囲まれていて、baz=zooが裸→ansible-playbookコマンドにとってはplaybookのように見えてるのかな・・・と。

で、このままだと困るので一応回避策。

config.vm.provision :ansible do |ansible|
  ansible.playbook = "site.yml"
  ansible.inventory_path = "ansible_hosts"
  ansible.raw_arguments = "--extra-vars=\\\"foo=bar\\\" \\\"baz=zoo\\\""
  ansible.verbose = "extra"
end

ソースを読んだ結果、raw_argumentsを発見。 コメントが恐ろしい感じだけどとりあえず気にしない。 これにより

c:\cygwin\bin\python2.7.exe c:\cygwin\bin\ansible-playbook --private-key=C:/Users/xxxx/.vagrant.d/insecure_private_key --user=vagrant "--extra-vars=\"foo=bar\" \"baz=zoo\"" --inventory-file=ansible_hosts -vvv site.yml

になって、ちゃんと複数のextra_varsが認識される。

オマケ。 verboseって公式ドキュメントを読む限り真偽値だと思ってたら、ソースを読んだら"extra"という文字列でも指定できて、そうすると-vvvとして実行されるのでより詳しいログが出てきます。

Windowsでもansible使ってvagrant provisionしたい

ゴチャゴチャいろいろやったのを記憶を頼りにまとめてみます。

  1. vagrantをインストール

    これは本家サイトからmsiパッケージをダウンロードしてインストールすれば良い

    ついでにvagrant-ansibleプラグインもインストール

  2. ansibleをインストール

     cinst python
     cinst pip
     pip install ansible
    

    は何となく成功するものの、ansible起動でなんかのモジュールが見つかりませんとか言われてコケる。

    cygwinでおkという記事を見たのでその通りに方針転換。記事通りおk。

  3. playbook.ymlとかinventoryファイルを作る

    まずは超簡単にplaybook.yml

     - hosts: vagrant
       tasks:
         - yum: name=/common/files/jdk-7u40-linux-x64.rpm state=present
           sudo: yes
    

    ついでにinventoryファイル

     [vagrant]
     vagrant
    

    inventoryにはIPを書かないで、後述のssh-configで設定した。

  4. Vagrantfileをいじる

    Provisioningの設定 config.vm.provision :ansible do |ansible| ansible.playbook = "site.yml" ansible.inventory_path = "ansible_hosts" ansible.verbose = true end

    ホストオンリーネットワークの設定 config.vm.network :private_network, ip: "192.168.192.168"

  5. ssh-configの設定を書く

     Host vagrant
         HostName    192.168.192.168
         User        vagrant
         IdentityFile    ~/.ssh/vagrant_insecure_key
         StrictHostKeyChecking   no
         UserKnownHostsFile  /dev/null
    

    HostNameにはVagrantfileで設定したIPを指定。1VMずつしか動かせない気がするのでココは課題・・・。あとはvagrant sshするときと同様の情報を設定。

  6. ここまで出来たらvagrant provision

    Failed to load the "vagrant-ansible" plugin. View logs for more details.
    

    こんな警告が出るがとりあえず無視して処理は進む。お、いけるか?と思いきや

    The executable 'ansible-playbook' Vagrant is trying to run was not 
    found in the %PATH% variable. This is an error. Please verify
    this software is installed and on the path.
    

    と言われてコケる。 単独でansible-playbookとやればコマンドは発動するので(;∀;)となるが、ansible-playbookはPythonスクリプトなので、Windowsでは動かない。ぐーぐる先生のお力を借りてbatでラップしちゃう。

     c:\cygwin\bin\python2.7.exe c:\cygwin\bin\ansible-playbook %*
    

    こんなbatファイルをPATH内のどっかに置いてやればおk。

  7. まずはansibleで実行。

      ansible-playbook -i ansible_hosts -vvvv site.yml
    

    -vvvvはログを詳細に表示してくれるオプション。 たまに?(結構頻繁)にSSHがエラーを起こす(原因不明調査中)のでそのために付けてます。

  8. いよいよvagrantで実行

      vagrant provision
    

    こいつもSSH接続で結構エラーを起こす。認証まわりっぽいがよく分からない。。。 うまくいけばProvisioningされて、JDKがインストールされてハッピーになれます。

6でbatファイルを作る必要があるのがミソでしょうか・・・。

以上、Windowsで頑張ってみた話でした。

  • ファイル更新?のタイミングで、ansible_hosts(Inventoryファイル)のパーミッションが+xになっていることがあって、そうなってるとansible_hostsが実行できませんとか意味不明なことを言われる。その場合はchmod -x ansible_hsotsして実行属性を取っ払ってやればおk。
  • YAMLのフォーマットがおかしいとか色々文句も言われるので結構いばらの道。
  • まだ課題もあるのでその辺は継続・・・。

VagrantでVMを管理する

既に書き古された感がありますが、自分用にまとめておく。

Vagrantとは?

公式サイトはこちら

VirtualBoxVMWareなどの仮想マシンを簡単に設定・管理するためのフレームワークです。 プラグインを使うことで、AWSのインスタンスも同様に管理することができます。

導入

ダウンロードページから最新バージョンを落としてきます。2013/09/06時点での最新版は1.2.7です。

インストール先のOSに応じてパッケージが用意されていますので、適切なパッケージをダウンロードし、ぽちぽちとインストールすればOKです。

あと、当然ですが、仮想マシン作れるように、必要な物をインストールしておく必要があります。 VMWareは面倒なのでVirtualBox使います。

VMを登録

個人で使うのであれば、VMがいっぱいあるサイトから、使いたいイメージのURLをメモっておけば良いと思います。 そうはいってもどこの誰が作ったかも分からんVMをなんて使ってられるかという人もいるでしょうから、そういう人はVMイメージ作成からやっちゃいましょう。

Packerは非常に簡単に使えますので、Minimalな設定ファイルをどっかで探してきて自分の用途に合うように書き換えて使えばいいと思います。

使うVMが決まったら以下のコマンドを実行。

vagrant init centos63 https://dl.dropbox.com/u/7225008/Vagrant/CentOS-6.3-x86_64-minimal.box

これで、実行したディレクトリ内にVagrantfileというファイルが作られます。 vagrant initとだけ書いて実行してしまうと、baseというVM名で作られてしまいますので、最初から名前をちゃんと指定しておくのがいいと思います。

Vagrant.configure("2") do |config|
  config.vm.box = "centos63"
  config.vm.box_url = "https://dl.dropbox.com/u/7225008/Vagrant/CentOS-6.3-x86_64-minimal.box"
end

そして、おもむろに以下を実行。

vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Box 'centos63' was not found. Fetching box from specified URL for
the provider 'virtualbox'. Note that if the URL does not have
a box for this provider, you should interrupt Vagrant now and add
the box yourself. Otherwise Vagrant will attempt to download the
full box prior to discovering this error.
Downloading or copying the box...
Extracting box...te: 2293k/s, Estimated time remaining: --:--:--)
Successfully added box 'centos63' with provider 'virtualbox'!
[default] Importing base box 'centos63'...
[default] Matching MAC address for NAT networking...
[default] Setting the name of the VM...
[default] Clearing any previously set forwarded ports...
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
[default] Preparing network interfaces based on configuration...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Booting VM...
[default] Waiting for VM to boot. This can take a few minutes.
[default] VM booted and ready for use!
[default] The guest additions on this VM do not match the installed version of
VirtualBox! In most cases this is fine, but in rare cases it can
cause things such as shared folders to not work properly. If you see
shared folder errors, please update the guest additions within the
virtual machine and reload your VM.

Guest Additions Version: 4.1.18
VirtualBox Version: 4.2
[default] Mounting shared folders...
[default] -- /vagrant
  1. Vagrantfile内で設定されているURLからVMイメージをダウンロードし
  2. VirtualBoxへ登録し
  3. VMを起動し、SSHによるアクセスが可能な状態へ

持って行ってくれます。超簡単。 インストールしてあるVirtualBoxとVMイメージに入ってるVirtualBoxアドオンのバージョン差異があるためゴチャゴチャ言われてますが、特に気にしなくてもいいと思います。 気になるならイメージ作成からやればいいだけです。

ここまでで、以下のことが達成できました。

  • 特定の状態のVMをコマンド数発で建てられます。
  • セットアップがどうとか考える必要が無くなります。

VMを使う

vagrant upしたVMには、vagrant sshで入ることができます。公開鍵認証が設定されているので、パスワードがどうとか悩む必要もありません。

注意したいのは、Vagrantfileがあるディレクトリ(ローカル)と、vagrant upされたVM内の/vagrantは同期されていて、どちらからもアクセス可能になっています。 ファイルの受け渡しに非常に便利ですが、VM上でrm -rf /なんてやると・・・VMだからと油断してるとせっかく書いたVagrantfileが消えたりして悲しい思いをします。。。

プラグインを入れよう

VMには往々にして様々なパッケージやツールが突っ込まれてすぐ調子が悪くなったりします。今のままでもVMを捨てて別のVMをvagrant upすればいいだけではあるのですが、また作りなおすのか・・・と考えると鬱になってしまいます。

そういうときに便利なのがsaharaです。 プラグインのインストールはこんな感じです。

vagrant plugin install sahara
vagrant sandbox on
vagrant ssh
# VM内で何か破壊的な操作(パッケージのインストールとか設定変更など)

# 満足したら
vagrant sandbox commit

# 調子が悪くなったら
vagrant sandbox rollback
vagrant sandbox off

これで、いつでもVMを元の状態に戻すことが出来るようになります。 何かやって起動しなくなった・・・とかなっても、rollbackすればすぐに元の状態に戻せるようになるので大変便利です。 が、sandboxをONにしてないとダメなのでそこは注意です。

saharaは、任意の状態に戻すことはできない(Snapshotを撮れるわけではない)ので、そういうことをしたいのであれば別のプラグインを入れます。

VirtualBox限定にはなってしまいますが、vagrant-vbox-snapshotもいいと思います。

使い方はこんな感じです。あとはサイトをみるのが早いです。

vagrant snapshot take $vmname $label
vagrant snapshot list $vmname

1点わかりにくいのが、$vmnameに何を指定するのか?です。

  • Vagrantfileに書かれているbox名?→NO
  • VirtualBoxに登録されるランダムな登録名?→NO
  • vagrant statusで出力される内容→YES

わかりにくいので実際の出力を。

ikanikama% vagrant status
Current machine states:

default                   running (virtualbox)

こんな出力が出るので、defaultが$vmnameになります。罠・・・?

ここまでで以下のことが達成できます。

  • VMへの破壊的な操作を即座にやり直せる
  • VirtualBox限定ですが)任意の状態へ戻すことができる

まとめ

VirtualBoxVMWareなどの仮想マシンを使うのであればVagrantを一緒に入れてしまうのが良いよ。

snapshotを取ることもできるし、VirtualBoxのコンソールを自分でゴチャゴチャいじる必要はありませんよ。