Mac OS X Mavericksでawscliをインストールする

家で余ってたMBAのセットアップ。
ついでに jq もインストールする。
以前は環境変数の設定周りがごちゃごちゃしてた気がするんだよな・・・。

前提条件

  • デフォルトのpythonは無視したい(homebrewで入れる)
  • zsh
  • /etc/paths を少しいじってる(/usr/local/bin/python が使われるようにして
    る)

インストール

意外とあっさり入った。

brew install python
pip install awscli
brew install jq

デフォルトで入っているpythonとのバージョン比較(3014/07/29現在)

[noguchiwataru@noguchiwataru-no-MacBook-Air] ~
% python --version
Python 2.7.8
[noguchiwataru@noguchiwataru-no-MacBook-Air] ~
% /usr/bin/python --version
Python 2.7.5

設定

アクセストークンはIAMから発行すること。
間違ってもAWSアカウント直で発行しないこと。死ぬ。
また、出力フォーマットはjqで整形できるのでJSONが望ましい。

% aws configure
AWS Access Key ID [None]: your_access_key_id
AWS Secret Access Key [None]: your_secret_access_key
Default region name [None]: ap-northeast-1
Default output format [None]: json

以下のようにすると設定ファイルが作成されていることがわかる。

% ls -F ~/.aws/
config

中身はこんな感じ。

[default]
output = json
region = ap-northeast-1
aws_access_key_id = your_access_key_id
aws_secret_access_key = your_secret_access_key

動作確認

次のコマンドが動作すればOK。

% aws ec2 describe-instances | jq '.'

補完機能を有効にする

zsh

一番最後の行に以下の1行を入れる。
一番最後じゃないと動かなかった気がする。
たぶんデフォルトでパスが通っている場所においてあると思う。

# ~/.zshrc
# (snip)
source aws_zsh_completer.sh

source ~/.zshrc

bash

~/.bashrc じゃだめなので注意。

# ~/.bash_profile
complete -C aws_completer aws

source ~/.bash_profile

References

  1. Configuring the AWS Command Line Interface
  2. Macのzshでawscliの補完を有効化する – 戦場のプログラマー

「hbstudy#60 SerfとConsulでシステム運用を楽しくしよう!」に行ってきました&Serf試してみました

hbstudy#60

行ってまいりました!今回は実際にSerfを使ってみましたので、お手すきの方は是非ごらんください。

今回の勉強会のToggeterまとめはこちらになっています!前佛さんが作成されました。

参加前

繰り上がるつもり・・・!!

f:id:wnoguchi0727:20140721230832p:plain

繰り上がりきたああああああ!(7/17)

概要

hbstudyの趣旨についてですが、インフラエンジニアの勉強会です。

世の中のエンジニアは開発と運用とを掛け持ちされている方も多いかと思われます。
ネットワーク機器のコンフィグをいじることはなくてもLinux系、Windows Server系に限らずサーバの設定やアプリケーションのデプロイ作業等はやったことがある方は結構多いと思います。
Webエンジニアであるからこそ、密接に関わるインフラに対する興味も尽きないわけで、その理解を深めるためにも参加してまいりました。

会場到着(開始前)

会場に到着すると会場の設営はほとんど済んでいるようでした。
参加費1,000円を渡すと首から下げるIDカードを貰いました。

f:id:wnoguchi0727:20140721230850p:plain

さすがに百何十人収容できる会議室は広い。
Wi-Fiはこの段階ではつながらないようだったため、ちょっとテザリングで対応しました。
(のちほどつながるようになりました)

勉強会が始まる段になると、株式会社ハートビーツの馬場さんが司会をつとめてくださいました。

SerfとConsulで運用を楽しくしよう!

  • 最近注目されているSerfとConsulの話と、活用して運用を楽しくしたいね!という話をしていただきます
  • 前佛 雅人さん
  • @zembutsu

いろいろとパロディを交えて楽しく講演をしていただきました。
スライドはこちらです。

Serfについて

Serf

軽量なオーケストレーションツールとのことです。

スクリーンにはVirtualBoxインスタンスを3台動かしている様子が映され、Serfのクラスタが構成するデモをが行われました。

  • バイナリ1個あれば動く
  • コマンド1個叩くだけで動く

同期してserf membersで表示される情報は

  • ホスト名
  • IPアドレス
  • ポート
  • alive, left 等のステータス

情報がすぐに同期される のがポイントらしいです。

  • クラスタが10台でも100台でもすぐに同期できる。

ということがわかっていればもう 帰宅 寝ていても大丈夫とのことです。
(そんなことあない!)

資料を作るときは自動保存するようにしましょうねと注意が促されました。確かに、苦労して作成したデータが保存されていなかったということはよくあると思います。

最近は新しい技術をキャッチアップしていくのが結構大変ですね。Dockerとか流行っています。

Docker Meetup Tokyo行ってみたかったです。

Dockerの講演でも使用されたスライドだそうですが、今回はバージョン1.02だそうです。

頭の悪い資料を作成することで有名とのことですが、そんなことはありません。

ここで、農業の話になり、ラックのようなところでレタスが栽培されているスライドが映しだされました。

ここで、 ラックマウントレタス という造語を思いついた方は少なく無いと思います。

農業でやるとでやるとものすごい初期投資がかかるが、この業界でも監視自動化とかやろうと思えばすぐに試すことができる。

Docker

  • Docker control group
  • namespace
  • aufs

まずはオーケストレーションツールを使ってみる

  • Dockerはエコシステム
  • Eucalyptus Confでしゃべったことがあるそうです。

自動化は

を包含する物

Fun(楽しい)とEasy(楽)は近づけることができる。

制御的な意味合いかな、ミドルウェアの設定はChef等でやる必要があると。
ごめんなさい、間違っていたら指摘をお願いします。

Serf

  • ノードの同期が数秒単位
  • タグ機能(Web、開発)
  • 障害、フェイルオーバ情報の同期
  • wgetでバイナリ1個とってくるだけで動作
  • 多くのプラットフォームで動作
  • HoshiCorpの方が作ったOSSプロダクト

Serfには以下の機能があるそうです。

  • メンバ管理
  • 障害検知
  • カスタムイベント

  • イベントをトリガとして動作する

  • シェルで動くものならなんでも実行できる
  • クラスタ参加・離脱

  • 参加したら監視システムに設定を投入するとか

  • 離脱したらLBから切り離すとか

メンバ管理

タグごとにグループ処理できる

さて

AとBがある

AからBにserf joinで両方を認識する

これでクラスタが構成される。

Cが参加したいとき

  • CがAに参加した
  • AがCに応答する
  • BもMemberjoinを受け取る
  • 以降はランダムに死活監視
  • SPOFがない

Bが突然の死

  1. 死んだのを認識
  2. それでもA, Cは定期的にBをチェックするが
  3. こいつだめだと思われたら容赦なく外す

  4. 多数決論理ではない

  5. NICの死に方によってはフラッピングするかもしれない

イベントが同期される

  • 参加・離脱
  • 伝搬速度はSerfのサイトでシミュレーションできる
  • 理論値で1秒で95%が、2秒で100%(Convergence Simulator – Serf

運用例

  • WebとLB
  • ChefとPuppetとは違う。混同しないこと。
  • メンバーの管理、イベントの発行
  • serf agentコマンドだけで立ち上がる

イベントハンドラ

  • イベントに応じていろんなコマンドを実行する
  • 起動オプションをjsonファイルにまとめられる

→日々の運用管理を楽にしてくれる

LVSに応用する

  • 致命的な問題がある
  • ノード自身が停止は分かる
  • サービスの停止はわからない

そこでConsulですよ

  • サービス検出
  • 障害検知
  • Nagiosプラグインみたいな方法で検出する
  • HTTP APIまたはDNSで結果を返すことができる
  • Zabbixの監視項目を動的化とかね

これらを応用すると

AWSみたいにOpenStackの上でオートスケールとかできるんじゃないでしょうか(聞き取り間違ってたらゴメンナサイ)

  • Web UI
  • HTTP API
  • ローカルのDNSと連携することができる
  • .internal
  • Consulは開発途上です
  • Webサーバのダウンをトリガとして一斉にコマンドを実行するなど

質疑応答

Q. なんでノード指定してjoinしてるのですか?

  1. マルチキャストDNSに対応している環境であれば参加先のノード名を指定する必要はない。
    今回のデモもdiscoverオプションでやっています。

Consul

サービスが消えるとクライアント自身が検出してサーバに送りつける
envconsul
Helokuもどきをつくれる
Qiita上にもいくつか投稿したかも

  • 軽量でシンプル
  • こんな複雑じゃないツールってなかったよね!!

たしかにPacemakerやHeartbeatでHAクラスタ構成する実験しようとしてWebサーバのHAクラスタ構成するだけでものすごい苦労した記憶あります。
私のスキルセットが足りないのが大きな一因なのかもしれませんが・・・。

実践Zabbix

  • Zabbixの管理の自動化
  • 興味があったら見てね〜
  • ZabbixにはAPIがある

cactiはもうオワコンなのだろうか。
たしかにGUIめんどくさい。
グラフ系はZabbixよく聞くようになったなあ・・・。

楽しいと楽をつなげるようなことができればいいな。

Google Group
オーケストレーションの部屋

を用意しました(します)とのことです。

休憩入ります~15:10

130人以上が一斉につなぐとWi-Fi重っ!

「consulについて」

  • HashiCorpの新しいOSSプロダクトConsulの紹介と簡単な応用事例等。
  • Michael H. Oshitaさん
  • @ijin

Consul – HashiCorp

替わりましてijinさんの公演となりました。
スライドはこちらです。

Consulについてもっと詳しく

  • 10年ぐらい日本住んでらっしゃる
  • 本名マイケルさん
  • トラブル☆しゅーたーず という障害対応の勉強会をやります(8/9)

トラブル☆しゅーたーずへの参加はこちらから!

懇親会にも参加しましたがijinさんとよく呼ばれていらっしゃるのでしょうか。
懇親会でもお話を聞くとAWSにものすごく詳しいそうです。
うおおおすごい。

HashiCorpの4つめのプロダクト Consul

  1. Vagrant
  2. Packer
  3. Serf
  4. Consul

特徴

画期的なのは

  • DNSまたはHTTPでできること
  • 複数のデータセンタをまたぐ
  • KVS(動的な設定情報の置き場所として使っている)

構成要素は

  • Consensus Protocol
  • Gossip Protocol
  • Sessions(Chuby)
  • TLS Jespen Testing

アーキテクチャ

エージェントをそれぞれのサーバに入れてサーバモード、またはクライアントモードで動作させる。

サーバモード

CONSISTENCY

  • CAPの定理
  • raftというものを使用している
  • トランザクションのクエリはリーダノードにいってwrite
  • スレーブにレプリケート

  • 半分以上に行ったらコミット成功とみなす

  • quorumにならないとコミットとみなさない

  • ネットワークの分断テストはどうするのか

    • JEPSEN TESTINGでシミュレーションしている

Consul agent

  • foo
  • bar
  • baz

DNS, HTTPで設定

  • タグservice[redis]
  • タグservice[01.web]
  • タグservice[02.web]
dig @localhost -p8600 bar.node.consul
01.web.service.consul
  • serviceでグルーピングすると複数のIPがかえってくる
  • v0.2まではTTLはデフォルトで0
  • 以降はキャッシュできるようになった

key/value endpoint

/v1/kv/<key>
  • RESTful
  • GET, PUT, DESTROY

kv

  • ここでもjqコマンドが使われている
  • base64エンコード
  • 生表示は ?raw をつける

catalog

health

  • ヘルスチェック
  • このへんはjsonで定義する
  • exitコードはnagiosっぽく
  • 内部DNSとして使用できる

ここでデモ

こちらのデモはグッときました。
関連記事はこちら。

Ansibleの場合は

  • staticなhostsファイルに対してpingを打つなど
  • サーバの台数が増えてくるとつらい
  • Ansibleにはダイナミックインベントリという機能がある

  • MySQLレプリケーションしているとき

  • マスタが死んだとき
  • MHA
  • 一番バイナリログが進んでいる奴に対して

  • VIPを変える

  • DNSでカタログのDNSを変更する

  • Consulでうまく連携する方法思いついたのでデモ

DNS引いて得られるIPが変わってスレーブがマスタに昇格する様子が映し出されます。

ベンチマーク

GET

0.2.0→0.3.0のバージョンアップで

  • TTLキャッシュで5倍ぐらいに向上した
  • consistensy

PUTについても改善。

consul-apiはGo言語で書かれている。

consulイイよ!

おしらせ

  • 8/9とらぶるしゅーたずきてね
  • 今日この中にさくらのクラウドの横田さんがいます!
  • SerfとConsulをやった結果をブログでアップしてください!

とのことでした。

以前さくらのクラウドAPIcurlで叩いて操作して、結果をjqで整形して見るようなエントリを書いて、横田さんにリツイートしてもらったのですが、是非一度お目にかかりたかったのでご挨拶してまいりました。
恐れ多くもさくらのクラウドのクーポン券を頂戴いたしました。
大切に使わせていただこうと思います。
横田さんありがとうございます!

f:id:wnoguchi0727:20140721230957p:plain

懇親会

一次会、二次会にまで参加してまいりました。
一応以前はインフラもちょっとは触っていましたが、
私とは比較にならないほどすごくレベルの高いインフラエンジニアの方々ばかりでした。
私は現在、Web系のシステム開発寄りのお仕事をしているのですが、インフラエンジニアの方々の現場の生の声がいろいろ聞けてとても面白かったです。

f:id:wnoguchi0727:20140721231026p:plain

一人大反省会

ちょっといろんな運用自動化系の知識が曖昧だったので整理が必要だなと感じました。今日だけで言葉だけ聞いたことがあるミドルウェアやインフラ基盤用語がいくつもでてきました。

  1. Serf: オーケストレーションツール
  2. Consul: オーケストレーションツール
  3. Ansible: Pythonで書かれた構成管理ツール(Chefの親戚)
  4. Fabric: Python製のデプロイツールCapistranoでやっとピンときた。
  5. Sensu: Nagiosを現代化した版。みんなSensu, Sensuって言ってたのでなんだろうと思ってたら、監視ツールのトレンドはNagiosではなくSensuなのか!Icingaは前に検討したことあったけど、あんまりはやってないのかな。
  6. SoftLayer: 懇親会の席ではデータセンターのクラウド版と言われて理解できなかったのですが、調べてみたら物理サーバーやネットワークの引き回しのレベルでいじれるようにしたクラウドプラットフォームなんだろうか?

  7. 監視ソフトをNagiosからSensuに切り替えて2ヶ月経ったのでまとめた – Glide Note – グライドノート

  8. chef – 次世代監視ツール Sensu リファレンス – Qiita
  9. Home – Icinga: Open Source Monitoring
  10. IBMの新しい高性能クラウド「SoftLayer」を使ってみた ~アカウント開設からインスタンス立ち上げまで (1/4):CodeZine

やってみた(次の日)

「SerfとConsulをやってみた結果をブログでアップしてくださいねー!」とのことでしたので、やってみました。
今回は自分のデスクトップマシンで実験してみようと思います。

僕のデスクトップPCは無駄に性能がいいです。
Core i7に実装メモリ32GB。
ディスプレイは最低2枚ないと生きていけないですね・・・。
最近グラボの調子が悪くて、引っ越してきてから上手く動かないんです。
これがあればディスプレイ4台まではいけるんだけど・・・。
電源の容量足りないのかな・・・?
しかたないからオンボードでデュアルしてます。

という話は置いておいて、こういうことやってるから私はあまりお金がないので、
この無駄に性能のいいマシンで serf のクラスタを構成してみたいと思います。

数の暴力

とりあえず、私はそこまで頭が良くないので Serf のクラスタリングのさわりだけやってみます。

32GBの実装メモリがあるので、これを可能な限り活用してみようと思います。
とりあえず必要最小限のアプリだけ立ち上げてメモリの使用量を減らしまくります。

f:id:wnoguchi0727:20140721231045p:plain

1インスタンス512MBの割り当てとして立ち上げた場合

(29 - 2) * 1000 / 512 = 52

52台分の仮想マシンが構成できます。

もっと頑張れば

(29 - 0.5) * 1000 / 512 ≒ 56

いける。

まずは2台でやってみた

50台近くも立てる予定なので、こんなのVagrant使わないとやってられないのでこの段階からVagrantを使います。
まずは2台。

C:\Users\wnoguchi\Documents\vagrant\serf>vagrant init chef/centos-6.5
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

Vagrantfile抜粋

# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "chef/centos-6.5"
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--memory", "512"]
end
config.vm.define "web_1" do |instance|
instance.vm.network :private_network, ip: "192.168.33.10"
end
config.vm.define "web_2" do |instance|
instance.vm.network :private_network, ip: "192.168.33.11"
end
end

仮想マシン2台立ち上げ

C:\Users\wnoguchi\Documents\vagrant\serf_minimum>vagrant up
Bringing machine 'web_1' up with 'virtualbox' provider...
Bringing machine 'web_2' up with 'virtualbox' provider...
==> web_1: Box 'chef/centos-6.5' could not be found. Attempting to find and install...
web_1: Box Provider: virtualbox
web_1: Box Version: >= 0
==> web_1: Loading metadata for box 'chef/centos-6.5'
web_1: URL: https://vagrantcloud.com/chef/centos-6.5
==> web_1: Adding box 'chef/centos-6.5' (v1.0.0) for provider: virtualbox
web_1: Downloading: https://vagrantcloud.com/chef/centos-6.5/version/1/provider/virtualbox.box
web_1: Progress: 100% (Rate: 5908k/s, Estimated time remaining: --:--:--)
==> web_1: Successfully added box 'chef/centos-6.5' (v1.0.0) for 'virtualbox'!
==> web_1: Importing base box 'chef/centos-6.5'...
==> web_1: Matching MAC address for NAT networking...
==> web_1: Checking if box 'chef/centos-6.5' is up to date...
==> web_1: Setting the name of the VM: serf_minimum_web_1_1405924483325_20292
==> web_1: Clearing any previously set network interfaces...
==> web_1: Preparing network interfaces based on configuration...
web_1: Adapter 1: nat
web_1: Adapter 2: hostonly
==> web_1: Forwarding ports...
web_1: 22 => 2222 (adapter 1)
==> web_1: Running 'pre-boot' VM customizations...
==> web_1: Booting VM...
==> web_1: Waiting for machine to boot. This may take a few minutes...
web_1: SSH address: 127.0.0.1:2222
web_1: SSH username: vagrant
web_1: SSH auth method: private key
web_1: Warning: Connection timeout. Retrying...
==> web_1: Machine booted and ready!
==> web_1: Checking for guest additions in VM...
==> web_1: Configuring and enabling network interfaces...
==> web_1: Mounting shared folders...
web_1: /vagrant => C:/Users/wnoguchi/Documents/vagrant/serf_minimum
==> web_2: Box 'chef/centos-6.5' could not be found. Attempting to find and install...
web_2: Box Provider: virtualbox
web_2: Box Version: >= 0
==> web_2: Loading metadata for box 'chef/centos-6.5'
web_2: URL: https://vagrantcloud.com/chef/centos-6.5
==> web_2: Adding box 'chef/centos-6.5' (v1.0.0) for provider: virtualbox
==> web_2: Importing base box 'chef/centos-6.5'...
==> web_2: Matching MAC address for NAT networking...
==> web_2: Checking if box 'chef/centos-6.5' is up to date...
==> web_2: Setting the name of the VM: serf_minimum_web_2_1405924553780_11101
==> web_2: Fixed port collision for 22 => 2222. Now on port 2200.
==> web_2: Clearing any previously set network interfaces...
==> web_2: Preparing network interfaces based on configuration...
web_2: Adapter 1: nat
web_2: Adapter 2: hostonly
==> web_2: Forwarding ports...
web_2: 22 => 2200 (adapter 1)
==> web_2: Running 'pre-boot' VM customizations...
==> web_2: Booting VM...
==> web_2: Waiting for machine to boot. This may take a few minutes...
web_2: SSH address: 127.0.0.1:2200
web_2: SSH username: vagrant
web_2: SSH auth method: private key
web_2: Warning: Connection timeout. Retrying...
==> web_2: Machine booted and ready!
==> web_2: Checking for guest additions in VM...
==> web_2: Configuring and enabling network interfaces...
==> web_2: Mounting shared folders...
web_2: /vagrant => C:/Users/wnoguchi/Documents/vagrant/serf_minimum

Serfのインストール

$ wget https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
Cannot write to “(snip)” (File name too long).

名前長すぎ!!って怒られてしまった。
また、このboxイメージだとunzipコマンドが入っていないっぽいのでインストール。

sudo yum -y install unzip

もとい、

wget -O 0.6.3_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
unzip 0.6.3_linux_amd64.zip
sudo mv serf /usr/local/bin/

バージョンを確認する。

[vagrant@localhost ~]$ serf version
Serf v0.6.3
Agent Protocol: 4 (Understands back to: 2)

Serfエージェントを立ち上げる

& バックグランドジョブにしないとプロンプトが帰ってこないから注意。

  • host1にて
serf agent -node=host1 &
  • host2にて
serf agent -node=host2 &

クラスタに加わる

mDNS(Multicast DNS)が有効かどうかはわからないので(このへん初心者)、serf join コマンドからとりあえず入門してみることにした。

  • host1にて
[vagrant@localhost ~]$ serf members
2014/07/21 07:04:28 [INFO] agent.ipc: Accepted client: 127.0.0.1:56604
host1  10.0.2.15:7946  alive

メンバは自分のみ。

  • host2に加える
[vagrant@localhost ~]$ serf join host2
2014/07/21 07:04:37 [INFO] agent.ipc: Accepted client: 127.0.0.1:56605
2014/07/21 07:04:37 [INFO] agent: joining: [host2] replay: false
2014/07/21 07:04:37 [WARN] memberlist: Failed to resolve host2: lookup host2: no such host
2014/07/21 07:04:37 [WARN] agent: error joining: lookup host2: no such host
Error joining the cluster: lookup host2: no such host

あれ、エラー・・・。
そうだよね、host1がhost2のIPアドレス知ってるわけないもんね・・・。

  • IP直指定でhost2に加える。
[vagrant@localhost ~]$ serf join 192.168.33.11
2014/07/21 07:11:39 [INFO] agent.ipc: Accepted client: 127.0.0.1:56606
2014/07/21 07:11:39 [INFO] agent: joining: [192.168.33.11] replay: false
2014/07/21 07:11:39 [INFO] serf: EventMemberJoin: host2 10.0.2.15
2014/07/21 07:11:39 [INFO] agent: joined: 1 nodes
Successfully joined cluster by contacting 1 nodes.
[vagrant@localhost ~]$     2014/07/21 07:11:40 [INFO] agent: Received event: member-join
2014/07/21 07:11:41 [WARN] memberlist: Got ping for unexpected node 'host2'
2014/07/21 07:11:42 [INFO] memberlist: Suspect host2 has failed, no acks received
2014/07/21 07:11:43 [WARN] memberlist: Got ping for unexpected node 'host2'
2014/07/21 07:11:44 [INFO] memberlist: Suspect host2 has failed, no acks received
2014/07/21 07:11:44 [WARN] memberlist: Got ping for unexpected node 'host2'
2014/07/21 07:11:45 [INFO] memberlist: Suspect host2 has failed, no acks received
2014/07/21 07:11:46 [WARN] memberlist: Got ping for unexpected node 'host2'
2014/07/21 07:11:47 [INFO] memberlist: Suspect host2 has failed, no acks received
2014/07/21 07:11:47 [INFO] memberlist: Marking host2 as failed, suspect timeout reached
2014/07/21 07:11:47 [INFO] serf: EventMemberFailed: host2 10.0.2.15
2014/07/21 07:11:48 [INFO] agent: Received event: member-failed

うまくい・・・ったようにみえて最終的に失敗している。

  • serf members の結果

host2との通信が失敗してる(failed となっている)。
いったんハンドシェイクが成功して繋がらなくなったような感じ。

[vagrant@localhost ~]$ serf members
2014/07/21 07:12:03 [INFO] agent.ipc: Accepted client: 127.0.0.1:56608
host1  10.0.2.15:7946  alive
host2  10.0.2.15:7946  failed

まてよ、と思い直す。
Vagrantfileでプライベートネットワークを構成するためにNIC追加してたんだ。
どのNICでリッスンしてるかわかんないと通信を確立していいIPアドレスもわからないんじゃないか。

改めてhost1, host2それぞれのNICの当たり方を確認してみる。

  • host1
[vagrant@localhost ~]$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:ce:08:3d brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
inet6 fe80::a00:27ff:fece:83d/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:5e:6e:58 brd ff:ff:ff:ff:ff:ff
inet 192.168.33.10/24 brd 192.168.33.255 scope global eth1
inet6 fe80::a00:27ff:fe5e:6e58/64 scope link
valid_lft forever preferred_lft forever
  • host2
[vagrant@localhost ~]$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:ce:08:3d brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
inet6 fe80::a00:27ff:fece:83d/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:ba:62:c3 brd ff:ff:ff:ff:ff:ff
inet 192.168.33.11/24 brd 192.168.33.255 scope global eth1
inet6 fe80::a00:27ff:feba:62c3/64 scope link
valid_lft forever preferred_lft forever

NIC3つついてるから eth0 のアドレスで通信を確立したらいいかどうか分かんなくて失敗したのかな。

NICを指定してSerfエージェントを立ち上げる

さて、仕切り直し。
fg してCtrl-C でプロセス殺して以下の設定でエージェント再度起動。

  • host1にて
serf agent -iface=eth1 -node=host1 &
  • host2にて
serf agent -iface=eth1 -node=host2 &

serf joinしてみる

[vagrant@localhost ~]$ serf join 192.168.33.11
2014/07/21 07:48:37 [INFO] agent.ipc: Accepted client: 127.0.0.1:56634
2014/07/21 07:48:37 [INFO] agent: joining: [192.168.33.11] replay: false
2014/07/21 07:48:37 [INFO] serf: EventMemberJoin: host2 192.168.33.11
2014/07/21 07:48:37 [INFO] agent: joined: 1 nodes
Successfully joined cluster by contacting 1 nodes.
[vagrant@localhost ~]$     2014/07/21 07:48:38 [INFO] agent: Received event: member-join

今度は成功したみたいだ。

serf membersの結果

どっちもaliveと表示された。

[vagrant@localhost ~]$ serf members
2014/07/21 07:48:44 [INFO] agent.ipc: Accepted client: 127.0.0.1:56636
host1  192.168.33.10:7946  alive
host2  192.168.33.11:7946  alive
  • 試しにhost2 のSerfエージェントを殺す。

上品な方法でシャットダウンするようです。

[vagrant@localhost ~]$ fg
serf agent -iface=eth1 -node=host2
^C==> Caught signal: interrupt
==> Gracefully shutting down agent...
2014/07/21 07:51:04 [INFO] agent: requesting graceful leave from Serf
2014/07/21 07:51:05 [INFO] serf: EventMemberLeave: host2 192.168.33.11
2014/07/21 07:51:05 [INFO] agent: requesting serf shutdown
2014/07/21 07:51:05 [INFO] agent: shutdown complete
  • host1側でメンバの一覧を確認。

failed ではなく left となっているところがポイントですね。

[vagrant@localhost ~]$ serf members
2014/07/21 07:51:12 [INFO] agent.ipc: Accepted client: 127.0.0.1:56642
host2  192.168.33.11:7946  left
host1  192.168.33.10:7946  alive

Serfエージェントを立ち上げる(マルチキャストDNS

50何台すべてにserf joinしてたらたまらないのでマルチキャストDNS版もためす。

  • host1にて
serf agent -iface=eth1 -node=host1 -discover=webapp &
  • host2にて
serf agent -iface=eth1 -node=host2 -discover=webapp &

ログの流れは次のような感じ

host1にてエージェントを立ち上げると

[vagrant@localhost ~]$ serf agent -iface=eth1 -node=host1 -discover=webapp &
[1] 2308
[vagrant@localhost ~]$ ==> Using interface 'eth1' address '192.168.33.10'
==> Starting Serf agent...
==> Starting Serf agent RPC...
==> Serf agent running!
Node name: 'host1'
Bind addr: '192.168.33.10:7946'
RPC addr: '127.0.0.1:7373'
Encrypted: false
Snapshot: false
Profile: lan
mDNS cluster: webapp
==> Log data will now stream in as it occurs:
2014/07/21 08:06:13 [INFO] agent: Serf agent starting
2014/07/21 08:06:13 [INFO] serf: EventMemberJoin: host1 192.168.33.10
2014/07/21 08:06:13 [INFO] agent: joining: [192.168.33.10:7946] replay: false
2014/07/21 08:06:13 [INFO] agent: joined: 1 nodes
2014/07/21 08:06:13 [INFO] agent.mdns: Joined 1 hosts
2014/07/21 08:06:14 [INFO] agent: Received event: member-join

ついでhost2で立ち上げるとhost2側では以下の様なログが流れ、

[vagrant@localhost ~]$ ==> Using interface 'eth1' address '192.168.33.11'
==> Starting Serf agent...
==> Starting Serf agent RPC...
==> Serf agent running!
Node name: 'host2'
Bind addr: '192.168.33.11:7946'
RPC addr: '127.0.0.1:7373'
Encrypted: false
Snapshot: false
Profile: lan
mDNS cluster: webapp
==> Log data will now stream in as it occurs:
2014/07/21 08:07:11 [INFO] agent: Serf agent starting
2014/07/21 08:07:11 [INFO] serf: EventMemberJoin: host2 192.168.33.11
2014/07/21 08:07:11 [INFO] agent: joining: [192.168.33.11:7946 192.168.33.10:7946] replay: false
2014/07/21 08:07:11 [INFO] serf: EventMemberJoin: host1 192.168.33.10
2014/07/21 08:07:11 [INFO] agent: joined: 2 nodes
2014/07/21 08:07:11 [INFO] agent.mdns: Joined 2 hosts
2014/07/21 08:07:12 [INFO] agent: Received event: member-join
  • host1側でも
    2014/07/21 08:07:11 [INFO] serf: EventMemberJoin: host2 192.168.33.11
2014/07/21 08:07:12 [INFO] agent: Received event: member-join
2014/07/21 08:07:13 [INFO] agent: joining: [192.168.33.11:7946] replay: false
2014/07/21 08:07:13 [INFO] agent: joined: 1 nodes
2014/07/21 08:07:13 [INFO] agent.mdns: Joined 1 hosts

という追加のログが流れる。

serf members の結果は

OK。

[vagrant@localhost ~]$ serf members
2014/07/21 08:09:33 [INFO] agent.ipc: Accepted client: 127.0.0.1:35347
host2  192.168.33.11:7946  alive
host1  192.168.33.10:7946  alive

ここまででVMは要らなくなったので一括削除。

vagrant destroy -f

ここまでのSerfの使い方で参考にしたのは前佛さんの以下の記事です。

  1. Serf設定オプションまとめ | Pocketstudio.jp log3
  2. 【Serf】v0.2.0 へのバージョンアップと、変わった所を確認してみた | Pocketstudio.jp log3
  3. ご注文は監視自動化ですか?

Vagrant複数インスタンスを立ち上げるのに参考にしたのは以下、

  1. vagrantの複数インスタンスをたてて遊んでみる – わすれっぽいきみえ
  2. study-vagrant/study4 at master · tmknom/study-vagrant

今度は予めプロビジョニングした状態のSerfクラスタを構成する

これができるようになるまで何回も vagrant destroy -f でぶっこわしまくりました。

# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "chef/centos-6.5"
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--memory", "512"]
end
config.vm.define "web_1" do |instance|
instance.vm.network :private_network, ip: "192.168.33.10"
instance.vm.provision :shell do |shell|
shell.inline = <<-EOS
        if [ ! `which unzip` ]; then sudo yum -y install unzip ;fi
        if [ ! `which serf` ]; then
          cd /tmp/
          wget -O 0.6.3_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
          unzip 0.6.3_linux_amd64.zip
          sudo mv serf /usr/local/bin/
          nohup /usr/local/bin/serf agent -iface=eth1 -node=host1 -discover=webapp 0<&- &>/dev/null&
          cat <<EOF >>/etc/rc.d/rc.local
          /usr/local/bin/serf agent -iface=eth1 -node=host1 -discover=webapp &
EOF
        fi
      EOS
end
end
config.vm.define "web_2" do |instance|
instance.vm.network :private_network, ip: "192.168.33.11"
instance.vm.provision :shell do |shell|
shell.inline = <<-EOS
        if [ ! `which unzip` ]; then sudo yum -y install unzip ;fi
        if [ ! `which serf` ]; then
          cd /tmp/
          wget -O 0.6.3_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
          unzip 0.6.3_linux_amd64.zip
          sudo mv serf /usr/local/bin/
          nohup /usr/local/bin/serf agent -iface=eth1 -node=host2 -discover=webapp 0<&- &>/dev/null&
          cat <<EOF >>/etc/rc.d/rc.local
          /usr/local/bin/serf agent -iface=eth1 -node=host2 -discover=webapp &
EOF
        fi
      EOS
end
end
end
  1. Linuxでのプロセスの管理(bg,fg,disown) – longicornの日記
  2. Linuxコマンド集 – 【 nohup 】 ログアウトした後もコマンドを実行し続ける:ITpro
  3. Shell provisioning fails to exit · Issue #1553 · mitchellh/vagrant

Serfクラスタ10台を構成する

いきなり50台はなんかうまくいかなそうな気がするので、10台からやってみる。
このままじゃプロビジョニングが美しくないのでRuby力を発揮する。

# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "chef/centos-6.5"
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--memory", "512"]
end
# Number of Virtual Machines
NUMBER_OF_VMS = 10
ip_addr_base = 10
(1..NUMBER_OF_VMS).each do |host_index|
define_name = "web_#{host_index}"
hostname = "host#{host_index}"
octet4 = ip_addr_base + host_index - 1
config.vm.define define_name do |instance|
instance.vm.network :private_network, ip: "192.168.33.#{octet4}"
instance.vm.provision :shell do |shell|
shell.inline = <<-EOS
          if [ ! `which unzip` ]; then sudo yum -y install unzip ;fi
          if [ ! `which serf` ]; then
            cd /tmp/
            wget -O 0.6.3_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
            unzip 0.6.3_linux_amd64.zip
            sudo mv serf /usr/local/bin/
            nohup /usr/local/bin/serf agent -iface=eth1 -node=#{hostname} -discover=webapp 0<&- &>/dev/null&
            cat <<EOF >>/etc/rc.d/rc.local
            /usr/local/bin/serf agent -iface=eth1 -node=#{hostname} -discover=webapp &
EOF
          fi
        EOS
end
end
end
end

このあたりになってくるとvagrant upコマンドがなかなか終わらないが、
始めのころのVMは既にアクセス可能になっているはずなので、
そのノードに接続してwatchコマンドとかでserf membersの変化とかを確認すると
出来上がったインスタンスから次々にSerfのクラスタwebappクラスタに加わっていって結構面白いことになってる。

watch -n 1 serf members

f:id:wnoguchi0727:20140721231247p:plain

冪等性も保証しているので、ひと通りメンバに加わったことがわかったらここで

vagrant reload

してみるのも面白い。

リロード中のVMはfailedのステータスになる。
さらに特定のVMだけを停止してみたり、

C:\Users\wnoguchi\Documents\vagrant\serf_minimum>vagrant halt web_3
==> web_3: Attempting graceful shutdown of VM...

f:id:wnoguchi0727:20140721231311p:plain

一斉にとめて一斉に再起動するのもfailedがどんどん増えていくのでなかなかおつなものです。
ただし接続している自分自身がシャットダウンされたら元も粉もないですけど。

C:\Users\wnoguchi\Documents\vagrant\serf_minimum>vagrant halt
==> web_10: Attempting graceful shutdown of VM...
==> web_9: Attempting graceful shutdown of VM...
==> web_8: Attempting graceful shutdown of VM...
==> web_7: Attempting graceful shutdown of VM...
==> web_6: Attempting graceful shutdown of VM...
==> web_5: Attempting graceful shutdown of VM...
==> web_4: Attempting graceful shutdown of VM...
==> web_2: Attempting graceful shutdown of VM...
==> web_1: Attempting graceful shutdown of VM...
C:\Users\wnoguchi\Documents\vagrant\serf_minimum>vagrant up
Bringing machine 'web_1' up with 'virtualbox' provider...
Bringing machine 'web_2' up with 'virtualbox' provider...
Bringing machine 'web_3' up with 'virtualbox' provider...
Bringing machine 'web_4' up with 'virtualbox' provider...
Bringing machine 'web_5' up with 'virtualbox' provider...
Bringing machine 'web_6' up with 'virtualbox' provider...
Bringing machine 'web_7' up with 'virtualbox' provider...
Bringing machine 'web_8' up with 'virtualbox' provider...
Bringing machine 'web_9' up with 'virtualbox' provider...
Bringing machine 'web_10' up with 'virtualbox' provider...
==> web_1: Checking if box 'chef/centos-6.5' is up to date...
==> web_1: Clearing any previously set forwarded ports...

52ノードクラスタへの挑戦

もはや定数定義を52にしてマシンパワーの限界に挑戦するような感じになってきました。

# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "chef/centos-6.5"
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--memory", "512"]
end
# Number of Virtual Machines
NUMBER_OF_VMS = 52
ip_addr_base = 10
(1..NUMBER_OF_VMS).each do |host_index|
define_name = "web_#{host_index}"
hostname = "host#{host_index}"
octet4 = ip_addr_base + host_index - 1
config.vm.define define_name do |instance|
instance.vm.network :private_network, ip: "192.168.33.#{octet4}"
instance.vm.provision :shell do |shell|
shell.inline = <<-EOS
          if [ ! `which unzip` ]; then sudo yum -y install unzip ;fi
          if [ ! `which serf` ]; then
            cd /tmp/
            wget -O 0.6.3_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
            unzip 0.6.3_linux_amd64.zip
            sudo mv serf /usr/local/bin/
            nohup /usr/local/bin/serf agent -iface=eth1 -node=#{hostname} -discover=webapp 0<&- &>/dev/null&
            cat <<EOF >>/etc/rc.d/rc.local
            /usr/local/bin/serf agent -iface=eth1 -node=#{hostname} -discover=webapp &
EOF
          fi
        EOS
end
end
end
end

あともうひと息だったのですが、フォワーディングするポートが衝突してしまい、息絶えました。

f:id:wnoguchi0727:20140721232212p:plain

==> web_51:   inflating: serf
==> web_52: Importing base box 'chef/centos-6.5'...
==> web_52: Matching MAC address for NAT networking...
==> web_52: Checking if box 'chef/centos-6.5' is up to date...
==> web_52: Setting the name of the VM: serf_minimum_web_52_1405943316239_88578
Vagrant found a port collision for the specified port and virtual machine.
While this port was marked to be auto-corrected, the ports in the
auto-correction range are all also used.
VM: web_52
Forwarded port: 22 => 2222

少し書きなおしてみる。

# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "chef/centos-6.5"
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--memory", "512"]
end
# Number of Virtual Machines
NUMBER_OF_VMS = 52
ip_addr_base = 10
(1..NUMBER_OF_VMS).each do |host_index|
define_name = "web_#{host_index}"
hostname = "host#{host_index}"
octet4 = ip_addr_base + host_index - 1
forwarding_port = 8080 + host_index - 1
config.vm.define define_name do |instance|
instance.vm.network :private_network, ip: "192.168.33.#{octet4}"
instance.vm.network "forwarded_port", guest: 22, host: forwarding_port
instance.vm.provision :shell do |shell|
shell.inline = <<-EOS
          if [ ! `which unzip` ]; then sudo yum -y install unzip ;fi
          if [ ! `which serf` ]; then
            cd /tmp/
            wget -O 0.6.3_linux_amd64.zip https://dl.bintray.com/mitchellh/serf/0.6.3_linux_amd64.zip
            unzip 0.6.3_linux_amd64.zip
            sudo mv serf /usr/local/bin/
            nohup /usr/local/bin/serf agent -iface=eth1 -node=#{hostname} -discover=webapp 0<&- &>/dev/null&
            cat <<EOF >>/etc/rc.d/rc.local
            /usr/local/bin/serf agent -iface=eth1 -node=#{hostname} -discover=webapp &
EOF
          fi
        EOS
end
end
end
end

今度はどうだろう。
ダメだった。

んー時間切れ。51ノードまでは確認できました。
ポートフォワーディングのコンフリクトが直せればもっといけそうな感じ。

f:id:wnoguchi0727:20140721232129p:plain

以上のVagrantfileは以下のGistからも取得可能です。

第60回: SerfとConsulでシステム運用を楽しくしよう!http://connpass.com/event/7322/ : 今回の実験使用したVagrantfileの一覧

Consulは?

Consulについてはサービス管理の機能がDNS, HTTP APIでシンプルに提供されいてることが分かったのですが、私の理解力が追いついていないため、今回は検証までには至りませんでした・・・。

以上です、ありがとうございました!

最近t1に加えてt2も出たのか―(PVからHVMにも変わってる)

7/1にt2インスタンスが発表されてます。
それに伴ってLaunch Wizardで選択できるAmazon LinuxのAMIもt2が選択できる代わりにHVMになっています。

今まで t1.micro ばっかり使っていて ParaVirtual(PV、準仮想化) しか知らなかったので、
HVM(Hardware-assited VM) で動くインスタンスがあるとは知らなんだ。

  • HVMってことはKVMみたいに完全仮想化になってるって考えていいのかな?
  • PVはXenみたいな準仮想化的な位置づけ。

間違ってたら教えて下さい。><

ちょっとやってみたけどHVMのAMIで作られたEC2インスタンスのEBSスナップショットからStampパターンのAMIを作るときにPVで作って動かそうとしたらうまく動かなかったよ。

リンク先を見たらわかるけど、結構手順が大変みたいだね。

References

  1. EC2のt1.microをt2.microへ移行する : アジャイル株式会社
  2. t2.micro、t2.smallインスタンスについて  | ナレコムAWSレシピ

Docker User Guideをやってみたよ(1)

今回はDockerコンテナでアプリケーションを動かすまで。

Getting Started with Docker Hub

Getting Started with Docker Hub – Docker Documentation

Docker Hubに登録する。
登録は簡単だった。

Welcomeページ

f:id:wnoguchi0727:20140717233734p:plain

ダッシュボード

f:id:wnoguchi0727:20140717233743p:plain

Dockerizing Applications: A “Hello world

Dockerizing Applications – Docker Documentation

Dockerはコンテナ内でのアプリケーション実行を可能とする。

[vagrant@localhost ~]$ sudo docker run ubuntu:14.04 /bin/echo 'Hello world'
Unable to find image 'ubuntu:14.04' locally
Pulling repository ubuntu
e54ca5efa2e9: Download complete
511136ea3c5a: Download complete
d7ac5e4f1812: Download complete
2f4b4d6a4a06: Download complete
83ff768040a0: Download complete
6c37f792ddac: Download complete
Hello world

Dockerは ubuntu:14.04 というイメージ名のものがローカルに存在することを確認し、
存在しなければ Docker Hub からダウンロードしてくる。

イメージの取得が終わればDockerは /bin/echo 'Hello world' を実行し、
そのコマンドの実行が終了すればただちにコンテナを終了するようになっている。
つまりHello worldと表示して終わり。

-t で擬似端末を割り当てて、 -i でDockerコンテナに対する標準入力を開いたままにする。つまりインタラクティブ

[vagrant@localhost ~]$ sudo docker run -t -i ubuntu:14.04 /bin/bash
root@d857fbed59d2:/# pwd
/
root@d857fbed59d2:/# ls -F
bin/  boot/  dev/  etc/  home/  lib/  lib64/  media/  mnt/  opt/  proc/  root/  run/  sbin/  srv/  sys/  tmp/  usr/  var/
root@d857fbed59d2:/# exit
exit

今度はコンテナ内のbashのプロセスが終了するタイミングでコンテナが停止した。
docker ps してみるとおもしろい。

[vagrant@localhost ~]$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS                          PORTS               NAMES
d857fbed59d2        ubuntu:14.04        /bin/bash              2 minutes ago       Exited (0) About a minute ago                       sad_engelbart
b122a6b2cb7f        ubuntu:14.04        /bin/echo 'Hello wor   3 minutes ago       Exited (0) 3 minutes ago                            drunk_pasteur
59d7660a51a8        centos:latest       /bin/bash              24 hours ago        Exited (0) 23 hours ago                             clever_nobel

デーモン化してみる

[vagrant@localhost ~]$ sudo docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
d9b0c80c495d41a11d8c552d39ceac65ed21b39a3d5adc695cf181d13dd9863c

1秒おきにhello worldを出力するジョブを半永久的に実行するコンテナで、これは -d オプションにてバックグラウンドで実行されるようになる。

hello worldは1つも標準出力に出てこない代わりにハッシュ値が得られた。
これがコンテナIDというらしい。
Gitのコミットハッシュみたいに先頭数桁使えばいけるのかな?

[vagrant@localhost ~]$ echo d9b0c80c495d41a11d8c552d39ceac65ed21b39a3d5adc695cf181d13dd9863c | wc -m
65

ちなみに65桁で構成されているようだ。

docker ps してみるとコンテナは終了せずに動き続けていることが分かる。

[vagrant@localhost ~]$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
d9b0c80c495d        ubuntu:14.04        /bin/sh -c 'while tr   2 minutes ago       Up 2 minutes                            hopeful_darwin

コンテナ名は便宜的に hopeful_darwin と付けられている。期待のMac OS X?英語のジョークはよくわからないな。

これじゃコンテナ内でどうなっているかわからないから docker logs コマンドを発行してみる。

[vagrant@localhost ~]$ sudo docker logs d9b0c80c495
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
[vagrant@localhost ~]$ sudo docker logs hopeful_darwin
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world

コンテナID、コンテナ名でもどちらでもいけるようだ。

片付けする

もう用済みなのでコンテナを停止する。

[vagrant@localhost ~]$ sudo docker stop hopeful_darwin
hopeful_darwin

停まったか確認する。

[vagrant@localhost ~]$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

すばらしい。今日はここまで。

References

  1. The Docker User Guide – Docker Documentation
  2. doc/DevOps/Docker/README.md at master · wnoguchi/doc

CentOS6.5にDockerインストールしてみた

Dockerすごく流行ってるらしいから今更ながら手を付けてみた。
Vagrantでバシッときれいな環境用意できるのがほんと手軽でいいね。

今回もこれで簡単に仮想マシン用意できました。

vagrant init chef/centos-6.5
vagrant up

インストール

  • CentOS6.5 x86_64

EPEL有効にする

EPEL – FedoraProject

sudo rpm -ivh http://ftp.jaist.ac.jp/pub/Linux/Fedora/epel/6/i386/epel-release-6-8.noarch.rpm

Dockerインストール

  • Docker(1.0.0-6.el6)

  • インストール

sudo yum install docker-io
  • Dockerのサービススタート。
sudo service docker start
Starting cgconfig service:                                 [  OK  ]
Starting docker:                                       [  OK  ]
sudo chkconfig docker on
  • Dockerがちゃんと動いていることを確認するために最新版のCentOSイメージを取得する。
[vagrant@localhost ~]$ sudo docker pull centos:latest
Pulling repository centos
1a7dc42f78ba: Download complete
511136ea3c5a: Download complete
34e94e67e63a: Download complete
  • 取得が完了したらCentOSのイメージの一覧が以下のコマンドでリストに表示されることを確認する。
[vagrant@localhost ~]$ sudo docker images centos
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              latest              1a7dc42f78ba        7 days ago          236.4 MB
  • イメージのテストをするためにbashを立ち上げてみよう。
sudo docker run -i -t centos /bin/bash

ちなみに -i はアタッチされていなくても標準入力を開いたままにしておくオプション。
-t は擬似端末(pseudo-tty)を割り当てることを意味する。
あいかわらずもやもやしている。

  -i, --interactive=false    Keep stdin open even if not attached
-t, --tty=false            Allocate a pseudo-tty

で、結果が以下。

[vagrant@localhost ~]$ sudo docker run -i -t centos /bin/bash
bash-4.2#

うん、プロンプト表示された。

実験

このままじゃ面白く無いからMySQL(クライアント)入れてみる。

bash-4.2# yum -y install mysql

当然ながらホストには全く影響がない。

[vagrant@localhost ~]$ mysql
-bash: mysql: コマンドが見つかりません
[vagrant@localhost ~]$ sudo -i
[root@localhost ~]# mysql
-bash: mysql: コマンドが見つかりません

本当はMySQLサーバ入れてみたかったんだけど、コンテナの中で

yum -y install mysql-server

すると「そんなのねぇ!」って怒られる。

mysql-server がどのリポジトリに入っているのか調べると updates リポジトリに入っていることが分かる。

[root@localhost ~]# yum info mysql-server
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: centos.mirror.secureax.com
* epel: ftp.jaist.ac.jp
* extras: centos.mirror.secureax.com
* updates: centosv4.centos.org
Available Packages
Name        : mysql-server
Arch        : x86_64
Version     : 5.1.73
Release     : 3.el6_5
Size        : 8.6 M
Repo        : updates
Summary     : The MySQL server and related files
URL         : http://www.mysql.com
License     : GPLv2 with exceptions
Description : MySQL is a multi-user, multi-threaded SQL database server. MySQL is a
: client/server implementation consisting of a server daemon (mysqld)
: and many different client programs and libraries. This package contains
: the MySQL server and some accompanying files and directories.

ホスト側をupdatesでgrepするとヒットする。

[root@localhost ~]# cat /etc/yum.repos.d/CentOS-Base.repo | grep updates
# geographically close to the client.  You should use this for CentOS updates
#released updates
[updates]
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates
#baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/

コンテナ内でgrepしてもヒットする。

bash-4.2# cat /etc/yum.repos.d/CentOS-Base.repo | grep updates
# geographically close to the client.  You should use this for CentOS updates
#released updates
[updates]
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates
#baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/

うーん。なんで?

決定的違いを発見。

  • ホスト
[root@localhost ~]# cat /etc/redhat-release
CentOS release 6.5 (Final)
  • コンテナ
bash-4.2# cat /etc/redhat-release
CentOS Linux release 7.0.1406 (Core)

なんじゃこりゃ。

コンテナではmariadbとか出てたし、CentOS7になってなんか変わったのだろうか。
追って色々調べよう。

とりあえず開発パッケージとか入れたりしてホストとコンテナの間で影響が無いことを確認して終了。

  • docker ps コマンドを発行してみる。

-a オプションは終了したコンテナ環境も一覧表示してくれる。

[vagrant@localhost ~]$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
59d7660a51a8        centos:latest       /bin/bash           33 minutes ago      Exited (0) 3 minutes ago                       clever_nobel

さっきのあるね。アタッチしてみよう。

[vagrant@localhost ~]$ sudo docker attach 59d7660a51a8
2014/07/16 14:30:54 You cannot attach to a stopped container, start it first

停止したコンテナはアタッチできないって言われた。では開始しよう。

[vagrant@localhost ~]$ sudo docker start 59d7660a51a8
59d7660a51a8

docker ps してみる。

[vagrant@localhost ~]$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
59d7660a51a8        centos:latest       /bin/bash           42 minutes ago      Up 25 seconds                           clever_nobel

おお動いてる。アタッチする。

[vagrant@localhost ~]$ sudo docker attach 59d7660a51a8
bash-4.2# which gcc
/usr/bin/gcc
bash-4.2#

ちゃんと環境復元できてる!そして exit したら

[vagrant@localhost ~]$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

でもコンテナは削除してないから

[vagrant@localhost ~]$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
59d7660a51a8        centos:latest       /bin/bash           43 minutes ago      Exited (0) 4 seconds ago                       clever_nobel

残ってる。
やばいおもしろい。

References

  1. CentOS 6.5 で Docker を使ってみる | CUBE SUGAR STORAGE
  2. CentOS – Docker Documentation