~nabeken/diary/
https://projects.tsuntsun.net/~nabeken/diary/
nabeken's diary
-
移転しました
https://projects.tsuntsun.net/~nabeken/diary/moved.html
<a href="http://mahiru.moe/>http://mahiru.moe/</a>に移転しました。
2015-01-18T18:00:00+09:00
-
ConoHaで使えるIPv6アドレスをDockerで有効活用する
https://projects.tsuntsun.net/~nabeken/diary/Sysadmin/conoha-docker-ipv6.html
<h2>UPDATE:</h2><ul>
<li>初稿 (Tue, 4 Feb 2014 13:10:04 +0900)</li>
</ul>
<div class="section" id="docker">
<h3>Dockerのネットワーク構成</h3>
<p>dockerをインストールするとブリッジインターフェース <tt class="docutils literal">docker0</tt> が作成されます。</p>
<pre class="literal-block">
$ ifconfig docker0
docker0 Link encap:Ethernet HWaddr be:d2:8e:4b:02:46
inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::bcd2:8eff:fe4b:246/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:668 (668.0 B)
</pre>
<p>コンテナ(LXC)の <tt class="docutils literal">eth0</tt> はホスト側の <tt class="docutils literal">vethXXXX</tt> とペアになっています。
そして、 <tt class="docutils literal">vethXXXX</tt> は <tt class="docutils literal">docker0</tt> へ追加されています。</p>
<p>IPv4の場合はiptablesによってNATすることでコンテナからインターネットへの通信ができます。
一方でインターネットからコンテナへは起動時にポート単位で指定しNATするようになっています。</p>
<p>docker0はdockerの標準的なセットアップなので、IPv6アドレス対応でもこの枠組みを使うことにします。</p>
</div><div class="section" id="conohaipv6">
<h3>ConoHaにおける追加IPv6アドレスの扱い</h3>
<p><a class="reference external" href="http://blog.livedoor.jp/goldfish_and_laser/archives/4548352.html">http://blog.livedoor.jp/goldfish_and_laser/archives/4548352.html</a> にあるように、
追加アドレスはDHCPv6で取得したIPv6アドレスから機械的に算出できます。</p>
<p>追加アドレスはホスト側のインターフェースには付与せず、コンテナの <tt class="docutils literal">eth0</tt> に付与します。
作業の前にホスト側に設定されている現在のデフォルトゲートウェイをメモしておきます。</p>
<pre class="literal-block">
$ ip -6 route | grep default
default via fe80::1052:1 dev eth0 metric 1024
</pre>
<p>おそらく <tt class="docutils literal"><span class="pre">fe80::1052:1</span></tt> になっていると思います。</p>
</div><div class="section" id="docker-runipv6">
<h3>docker run時にIPv6アドレスを指定する</h3>
<p><a class="reference external" href="http://zargony.com/2013/10/13/ipv6-in-docker-containers">http://zargony.com/2013/10/13/ipv6-in-docker-containers</a> を参考に以下で指定します。</p>
<pre class="literal-block">
$ docker run -i -t -lxc-conf="lxc.network.ipv6 = 2001:db8::1/128" ubuntu /bin/bash
</pre>
<p>LXCの設定ではデフォルトゲートウェイも設定することができます。
しかし、/128ということはこのリンク上には自分以外誰もいないため、
デフォルトゲートウェイは別のネットワークから指定する必要があります。
IPv6にはリンク上でのみ使えるアドレスとしてlink-localアドレスがありますが、
docker0のMACアドレスはdockerが起動する度に変化するため、
そのままではデフォルトゲートウェイのアドレスとしては不適当です。</p>
<p>さらに、Ubuntu 13.10のlxcでは <tt class="docutils literal">lxc.network.ipv6.gateway</tt> にはlink-localアドレスを指定できませんでした。</p>
<p>今回はdocker0のlink-localアドレスを固定するのではなく、RA(ルータ広告)を使用し、
デフォルトゲートウェイだけ自動で配布するようにします。</p>
</div><div class="section" id="id2">
<h3>コンテナにデフォルトゲートウェイを通知する</h3>
<p>RAを送信するということはホスト側はルータとなり、ホストとコンテナ間でパケットを転送することを意味します。
Linuxでパケット転送をするためにsysctlを忘れずに設定します。</p>
<p>注意: ルータはRAを無視しなければならないため、この時点でホストはデフォルトゲートウェイをRAから取得できなくなります。
場合によってはDHCPv6で取得した標準のIPv6アドレスへの到達性を失います。作業時は注意してください。
作業前に控えたデフォルトゲートウェイを元に手動で再設定します。</p>
<pre class="literal-block">
$ grep ipv6.conf.all.forwarding /etc/sysctl.conf
net.ipv6.conf.all.forwarding=1
$ sudo sysctl -p
$ sudo ip -6 route add default via fe80::1052:1 dev eth0
</pre>
<p>RAの送信には <tt class="docutils literal">radvd</tt> パッケージを使用します。</p>
<pre class="literal-block">
$ sudo apt-get install radvd
$ cat /etc/radvd.conf
interface docker0
{
AdvSendAdvert on;
};
$ sudo service radvd start
</pre>
<p>ここまででコンテナ側の設定は完了しました。試しに起動してみます。</p>
<pre class="literal-block">
$ sudo docker run -i -t -lxc-conf="lxc.network.ipv6 = 2001:db8::1/128" ubuntu /bin/bash
# ifconfig eth0
eth0 Link encap:Ethernet HWaddr 86:d6:18:21:43:a5
inet addr:172.17.0.4 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::84d6:18ff:fe21:43a5/64 Scope:Link
inet6 addr: 2001:db8::1/128 Scope:Global
UP BROADCAST RUNNING MTU:1500 Metric:1
RX packets:10 errors:0 dropped:0 overruns:0 frame:0
TX packets:5 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:916 (916.0 B) TX bytes:446 (446.0 B)
# ip -6 route
2001:db8::1 dev eth0 proto kernel metric 256
fe80::/64 dev eth0 proto kernel metric 256
default via fe80::bcd2:8eff:fe4b:246 dev eth0 proto ra metric 1024 expires 1791sec
</pre>
<p>デフォルトゲートウェイが設定されていることを確認してください。また、アドレスがホスト側の <tt class="docutils literal">docker0</tt> に付与
されたlink-localアドレスであることを確認してください。</p>
<p>これでコンテナからインターネットへの通信はすべてホスト側のdocker0へルーティングされるようになりました。
しかし、これだけでは外部からの追加アドレス宛通信はコンテナへルーティングされません。</p>
</div><div class="section" id="id3">
<h3>追加アドレスをコンテナへルーティングする</h3>
<p>まずはホスト側からコンテナへルーティングする必要があります。
ホスト側のルーティングテーブルにコンテナで使用している/128への経路を追加します。</p>
<pre class="literal-block">
$ sudo ip -6 route add 2001:db8::1/128 dev docker0
</pre>
<p>これでホストからコンテナへpingが通るようになります。</p>
<pre class="literal-block">
$ ping6 -c 1 2001:db8::1
PING 2001:db8::1(2001:db8::1) 56 data bytes
64 bytes from 2001:db8::1: icmp_seq=1 ttl=64 time=0.064 ms
--- 2001:db8::1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.064/0.064/0.064/0.000 ms
</pre>
<p>次に、docker0に閉じ込もっているコンテナに代わりホスト側で追加アドレスに対するND(近隣探索)に
代理応答するようにします。
これにより、コンテナへのトラフィックを一旦ホスト側で受信できるようになります。</p>
<pre class="literal-block">
$ sudo ip -6 neigh add proxy 2001:db8::1 dev eth0
</pre>
<p>ndpプロキシはsysctlで有効にする必要があります。
<tt class="docutils literal">eth0</tt> が接続されているネットワークからのみ代理応答するように設定します。</p>
<pre class="literal-block">
$ grep ipv6.conf.eth0.proxy_ndp /etc/sysctl.conf
net.ipv6.conf.eth0.proxy_ndp=1
$ sudo sysctl -p
</pre>
<p>これでdockerで起動したコンテナに対して外部からpingが通るはずです。</p>
<p>注意: 作業中、コンテナのシェルから抜けるとコンテナは停止してしまうため試験時は起動しなおすのを忘れずに
(C-p C-qでdetachできます)。</p>
<pre class="literal-block">
$ docker run -i -t -lxc-conf="lxc.network.ipv6 = 2001:db8::1/128" ubuntu /bin/bash
</pre>
<p><a class="reference external" href="https://mebsd.com/ipv6-ping-and-traceroute">https://mebsd.com/ipv6-ping-and-traceroute</a> などを利用し、外部からpingを打って疎通を確認してください。</p>
</div><div class="section" id="id4">
<h3>起動時に設定する</h3>
<p>追加IPv6アドレス16個に対して経路とNDの代理応答を <tt class="docutils literal">/etc/rc.local</tt> で設定します(場所が気にいらない場合はどこか適当な場所へ)。</p>
<pre class="literal-block">
# wait for docker ready
sleep 10
FIRST=$(/sbin/ifconfig eth0 | grep -i global | awk '{ print $3 }' | cut -d":" -f1-4)
SECOND=$(/sbin/ifconfig eth0 | grep -i global | cut -d":" -f6,7,8,9 | cut -d"/" -f1)
IPV6=${FIRST}:a${SECOND}
for SUFFIX in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
ip -6 route add "${IPV6}${SUFFIX}"/128 dev docker0
ip -6 neigh add proxy "${IPV6}${SUFFIX}" dev eth0
done
ip -6 route add default via fe80::1052:1 dev eth0
</pre>
<p>再起動後 <tt class="docutils literal">docker run</tt> するだけで簡単に追加IPv6アドレスがdockerで使えるようになります。
実際に使用する際はip6tablesで適切にパケットフィルターを設定してください。
ufwはIPv6向けにもきちんとしたデフォルトのフィルターがあるのでオススメです。</p>
<p>今回は <tt class="docutils literal">docker0</tt> を残したままIPv6対応をしたので <tt class="docutils literal">docker run <span class="pre">-p</span></tt> によるIPv4アドレスに対するポート設定とも併用できます。
IPv4アドレスは1つしかありませんが、IPv6なら16個も使えます。やったね!!</p>
</div>
2014-02-04T13:10:04+09:00
-
knife-soloとVagrantの組み合せ方を工夫して本番環境と試験環境にプロビジョニングする
https://projects.tsuntsun.net/~nabeken/diary/Sysadmin/knife-solo-and-vagrant.html
<h2>UPDATE:</h2><ul>
<li>Vagrant 1.2.7では chef_add_recipe nil が不要だったので削除 (Sun, 4 Aug 2013 20:54:45 +0900)</li>
<li>knife-solo 0.3.0がリリースされたのでGemfile修正 (Sat, 3 Aug 2013 15:57:37 +0900)</li>
<li>s/デプロイ/プロビジョニング/g (Wed, 31 Jul 2013 09:51:04 +0900)</li>
</ul>
<div class="section" id="id2">
<h3>ディレクトリ構成</h3>
<p><a class="reference external" href="https://github.com/opscode/chef-repo">chef-repo</a> をベースとしたリポジトリ構成は以下になります。</p>
<pre class="literal-block">
$ tree -d
(不要なものは削除)
.
├── certificates
├── config
├── cookbooks
│ ├── tknetworks
│ ├── tknetworks_bird
│ ├── tknetworks_openbsd
│ ├── tknetworks_openvpn
│ ├── tknetworks_sudo
├── data_bags
│ ├── certs
│ ├── ipsec
│ ├── openvpn
│ ├── ssh_keys
│ └── tknetworks-ipsec
├── fabfile
├── nodes
│ ├── gw-openbsd1.osaka.tknetworks.org
│ └── nino.sakura.tknetworks.org
└── roles
</pre>
<p>ほとんどchef-repoそのままですが、 <tt class="docutils literal">nodes</tt> ディレクトリ以下にはさらに各ノードのディレクトリがあり、
そのディレクトリには</p>
<pre class="literal-block">
$ ls -alh nodes/nino.sakura.tknetworks.org
-rw-r--r-- 1 nabeken staff 958B 7 15 22:52 Vagrantfile
-rw-r--r-- 1 nabeken staff 315B 7 19 10:04 node.json
</pre>
<p>と、各ノード毎に専用のVagrantfileと本番環境に適用するJSONを配置しています。</p>
<p>この状態で試験環境にプロビジョニングする場合はVagrantを使用します。</p>
<pre class="literal-block">
$ cd nodes/nino.osaka.tknetworks.org
$ vagrant up
</pre>
<p>本番環境にプロビジョニングする場合は <tt class="docutils literal">knife solo cook</tt> を使用します。</p>
<pre class="literal-block">
$ bundle exec knife solo cook root@nino.osaka.tknetworks.org
</pre>
<p>ディレクトリ構造を少し変更したのは <em>Vagrantfileを各ノード単位で用意したかったから</em> です。
単一のVagrantfileに各ノードを定義することもできますが、1システム 1 Vagrantfileと考えると
別々に管理したいと思いました。</p>
<p>では具体的に見ていきます。</p>
</div><div class="section" id="knife-solo">
<h3>knife-solo</h3>
<p>すでにいろいろな記事がありますが、 <a class="reference external" href="http://matschaffer.github.io/knife-solo/">knife-solo</a> は0.3系以上を使用してください(2013/08/03 追記: 0.3.0がリリースされました)。
chef-repoにGemfileを用意しておくのが便利です。</p>
<pre class="literal-block">
$ cat Gemfile
source 'https://rubygems.org'
gem 'chef'
gem 'chefspec'
gem 'knife-solo'
$ bundle install
$ bundle exec knife
</pre>
<p>knife-soloがインストールされていれば以下のサブコマンドが表示されます。</p>
<pre class="literal-block">
** SOLO COMMANDS **
knife solo cook [USER@]HOSTNAME [JSON] (options)
knife solo init DIRECTORY
knife solo prepare [USER@]HOSTNAME [JSON] (options)
knife solo bootstrap [USER@]HOSTNAME [JSON] (options)
knife solo clean [USER@]HOSTNAME
</pre>
<p>通常、 <tt class="docutils literal">knife solo cook foo.example.org</tt> とした場合、JSONは自動的に <tt class="docutils literal">nodes/foo.example.org.json</tt> から読み込まれます。
今回は <tt class="docutils literal">nodes/foo.example.org/node.json</tt> から読み込んで欲しいので、
chef-repoのトップディレクトリに <tt class="docutils literal">.chef</tt> ディレクトリを用意し、
ここにmonkey patchのためのknife pluginを用意しました。</p>
<pre class="literal-block">
$ cat .chef/plugins/knife/solo_patch.rb
module KnifeSolo
module NodeConfigCommand
def node_config
Pathname.new(@name_args[1] || "#{nodes_path}/#{node_name}/node.json")
end
end
end
</pre>
<p>これで <tt class="docutils literal">knife solo cook root@foo.example.org</tt> とすれば
第2引数で明示的にJSONを指定しなくても自動的に <tt class="docutils literal">nodes/foo.example.org/node.json</tt> から設定を読み込んでくれます。</p>
</div><div class="section" id="knife-soloknife-rb">
<h3>knife-solo向けknife.rb</h3>
<p>書いたrecipeはできる限り公開することにしています。私自身、community cookbookを参考にすることはよくあります。
最近はGithubに専用のorganizationを作成し、1 cookbook 1 repositoryで管理してます。</p>
<ul class="simple">
<li><a class="reference external" href="https://github.com/tknetworks-cookbooks/">https://github.com/tknetworks-cookbooks/</a></li>
</ul>
<p>community cookbookをフォークするのはアンチパターンの1つのようですが、私がフォークする場合の主な理由は</p>
<ul class="simple">
<li>OpenBSD対応とかFreeBSD対応を考えるとき</li>
<li>wrapper cookbookで対処しきれないとき(definitionやprovider内のリソース定義が当てはまる)</li>
</ul>
<p>などです。どうせフォークするならGithubのorganizationを作り、そこへフォークしておくと管理がすこしは楽になります。
さもないと、個人アカウントに紛らわしいリポジトリ名がたくさんできてしまいます。</p>
<p>話がそれましたが、chef-repoのcookbookには非公開のcookbookを入れています。
機密情報は必ずencrypted data bagで格納し、鍵は別リポジトリに保管しています。
encrypted data bagをchef-solo環境向けに作成するには簡単なツールを使うのが便利です。
私は <a class="reference external" href="http://ed.victavision.co.uk/blog/post/4-8-2012-chef-solo-encrypted-data-bags">Chef Solo encrypted data bags</a> を参考に
<a class="reference external" href="https://gist.github.com/nabeken/5989715">既存のdata bagのJSONを暗号化するスクリプト</a> を作成し、使用しています。</p>
<script src="https://gist.github.com/nabeken/5989715.js"></script><p>このスクリプトを使うと</p>
<pre class="literal-block">
$ cat data_bag.json | ruby json2encrypted_data_bag.rb
</pre>
<p>で暗号化されたJSONが得られます。</p>
<p>これらを踏まえた最低限の <tt class="docutils literal">knife.rb</tt> は以下になります。</p>
<pre class="literal-block">
$ cat ~/.chef/knife.rb
encrypted_data_bag_secret '/path/to/data_bag.key'
cookbook_path %w{
/path/to/tknetworks-cookbooks
/path/to/chef-repo/cookbooks
}
role_path '/path/to/chef-repo/roles'
data_bag_path '/path/to/chef-repo/data_bags'
</pre>
</div><div class="section" id="vagrant">
<h3>Vagrant</h3>
<ul class="simple">
<li>Vagrant(試験環境)とknife-solo(本番環境)の設定が食い違うとVagrantの意味がない</li>
<li>しかし、Vagrant特有の設定はknife-soloに適用したくない</li>
</ul>
<p>などの理由からknife-soloのJSONに影響を与えずにVagrant特有の設定を入れる必要があります。
例えばsudoをrecipeで管理する場合、knife-soloではvagrantユーザーに対するsudoの設定は不要ですが、
Vagrant環境では設定が必要です。</p>
<p>これらの要件を満すためVagrantfileに工夫しています。</p>
<pre class="literal-block">
Vagrant.configure("2") do |config|
# <snip>
config.vm.provision :chef_solo do |chef|
chef.encrypted_data_bag_secret_key_path = '../../../path/to/data_bag.key'
chef.cookbooks_path = %w{../../../tknetworks-cookbooks ../../cookbooks}
chef.data_bags_path = "../../data_bags"
chef.roles_path = "../../roles"
chef.json = JSON.parse(open(File.expand_path('../node.json', __FILE__)).read).tap { |j|
j['run_list'] += %w{tknetworks_sudo::vagrant tknetworks_openbsd::vagrant}
}
end
end
</pre>
<p>chef-solo provisonerでは設定をJSONから読み込めるため、まずknife-solo用の設定を読み込み、 <tt class="docutils literal">Object#tap</tt> を
使いVagrant特有のrun_listを追加しています。</p>
</div><div class="section" id="id4">
<h3>最後に</h3>
<p>knife-soloとVagrantの組み合わせ方法を工夫し、試験環境と本番環境の切り替える方法をまとめてみました。
それではよいcookingを。</p>
</div>
2013-08-04T20:54:45+09:00
-
VagrantでOpenBSD + chef-solo provisoner環境を構築する
https://projects.tsuntsun.net/~nabeken/diary/OpenBSD/vagrant-openbsd.html
<h2>UPDATE:</h2><ul>
<li>Use :openbsd_v2 instead of :openbsd (Sat, 30 Mar 2013 17:43:03 +0900)</li>
<li>Fix indentation (Fri, 29 Mar 2013 20:46:05 +0900)</li>
<li>抜けていた手順を追加 (Fri, 29 Mar 2013 20:33:31 +0900)</li>
</ul>
<div class="section" id="vagrant">
<h3>Vagrantについて</h3>
<p><a class="reference external" href="http://www.vagrantup.com/">Vagrant</a> はRubyで書かれた仮想マシン管理のフロントエンドです。Vagrantを使うことで
仮想環境を <em>再現可能な形</em> で配布し、それらを統一されたフローで扱うことができます。</p>
<p>1.1からは仮想マシンのデプロイ先として、Virtualboxの他にVMware Fusion, Amazon EC2に対応しています。</p>
<p>Vagrantの話は <a class="reference external" href="http://d.hatena.ne.jp/naoya/20130205/1360062070">Vagrant (naoyaのはてなダイアリー)</a> をどうぞ。</p>
</div><div class="section" id="openbsd-box">
<h3>OpenBSD box</h3>
<p>VagrantのOSイメージは非公式なものを含め、 <a class="reference external" href="http://www.vagrantbox.es/">Vagrantbox.es</a> に一覧があります。
AMIと同様、Boxの作者が信頼できる人/組織か確認できない場合は自作したほうがよいと思います。</p>
<p>今回はOpenBSD 5.2-stableのboxを作成しました。</p>
<ol class="arabic">
<li>
<p class="first">Virtualboxで普段通りにOpenBSD 5.2をインストール</p>
<p>em0はdhcpにしておきます。em0はVirtualbox経由でNATして外に出るために必要になります。</p>
<p>rootのパスワードはパスワードポリシーを考慮して <tt class="docutils literal">vagrant!</tt> にしておきます。
vagrantのパスワードは <tt class="docutils literal">vagrant</tt> にしておきます。</p>
<p><a class="reference external" href="http://docs-v1.vagrantup.com/v1/docs/base_boxes.html">Base Boxes</a> を参考に</p>
<ul class="simple">
<li>sudoの設定</li>
<li>vagrantユーザーにデフォルトの公開鍵をインストール</li>
</ul>
<p>を実施します。</p>
</li>
<li>
<p class="first">パッケージをインストール</p>
<p>OpenBSDのpackagesから最低限のパッケージをインストールします。</p>
<pre class="literal-block">
# export PKG_PATH=http//ftp.iij.ad.jp/pub/OpenBSD/5.2/packages/`machine -a`/
# pkg_add bash git rsync ruby wget
</pre>
<p>chefはgemからインストールします。</p>
<pre class="literal-block">
# gem19 install chef
</pre>
<p>最後にシンボリックリンクを張っておきます。</p>
<pre class="literal-block">
# for i in /usr/local/bin/*19; do sudo ln -sf $i ${i%19}; done
</pre>
</li>
<li>
<p class="first">仮想マシンをパッケージング</p>
<p>作成した仮想マシンをシャットダウンし、以下のコマンドでパッケージングします。</p>
<pre class="literal-block">
$ vagrant package --base <仮想マシン名>
</pre>
<p>パッケージングされたboxは <tt class="docutils literal"><span class="pre">${HOME}/package.box</span></tt> に作成されます。</p>
</li>
<li>
<p class="first">パッケージングされたBoxを追加する</p>
<p>http経由でアクセスできる場所へ <tt class="docutils literal">package.box</tt> をコピーします。今回、私が作成したboxは以下で公開しています。</p>
<p><a class="reference external" href="https://projects.tsuntsun.net/~nabeken/boxes/vagrant-openbsd-52.box">https://projects.tsuntsun.net/~nabeken/boxes/vagrant-openbsd-52.box</a></p>
<p>このboxを追加する場合は:</p>
<pre class="literal-block">
$ vagrant box add vagrant-openbsd-52 https://projects.tsuntsun.net/~nabeken/vagrant-openbsd-52.box
</pre>
<p>もちろん、httpである必要はありません。作成されたファイルを直接追加することもできます。</p>
</li>
</ol>
</div><div class="section" id="vagrant-guests-plugin-for-openbsd">
<h3>Vagrant guests plugin for OpenBSD</h3>
<p>Vagrant 1.1のOpenBSDプラグインは実装が不十分です。このままでは複数のネットワーク設定およびNFSによる共有フォルダが使用できません。
後述するchef-solo provisonerが使えないため、まずはこのプラグインから修正する必要があります。</p>
<p>Vagrantのプラグイン機構の学習とGemの公開練習を兼ねて <a class="reference external" href="https://github.com/nabeken/vagrant-guests-openbsd">vagrant-guests-openbsd</a> プラグインを公開しました。
このプラグインは現状のVagrant 1.1に対するOpenBSDプラグインに複数のネットワーク設定とNFSによる共有フォルダサポートを追加します。
Vagrant本体への取り込みまでの間、このプラグインが役に立つと思います。</p>
<p>インストール:</p>
<pre class="literal-block">
$ vagrant plugin install vagrant-guests-openbsd
</pre>
<p>Vagrantに付属している既存のOpenBSDプラグインを無効化する必要があります。Mac OS Xの場合は以下のようにして
読み込みできないようにしておきます。</p>
<pre class="literal-block">
$ sudo chmod 0000 /Applications/Vagrant/embedded/gems/gems/vagrant-1.1.2/plugins/guests/openbsd
</pre>
<p>追記:以上のdirty hackは0.0.2以上から
<tt class="docutils literal">config.vm.guest = :openbsd_v2</tt>
とすることで、不要になりました。</p>
</div><div class="section" id="chef-solo-provisonervagrantfile">
<h3>chef-solo provisonerを使ったVagrantfileの例</h3>
<p>準備ができたので、最後にchef-solo provisonerを使ったVagrantfileの例を載せます。</p>
<pre class="literal-block">
# インストールしたプラグインを読み込ませる
Vagrant.require_plugin "vagrant-guests-openbsd"
Vagrant.configure("2") do |config|
config.vm.box = "vagrant-openbsd-52"
config.vm.box_url = "https://projects.tsuntsun.net/~nabeken/boxes/vagrant-openbsd-52.box"
config.vm.guest = :openbsd_v2
config.vm.hostname = "vagrant-openbsd"
config.vm.network :private_network, ip: "192.168.67.10", netmask: "255.255.255.0"
config.vm.provision :chef_solo do |chef|
chef.nfs = true
chef.cookbooks_path = ".."
chef.add_recipe "openbsd"
end
end
</pre>
<p><tt class="docutils literal">vagrant up</tt> で指定したcookbookを読み込み、自動的に <tt class="docutils literal"><span class="pre">chef-solo</span></tt> が実行されます。
今回の例は <a class="reference external" href="https://github.com/tknetworks-cookbooks/openbsd">https://github.com/tknetworks-cookbooks/openbsd</a> を使用しています。</p>
<pre class="literal-block">
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'vagrant-openbsd-52'...
[default] No guest additions were detected on the base box for this VM! Guest
additions are required for forwarded ports, shared folders, host only
networking, and more. If SSH fails on this machine, please install
the guest additions and repackage the box to continue.
This is not an error message; everything may continue to work properly,
in which case you may ignore this message.
[default] Matching MAC address for NAT networking...
[default] Setting the name of the VM...
[default] Clearing any previously set forwarded ports...
Pruning invalid NFS exports. Administrator privileges will be required...
Password:
[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] Setting hostname...
[default] Configuring and enabling network interfaces...
[default] Mounting shared folders...
[default] -- /vagrant
[default] Exporting NFS shared folders...
Preparing to edit /etc/exports. Administrator privileges will be required...
[default] Mounting NFS shared folders...
[default] Running provisioner: VagrantPlugins::Chef::Provisioner::ChefSolo...
Generating chef JSON and uploading...
Running chef-solo...
[2013-03-25T08:28:42+09:00] INFO: *** Chef 10.24.0 ***
[2013-03-25T08:28:43+09:00] INFO: Setting the run_list to ["recipe[openbsd]"] from JSON
[2013-03-25T08:28:43+09:00] INFO: Run List is [recipe[openbsd]]
[2013-03-25T08:28:43+09:00] INFO: Run List expands to [openbsd]
[2013-03-25T08:28:43+09:00] INFO: Starting Chef Run for vagrant
[2013-03-25T08:28:43+09:00] INFO: Running start handlers
[2013-03-25T08:28:43+09:00] INFO: Start handlers complete.
[2013-03-25T08:28:43+09:00] INFO: Processing execute[openbsd-add-manip-pkg-script] action run (openbsd::default line 23)
[2013-03-25T08:28:43+09:00] INFO: execute[openbsd-add-manip-pkg-script] ran successfully
[2013-03-25T08:28:43+09:00] INFO: Processing execute[openbsd-add-manip-rc-local-chef] action run (openbsd::default line 36)
[2013-03-25T08:28:43+09:00] INFO: execute[openbsd-add-manip-rc-local-chef] ran successfully
[2013-03-25T08:28:43+09:00] INFO: Processing openbsd_rc_conf[inetd] action enable (openbsd::default line 49)
[2013-03-25T08:28:43+09:00] INFO: openbsd_rc_conf[inetd]: is_absent? true, {}
[2013-03-25T08:28:43+09:00] INFO: openbsd_rc_conf[inetd]: is_modified? true, {}
[2013-03-25T08:28:43+09:00] INFO: Processing openbsd_rc_conf[sndiod] action enable (openbsd::default line 49)
[2013-03-25T08:28:43+09:00] INFO: openbsd_rc_conf[sndiod]: is_absent? true, {"inetd"=>"NO"}
[2013-03-25T08:28:43+09:00] INFO: openbsd_rc_conf[sndiod]: is_modified? true, {"inetd"=>"NO"}
[2013-03-25T08:28:43+09:00] INFO: Chef Run complete in 0.131657235 seconds
[2013-03-25T08:28:43+09:00] INFO: Running report handlers
[2013-03-25T08:28:43+09:00] INFO: Report handlers complete
$ vagrant ssh
# hostname
vagrant-openbsd
# cat /etc/rc.conf.local.chef
inetd_flags="NO"
sndiod_flags="NO"
</pre>
<p>NFSでホスト側のcookbook_pathをmountし、自動的にrun_listを含んだJSONを生成しchef-soloが実行されたことが確認できます。</p>
<p>次回はこの環境を元にcookbookへテストを追加し、テスト駆動開発していきます。</p>
</div><div class="section" id="id3">
<h3>参考文献</h3>
<ul class="simple">
<li><a class="reference external" href="http://docs.vagrantup.com/v2/">VAGRANT DOCS</a></li>
<li><a class="reference external" href="http://d.hatena.ne.jp/naoya/20130205/1360062070">Vagrant (naoyaのはてなダイアリー)</a></li>
</ul>
</div>
2013-03-30T17:43:03+09:00
-
OpenBSD 5.1でGRE over IPSec with NAT-T + rdomain
https://projects.tsuntsun.net/~nabeken/diary/OpenBSD/ipsec-and-nat-t.html
<h2>UPDATE:</h2><ul>
<li>rc.confでipsec.confを読み込むように修正 (Sun, 2 Dec 2012 15:07:40 +0900)</li>
<li>初稿 (Thu, 25 Oct 2012 00:37:58 +0900)</li>
</ul>
<div class="section" id="id2">
<h3>構成</h3>
<p>3G回線(バックアップ回線)は月額980円の <a class="reference external" href="http://www.bmobile.ne.jp/aeon">イオンSIM</a> をb-mobile WiFi刺し、用意しました。
OpenBSD 5.1では870円で購入した <a class="reference external" href="http://www.planex.co.jp/product/wireless/gw-usnano2/">GW-USNano2</a> を装着し、無線LANへ接続しました。</p>
<p><a class="reference external" href="fuguita-5.1-amd64.rst">前回の記事</a> では無線LAN I/Fをデフォルトのrdomain 0に所属させたまま、VPNエンドポイントへのスタティックルーティング
を登録する手法を紹介しました。しかし、この手法では問題がありました。
gwはNAPTで各サービスへトラフィックを転送しています。VPNエンドポイントもそのサービスを利用しています。
この手法ではVPNエンドポイントからの通信で戻りが非対称(IPアドレスも変わってしまう)になってしまうため、
実運用には使えませんでした。</p>
<p>この問題を回避するため、rdomain(Routing Domain)によるルーティングテーブルの分離を行ないました。
OpenBSDの場合は特定のプロセスをrdomainにattachするだけでなく、ネットワークインターフェースもrdomainにattachすることもできます。
(FreeBSDだとVIMAGEのほうが近い。Linuxではnamespaceによってネットワークスタックを分離できるようです。)</p>
<p>バックアップ回線用のネットワークインターフェースを別rdomainに収容することで既存ルーティング
に影響を与えずにネットワークを拡張できます。さらに素晴しいことに、OpenBSDのgif(4)やgre(4)は
outer(encapしたトラフィックのI/F)のrdomainとinner(encapする前のトラフィックのI/F)のrdomainを別々に指定できます。
つまり、トンネルのための回線は既存ルーティングに影響を与えないようにしつつ、トンネルで運ぶ対象のトラフィック
は既存ルーティングに載せることができます。</p>
<p>最終的な構成は以下を目指します。この上にBirdでOSPFを流します。3G回線を通るgreはコストを上げておき、
平常時はPPPoE経由のOpenVPNにトラフィックが流れるようにします。:</p>
<pre class="literal-block">
+----------+ GRE(outer) over IPSec w/ nat-t
| ipsec-gw |----------(via 3G)----------+
+--+----+--+ |
| | | urtwn0 rdomain 1
| | OpenVPN +------+-----+ -------------------------
| +------(via PPPoE)-------+ openbsd-gw | rdomain 0
| tun0 +------------+
| | gre0
+------------------------------------+
GRE(inner)
</pre>
<p>ipsec-gwは固定IPv4アドレスが振られています。
openbsd-gwは非固定IPv4アドレスによるNAT配下にいる想定です。</p>
</div><div class="section" id="routing-domain-in-openbsd">
<h3>Routing Domain in OpenBSD</h3>
<p>OpenBSDのrdomainは <a class="reference external" href="http://www.packetmischief.ca/2011/09/20/virtualizing-the-openbsd-routing-table/">Virtualizing the OpenBSD Routing Table</a> が詳しいです。</p>
<p>OpenBSD 5.1ではrdomainはIPv4のみです(参考: <a class="reference external" href="http://www.openbsd.org/papers/eurobsd2012/phessler-rdomains/mgp00002.html">rtable vs rdomain</a>)。
参考によれば、作業中とのことなので、遠くないリリースでは対応すると思われます。
今回の構成ではtunneldomainだけがrdomain対象なので、GREで通すIPv6パケットは問題なく通過します。</p>
</div><div class="section" id="id4">
<h3>バックアップ回線のセットアップ</h3>
<p>無線LANのNICはurtwn(4)を使用しました。</p>
<pre class="literal-block">
# dmesg | grep urtwn
urtwn0 at uhub0 port 1 "Planex Communications Inc. GW-USNano2" rev 2.00/2.00 addr 2
urtwn0: MAC/BB RTL8188CUS, RF 6052 1T1R, address 00:XX:XX:XX:XX:XX
# cat /etc/hostname.urtwn0
nwid hogehoge wpakey secret
rdomain 1
dhcp
</pre>
<p>こうすることで、DHCPによって取得したデフォルトゲートウェイはrdomain 1へ入ります。
このままでは <tt class="docutils literal">/etc/resolv.conf</tt> は上書きされてしまいます。5.1のdhclientには
ignoreオプションが入っていないため、 <tt class="docutils literal">/etc/dhclient.conf</tt> で予めDNSサーバを指定しておきます。</p>
<pre class="literal-block">
# cat /etc/dhclient.conf
supersede domain-name-servers 8.8.8.8;
request subnet-mask, broadcast-address, time-offset, routers, domain-name;
</pre>
<p>GREとIPSecを以下のように構成します。</p>
<pre class="literal-block">
+----------+ (gre0: 192.168.0.1/32) +------------+
| ipsec-gw +-----------------------------------------------+ openbsd-gw |
+----------+ (gre0: 192.168.0.2/32) +------------+
(lo1: 10.0.0.1/32) (lo1: 10.0.0.2/32)
| |
+-----------------------[ IPSec ]--------------------------+
</pre>
<p>それぞれのlo1にGREの終端のためにIPアドレスを振ります。ここではまだ起動させません。</p>
<pre class="literal-block">
ipsec-gw# cat /etc/hostname.lo1
inet 10.0.0.2/32
ipsec-gw# cat /etc/hostname.gre0
tunnel 10.0.0.2 10.0.0.1
192.168.0.2 192.168.0.1 netmask 255.255.255.255
ipsec-gw# cat /etc/hostname.enc0
up
openbsd-gw# cat /etc/hostname.lo1
rdomain 1
inet 10.0.0.1/32
openbsd-gw# cat /etc/hostname.gre0
tunneldomain 1
tunnel 10.0.0.1 10.0.0.2
192.168.0.1 192.168.0.2 netmask 255.255.255.255
</pre>
<p><tt class="docutils literal">enc(4)</tt> をrdomain 1に作成します。</p>
<pre class="literal-block">
openbsd-gw# cat /etc/hostname.enc1
rdomain 1
up
</pre>
</div><div class="section" id="pf">
<h3>pf</h3>
<p>ipsec-gw, openbsd-gw共通として:</p>
<ul>
<li>
<p class="first">gre0はskip</p>
<pre class="literal-block">
set skip on { lo0, gre0 }
</pre>
</li>
</ul>
<p>ipsec-gwでは:</p>
<ul>
<li>
<p class="first">enc0はskip</p>
<pre class="literal-block">
set skip on { enc0 }
</pre>
</li>
<li>
<p class="first">不特定多数からのesp/udpを許可</p>
<p>NAT-T(NATトラバーサル)ではudpにカプセル化されるので併せて許可します。</p>
<pre class="literal-block">
pass in on $ext_if proto udp from any to ($ext_if) port { isakmp, ipsec-nat-t }
pass in on $ext_if proto esp from any to ($ext_if)
</pre>
</li>
</ul>
<p>openbsd-gwでは:</p>
<ul>
<li>
<p class="first">enc1はskip</p>
<pre class="literal-block">
set skip on { enc1 }
</pre>
</li>
<li>
<p class="first">ipsec-gwから/へのesp/udpを許可</p>
<pre class="literal-block">
ipsec_gw = "X.X.X.X"
pass out on $ext_if proto udp from ($ext_if) to $ipsec_gw port { isakmp, ipsec-nat-t }
pass out on $ext_if proto esp from ($ext_if) to $ipsec_gw
</pre>
</li>
</ul>
<p>設定したら <tt class="docutils literal">pfctl <span class="pre">-ef</span> /etc/pf.conf</tt> しておきます。</p>
</div><div class="section" id="gre">
<h3>GRE</h3>
<p>GREを通しておきます。</p>
<pre class="literal-block">
ipsec-gw# sh /etc/netstart enc0
ipsec-gw# sh /etc/netstart lo1
ipsec-gw# sh /etc/netstart gre0
ipsec-gw# ifconfig lo1
lo1: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 33152
priority: 0
groups: lo
inet6 fe80::1%lo1 prefixlen 64 scopeid 0xe
inet 10.0.0.2 netmask 0xffffffff
ipsec-gw# ifconfig gre0
gre0: flags=9011<UP,POINTOPOINT,LINK0,MULTICAST> mtu 1476
priority: 0
groups: gre
physical address inet 10.0.0.2 --> 10.0.0.1
inet6 fe80::xxxx:xxxx:xxxx:xxxx%gre0 -> prefixlen 64 scopeid 0xf
inet 192.168.0.2 --> 192.168.0.1 netmask 0xffffffff
openbsd-gw# sh /etc/netstart enc1
openbsd-gw# sh /etc/netstart lo1
openbsd-gw# sh /etc/netstart gre0
openbsd-gw# ifconfig enc1
enc1: flags=20041<UP,RUNNING,NOINET6> rdomain 1
priority: 0
groups: enc
status: active
openbsd-gw# ifconfig lo1
lo1: flags=28049<UP,LOOPBACK,RUNNING,MULTICAST,NOINET6> rdomain 1 mtu 33152
priority: 0
groups: lo
inet 10.0.0.1 netmask 0xffffffff
openbsd-gw# ifconfig gre0
gre0: flags=9011<UP,POINTOPOINT,LINK0,MULTICAST> mtu 1476
priority: 0
groups: gre
physical address inet 10.0.0.1 --> 10.0.0.2 rdomain 1
inet6 fe80::yyyy:yyyy:yyyy:yyyy%gre0 -> prefixlen 64 scopeid 0x25
inet 192.168.0.1 --> 192.168.0.2 netmask 0xffffffff
</pre>
</div><div class="section" id="ipsec">
<h3>IPSecのセットアップ</h3>
<p><tt class="docutils literal">ipsec.conf(5)</tt> を用意します。</p>
<pre class="literal-block">
ipsec-gw# cat /etc/ipsec.conf
ike passive esp proto gre from 10.0.0.2/32 to 10.0.0.1/32 peer any srcid ipsec-gw.example.com psk secret
openbsd-gw# cat /etc/ipsec.conf
ipsec_gw = "X.X.X.X"
me = "10.0.0.1"
remote = "10.0.0.2"
ike dynamic esp proto gre from $me/32 to $remote/32 peer $ipsec_gw psk secret
</pre>
<p>デバッグのため、まずは手でisakmpd(8)を動かします。</p>
<pre class="literal-block">
ipsec-gw# isakmpd -K -d -v
ipsec-gw# ipsecctl -f /etc/ipsec.conf
openbsd-gw# route -T 1 exec isakmpd -K -d -v
openbsd-gw# route -T 1 exec ipsecctl -f /etc/ipsec.conf
</pre>
<p>疎通を確認します。</p>
<pre class="literal-block">
ipsec-gw# ping -c 5 192.168.0.1
openbsd-gw# ping -c 5 192.168.0.2
// このpingはrdomain 0から通ることに注意
</pre>
<p>うまくいけばphase 2が完了し、FLOWが確立しているはずです。</p>
<pre class="literal-block">
ipsec-gw# ipsecctl -sa
FLOWS:
flow esp in from 10.0.0.1 to 10.0.0.2 peer Z.Z.Z.Z srcid ipsec-gw.example.com dstid openbsd-gw.localdomain type use
flow esp out from 10.0.0.2 to 10.0.0.1 peer Z.Z.Z.Z srcid ipsec-gw.example.com dstid openbsd-gw.localdomain type require
SAD:
esp tunnel from Z.Z.Z.Z to X.X.X.X spi 0x03212efb auth hmac-sha2-256 enc aes
esp tunnel from X.X.X.X to Z.Z.Z.Z spi 0xae7c067e auth hmac-sha2-256 enc aes
openbsd-gw# route -T 1 exec ipsecctl -sa
FLOWS:
flow esp in from 10.0.0.2 to 10.0.0.1 peer X.X.X.X srcid openbsd-gw.localdomain dstid ipsec-gw.example.com type use
flow esp out from 10.0.0.1 to 10.0.0.2 peer X.X.X.X srcid openbsd-gw.localdomain dstid ipsec-gw.example.com type require
SAD:
esp tunnel from Y.Y.Y.Y to X.X.X.X spi 0x03212efb auth hmac-sha2-256 enc aes
esp tunnel from X.X.X.X to X.X.X.X spi 0xae7c067e auth hmac-sha2-256 enc aes
</pre>
<p>忘れずに起動スクリプトに仕込んでおきます。</p>
<pre class="literal-block">
ipsec-gw# echo ipsec=\"YES\" >> /etc/rc.conf.local
ipsec-gw# echo isakmpd_flags=\"-K\" >> /etc/rc.conf.local
openbsd-gw# echo 'route -T 1 exec isakmpd -K' >> /etc/rc.local
openbsd-gw# echo 'route -T 1 exec ipsecctl -f /etc/ipsec.conf' >> /etc/rc.local
</pre>
</div><div class="section" id="bird">
<h3>bird</h3>
<p>上で用意したgreをcost 50としてOSPFに突っ込みます(birdのデフォルトコスト値は10) 。
適当なエリアに以下のinterfaceを追加します。</p>
<pre class="literal-block">
# ipsec-gw
interface "gre0" {
hello 10;
dead 40;
priority 100;
cost 50;
};
# openbsd-gw
interface "gre0" {
hello 10;
dead 40;
priority 0;
cost 50;
};
</pre>
<p>再起動し、neighborが確立していることを確認します(tun0はPPPoE経由のOpenVPN)。</p>
<pre class="literal-block">
# ipsec-gw
bird> show ospf neighbors
TKNETWORKS:
Router ID Pri State DTime Interface Router IP
10.0.5.10 1 full/bdr 00:38 tun0 fe80::yyyy:yyyy:yyyy:yyyy
10.0.5.10 0 full/ptp 00:38 gre0 fe80::xxxx:xxxx:xxxx:xxxx
# openbsd-gw
bird> show ospf neighbors
TKNETWORKS:
Router ID Pri State DTime Interface Router IP
10.7.15.10 100 full/dr 00:37 tun0 fe80::xxxx:xxxx:xxxx:xxxx
10.7.15.10 100 full/ptp 00:37 gre0 fe80::yyyy:yyyy:yyyy:yyyy
</pre>
<p>お待ちかねの経路切り替えを観察します。OpenVPNとbirdでリンクアップ検知の設定をまだ詰めていないため復旧時間がやや長いです。</p>
<p>icmp_seq=4まではPPPoE経由のOpenVPNを通っています。ここで、 <tt class="docutils literal"><span class="pre">openbsd-gw</span></tt> 側のOpenVPNを落します。
その結果が <tt class="docutils literal">Host is down</tt> になっています。無事にicmp_seq=39からは3G回線経由に切り替わっています。
すぐにOpenVPNをstartさせ、icmp_seq=98で元の状態に収束しているのが確認できました。</p>
<pre class="literal-block">
openbsd-gw# ping6 2001:db8::1
PING6(56=40+8+8 bytes) 2001:380:6dc:7aa::2 --> 2001:db8::1
16 bytes from 2001:db8::1, icmp_seq=0 hlim=64 time=4.612 ms
16 bytes from 2001:db8::1, icmp_seq=1 hlim=64 time=4.758 ms
16 bytes from 2001:db8::1, icmp_seq=2 hlim=64 time=4.414 ms
16 bytes from 2001:db8::1, icmp_seq=3 hlim=64 time=4.224 ms
16 bytes from 2001:db8::1, icmp_seq=4 hlim=64 time=4.703 ms
ping6: sendmsg: Host is down
ping6: wrote 2001:db8::1 16 chars, ret=-1
ping6: sendmsg: Host is down
ping6: wrote 2001:db8::1 16 chars, ret=-1
ping6: sendmsg: Host is down
ping6: wrote 2001:db8::1 16 chars, ret=-1
ping6: sendmsg: Host is down
ping6: wrote 2001:db8::1 16 chars, ret=-1
ping6: sendmsg: Host is down
ping6: wrote 2001:db8::1 16 chars, ret=-1
ping6: sendmsg: Host is down
ping6: wrote 2001:db8::1 16 chars, ret=-1
ping6: sendmsg: Host is down
ping6: wrote 2001:db8::1 16 chars, ret=-1
ping6: sendmsg: Host is down
ping6: wrote 2001:db8::1 16 chars, ret=-1
16 bytes from 2001:db8::1, icmp_seq=39 hlim=64 time=3988.44 ms
16 bytes from 2001:db8::1, icmp_seq=40 hlim=64 time=3968.82 ms
16 bytes from 2001:db8::1, icmp_seq=41 hlim=64 time=4470.2 ms
16 bytes from 2001:db8::1, icmp_seq=42 hlim=64 time=4390.02 ms
16 bytes from 2001:db8::1, icmp_seq=43 hlim=64 time=3469.87 ms
16 bytes from 2001:db8::1, icmp_seq=44 hlim=64 time=2740.37 ms
16 bytes from 2001:db8::1, icmp_seq=45 hlim=64 time=1750.51 ms
16 bytes from 2001:db8::1, icmp_seq=46 hlim=64 time=831.138 ms
16 bytes from 2001:db8::1, icmp_seq=47 hlim=64 time=411.364 ms
16 bytes from 2001:db8::1, icmp_seq=48 hlim=64 time=441.882 ms
16 bytes from 2001:db8::1, icmp_seq=49 hlim=64 time=642.324 ms
16 bytes from 2001:db8::1, icmp_seq=50 hlim=64 time=972.566 ms
16 bytes from 2001:db8::1, icmp_seq=51 hlim=64 time=1262.94 ms
16 bytes from 2001:db8::1, icmp_seq=52 hlim=64 time=1283.34 ms
16 bytes from 2001:db8::1, icmp_seq=53 hlim=64 time=1293.71 ms
16 bytes from 2001:db8::1, icmp_seq=54 hlim=64 time=1294.96 ms
16 bytes from 2001:db8::1, icmp_seq=55 hlim=64 time=1304.32 ms
16 bytes from 2001:db8::1, icmp_seq=56 hlim=64 time=1477.74 ms
16 bytes from 2001:db8::1, icmp_seq=57 hlim=64 time=1255.12 ms
16 bytes from 2001:db8::1, icmp_seq=58 hlim=64 time=705.29 ms
16 bytes from 2001:db8::1, icmp_seq=59 hlim=64 time=145.904 ms
16 bytes from 2001:db8::1, icmp_seq=60 hlim=64 time=156.342 ms
16 bytes from 2001:db8::1, icmp_seq=61 hlim=64 time=146.49 ms
16 bytes from 2001:db8::1, icmp_seq=62 hlim=64 time=236.893 ms
16 bytes from 2001:db8::1, icmp_seq=63 hlim=64 time=285.795 ms
16 bytes from 2001:db8::1, icmp_seq=64 hlim=64 time=147.682 ms
16 bytes from 2001:db8::1, icmp_seq=65 hlim=64 time=148.085 ms
16 bytes from 2001:db8::1, icmp_seq=66 hlim=64 time=138.578 ms
16 bytes from 2001:db8::1, icmp_seq=67 hlim=64 time=148.899 ms
16 bytes from 2001:db8::1, icmp_seq=68 hlim=64 time=289.307 ms
16 bytes from 2001:db8::1, icmp_seq=69 hlim=64 time=149.47 ms
16 bytes from 2001:db8::1, icmp_seq=70 hlim=64 time=149.384 ms
16 bytes from 2001:db8::1, icmp_seq=71 hlim=64 time=150.285 ms
16 bytes from 2001:db8::1, icmp_seq=72 hlim=64 time=150.676 ms
16 bytes from 2001:db8::1, icmp_seq=73 hlim=64 time=151.024 ms
16 bytes from 2001:db8::1, icmp_seq=74 hlim=64 time=148.4 ms
16 bytes from 2001:db8::1, icmp_seq=75 hlim=64 time=152.07 ms
16 bytes from 2001:db8::1, icmp_seq=76 hlim=64 time=152.222 ms
16 bytes from 2001:db8::1, icmp_seq=77 hlim=64 time=152.889 ms
16 bytes from 2001:db8::1, icmp_seq=78 hlim=64 time=153.04 ms
16 bytes from 2001:db8::1, icmp_seq=79 hlim=64 time=163.178 ms
16 bytes from 2001:db8::1, icmp_seq=80 hlim=64 time=273.66 ms
16 bytes from 2001:db8::1, icmp_seq=81 hlim=64 time=173.819 ms
16 bytes from 2001:db8::1, icmp_seq=82 hlim=64 time=144.435 ms
16 bytes from 2001:db8::1, icmp_seq=83 hlim=64 time=144.619 ms
16 bytes from 2001:db8::1, icmp_seq=84 hlim=64 time=145.237 ms
16 bytes from 2001:db8::1, icmp_seq=85 hlim=64 time=235.374 ms
16 bytes from 2001:db8::1, icmp_seq=86 hlim=64 time=145.794 ms
16 bytes from 2001:db8::1, icmp_seq=87 hlim=64 time=144.179 ms
16 bytes from 2001:db8::1, icmp_seq=88 hlim=64 time=146.573 ms
16 bytes from 2001:db8::1, icmp_seq=89 hlim=64 time=157.132 ms
16 bytes from 2001:db8::1, icmp_seq=90 hlim=64 time=147.372 ms
16 bytes from 2001:db8::1, icmp_seq=91 hlim=64 time=307.801 ms
16 bytes from 2001:db8::1, icmp_seq=92 hlim=64 time=148.159 ms
16 bytes from 2001:db8::1, icmp_seq=93 hlim=64 time=148.573 ms
16 bytes from 2001:db8::1, icmp_seq=94 hlim=64 time=148.974 ms
16 bytes from 2001:db8::1, icmp_seq=95 hlim=64 time=446.143 ms
16 bytes from 2001:db8::1, icmp_seq=96 hlim=64 time=149.767 ms
16 bytes from 2001:db8::1, icmp_seq=97 hlim=64 time=49.931 ms
16 bytes from 2001:db8::1, icmp_seq=98 hlim=64 time=4.134 ms
16 bytes from 2001:db8::1, icmp_seq=99 hlim=64 time=4.699 ms
16 bytes from 2001:db8::1, icmp_seq=100 hlim=64 time=4.104 ms
16 bytes from 2001:db8::1, icmp_seq=101 hlim=64 time=4.151 ms
16 bytes from 2001:db8::1, icmp_seq=102 hlim=64 time=4.384 ms
16 bytes from 2001:db8::1, icmp_seq=103 hlim=64 time=4.352 ms
</pre>
<p>さくらのVPS上のOpenBSDをハブにすることで、PPPoEと3G回線を組み合せた構成が作れました。</p>
</div>
2012-12-02T15:07:40+09:00
-
instance store-backedなCentOS 5.xのAMIからEBS-backedなAMIを作る
https://projects.tsuntsun.net/~nabeken/diary/Sysadmin/creating-centos5-ami-on-amazon-linux-2.html
<h2>UPDATE:</h2><ul>
<li>SSH公開鍵を削除し忘れていたので追加 (Sun, 2 Dec 2012 13:31:37 +0900)</li>
<li>初稿 (Fri, 9 Mar 2012 23:07:55 +0900)</li>
</ul>
<div class="section" id="instance-store-backed-vs-ebs-backed">
<h3>instance store-backed vs. EBS-backed</h3>
<p>今回は pvgrub + パーティションのないディスクイメージ (swapをディスクイメージとして持つ) で作成します。
先日リリースされた待望の <em>m1.small (x86_64)</em> でも動きます。</p>
<p>ストレージの種別について、前回の記事から再掲します。
(このあたりはXenがどのようにゲストへディスクを見せるかという話です。)</p>
<ul>
<li>
<p class="first">instance store-backed (S3-backed)</p>
<p>インスタンスストレージ(ephemeral領域と同じ種別)上にディスクイメージを展開したものをroot deviceにする。
root deviceになる場合、domUからはsdaとしては見えず、パーティション1(sda <em>1</em>)として見える。</p>
</li>
<li>
<p class="first">EBS-backed</p>
<p>通常、EBSはディスク(sdaなど)として見えます。パーティションを切って使うこともできます。</p>
<p>パーティションを切らない場合(domU的にパーティションXとして見える)は
instance store-backedと同様の扱いになります。</p>
</li>
</ul>
<p>ややこしいのは、ストレージの種別とdomU(インスタンス)からみた場合の見えかたは直接は関係ありません。</p>
<ul>
<li>
<p class="first">raw または unpartitioned disk image</p>
<p>domUからはパーティション1(sda1)のように見える。pvgrubからみるとこれを <em>whole disk</em> と
呼んでいる。ほとんどのAMIがこの形式。</p>
<p>instance store-backedのAMIは通常この形式になる。実のところ、EBS-backedのAMIも
ほとんどがこの形式。</p>
<p>(なぜなら、m1.smallはsda2にephemeral領域, sda3にスワップ領域をねじこむため、sdaにEBSをattach
してもsda2, sda3は見えない。全インスタンスタイプに対応可能なAMIを作る場合はsda1を <tt class="docutils literal">/</tt> にして、
EBSをattachするのが得策。)</p>
<p><em>pvgrubを使う場合は "hd0" 版を使います</em> 。</p>
</li>
<li>
<p class="first">partitioned disk image / image that has a partition table</p>
<p>domUからはディスクそのもの(sda)のように見える。</p>
<p>LVMルートにする場合、 <tt class="docutils literal">/</tt> はpvgrubから見えないため、/bootだけ通常のファイルシステム
として見せる必要があります。そのため、パーティションを切る必要でてきます。</p>
<p>/bootを分割する必要がなければわざわざこの形式を選ぶことはいと思います。
swapもディスクイメージとして持てるのでわざわざ切る必要はありません。</p>
<p><em>pvgrubを使う場合は "hd00" 版を使います</em> 。</p>
</li>
</ul>
</div><div class="section" id="instance-store-backed-ebs-backed-ami">
<h3>instance store-backed から EBS-backed AMIを構築する</h3>
<p>手順は以下。</p>
<ol class="arabic">
<li>
<p class="first">作成したinstance store-backed AMIから起動</p>
<p><tt class="docutils literal"><span class="pre">ec2-run-instances</span></tt> でもManagement Consoleでもなんでも。</p>
</li>
<li>
<p class="first">EBS-backedにするために新規にEBS volumeを作成</p>
<p>作成時、AZを起動したインスタンスに合せます。生のEBSはAZを跨いでattachできません。
(EBSから作ったスナップショットはリージョン内ならAZ問わず参照可能)。</p>
<p>このEBS volumeが <tt class="docutils literal">/</tt> になります。容量がここで決まります。今回は10GiBにしました。</p>
</li>
<li>
<p class="first">作成したEBS volumeを起動したインスタンスにattach</p>
<p>今回は <tt class="docutils literal">/dev/sdf</tt> にattachしました。</p>
</li>
<li>
<p class="first">起動したインスタンスでattachしたEBS volumeを下ごしら</p>
<p><em>パーティションは切らずに</em> そのまま <tt class="docutils literal">/dev/sdf</tt> をext4でフォーマットします。</p>
<pre class="literal-block">
# yum install -y e4fsprogs
(必要に応じて)
# /sbin/mkfs.ext4 -L '/' /dev/sdf
# mkdir /media/ebs-root
# mount /dev/sdf /media/ebs-root
</pre>
</li>
<li>
<p class="first">EBS volumeへ起動中のインスタンスの中身をコピー</p>
<p>rsyncでいっきにコピーします。</p>
<pre class="literal-block">
# rsync -avP --exclude=/proc --exclude=/sys --exclude=/media / /media/ebs-root/
# mkdir /media/ebs-root/{proc,sys,media}
</pre>
</li>
<li>
<p class="first">スワップをディスクイメージで用意</p>
<p>m1.smallにはもともと1GBのswapパーティションがついてきますが、全インスタンスで共通化するため、
EBS内部に含めておきます。</p>
<pre class="literal-block">
# dd if=/dev/zero of=/media/ebs-root/SWAP.IMG bs=1M count=1000
# mkswap /media/ebs-root/SWAP.IMG
</pre>
</li>
<li>
<p class="first">fstab調整</p>
<p>swapを追加します。</p>
<pre class="literal-block">
# vi /media/ebs-root/etc/fstab
/SWAP.IMG none swap sw 0 0
</pre>
</li>
<li>
<p class="first">痕跡を削除</p>
<p>念のため <tt class="docutils literal">.bash_history</tt> が存在していれば削除します。</p>
<pre class="literal-block">
# rm /media/ebs-root/root/.bash_history
</pre>
<p>忘れずに公開鍵も削除しておきます。</p>
<pre class="literal-block">
# rm /media/ebs-root/root/authorized_keys
</pre>
</li>
<li>
<p class="first">EBS volumeをumountしてスナップショット作成</p>
<pre class="literal-block">
# umount /media/ebs-root
</pre>
<p><tt class="docutils literal"><span class="pre">ec2-create-snapshot</span></tt> を使うなりManagment Consoleを使うなりしてEBS volumeに対してスナップショットを作成します。</p>
</li>
<li>
<p class="first">AMIを作成</p>
<p>出来上がったスナップショットをroot deviceにしてAMIを作成します。ついでにephemeral領域も最大限有効にしておきます。</p>
<pre class="literal-block">
# ec2-register --cert ${EC2_CERT} --private-key ${EC2_PRIVATE_KEY} -a x86_64 \
-n 'CentOS 5.6 (x86_64) EBS-backed/swap/ephemeral0-3' \
-d 'CentOS 5.6 (x86_64) EBS-backed w/swap/ephemeral[0-3]' --snapshot snap-XXXXX \
-b '/dev/sdc=ephemeral0' -b '/dev/sdd=ephemeral1' -b '/dev/sde=ephemeral2' -b '/dev/sdf=ephemeral3' \
--kernel aki-aki-ee5df7ef
</pre>
</li>
<li>
<p class="first">できあがったAMIで起動する</p>
<p>念のため各インスタンスタイプ(t1.micro, m1.{small,large}など)で起動するかを確認します。</p>
</li>
</ol>
<p>作成に使ったEBS volumeは置いておくと便利です。
今後、AMIを更新する必要があればまたEBSをattachし、更新後スナップショットを取り <tt class="docutils literal"><span class="pre">ec2-register</span></tt> するだけです。</p>
<p>たぶん、 <tt class="docutils literal"><span class="pre">ec2-create-image</span></tt> とか他のを使えばもう少し楽かもしれません。</p>
</div><div class="section" id="id2">
<h3>参考文献</h3>
<ul class="simple">
<li><a class="reference external" href="http://www.slideshare.net/kentamagawa/aws1-ec2-ebs">仮想サーバーEC2 & EBS詳細 -ほぼ週刊AWSマイスターシリーズ "Reloaded"-</a></li>
</ul>
</div>
2012-12-02T13:31:37+09:00
-
Fuguita 5.1をamd64化してPCルータにした (あるいは4.9から5.1への移行)
https://projects.tsuntsun.net/~nabeken/diary/OpenBSD/fuguita-5.1-amd64.html
<h2>UPDATE:</h2><ul>
<li>初稿 (Fri, 31 Aug 2012 23:01:13 +0900)</li>
</ul>
<div class="section" id="usb">
<h3>USBメモリブートについて</h3>
<p>PCルータでは可動部をできるだけ減らすためハードディスクの代わりにUSBメモリを使うことがあります。
しかし、
<a class="reference external" href="http://www.openbsd.org/faq/faq14.html#flashmemPortable">http://www.openbsd.org/faq/faq14.html#flashmemPortable</a>
にもあるようにUSBメモリは品質のバラツキが激しいと言われています。
そのまま使うと24時間つけっぱなしによる断続的な書き込みに耐えられず、ファイルシステムが破損する
ことがあります。</p>
</div><div class="section" id="id2">
<h3>USBメモリブート後、メモリファイルシステムへ移行する</h3>
<p>断続的な書き込みが行なわれているファイルを特定し、原因となるプログラムの設定変更もできます。
もっと効果的な手段はUSBメモリ後、ルートファイルシステムをメモリファイルシステム(mfs)に切り替える
ことです。これにより、USBメモリへの書き込みは設定変更時の永続化時のみになり高寿命化が期待できます。</p>
<p>PCルータは1度設定すればほとんど設定変更もないためメモリファイルシステムと相性はよいと思います。</p>
<dl class="docutils">
<dt>メリット</dt>
<dd><ul class="first last simple">
<li>1度ブートすればシャットダウン時の設定保存以外USBメモリへの書き込みが一切発生しない</li>
<li>メモリファイルシステムなので動作中の読み込み/書き込みはそこそこ速い(めちゃめちゃ速いわけではないようです)</li>
</ul></dd>
<dt>デメリット</dt>
<dd><ul class="first last simple">
<li>ログなどはシャットダウンすると消えてしまうため別途syslogサーバが必要</li>
<li>もともと実装メモリ容量が小さい場合は増設を検討する必要がある</li>
</ul></dd>
</dl>
</div><div class="section" id="fuguita">
<h3>FuguIta</h3>
<p><a class="reference external" href="http://kaw.ath.cx/openbsd/index.php?LiveCD">FuguIta</a> はOpenBSDのLiveCDディストリビューションの1つです。現在はi386版のみ配布されています。
今回は技術的興味もあり、amd64版で動くようにportしてみました。それが <a class="reference external" href="https://github.com/nabeken/myfuguita">MyFuguita</a> です。</p>
<p>今回はOpenBSDの標準ビルドシステム(/usr/src/distrib)に統合するすることでamd64へポートしました。
ビルドシステムへ載せることで、アーキテクチャ非依存の部分はISOイメージ作成部分に吸収できました。</p>
<p>FuguIta(およびMyFuguIta)のインスール方法などはそれぞれのページを参照してください。</p>
</div><div class="section" id="port">
<h3>port時の諸問題</h3>
<p>つらつらと書きます。</p>
<ol class="arabic">
<li>
<p class="first">RAMDISK内のバイナリはcrunched binaryと呼ばれるものになっている</p>
<p>1つのバイナリに複数のバイナリを埋め込み、ハードリンクを張る手法です。ディスク容量とinodeの節約のためと思われます。
(RAMDISKは埋め込められる容量に上限があるので重要な手法です)</p>
</li>
<li>
<p class="first">RAMDISKの/sbin/initはsingle-user mode用にビルドされている</p>
<p>RAMDISK埋め込み時は <tt class="docutils literal">/usr/src/distrib/special/init</tt> でビルドしたものを使っているようです。
ここでビルドする際はブート時のモードが single-user モード固定になっています。したがって、起動時
に自動的に <tt class="docutils literal">/etc/rc</tt> は実行されません。これに気がつくまでかなり時間がかかりました。
(RAMDISK使用時、インストーラーは /.profile 経由で起動しているようです)</p>
<p>MyFuguitaでは /usr/dest/sbin/init をコピーするようにしました。</p>
</li>
<li>
<p class="first">RAMDISKにどのファイルをコピーするか</p>
<p>RAMDISKにどのファイルをコピーするかはすべてリストで管理されています。
<tt class="docutils literal">/usr/src/distrib/amd64/ramdisk_cd/list.local</tt> がその一例です。</p>
<p>MyFuguitaの主な成果物はこのリストファイルです。MyFuguitaでは共通リストはincludeせずに、
コピーしてカスタマイズしています。(special/initを使わない、など)</p>
<p><a class="reference external" href="https://github.com/nabeken/myfuguita/blob/master/distrib/amd64/fuguita_cd/list">https://github.com/nabeken/myfuguita/blob/master/distrib/amd64/fuguita_cd/list</a></p>
</li>
<li>
<p class="first">GENERICにいくつか足す</p>
<ul>
<li>
<p class="first">FuguItaは/dev/vnd5が必要なので数を増やしておく (vnd 6くらいに)</p>
</li>
<li>
<p class="first">GENERICにはrd(RAMDISK)が含まれていないので入れておく(pseudo-device rd 1)</p>
</li>
<li>
<p class="first">GENERICにRAMDISK埋め込み用の設定を入れておく</p>
<pre class="literal-block">
option RAMDISK_HOOKS
option MINIROOTSIZE=4480
config bsd root on rd0a swap on rd0b and wd0b and sd0b
</pre>
</li>
<li>
<p class="first">PPPoEを喋らせるので option PPPOE_TERM_UNKNOWN_SESSIONS も追加</p>
</li>
<li>
<p class="first">最終的なconfigはgithubに置いてあります。MP用になっていませんが、適宜足せばできます。
このconfigはGENERICを埋め込んでいますが、本来はincludeした上で不必要なものを <tt class="docutils literal">rmoption</tt>
するほうがよいです。今後修正予定です。</p>
<p><a class="reference external" href="https://github.com/nabeken/myfuguita/blob/master/sys/arch/amd64/conf/FUGUITA">https://github.com/nabeken/myfuguita/blob/master/sys/arch/amd64/conf/FUGUITA</a></p>
</li>
</ul>
</li>
</ol>
</div><div class="section" id="id4">
<h3>シャットダウン時に自動的にUSBメモリへ永続化する</h3>
<p>FuguItaは <tt class="docutils literal">/boottmp/usbfadm</tt> を使うことでメモリファイルシステム上のファイルをUSBメモリへ
永続化することができます。シャットダウン時に自動的に実行するようにしました。
(本来は設定変更時に明示的にやるほうがいいとは思うのですが…)</p>
<pre class="literal-block">
# cat /etc/rc.shutdown
export PATH=$PATH:/usr/local/bin # rsyncは/usr/local/binにあるため、通しておく
cat <<EOF | /boottmp/usbfadm # usbfadmは引数で制御できないっぽいのでやや強引に
sync
y
q
EOF
</pre>
</div><div class="section" id="to-5-1">
<h3>冗長化まであと1、2歩というところでの4.9 to 5.1</h3>
<p>前回の記事
<a class="reference external" href="https://projects.tsuntsun.net/~nabeken/diary/OpenBSD/h61m-usb3-and-openbsd49.html">https://projects.tsuntsun.net/~nabeken/diary/OpenBSD/h61m-usb3-and-openbsd49.html</a>
からネットワークの構成変更を実施し、VLANによる論理分割を実施しました。今後を考え、2物理NICでも
対応できるようにtrunk接続し、VLANを切るようにしました。</p>
<p>gw0は物理NICが3つあるので、ONU向け、サーバ側、クライアント側で3つ。gw1は物理NICが2つしかないので、
ONU向けに1物理NIC、サーバ側とクライアント側は1物理NICからVLANで切り出しました。</p>
<p>これでようやく、gw0, gw1の冗長構成に…と言いたかったのですが、carp, pfsync, サービス切り替えの
検証ができず、また次回となりそうです。</p>
<p>gw1の物理構成図:</p>
<pre class="literal-block">
--------------
The Internet
--------------
|
| (pppoe0 on re0) | |
| | |
+-----+ | |
| gw1 |-----[vlan103/re1]-------| +-------+ |
+-----+ |--------| rt57i |--------| クライアント
| | +-------+ |
| (vlan101/re1) | |
|
-------------
サーバ
</pre>
<p>vlan101側をcarp0、vlan103側をcarp1にして構成します。carp周りの設定はI/F名以外は前回の記事通りです。
今回はひとまず、筐体に問題が発生したら都度ケーブルを差し替える運用としました。</p>
</div><div class="section" id="g">
<h3>(おまけ)安価な3G回線によるバックアップ回線の構築</h3>
<p>PCルータ更新に合わせて、3G回線による安価(月額980円)なバックアップ回線を用意しました。
何かあったとき、新幹線代が往復3万以上なことを考えると十分元は取れます。
(もともとDebianを入れたThinkpadにデータカードを刺してイオンSIMで運用していましたが、今回から
OpenBSD箱から直接バックアップ回線に流せるようにしました)</p>
<p>最近はIIJやDTIからも安価な3Gサービスがでていますが、今回はbmobileがイオン限定で販売している
<a class="reference external" href="http://www.bmobile.ne.jp/aeon">イオンSIM</a> にSIMフリーのモバイルWiFiルーターを組合せて安上がりなリモートメンテナンス環境を作りました。</p>
<p>データカードを直接刺す場合、バックアップ回線の恩恵を受けられるのは同時に1台です(ルーティングとか考えない場合)。
丁度、以前購入したSIMフリーなモバイルWiFiルーター <a class="reference external" href="http://www.bmobile.ne.jp/wifi/">bmobile WiFi</a> が余っていたのと、
USBの無線LANアダプタ <a class="reference external" href="http://www.planex.co.jp/product/wireless/gw-usnano2/">GW-USNano2</a> が870円で、かつOpenBSDでも問題なく動くことがわかったので急遽OpenBSD + urtwn(8)で構成しました
(GW-USNano2は2つ購入し、gw0とgw1に装着)。</p>
<pre class="literal-block">
urtwn0 at uhub0 port 1 "Planex Communications Inc. GW-USNano2" rev 2.00/2.00 addr 3
urtwn0: MAC/BB RTL8188CUS, RF 6052 1T1R, address 00:XX:XX:YY:ZZ:XX
</pre>
<p>(おまけ:GW-USNano2-GはUSNano2と同じです。パッケージだけ異なるようです。)</p>
<p>端末に払い出されるIPアドレスはプライベートIPアドレスです。さくらのVPS上のOpenVPNに接続し、
外部からのバックアップ回線経由のIPv6到達性を用意しました。</p>
<p>gw1のネットワーク構成図:</p>
<pre class="literal-block">
-------------------------------------------------------------------------------------------
The Internet
-------------------------------------------------------------------------------------------
| |
| |
(OpenVPN) |
| |
| |
+---------+ |
| bm WiFi | (pppoe0 on re0) | |
+---------+ | | |
| +-----+ | |
[urtwn0]----| gw1 |-----[vlan103/re1]-------| +-------+ |
+-----+ |--------| rt57i |--------| クライアント
| | +-------+ |
| (vlan101/re1) | |
|
-------------
サーバ
</pre>
<p>VPNサーバ(X.X.X.X)への通信だけbmobile WiFi(Y.Y.Y.Y)を経由させます。</p>
<pre class="literal-block">
# route add -host X.X.X.X Y.Y.Y.Y
</pre>
<p>今後はリモートからgw0/gw1を切り替えながら作業することが可能になります。
回線障害時にも威力を発揮してくれると期待しています。</p>
</div><div class="section" id="id5">
<h3>今後の目論見</h3>
<p>L3的にはcarpで冗長化ができます。しかし、L3以外にも考えることはあります。
例えば…</p>
<ol class="arabic">
<li>
<p class="first">PPPoE</p>
<p>切り替えがおきたら、新masterで再接続する必要がある
旧masterでは再接続を止める必要がある。</p>
</li>
<li>
<p class="first">NAT</p>
<p>pfsyncを使い、状態を同期する必要がある。
できれば専用の線がほしい。(たぶんVLANになるけど)</p>
</li>
</ol>
<ol class="arabic" start="2">
<li>
<p class="first">gre</p>
<p>切り替えがおきたら、新masterで再接続する必要がある
(最悪、起動しっぱなしでもPPPoE再接続のタイミングで効果を発揮する)</p>
</li>
<li>
<p class="first">OpenVPN</p>
<p>切り替えがおきたら、新masterで起動する必要がある
(0.0.0.0で待ち受けて起動しっぱなしにしておいて、pfでPPPoEからのみにする手もある。)</p>
</li>
<li>
<p class="first">Quagga, Bird</p>
<p>設定ファイルでは、I/Fにcarpを指定している。そのため、BACKUP状態では動かないはず。
検証が必要。</p>
</li>
<li>
<p class="first">設定の同期</p>
<p>2台のマシン間で設定を同期する必要がある。完全に一致するわけではないので工夫が必要。
USBメモリという特性上、ネットワーク越しにバックアップも取らなければならない。
(usbfadmでsync時にネットワーク越しにもrsyncできればよさそう)</p>
</li>
</ol>
</div>
2012-08-31T23:01:13+09:00
-
Amazon Linux上でCentOS 5.xのAMIを作る
https://projects.tsuntsun.net/~nabeken/diary/Sysadmin/creating-centos5-ami-on-amazon-linux-1.html
<h2>UPDATE:</h2><ul>
<li>ストレージ種別の説明を一部修正 (Fri, 9 Mar 2012 20:01:27 +0900)</li>
<li>初稿 (Mon, 5 Mar 2012 01:30:41 +0900)</li>
</ul>
<div class="section" id="amazon-linux">
<h3>Amazon Linuxについて</h3>
<p><a class="reference external" href="http://aws.amazon.com/jp/amazon-linux-ami/">Amazon Linux</a> はEC2用AMIとしてAmazonがメンテナンスしているディストリビューションです。
最新版はRHEL6互換 + ec2系のツール、cloud-initがセットアップ済みです。</p>
<p>どうしてもCentOSでなければならない理由がなければ、そのままAmazon Linuxを使うのが楽だと思います。
今回はどの環境でも動くことが要件なので、CentOSをベースにする必要がありました。</p>
<p>そんなわけで、Amazon Linux上でCentOS 5、今回は事情により特にCentOS 5.6 (x86_64)のリリース版最小構成でAMIを作成します。
このAMIは今後のカスタマイズの基本AMIとするため、swap領域、cloud-init的なものは一切セットアップしません。
root deviceはinstance store-backedで、ephemeral領域とsshの公開鍵のセットアップのみを施します。</p>
<p>使用するAmazon Linuxは <tt class="docutils literal">Basic <span class="pre">64-bit</span> Amazon Linux AMI 2011.09 (AMI Id: <span class="pre">ami-0a44f00b)</span></tt> です。</p>
</div><div class="section" id="id3">
<h3>作業用インスタンスを起動する</h3>
<p>節約のため、作業用インスタンスはスポットインスタンスで起動させます。
また、AMI用のディスクイメージ作成作業用の領域としてEBSはコストがかかるため、ephemeral領域(instance store)にディスクイメージを展開して作業します。</p>
<p>スポットインスタンスにephemeral領域を付けて起動する場合、Management Consoleからはできないため、コマンドから入札します。
コマンドの詳細はヘルプを見てもらうとして、ここで大事なのは <tt class="docutils literal"><span class="pre">-b</span> /dev/sdb=ephemeral0</tt> の部分だけです。</p>
<pre class="literal-block">
$ ec2-request-spot-instances ami-0a44f00b -b /dev/sdb=ephemeral0 --region ap-northeast-1 \
-t m1.large -k your-keypair --price your-price --instance-count 1
</pre>
<p>入札が成功するとインスタンスが起動するはずです。
起動したインスタンスにec2-userでログインします。</p>
</div><div class="section" id="ephemeralami">
<h3>ephemeral領域にAMI用のディスクイメージを用意する</h3>
<p>ephemeral領域にディスクイメージを作成し、loopbackマウントします。
マウント後、いくつか下ごしらえをします。</p>
<pre class="literal-block">
$ cd /media/ephemeral0
$ sudo mkdir ami-{bundle,root}
$ sudo dd if=/dev/zero of=CentOS-5.6-x86_64.img bs=1M count=8000
$ sudo /sbin/mkfs.ext4 -F CentOS-5.6-x86_64.img
$ sudo mount -o loop CentOS-5.6-x86_64.img /media/ephemeral0/ami-root
$ sudo mkdir /media/ephemeral0/ami-root/{etc,proc,dev}
$ sudo mount -t proc none /media/ephemeral0/ami-root/proc
$ for i in console null zero; do sudo /sbin/MAKEDEV -d /media/ephemeral0/ami-root/dev -x $i; done
</pre>
<p>AMI用のfstabは <tt class="docutils literal">/etc/fstab</tt> をコピーし、一部修正します。</p>
<pre class="literal-block">
$ sudo cp /etc/fstab ami-root/etc/
$ sudo vi ami-root/etc/fstab
ephemeral0の部分は必要ないので削除します。
</pre>
<p>ディスクイメージの下ごしらえは完了です。</p>
</div><div class="section" id="centos-5-6-x86-64-yum">
<h3>CentOS 5.6 (x86_64)のリリース版yumリポジトリを用意する</h3>
<p>今回は基本AMIとして作るため、CentOS 5.6 (x86_64)のリリース版でyumを実行します。作成時点ではアップデートは一切適用しません。
DVDのISOイメージをすでに持っている場合はその中身をどこか適当なWebサーバへ展開します。</p>
<p>持っていない場合はvault.centos.org (アーカイブ)から調達する必要があります。
今回の作成にあたり、私が5.6のi386, x86_64をrsyncしたものを以下で公開しています。
このリポジトリは予告なく公開を終了する場合があります。
(ちなみに、isosをexcludeしても26GBほどあります。updatesとi386もexcludeすればDVD1枚分になりそう…)</p>
<ul class="simple">
<li><a class="reference external" href="https://projects.tsuntsun.net/~nabeken/CentOS/5.6/">https://projects.tsuntsun.net/~nabeken/CentOS/5.6/</a></li>
</ul>
</div><div class="section" id="yumcentos-5-6-x86-64">
<h3>yumコマンドでCentOS 5.6 (x86_64)環境を構築する</h3>
<p>リポジトリの準備ができたら、次は <tt class="docutils literal">yum.conf</tt> を用意します。updates-releasedリポジトリは無効化しています。
baseurlの部分は適宜読み替えてください。</p>
<pre class="literal-block">
$ cat /media/ephemeral0/yum.conf
[main]
cachedir=/var/cache/yum
debuglevel=2
logfile=/var/log/yum.log
exclude=*-debuginfo
gpgcheck=0
obsoletes=1
reposdir=/dev/null
[base]
name=CentOS 5.6 - Base
baseurl=https://projects.tsuntsun.net/~nabeken/CentOS/5.6/os/$basearch/
enabled=1
[updates-released]
name=CentOS 5.6 - Released Updates
baseurl=https://projects.tsuntsun.net/~nabeken/CentOS/5.6/updates/$basearch/
enabled=0
</pre>
<p>groupinstallしたくなりますが、まずは <tt class="docutils literal">yum</tt> コマンドだけ先にインストールします。</p>
<p>実はAmazon Linuxの <tt class="docutils literal">yum</tt> およびrpm実行環境はCentOS 5系からみるとrpmデータベースで使っているデータベース(Berkeley DB)の形式が新しいため、
このままでは作成したAMIで起動しても自分自身の <tt class="docutils literal">yum</tt> コマンド(rpmコマンド)が使えなくなります。そこで、</p>
<ol class="arabic simple">
<li>
<tt class="docutils literal">yum</tt> コマンドをインストール</li>
<li>CentOS 5の環境にchrootし、rpmデータベースをクリア</li>
<li>再度 <tt class="docutils literal">yum</tt> をインストールし、rpmデータベースを再作成</li>
</ol>
<p>の手順を踏みます。</p>
<pre class="literal-block">
$ sudo yum -c /media/ephemeral0/yum.conf --installroot=/media/ephemeral0/ami-root install -y yum
</pre>
<p>chrootした後に必要となるファイルを予めコピーしておきます。</p>
<pre class="literal-block">
$ sudo cp /etc/resolv.conf /media/ephemeral0/ami-root/etc
$ sudo cp /media/ephemeral0/yum.conf /media/ephemeral0/ami-root/
(このファイルは最後に削除します)
</pre>
<p>chrootします。</p>
<pre class="literal-block">
$ sudo chroot /media/ephemeral0/ami-root /bin/bash
# source /etc/profile
# yum
(ここでyumがデータベースのバージョンが新しすぎると文句をいう)
Loaded plugins: fastestmirror
rpmdb: /var/lib/rpm/Packages: unsupported hash version: 9
error: cannot open Packages index using db3 - Invalid argument (22)
error: cannot open Packages database in /var/lib/rpm
Traceback (most recent call last):
File "/usr/bin/yum", line 29, in ?
yummain.user_main(sys.argv[1:], exit_code=True)
File "/usr/share/yum-cli/yummain.py", line 309, in user_main
errcode = main(args)
File "/usr/share/yum-cli/yummain.py", line 157, in main
base.getOptionsConfig(args)
File "/usr/share/yum-cli/cli.py", line 187, in getOptionsConfig
self.conf
File "/usr/lib/python2.4/site-packages/yum/__init__.py", line 665, in <lambda>
conf = property(fget=lambda self: self._getConfig(),
File "/usr/lib/python2.4/site-packages/yum/__init__.py", line 240, in _getConfig
self._conf = config.readMainConfig(startupconf)
File "/usr/lib/python2.4/site-packages/yum/config.py", line 804, in readMainConfig
yumvars['releasever'] = _getsysver(startupconf.installroot, startupconf.distroverpkg)
File "/usr/lib/python2.4/site-packages/yum/config.py", line 877, in _getsysver
idx = ts.dbMatch('provides', distroverpkg)
TypeError: rpmdb open failed
# rm -f /var/lib/rpm/*
# yum -c /yum.conf install -y yum
(もう1度すべてインストールしなおすことでrpmデータベースも再作成)
# ls -l /var/lib/rpm
# yum -c /yum.conf groupinstall -y Core Base
</pre>
<p>CentOS 5.6リリース版環境の構築が完了しました。</p>
</div><div class="section" id="centos-5-6-x86-64">
<h3>CentOS 5.6 (x86_64)環境の設定</h3>
<p>本来インストーラーで行なわれる処理をchroot内で手動にて行ないます。</p>
<ol class="arabic">
<li>
<p class="first">ネットワーク設定</p>
<pre class="literal-block">
# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
TYPE=Ethernet
USERCTL=yes
PEERDNS=yes
IPV6INIT=no
# cat /etc/sysconfig/network
NETWORKING=yes
# echo '127.0.0.1 localhost.localdomain localhost' > /etc/hosts
</pre>
</li>
<li>
<p class="first">sshdの設定</p>
<p>パスワード認証を無効化し、公開鍵認証のみにします。</p>
<pre class="literal-block">
# vi /etc/ssh/sshd_config
PasswordAuthentication no
PermitRootLogin without-password
UsePAM no
</pre>
</li>
<li>
<p class="first">/etc/shadowの生成</p>
<p>/etc/shadowが存在していない場合、 <tt class="docutils literal">passwd</tt> コマンドが使用できません。手動で <tt class="docutils literal">pwconv</tt> コマンド
を実行し、生成します。</p>
<pre class="literal-block">
# pwconv
</pre>
</li>
<li>
<p class="first">selinuxの無効化</p>
<p>disabledにします。</p>
<pre class="literal-block">
# vi /etc/sysconfig/selinux
SELINUX=disabled
</pre>
</li>
<li>
<p class="first">起動サービスの設定</p>
<p>必要のないサービスを落とします。</p>
<pre class="literal-block">
# chkconfig --list | grep -E '[2345]:on'
# for i in bluetooth firstboot gpm hidd ip6tables iscsi iscsid \
kudzu nfslock pcscd portmap rpcgssd rpcidmapd smartd yum-updatesd; do \
chkconfig --level 2345 $i off; \
done
</pre>
</li>
<li>
<p class="first">root用のssh公開鍵の取得処理</p>
<p>インスタンスの初回起動時にmetadataからkeypairを取得し、rootのssh公開鍵として設定する必要があります。
RHEL6系であれば、Amazon Linuxのcloud-initパッケージを流用できそうですが、今回は
<a class="reference external" href="http://kray.jp/blog/centos62-s3backed-ami-from-scratch/">[Amazon EC2] AMI をゼロから作る CentOS 6.2 / S3-Backed 版</a>
を参考に <tt class="docutils literal">/etc/rc.local</tt> へ取得処理を追加します。</p>
</li>
<li>
<p class="first">Xen domU用カーネルのインストール</p>
<p>CentOS 5系では標準カーネルのままだとXenのdomUとしては起動しないため、別途カーネルをインストールします。</p>
<pre class="literal-block">
# yum install -y kernel-xen
</pre>
</li>
<li>
<p class="first">Xen domU用にinitrdを再生成</p>
<p>domU用に必要なモジュールを組み込んで再生成します。</p>
<pre class="literal-block">
# ls -l /boot
(el5xenなカーネルを探します。)
# mkinitrd --with xenblk --with xennet /boot/initrd-2.6.18-274.18.1.el5xen_ec2.img 2.6.18-274.18.1.el5xen
# ls -l /boot/initrd-2.6.18-274.18.1.el5xen_ec2.img
(できあがっているのを確認する)
</pre>
</li>
<li>
<p class="first">grubの設定</p>
<p>後述しますが、このAMIはpvgrub経由で起動させるため、grubの設定を用意します。
今回はinstance store-backedなのでkernelに渡すrootは <tt class="docutils literal">sda1</tt> を指定します。</p>
<pre class="literal-block">
# cat /boot/grub/menu.lst
default=0
timeout=0
hiddenmenu
title CentOS 5.6 (x86_64)
root (hd0)
kernel /boot/vmlinuz-2.6.18-274.18.1.el5xen root=/dev/sda1
initrd /boot/initrd-2.6.18-274.18.1.el5xen_ec2.img
</pre>
</li>
<li>
<p class="first">一時ファイルの削除</p>
<p>最後にセットアップに使ったファイルを削除します。chrootから抜けて作業します。</p>
<pre class="literal-block">
# exit
(chrootから抜ける)
$ sudo rm /media/ephemeral0/ami-root/{yum.conf,root/.bash_history}
</pre>
<p>また、 <tt class="docutils literal">yum</tt> コマンドを再インストールした際のrpmnewファイルを削除します。
(パッケージを入れ直した時、既存ファイルを上書きせずに新しいファイルをファイル名.rpmnewとして保存する仕組みがあります。
今回は初期状態のため、rpmnewファイルは削除しても問題ありません。)</p>
<pre class="literal-block">
$ sudo find /media/ephemeral0/ami-root -type f -name *\.rpmnew
(対象ファイルが問題なさそうなことを確認)
$ sudo find /media/ephemeral0/ami-root -type f -name *\.rpmnew | sudo xargs rm
</pre>
</li>
</ol>
</div><div class="section" id="bundle">
<h3>ディスクイメージのbundleイメージ化</h3>
<p>作成したディスクイメージをS3へアップロードする下準備をします。まずはイメージをunmountします。</p>
<pre class="literal-block">
$ cd /media/ephemeral0
$ sudo umount /media/ephemeral0/ami-root/proc
$ sudo umount /media/ephemeral0/ami-root
$ sudo chown ec2-user:ec2-user -R .
(ec2-*コマンドをec2-userで使いため)
</pre>
<p>ec2コマンドを作業用インスタンスで行なうための下準備は済んでいるものとします。
(環境変数の設定、証明書のコピーなど。リージョンは環境変数で指定していると仮定。)</p>
<p>下準備ができたら <tt class="docutils literal"><span class="pre">ec2-bundle-image</span></tt> コマンドを実行します。</p>
<pre class="literal-block">
$ ec2-bundle-image --cert ${EC2_CERT} --privatekey ${EC2_PRIVATE_KEY} --user 1111-2222-3333 \
-i CentOS-5.6-x86_64.img -r x86_64 -d /media/ephemeral0/ami-bundle/
(--userの引数に与えるIDはアカウントアクティビティから確認可能)
</pre>
<p>内部ではディスクイメージをtarしてgzipしてAESで暗号化しているようです。</p>
</div><div class="section" id="bundles3">
<h3>作成したbundleイメージをS3へアップロードする</h3>
<p>bundleイメージ保存用のS3のバケットはすでに作成済みとします。ここでは <tt class="docutils literal"><span class="pre">nabeken-amis</span></tt> とします。</p>
<pre class="literal-block">
$ ec2-upload-bundle --access-key ${EC2_ACCESS_KEY} --secret-key ${EC2_SECRET_KEY} \
--bucket nabeken-amis/CentOS/5.6/ -m ./ami-bundle/CentOS-5.6-x86_64.img.manifest.xml
(外部からS3へアップロードするよりも、EC2、S3間は非常に早い)
</pre>
</div><div class="section" id="pvgrubakiephemeralami">
<h3>pvgrub用のAKIとephemeral領域を設定してAMIを作成する</h3>
<p>今回作成するAMIはinstance store-backedなAMIです。</p>
<ul>
<li>
<p class="first">instance store-backed (S3-backed)</p>
<p>インスタンスストレージ(ephemeral領域と同じ種別)上にディスクイメージを展開したものをroot deviceにする。
root deviceになる場合、domUからはsdaとしては見えず、パーティション1(sda <em>1</em>)として見える。</p>
</li>
<li>
<p class="first">EBS-backed</p>
<p>EBSは通常のディスク(sdaなど)として見せることも可能。実際には、各インスタンス種別
(m1.{small,large}, t1.microなど)にかかわらず使えるようにする場合は
instance store-backedと合せて sda1 を <tt class="docutils literal">/</tt> と構成することをオススメします。</p>
<p>ただし、LVMルートやRAIDXルートをする場合は <tt class="docutils literal">/boot</tt> を分ける必要があるため、
パーティションを切る必要があるでしょう。</p>
</li>
</ul>
<p>pvgrubを使う場合、この違いが重要になります。</p>
<ul>
<li>
<p class="first"><a class="reference external" href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/UserProvidedkernels.html">Enabling Your Own Linux Kernels</a></p>
<p>Several PV-GRUB AKIs are available depending on the type and location of your instance. There are AKIs for 32-bit and 64-bit architecture types, with each having one AKI for partitioned images and another AKI for partitionless images. You must choose an AKI with "hd0" in the name if you want a raw or unpartitioned disk image (most images). Choose an AKI with "hd00" in the name if you want an image that has a partition table.</p>
<p>インスタンスのロケーション、種類に応じて数種類の PV-GRUB AKI (Amazon Kernel Image)が利用可能です。
32bit, 64bitにそれぞれパーティションテーブルのあるディスクイメージとパーティションテーブルのないディスクイメージに対して1つのAKIがあります。
rawパーティションあるいはパーティションテーブルのないディスクイメージで使いたい場合は <em>"hd0"</em> のAKIを選ばなければなりません。
パーティションテーブルのあるディスクイメージで使いたい場合は <em>"hd00"</em> のAKIを選択してください。</p>
</li>
</ul>
<p>今回は東京リージョン(northeast-1)でinstance store-backedなx86_64のAMIを作るので、
<tt class="docutils literal"><span class="pre">aki-ee5df7ef</span> <span class="pre">ec2-public-images-ap-northeast-1/pv-grub-hd0_1.02-x86_64.gz.manifest.xml</span></tt>
を選択します。</p>
<pre class="literal-block">
$ ec2-register --cert ${EC2_CERT} --private-key ${EC2_PRIVATE_KEY} nabeken-amis/CentOS/5.6/CentOS-5.6-x86_64.img.manifest.xml \
-a x86_64 -n 'CentOS 5.6 (x86_64) instance store/ephemeral0-3' -d 'CentOS 5.6 (x86_64) instance store w/ephemeral[0-3]' \
-b '/dev/sdc=ephemeral0' -b '/dev/sdd=ephemeral1' -b '/dev/sde=ephemeral2' -b '/dev/sdf=ephemeral3' \
--kernel aki-ee5df7ef --root-device-name /dev/sda1
IMAGE ami-XXXXXXXX
</pre>
</div><div class="section" id="ami">
<h3>作成したAMIで起動してみる</h3>
<p>スポットインスタンスで起動してみます。今回はManagement Consoleから作成したAMIで起動します。
起動したら <tt class="docutils literal">root</tt> でログインできるはずです。</p>
<pre class="literal-block">
$ ssh -l root ec2-XXX-XXX-XXX-XXX.ap-northeast-1.compute.amazonaws.com
# uname -a
Linux ip-XXX-XXX-XXX-XXX 2.6.18-274.18.1.el5xen #1 SMP Thu Feb 9 13:27:02 EST 2012 x86_64 x86_64 x86_64 GNU/Linux
# cat /etc/redhat-release
CentOS release 5.6 (Final)
</pre>
<p><tt class="docutils literal"><span class="pre">ec2-get-console-output</span></tt> でコンソールのログを確認できます。
このログはリアルタイムではなく、2分程度のバッチ更新になっているようです。</p>
<pre class="literal-block">
$ ec2-get-console-output i-XXXXXXX
</pre>
<p>今後はこのAMIをベースに作り込みを行い、EBS-backedなAMIにしていきます。</p>
</div><div class="section" id="id4">
<h3>参考文献</h3>
<ul class="simple">
<li><a class="reference external" href="http://dev.classmethod.jp/cloud/amazon-ec2-ephemeral/">Amazon EC2(Root Device Type=EBS)でInstance Store(Ephemeral Store)を使う | Classmethod.dev()</a></li>
<li><a class="reference external" href="http://kray.jp/blog/centos62-s3backed-ami-from-scratch/">[Amazon EC2] AMI をゼロから作る CentOS 6.2 / S3-Backed 版 | KRAY Inc</a></li>
<li><a class="reference external" href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/creating-loopback-s3-linux.html">From a Loopback - Amazon Elastic Compute Cloud</a></li>
</ul>
</div>
2012-03-09T20:01:27+09:00
-
Windows 7をiSCSI targetへインストールする
https://projects.tsuntsun.net/~nabeken/diary/Sysadmin/windows7-installing-iscsi-over-pxeboot.html
<h2>UPDATE:</h2><ul>
<li>初稿 (Wed, 7 Sep 2011 09:48:19 +0900)</li>
</ul>
<div class="section" id="id2">
<h3>構成</h3>
<dl class="docutils">
<dt>M/B</dt>
<dd>Intel D501MO</dd>
<dt>OS</dt>
<dd>Windows 7 Professional (64bit)</dd>
<dt>Mem</dt>
<dd>DDR2 2GB x1, 512MB x1</dd>
<dt>機材</dt>
<dd>PT2, QRS-UT100B</dd>
</dl>
<p>PT2、QRS-UT100BをWindows 7 64bitで動かす方法は割愛します。
TvRock + TvTestで快適に録画できています。</p>
</div><div class="section" id="iscsi-target">
<h3>iSCSI target側構成</h3>
<dl class="docutils">
<dt>OS</dt>
<dd>FreeBSD 8.2-RELEASE</dd>
<dt>target</dt>
<dd>istgt version 0.4.20110717</dd>
<dt>fs</dt>
<dd>もちろんZFS!!!</dd>
</dl>
</div><div class="section" id="gpxesanboot">
<h3>gPXE経由でsanboot</h3>
<p>gPXE経由でsanbootすればWindows 7を直接iSCSI targetへインストールできると信じていました…。</p>
<p>問題はいくつかありました。</p>
<ol class="arabic">
<li>
<p class="first">自分でDHCPサーバを立ててroot-pathを渡す</p>
<p>この場合、インストーラーではiSCSI targetを認識できますが、
エラーメッセージがでてインストールできません。</p>
<p>(dhcpd.confでgPXEの値によってfilenameを渡したりroot-pathを渡している場合)</p>
</li>
<li>
<p class="first">gPXE経由でsanbootしてもインストーラーではiSCSI targetは認識できない</p>
<p>さまざまな記事ではさもsanbootすれば認識できるかのように書いてあります。
が、実際にはDHCPサーバの設定に左右されます。以下の設定の場合、DHCPサーバで
PXEブート用の filename 設定(gPXE用)が入っている場合は失敗します。</p>
<pre class="literal-block">
dhcp net0
set keep-san 1
sanboot iscsi:10.3.5.35::::iqn.2000-07.org.example:moge
exit
</pre>
<p>この問題を回避する場合はdhcp net0ではなくて、手動でIPアドレスを設定します。
なお、この設定はiBT領域に書き込まれ、その後Windows側のIPアドレス設定としても使われます。</p>
<pre class="literal-block">
ifopen net0
set net0/ip X.X.X.X
set net0/netmask X.X.X.X
set net0/gatewayh X.X.X.X>
set net0/dns 8.8.8.8
</pre>
</li>
</ol>
<p>そもそもの問題はWindows 7のインストーラでiSCSI targetを認識していてもインストールできない件です。
残念ですが、一旦実機のハードディスク上へインストールする必要があります。
(仮想マシンではなくて実機です。iSCSIブートに使用するNICを含んでインストールする必要があります)</p>
<ol class="arabic">
<li>
<p class="first">ハードディスクを実機に接続し、DVDROMからWindows 7をインストール</p>
</li>
<li>
<p class="first">NICのLWF (Light Weight Firewall) を切る</p>
<p>参考: <a class="reference external" href="http://blog.zorinaq.com/?e=41">http://blog.zorinaq.com/?e=41</a></p>
<p>私の環境では再起動すると毎度設定が復活するため、強引にレジストリの該当キーを書き込み不可にしました。</p>
</li>
<li>
<p class="first">ハードディスクの中身をiSCSIターゲットへコピー</p>
<p>私はインストール直後の環境でSystemRescue CDから起動し、ddしました。</p>
</li>
</ol>
<ol class="arabic" start="3">
<li>
<p class="first">ネットワーク設定</p>
<p>iSCSIブートしたWindows 7ではgpxeで設定したネットワーク設定がそのまま使われます。
ただし、デフォルトゲートウェイだけはどうやってもiSCSIターゲットのIPアドレスになって
しまいます。</p>
<p>Windows 7ではDNSサーバもIPv6アドレスを設定できるので、全部IPv6へ移行するのも手です(httpプロキシとか)。
IPv4でなんとかしたい場合は「デフォルトゲートウェイ削除→デフォルトゲートウェイ再設定」するバッチファイルを
作る必要があります。</p>
<p>もっとも、録画専用機なのでインターネットに繋がっていなくても問題はなくどちらの対策もまだ行なっていません…。</p>
</li>
</ol>
<p>一旦、iSCSIブートできるようになるとあとは <tt class="docutils literal">zfs snapshot</tt> が使えるようになるのでこれまでの苦行も報われるというものです。</p>
</div><div class="section" id="id3">
<h3>結論</h3>
<p>WindowsをiSCSIブートさせるなら:</p>
<ul class="simple">
<li>素直にDHCPサーバを立てる</li>
<li>IntelのNICを買ってiSCSIブートできるROMを焼く</li>
</ul>
<p>LinuxならgPXEで何の問題もありません。Windowsは疲れます。</p>
</div>
2011-09-07T09:48:19+09:00
-
Dual GbEの付いたMini-ITXな MINIX H61M-USB に OpenBSD 4.9 を入れてPCルータを作った
https://projects.tsuntsun.net/~nabeken/diary/OpenBSD/h61m-usb3-and-openbsd49.html
<h2>UPDATE:</h2><ul>
<li>セクション番号修正、PPPoE failoverの部分を移動、その他微修正 (Wed, 7 Sep 2011 09:32:35 +0900)</li>
<li>初稿 (Tue, 6 Sep 2011 20:24:38 +0900)</li>
</ul>
<div class="section" id="id2">
<h3>ことのはじまり</h3>
<p>2011年7月29日(金)の午前2時ごろ、当ネットワークのサーバ側セグメントのPCルータが
ハードウェア障害を起こし、全サービスが停止しました。
(実際にはメール、DNS、LDAPは海外のVPSでセカンダリを動かしていたので全滅ではなかった)</p>
<p>予め取得していたUSBメモリのディスクイメージを新規USBメモリに流し込み、
手元の余っていたノートパソコンへ刺して代替機として発送、交換し復旧しました。</p>
<p>使用していたハードウェアは私が始めて組んだマシンで、ちょうど10年経過したところです。
よく働いてくれました。</p>
<p>該当箇所は冗長化しておらず、ハードウェア交換と冗長化が急務でした。
また、現在はIX2015でPPPoEを喋っていますがIX2015で今後も運用するのは厳しいと判断したため、
このリプレイスも必要でした。</p>
<p>さて、IPv4とIPv6に対応した冗長化が必要です。keepalivedの独自対応したVRRPかOpenBSD由来のCARPか…</p>
<p>独自対応がどうも気持ちが悪いのでOpenBSD + CARPで冗長化することにしました。
(FreeBSDにしなかったのはOpenBSDつかってみたかったから)</p>
<p>問題はハードウェアの選定です。</p>
<ul class="simple">
<li>安い</li>
<li>小さいほうがいい</li>
<li>オンボードでNICが2つ(以上)欲しい</li>
</ul>
<p>ありました。</p>
</div><div class="section" id="minixh61m-usb3">
<h3>MINIXのH61M-USB3</h3>
<p>アキバを巡回していたらMini-ITXでNICが2つ載っているマザーを2つ見つけました。</p>
<ul class="simple">
<li>
<a class="reference external" href="http://www.jwele.com/motherboard_detail.php?949">MINIX 890GX-USB3</a> (AMD)</li>
<li>
<a class="reference external" href="http://www.jwele.com/motherboard_detail.php?1035">MINIX H61M-USB3</a> (Intel)</li>
</ul>
<p>どちらも同じJ&W製のマザーでした(今後要チェックです)。
IntelとAMDを選ぶことになります。今回はIntel(H61M-USB3)を選びました。</p>
<dl class="docutils">
<dt>CPU</dt>
<dd>Pentium G620T</dd>
<dt>Mem</dt>
<dd>DDR3 1033 2GB x1</dd>
<dt>HDD</dt>
<dd>USBメモリ 4GB x1</dd>
<dt>Pow</dt>
<dd>ありあわせ</dd>
<dt>NIC</dt>
<dd>追加でPCIeなIntel NICを1枚刺しました</dd>
</dl>
<p>USBメモリにOpenBSDを入れて構築することにします。</p>
</div><div class="section" id="h61m-usb3openbsd-4-9-amd64">
<h3>H61M-USB3にOpenBSD 4.9 (amd64)をインストール</h3>
<p>CDROMはないのでPXEブートでインストールしました。
IX2015でPXEブートの設定を入れてみました。</p>
<pre class="literal-block">
config# ip dhcp profile XXXX
config-dhcp-XXXX# next-server 10.X.X.X (tftpサーバのIPアドレス)
config-dhcp-XXXX# bootfile pxeboot (OpenBSDの配布物のpxeboot)
</pre>
<p>インストール後(かつ、カーネル再構築後)の <tt class="docutils literal">dmesg</tt> は以下。</p>
<pre class="literal-block">
OpenBSD 4.9 (GENERIC.MP) #2: Thu Sep 1 22:43:51 JST 2011
root@gw-openbsd.osaka.tknetworks.org:/usr/src/gw-openbsd/sys/arch/amd64/compile/GENERIC.MP
real mem = 2082504704 (1986MB)
avail mem = 2013044736 (1919MB)
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.7 @ 0xe92d0 (104 entries)
bios0: vendor American Megatrends Inc. version "4.6.4" date 04/27/2011
bios0: MINIX MINIX H61-USB3
acpi0 at bios0: rev 2
acpi0: sleep states S0 S3 S4 S5
acpi0: tables DSDT FACP APIC SSDT MCFG HPET ASPT
acpi0: wakeup devices PS2K(S3) PS2M(S3) BR20(S3) EUSB(S4) USBE(S4) PEX0(S4) PEX1(S4) PEX2(S4) PEX3(S4) PEX4(S4) PEX5(S4) PEX6(S4) PEX7(S4) GBE_(S4) P0P1(S4) P0P2(S4) P0P3(S4) P0P4(S4) SLPB(S0) PWRB(S3)
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Intel(R) Pentium(R) CPU G620T @ 2.20GHz, 2195.32 MHz
cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,SBF,SSE3,PCLMUL,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,POPCNT,XSAVE,NXE,LONG
cpu0: 256KB 64b/line 8-way L2 cache
cpu0: apic clock running at 99MHz
cpu1 at mainbus0: apid 2 (application processor)
cpu1: Intel(R) Pentium(R) CPU G620T @ 2.20GHz, 2195.02 MHz
cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,SBF,SSE3,PCLMUL,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,POPCNT,XSAVE,NXE,LONG
cpu1: 256KB 64b/line 8-way L2 cache
ioapic0 at mainbus0: apid 0 pa 0xfec00000, version 20, 24 pins
acpimcfg0 at acpi0 addr 0xe0000000, bus 0-255
acpihpet0 at acpi0: 14318179 Hz
acpiprt0 at acpi0: bus 0 (PCI0)
acpiprt1 at acpi0: bus -1 (BR20)
acpiprt2 at acpi0: bus 2 (PEX0)
acpiprt3 at acpi0: bus 3 (PEX1)
acpiprt4 at acpi0: bus 4 (PEX2)
acpiprt5 at acpi0: bus -1 (PEX3)
acpiprt6 at acpi0: bus 5 (PEX4)
acpiprt7 at acpi0: bus -1 (PEX5)
acpiprt8 at acpi0: bus -1 (PEX6)
acpiprt9 at acpi0: bus -1 (PEX7)
acpiprt10 at acpi0: bus 1 (P0P1)
acpiprt11 at acpi0: bus -1 (P0P2)
acpiprt12 at acpi0: bus -1 (P0P3)
acpiprt13 at acpi0: bus -1 (P0P4)
acpicpu0 at acpi0: C3, C3, C1, PSS
acpicpu1 at acpi0: C3, C3, C1, PSS
acpibtn0 at acpi0: SLPB
acpibtn1 at acpi0: PWRB
cpu0: unknown i686 model 0x2a, can't get bus clock
cpu0: Enhanced SpeedStep 2195 MHz: speeds: 2200, 2100, 2000, 1900, 1800, 1700, 1600 MHz
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 vendor "Intel", unknown product 0x0100 rev 0x09
ppb0 at pci0 dev 1 function 0 vendor "Intel", unknown product 0x0101 rev 0x09: apic 0 int 16 (irq 11)
pci1 at ppb0 bus 1
em0 at pci1 dev 0 function 0 "Intel PRO/1000 MT (82574L)" rev 0x00: apic 0 int 16 (irq 11), address 00:XX:XX:XX:XX:XX
vga1 at pci0 dev 2 function 0 vendor "Intel", unknown product 0x0102 rev 0x09
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
intagp at vga1 not configured
vendor "Intel", unknown product 0x1c3a (class communications subclass miscellaneous, rev 0x04) at pci0 dev 22 function 0 not configured
ehci0 at pci0 dev 26 function 0 vendor "Intel", unknown product 0x1c2d rev 0x05: apic 0 int 16 (irq 11)
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 "Intel EHCI root hub" rev 2.00/1.00 addr 1
azalia0 at pci0 dev 27 function 0 vendor "Intel", unknown product 0x1c20 rev 0x05: apic 0 int 22 (irq 10)
azalia0: codecs: Realtek/0x0892, Intel/0x2805, using Realtek/0x0892
audio0 at azalia0
ppb1 at pci0 dev 28 function 0 vendor "Intel", unknown product 0x1c10 rev 0xb5: apic 0 int 17 (irq 5)
pci2 at ppb1 bus 2
ppb2 at pci0 dev 28 function 1 vendor "Intel", unknown product 0x1c12 rev 0xb5: apic 0 int 16 (irq 11)
pci3 at ppb2 bus 3
ppb3 at pci0 dev 28 function 2 vendor "Intel", unknown product 0x1c14 rev 0xb5: apic 0 int 18 (irq 3)
pci4 at ppb3 bus 4
bge0 at pci4 dev 0 function 0 "Broadcom BCM57788" rev 0x01, BCM57780 A1 (0x57780001): apic 0 int 18 (irq 3), address 00:e0:b6:XX:XX:XX
brgphy0 at bge0 phy 1: BCM57780 10/100/1000baseT PHY, rev. 1
ppb4 at pci0 dev 28 function 4 vendor "Intel", unknown product 0x1c18 rev 0xb5: apic 0 int 17 (irq 5)
pci5 at ppb4 bus 5
bge1 at pci5 dev 0 function 0 "Broadcom BCM57788" rev 0x01, BCM57780 A1 (0x57780001): apic 0 int 16 (irq 11), address 00:e0:b6:XX:XX:XX
brgphy1 at bge1 phy 1: BCM57780 10/100/1000baseT PHY, rev. 1
ehci1 at pci0 dev 29 function 0 vendor "Intel", unknown product 0x1c26 rev 0x05: apic 0 int 23 (irq 7)
usb1 at ehci1: USB revision 2.0
uhub1 at usb1 "Intel EHCI root hub" rev 2.00/1.00 addr 1
pcib0 at pci0 dev 31 function 0 vendor "Intel", unknown product 0x1c5c rev 0x05
vendor "Intel", unknown product 0x1c22 (class serial bus subclass SMBus, rev 0x05) at pci0 dev 31 function 3 not configured
isa0 at pcib0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
pckbc0 at isa0 port 0x60/5
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
lpt0 at isa0 port 0x378/4 irq 7
fdc0 at isa0 port 0x3f0/6 irq 6 drq 2
mtrr: Pentium Pro MTRR support
uhub2 at uhub0 port 1 "Intel product 0x0024" rev 2.00/0.00 addr 2
uplcom0 at uhub2 port 4 "Prolific Technology Inc. USB-Serial Controller" rev 1.10/3.00 addr 3
ucom0 at uplcom0
uhub3 at uhub1 port 1 "Intel product 0x0024" rev 2.00/0.00 addr 2
umass0 at uhub3 port 3 configuration 1 interface 0 "ADATA ADATA USB Flash Drive" rev 2.00/1.00 addr 3
umass0: using SCSI over Bulk-Only
scsibus0 at umass0: 2 targets, initiator 0
sd0 at scsibus0 targ 1 lun 0: <ADATA, USB Flash Drive, 0.00> SCSI2 0/direct removable
sd0: 7509MB, 512 bytes/sec, 15378432 sec total
vscsi0 at root
scsibus1 at vscsi0: 256 targets
softraid0 at root
root on sd0a swap on sd0b dump on sd0b
carp: carp0 demoted group carp by 1 to 129 (carpdev)
carp: carp1 demoted group carp by 1 to 130 (carpdev)
pppoe (data): input for unknown session 0x54b, sending PADT
carp: carp1 demoted group carp by -1 to 129 (carpdev)
carp: carp0 demoted group carp by -1 to 128 (carpdev)
carp1: state transition: BACKUP -> MASTER
pppoe0: received unexpected PADO
pppoe0: received unexpected PADO
pppoe0: received unexpected PADO
pppoe0: received unexpected PADO
pppoe0: received unexpected PADO
pppoe0: received unexpected PADO
pppoe0: received unexpected PADO
carp0: state transition: BACKUP -> MASTER
</pre>
<div class="section" id="id3">
<h4>問題点</h4>
<ul class="simple">
<li>USBメモリへのディスクアクセスが遅い (USBメモリの問題かどうかは不明)</li>
<li>birdでうまく経路が扱えない (OpenBSD対応時の問題な気がする)</li>
</ul>
</div>
</div><div class="section" id="id4">
<h3>ネットワーク構成</h3>
<p>3つのネットワークのルータにします(VLANでもいい気もしますが…)。</p>
<p>まずは冗長構成がない場合の論理構成:</p>
<pre class="literal-block">
--------------
The Internet
--------------
|
| (pppoe0 on bge0) | |
| | |
+-----+ | |
| gw0 |-----[em0]-------| +-------+ |
+-----+ |--------| rt57i |--------| クライアント
| | +-------+ |
| (bge1) | |
|
-------------
サーバ
</pre>
<p>gw0とgw1で冗長構成にします。</p>
<dl class="docutils">
<dt>carp0 (192.168.0.10/24, 2001:db8:a::10/64)</dt>
<dd><ul class="first last simple">
<li>サーバ側セグメントのグループ。</li>
<li>gw0: 192.168.0.1/24, 2001:db8:a::1/64</li>
<li>gw1: 192.168.0.2/24, 2001:db8:a::2/64</li>
</ul></dd>
<dt>carp1 (192.168.5.10/24, 2001:db8:b::10/64)</dt>
<dd><ul class="first last simple">
<li>サーバ以外のセグメントを収容するグループ。</li>
<li>gw0: 192.168.5.1/24, 2001:db8:b::1/64</li>
<li>gw1: 192.168.5.2/24, 2001:db8:b::2/64</li>
</ul></dd>
</dl>
<pre class="literal-block">
-------------------------------------------
The Internet
------+--------------------------+---------
| |
| |
| |
+--+--+ +--+--+ |
| gw0 | | gw1 +-----------+ |
+--+-++ +--+--+ | +-------+ |
| | (carp1) | |--------| rt57i |------| クライアント
| +------------------------|--------------+ +-------+ |
| | |
| (carp0) |
------+--------------------------+---------
サーバ
</pre>
<p>2011/09現在、gw1の手配が間にあっていないため実際はgw0だけの構成になっています。</p>
</div><div class="section" id="id5">
<h3>目標</h3>
<ol class="arabic">
<li>
<p class="first">carp[01]の何れかでfailoverが発生するとBACKUPへ切り替える</p>
<p>障害が起きたcarpだけ切り替わっても意味がないため。</p>
</li>
<li>
<p class="first">failover時はPPPoEもfailoverする</p>
<p>failoverを検知してPPPoEのコネクションを張りなおす。</p>
</li>
<li>
<p class="first">failover時はその他雑多なdaemonも切り替える</p>
<p>OpenVPN, Quagga, miredo, birdなど。</p>
</li>
</ol>
<p>冗長構成はまだできていないので、これは次回の宿題。</p>
</div><div class="section" id="carp">
<h3>CARPの設定</h3>
<p>まずは <a class="reference external" href="http://www.openbsd.org/cgi-bin/man.cgi?query=hostname.if&sektion=5&arch=i386&apropos=0&manpath=OpenBSD+Current">hostname.if(5)</a> を設定しまくります。</p>
<pre class="literal-block">
gw0# cat /etc/hostname.bge0
up
gw0# cat /etc/hostname.bge1
inet 192.168.0.1 255.255.255.0
inet6 2001:db8:a::1 64
gw0# cat /etc/hostname.carp0
advbase 1 advskew 0 vhid 1 carpdev bge1 pass secret
inet 192.168.0.10 255.255.255.0
inet6 2001:db8:a::10 64
gw0# cat /etc/hostname.em0
inet 192.168.5.1 255.255.255.0
inet6 2001:db8:b::1 64
gw0# cat /etc/hostname.carp1
advbase 1 advskew 0 vhid 2 carpdev em0 pass secret
inet 192.168.5.10 255.255.255.0
inet6 2001:db8:b::10 64
gw1# cat /etc/hostname.bge0
up
gw1# cat /etc/hostname.bge1
inet 192.168.0.2 255.255.255.0
inet6 2001:db8:a::2 64
gw1# cat /etc/hostname.carp0
advbase 1 advskew 100 vhid 1 carpdev bge1 pass secret
inet 192.168.0.10 255.255.255.0
inet6 2001:db8:a::10 64
gw1# cat /etc/hostname.em0
inet 192.168.5.2 255.255.255.0
inet6 2001:db8:b::2 64
gw1# cat /etc/hostname.carp1
advbase 1 advskew 100 vhid 2 carpdev em0 pass secret
inet 192.168.5.10 255.255.255.0
inet6 2001:db8:b::10 64
</pre>
<p>gw0, gw1で/etc/sysctl.confを設定します。
一部値は <a class="reference external" href="https://calomel.org/network_performance.html">Network Tuning and Performance Guide (OpenBSD)</a> を参考にしました。</p>
<pre class="literal-block">
net.inet.ip.forwarding=1
net.inet.ip.mforwarding=1
net.inet.gre.allow=1
net.inet6.ip6.forwarding=1
net.inet6.ip6.mforwarding=1
net.inet6.ip6.accept_rtadv=0
net.inet.carp.preempt=1
net.inet.carp.log=3
net.inet.ip.ifq.maxlen=1024
kern.bufcachepercent=90
</pre>
</div><div class="section" id="ppp-8-pppoe-8">
<h3>ppp(8) + pppoe(8)で低速病</h3>
<p>ユーザランドのppp + pppoe構成だと速度が50Mbps〜を越えると割り込み、
コンテキストスイッチが爆発し通信が詰まっていることが判明しました。</p>
<p>pppoe(8)で 40Mbps〜70Mbps 時のvmstat:</p>
<pre class="literal-block">
procs memory page disk traps cpu
r b w avm fre flt re pi po fr sr sd0 int sys cs us sy id
0 0 0 265248 1334864 74 0 0 0 0 0 0 46 668 113 0 0 100
0 0 0 265248 1334864 77 0 0 0 0 0 0 43 655 118 0 0 100
0 0 0 265248 1334864 405 0 0 0 0 0 0 46 760 112 0 0 100
0 0 0 265248 1334864 74 0 0 0 0 0 0 3141 50811 11431 1 10 89
0 0 0 265248 1334864 74 0 0 0 0 0 0 8091 132264 29514 4 21 75
0 0 0 265252 1334860 74 0 0 0 0 0 0 6750 102647 24246 2 18 80
2 0 0 265252 1334860 82 0 0 0 0 0 0 7168 109002 25727 3 21 76
0 0 0 265252 1334860 403 0 0 0 0 0 0 5331 81630 18822 2 11 87
0 0 0 265252 1334860 74 0 0 0 0 0 0 45 667 110 0 0 100
0 0 0 265252 1334860 73 0 0 0 0 0 0 39 629 111 0 0 100
</pre>
<p>次項のパッチ当て、再構築した時のpppoe(4)で 40Mbps〜 時のvmstat:</p>
<pre class="literal-block">
procs memory page disk traps cpu
r b w avm fre flt re pi po fr sr sd0 int sys cs us sy id
1 0 0 14012 1908544 7 0 0 0 0 0 0 4568 51 18 0 5 95
0 0 0 14012 1908544 14 0 0 0 0 0 0 3041 49 17 0 1 99
0 0 0 14012 1908544 11 0 0 0 0 0 0 3816 55 20 0 1 99
0 0 0 14012 1908544 7 0 0 0 0 0 0 3354 35 15 0 1 99
0 0 0 14012 1908544 7 0 0 0 0 0 0 4541 35 16 0 3 97
0 0 0 14012 1908544 7 0 0 0 0 0 0 7326 60 20 0 4 96
0 0 0 14012 1908544 7 0 0 0 0 0 0 7161 43 20 0 6 94
0 0 0 14012 1908544 11 0 0 0 0 0 0 6642 47 20 0 3 97
</pre>
<p>pppoe(8)で見られた数値はまったく見られず、
高負荷状態ではカーネルモードPPPoEが安定していることがわかります。</p>
</div><div class="section" id="pppoe-4">
<h3>pppoe(4)を設定する</h3>
<p>OpenBSD 4.9のpppoe(4)には問題(<a class="reference external" href="http://old.nabble.com/%22splassert%3A-assertwaitok%3A-want--1-have-1%22-td31672632.html">"splassert: assertwaitok: want -1 have 1"</a>)が報告されています。
すでに -current もしくは 5.0 では修正されています。
今回は <a class="reference external" href="http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/if_spppsubr.c.diff?r1=1.87;r2=1.84">パッチ</a> を 4.9 へバックポートしてカーネルを再構築しました。
ついでにconfigに <tt class="docutils literal">option PPPOE_TERM_UNKNOWN_SESSIONS</tt> を追加しました。</p>
<pre class="literal-block">
# cd /usr/src
# wget http://ftp.iij.ad.jp/pub/OpenBSD/4.9/sys.tar.gz
# tar zxvf sys.tar.gz
# wget 'http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/if_spppsubr.c.diff?r1=1.87;r2=1.84' -O if_spppsubr.patch
# patch -p1 < if_spppsubr.patch
# cd sys/arch/amd64/conf
# config GENERIC.MP
# cd ../compile/GENERIC.MP
# make clean && make depend && make
# make install
</pre>
<p>設定は <tt class="docutils literal">/etc/hostname.pppoe0</tt> で行ないます。</p>
<pre class="literal-block">
# cat /etc/hostname.pppoe0
inet 0.0.0.0 255.255.255.255 NONE pppoedev bge0 authproto chap authname 'user' authkey 'secret' up
dest 0.0.0.1
!/sbin/route add default -ifp pppoe0 0.0.0.1
</pre>
<p>destがないと動きません。</p>
<pre class="literal-block">
# sh /etc/netstart pppoe0
</pre>
</div><div class="section" id="pf">
<h3>pf</h3>
<p><a class="reference external" href="http://nostarch.com/pf2.htm">PF本(第2版)</a> をOpenBSDプロジェクトへの寄付も兼ねて電子書籍版を購入しました。
4.9のpfはデフォルトでkeep stateなため注意が必要です。</p>
<p>systat(1)でI/Fの様子が見れるのはうれしい。</p>
<pre class="literal-block">
# systat -w 1 ifstat 1
# systat -w 1 state 1
</pre>
</div><div class="section" id="openvpn">
<h3>OpenVPN</h3>
<p>参考文献:</p>
<ul class="simple">
<li><a class="reference external" href="http://openvpn.net/archive/openvpn-users/2006-05/msg00353.html">[Openvpn-users] openbsd openvpn bridge only arp and broadcast</a></li>
<li><a class="reference external" href="http://www.chrisk.de/blog/2010/03/how-to-openvpn-on-openbsd-as-layer2-vpn/">How to OpenVPN on OpenBSD as Layer2 VPN</a></li>
</ul>
<p>packagesからインストールします。</p>
<p>Linuxでいうtapデバイスを使うにはtun(4)を作成する際に <tt class="docutils literal">link0</tt> フラグを渡す必要があります。
<tt class="docutils literal">link0</tt> フラグを渡すとそれまでの設定を失なうので注意。</p>
<pre class="literal-block">
# ifconfig tun0 create
# ifconfig tun0 link0
</pre>
<p>OpenVPNの設定ファイルでは <tt class="docutils literal"><span class="pre">dev-type</span> tap</tt> にして <tt class="docutils literal">dev tun0</tt> にすると自動で <tt class="docutils literal">link0</tt> をフラグを立ててくれます。
場合によっては立ててくれないので自分で立てる必要があります。</p>
<p>OpenVPNは <tt class="docutils literal">hostname.if</tt> 経由で起動させると便利です。</p>
<pre class="literal-block">
# cat /etc/hostname.tun1
up link0
!/usr/local/sbin/openvpn --config /etc/openvpn/openvpn.conf --daemon
inet6 fe80::1 64
inet6 2001:db8::1 64
</pre>
<p>デフォルトでは <tt class="docutils literal"><span class="pre">/dev/tun[0-4]</span></tt> までしかありません。
<tt class="docutils literal">tun100</tt> が欲しければ作成する必要があります。</p>
<pre class="literal-block">
# cd /dev
# ./MAKEDEV tun100
</pre>
</div><div class="section" id="usb">
<h3>USBシリアルコンソール</h3>
<p>USBシリアル変換を経由したシリアルコンソールを用意しました。
私の環境ではbmobileが提供するイオンSIMを経由したメンテナンス回線を用意し、
リモートメンテナンスができるようにしています。
月額980円で3G経由のメンテナンス回線を用意できるのは魅力的です。</p>
<p>(正確にはbmobile経由でさくらのVPS上に構築したOpenVPNに接続しIPv6ネットワークに参加しています)</p>
<p>シリアルコンソールは <tt class="docutils literal">/etc/ttys</tt> (<a class="reference external" href="http://www.openbsd.org/cgi-bin/man.cgi?query=ttys&apropos=0&sektion=5&manpath=OpenBSD+Current&arch=i386&format=html">ttys(5)</a>)で設定します。</p>
<pre class="literal-block">
ttyU0 "/usr/libexec/getty std.9600" vt220 on secure
</pre>
<p>設定後、 <a class="reference external" href="http://www.openbsd.org/cgi-bin/man.cgi?query=init&apropos=0&sektion=8&manpath=OpenBSD+Current&arch=i386&format=html">init(8)</a> をリスタートさせます。</p>
<pre class="literal-block">
# kill -HUP 1
</pre>
<p>別のマシンから <a class="reference external" href="http://www.openbsd.org/cgi-bin/man.cgi?query=cu&apropos=0&sektion=1&manpath=OpenBSD+Current&arch=i386&format=html">cu(1)</a> を使って接続できることを確認します。</p>
<pre class="literal-block">
# cu -l cuaU0
</pre>
</div><div class="section" id="pppoe-openbsd">
<h3>おまけ: PPPoEの試験環境を OpenBSD で作成する</h3>
</div><div class="section" id="pppoe-failover">
<h3>PPPoE failover</h3>
<p>このPPPoE failoverは <em>ユーザランドでの検証</em> です。カーネルモードでは未検証ですが、ユーザランドでは動いていたので
載せておきます(せっかくなので)。</p>
<p>ppp.confの設定が重要。PPPoEではモデムのキャリアセンスが使えないため <tt class="docutils literal">enable lqr</tt> と <tt class="docutils literal">set lqrperiod 5</tt> が必須。
これがないとlink downが検知できずに自動再接続機能が働きません。
詳細は PPPoE Client を参照。</p>
<p><tt class="docutils literal">/etc/ifstated.conf</tt></p>
<pre class="literal-block">
# cat /etc/ifstated.conf
# $OpenBSD: ifstated.conf,v 1.6 2005/02/07 06:08:10 david Exp $
# This is a sample config for a pair of firewalls with two interfaces
#
# carp0 and carp1 have ip addresses on 192.168.3.0/24 and 192.168.6.0/24
# respectively.
# net.inet.carp.preempt must be enabled (set to 1) for this to work correctly.
# Uncomment one of the following lines to force primary/backup status.
# init-state primary
# init-state backup
carp_up = "carp0.link.up && carp1.link.up"
carp_down = "!carp0.link.up && !carp1.link.up"
#carp_sync = "carp0.link.up && carp1.link.up || \
# !carp0.link.up && !carp1.link.up"
state auto {
if $carp_up
set-state primary
if $carp_down
set-state backup
}
state primary {
init {
# PPPoE
# bird
# quagga
# miredo
run "[ -S /var/run/pppoe ] || /usr/sbin/ppp -nat -ddial pppoe"
}
if $carp_down
set-state backup
}
state backup {
init {
# PPPoE
# bird
# quagga
# miredo
run "[ -S /var/run/pppoe ] && /usr/sbin/pppctl -p '' /var/run/pppoe bye all"
}
if $carp_up
set-state primary
}
</pre>
<div class="section" id="pppoe-server">
<h4>PPPoE Server</h4>
<p>PPPoE Serverは <a class="reference external" href="http://www.openbsd.org/cgi-bin/man.cgi?query=ppp&sektion=8&arch=&apropos=0&manpath=OpenBSD+Current">ppp(8)</a> + <a class="reference external" href="http://www.openbsd.org/cgi-bin/man.cgi?query=pppoe&sektion=8">pppoe(8)</a> で作成できます。</p>
<p>まず、 <tt class="docutils literal">/etc/ppp/ppp.conf</tt> を設定します。デフォルトの <tt class="docutils literal">/etc/ppp/ppp.conf.sample</tt> をコピーします。
最下部の以下の <tt class="docutils literal">pppoe</tt> の設定があります。これを使用します。</p>
<dl class="docutils">
<dt>set device</dt>
<dd>-i はPPPoEで待ち受けるI/F名です。</dd>
<dt>set ifaddr</dt>
<dd>IPCPでpeerに配布するIPアドレス帯を設定します。
第1引数はPPPoEサーバ自身(local)のアドレス。第2引数はpeerに配布するIPアドレス帯を指定します。</dd>
<dt>enable ipv6cp</dt>
<dd>IPV6CPを使ってリンクローカルアドレスを設定させます。</dd>
<dt>enable chap</dt>
<dd>
<p class="first">CHAP認証を使用します。ユーザ名とパスワードは <tt class="docutils literal">/etc/ppp/ppp.secret</tt> に保存します。例:</p>
<pre class="last literal-block">
user password
</pre>
</dd>
</dl>
<pre class="literal-block">
# A PPPoE (PPP over Ethernet) setup may look like this:
#
pppoe:
set device "!/usr/sbin/pppoe -i pcn0"
set mtu max 1492
set mru max 1492
set speed sync
disable acfcomp protocomp
deny acfcomp
set ifaddr 192.168.1.1 192.168.1.10-192.168.1.20
enable ipv6cp
enable chap
</pre>
<p>設定ができたら起動します。 <tt class="docutils literal"><span class="pre">-p</span></tt> で名前に対応する <tt class="docutils literal">ppp.conf</tt> のプロファイル名を指定できます。</p>
<pre class="literal-block">
# pppoe -i pcn0 -p pppoe -s
</pre>
</div>
<div class="section" id="pppoe-client">
<h4>PPPoE Client</h4>
<p>PPPoE Client は <a class="reference external" href="http://www.openbsd.org/cgi-bin/man.cgi?query=ppp&sektion=8&arch=&apropos=0&manpath=OpenBSD+Current">ppp(8)</a> + <a class="reference external" href="http://www.openbsd.org/cgi-bin/man.cgi?query=pppoe&sektion=8">pppoe(8)</a> のユーザランドのものと <a class="reference external" href="http://www.openbsd.org/cgi-bin/man.cgi?query=pppoe&sektion=4&arch=&apropos=0&manpath=OpenBSD+Current">pppoe(4)</a> のカーネルモードの2つがあります。</p>
<p>OpenBSD 4.9 の <a class="reference external" href="http://www.openbsd.org/cgi-bin/man.cgi?query=pppoe&sektion=4&arch=&apropos=0&manpath=OpenBSD+Current">pppoe(4)</a> が腐っているため使用するにはパッチを当てる必要があります。</p>
<ul class="simple">
<li><a class="reference external" href="http://comments.gmane.org/gmane.os.openbsd.misc/185837">http://comments.gmane.org/gmane.os.openbsd.misc/185837</a></li>
</ul>
<p>今回はさっくり検証したかったため ppp(8) + pppoe(8) でPPPoE Clientを作成しました。
本番ではpppoe(4)を使っています。</p>
<p>まず、 <tt class="docutils literal">/etc/ppp/ppp.conf</tt> を設定します。デフォルトの <tt class="docutils literal">/etc/ppp/ppp.conf.sample</tt> をコピーします。
最下部に以下の <tt class="docutils literal">pppoe</tt> の設定があります。これを使用します。</p>
<p><tt class="docutils literal">set device</tt> の引数に pppoe(8) を渡します。これらもわかるように pppoe(8) はユーザが直接呼ぶものではありません。
<tt class="docutils literal"><span class="pre">-i</span></tt> へ与える引数は適宜調整してください。</p>
<p><tt class="docutils literal">set server</tt> は pppctl(8) で外部から制御するためのソケットファイルを指定します。</p>
<p><tt class="docutils literal">set authname</tt> と <tt class="docutils literal">set authkey</tt> はそれぞれユーザ名とパスワードです。</p>
<p><tt class="docutils literal">enable lqr</tt> と <tt class="docutils literal">set lqrperiod 5</tt> はキャリアセンスに頼らないlink-detection。PPPoEには必須。</p>
<p>defaultのプロファイルから <tt class="docutils literal">set device</tt>, <tt class="docutils literal">set speed</tt> を削除します。</p>
<pre class="literal-block">
# A PPPoE (PPP over Ethernet) setup may look like this:
#
pppoe:
set device "!/usr/sbin/pppoe -i bge0"
set mtu max 1492
set mru max 1492
set speed sync
set server /var/run/pppoe "" 0177
set authname "user"
set authkey "password"
set lqrperiod 5
set timeout 60
set reconnect 3 28000
set redial 3 28000
disable acfcomp protocomp
deny acfcomp
enable lqr
</pre>
<p>設定ができれば ppp(8) を呼びます。 <tt class="docutils literal"><span class="pre">-ddial</span> pppoe</tt> で <tt class="docutils literal">/etc/ppp/ppp.conf</tt> 内の pppoe プロファイルが呼び出されます。</p>
<pre class="literal-block">
# ppp -ddial pppoe
# ifconfig tun0
tun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1454
priority: 0
groups: tun
status: active
inet 192.168.1.14 --> 192.168.1.1 netmask 0xffffffff
inet6 fe80::2e0:b6ff:fe07:69e%tun0 -> prefixlen 64 scopeid 0x8
</pre>
<p>pppctl(8) を使って外から呼ぶ。</p>
<pre class="literal-block">
# pppctl -p '' /var/run/pppoe show iface
</pre>
<p>おまけおしまい。</p>
<p>次回はカーネルモードPPPoEのfailoverを含めた冗長構成に挑戦します。</p>
</div>
</div>
2011-09-07T09:32:35+09:00
-
Debian (squeeze) + KVM + libvirt + iSCSIへ移行した
https://projects.tsuntsun.net/~nabeken/diary/Sysadmin/libvirt-iscsi.html
<h2>UPDATE:</h2><ul>
<li>初稿 (Sun, 20 Mar 2011 19:56:08 +0900)</li>
</ul>
<div class="section" id="lvmsnapshot">
<h3>LVMのsnapshotを取るとカーネル・パニック!</h3>
<p>squeezeのXenカーネルでLVM snapshotを何度もcreate && destroyしていると以下のカーネルパニックが発生します。数回すると確実に再現できます。</p>
<pre class="literal-block">
[ 1500.617898] ------------[ cut here ]------------
[ 1500.617951] kernel BUG at /build/buildd-linux-2.6_2.6.32-30-amd64-d4MbNM/linux-2.6-2.6.32/debian/build/source_amd64_xen/arch/x86/xen/mmu.c:1649!
[ 1500.618021] invalid opcode: 0000 [#1] SMP
[ 1500.618144] last sysfs file: /sys/devices/virtual/bdi/253:4/uevent
[ 1500.618193] CPU 1
[ 1500.618267] Modules linked in: ext4 jbd2 crc16 reiserfs nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack xt_physdev iptable_filter ip_tables x_tables bridge stp xen_evtchn xenfs ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr dm_snapshot loop snd_hda_codec_realtek snd_hda_intel snd_hda_codec snd_hwdep snd_pcm snd_timer pl2303 snd i2c_nforce2 soundcore edac_core pcspkr usbserial k8temp snd_page_alloc edac_mce_amd i2c_core evdev parport_pc parport processor acpi_processor button ext3 jbd mbcache dm_mod raid1 raid0 md_mod crc32c iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi sd_mod crc_t10dif ata_generic usb_storage thermal sata_nv ohci_hcd floppy thermal_sys e1000e pata_amd forcedeth libata ehci_hcd scsi_mod usbcore nls_base [last unloaded: scsi_wait_scan]
[ 1500.620879] Pid: 11739, comm: dmsetup_env Tainted: G W 2.6.32-5-xen-amd64 #1
[ 1500.620939] RIP: e030:[<ffffffff8100c694>] [<ffffffff8100c694>] pin_pagetable_pfn+0x2d/0x36
[ 1500.621012] RSP: e02b:ffff8800b4cfbe08 EFLAGS: 00010282
[ 1500.621012] RAX: 00000000ffffffea RBX: 00000000000b2b13 RCX: 0000000000000001
[ 1500.621012] RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffff8800b4cfbe08
[ 1500.621012] RBP: ffff880002180380 R08: 0000000000000898 R09: ffffea0002716c28
[ 1500.621012] R10: 0000000000007ff0 R11: ffff880000000e98 R12: ffff8800b5a3e518
[ 1500.621012] R13: ffff8800b5d58958 R14: ffff8800025b3170 R15: ffff8800b5a3e518
[ 1500.621012] FS: 00007f3994bd3700(0000) GS:ffff880003b1f000(0000) knlGS:0000000000000000
[ 1500.621012] CS: e033 DS: 0000 ES: 0000 CR0: 000000008005003b
[ 1500.621012] CR2: 00007f39946fd876 CR3: 00000000158ab000 CR4: 0000000000000660
[ 1500.621012] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 1500.621012] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[ 1500.621012] Process dmsetup_env (pid: 11739, threadinfo ffff8800b4cfa000, task ffff8800025b3170)
[ 1500.621012] Stack:
[ 1500.621012] 0000000000000000 0000000000042336 ffffea0002716c28 00000000000b2b13
[ 1500.621012] <0> ffff880002180380 ffffffff810cd4e2 ffff8800b3103730 00007f39946fd876
[ 1500.621012] <0> 00000000b3103000 ffffffff810cb394 ffff8800b5d58958 00007f39946fd876
[ 1500.622220] Call Trace:
[ 1500.622331] [<ffffffff810cd4e2>] ? __pte_alloc+0x6b/0xc6
[ 1500.622331] [<ffffffff810cb394>] ? pmd_alloc+0x28/0x5b
[ 1500.622331] [<ffffffff810cd60b>] ? handle_mm_fault+0xce/0x80f
[ 1500.622331] [<ffffffff8130ceb5>] ? page_fault+0x25/0x30
[ 1500.622331] [<ffffffff8130d0ea>] ? error_exit+0x2a/0x60
[ 1500.622331] [<ffffffff8101251d>] ? retint_restore_args+0x5/0x6
[ 1500.622331] [<ffffffff8130f016>] ? do_page_fault+0x2e0/0x2fc
[ 1500.622331] [<ffffffff8130ceb5>] ? page_fault+0x25/0x30
[ 1500.622331] Code: ec 28 89 3c 24 48 89 f7 e8 a2 fd ff ff 48 89 e7 48 89 44 24 08 be 01 00 00 00 31 d2 41 ba f0 7f 00 00 e8 b0 cc ff ff 85 c0 74 04 <0f> 0b eb fe 48 83 c4 28 c3 55 49 89 ca 48 89 d5 40 88 f1 48 89
[ 1500.622331] RIP [<ffffffff8100c694>] pin_pagetable_pfn+0x2d/0x36
[ 1500.622331] RSP <ffff8800b4cfbe08>
[ 1500.622331] ---[ end trace a7919e7f17c0a727 ]---
</pre>
<p>domUのバックアップはlvm snapshotに頼っていたためこれは無視できません。DebianのBTSにも同種の報告がありました。</p>
<ul class="simple">
<li><a class="reference external" href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=617302">crash on lvconvert while moving mirrors between pvs</a></li>
</ul>
<p>カーネルに手を入れなければならないXen/dom0ならではの不具合です(最新ではmain lineにdom0がマージされていますが…)。
どのみち、XenのアプローチはKVMがメインになればなるほど不利になるのでこの機会に移行することにしました。</p>
<p>Xenともうひとつ、reiserfsも移行対象の1つでした。reiserfs + LVMの数年前まで鉄板でしたが、現在はext4がほぼ問題ない状況
なため全ファイルシステムをext4へ移行しました。</p>
<p>Xenで使っていたディスクはそのままKVMでは使えません。手で移行してやる必要があります。これは以前書いたのでそちらを参照してください。</p>
<ul class="simple">
<li><a class="reference external" href="https://projects.tsuntsun.net/~nabeken/diary/Sysadmin/Xen-and-KVM.html">Xen のディスクイメージを KVM で使用する</a></li>
</ul>
<p>移行の初期段階ではXenのディスク + KVM用の起動ディスク構成でした。
最終的にはホストマシンのディスクをすべて交換する必要があったため、一旦FreeBSD上のistgt (on zfs)上へすべて移行しました。
今回のメインのお話です。</p>
</div><div class="section" id="debian-libvirt">
<h3>まずはDebian + libvirt</h3>
<p>まずはKVM環境を揃えます。 Debian Wikiの <a class="reference external" href="http://wiki.debian.org/KVM">Kernel Based Virtual Machine (KVM)</a> を参考にパッケージをインストールします。</p>
<pre class="literal-block">
# apt-get install qemu-kvm libvirt-bin virtinst
</pre>
<p>これでKVM + libvirt (virsh) と virt-install を使えるようになります。Xenカーネルの場合は手動で通常カーネルへ切り替える必要があります。
<tt class="docutils literal">/etc/default/grub</tt> の <tt class="docutils literal">GRUB_DEFAULT</tt> 変数を再設定してください。</p>
<p>私の場合はこの環境は前回のiSCSI rootのままにしています。</p>
<p>あと、ネットワーク構成に応じてブリッジインターフェースを作成する必要があります。XenではXen側がこのあたり面倒を見てくれていました。
私はeth0の設定をそのままbr0として再設定しました。</p>
</div><div class="section" id="virshiscsi-pool">
<h3>virshでiSCSI poolを作成</h3>
<ul class="simple">
<li><a class="reference external" href="http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Virtualization/chap-Virtualization-Storage_Pools-Storage_Pools.html#sect-Virtualization-Storage_Pools-Creating-iSCSI">26.1.5. iSCSI-based storage pools</a></li>
</ul>
<p>virshでiSCSIなstorage poolを作ります。XMLで流し込む方法が主流ですが、コマンドでも可能です。今回はコマンドから作成します。
ドキュメントによっては引数の順番がおかしい場合があります(RHEL6のドキュメントとか…)。注意してください。コマンド例:</p>
<pre class="literal-block">
virsh# pool-define-as aoi-iscsi iscsi X.X.X.X - iqn.2010-12.org.example:libvirt - /dev/disk/by-path
第1引数はpool名、第2引数はstorage種別、第3引数はiscsi targetのIPアドレス、第4引数は未使用、第5引数はiqn名、第6引数は未使用、第7引数はホスト側のmount point
</pre>
<p>このコマンドを実行すると裏でiscsiadmが動き、/dev/disk/by-path以下にiSCSIデバイスが見えるようになります。
iSCSI target側でLUNを設定している場合はlibvirt側ではvolumeとして認識されています。</p>
<pre class="literal-block">
virsh# vol-list aoi-iscsi
Name Path
-----------------------------------------
8.0.0.0 /dev/disk/by-path/ip-X.X.X.X:3260-iscsi-iqn.2010-12.org.example:libvirt-lun-0
8.0.0.1 /dev/disk/by-path/ip-X.X.X.X:3260-iscsi-iqn.2010-12.org.example:libvirt-lun-1
8.0.0.2 /dev/disk/by-path/ip-X.X.X.X:3260-iscsi-iqn.2010-12.org.example:libvirt-lun-2
8.0.0.3 /dev/disk/by-path/ip-X.X.X.X:3260-iscsi-iqn.2010-12.org.example:libvirt-lun-3
8.0.0.4 /dev/disk/by-path/ip-X.X.X.X:3260-iscsi-iqn.2010-12.org.example:libvirt-lun-4
</pre>
<p>この出力からわかるように、libvirtのiSCSIなストレージプールは単にiscsiadmのラッパとして見えます(virsh的な名前と対応するデバイス名を持っているだけ)。
このままでは再起動時にpoolが自動で構成されません。pool-autstartコマンドで自動起動するようにしておきます。</p>
<pre class="literal-block">
virsh# pool-autostart aoi-iscsi
virsh# pool-list
Name State Autostart
-----------------------------------------
aoi-iscsi active yes
</pre>
</div><div class="section" id="xen">
<h3>Xenのディスクからコピー</h3>
<p>こまで来れば/dev/disk/by-path以下に通常のブロックデバイスとしてiSCSIが見えています。
<tt class="docutils literal">fdisk</tt> や <tt class="docutils literal">cfdisk</tt> でパーティションを切ります。</p>
<pre class="literal-block">
# cfdisk /dev/disk/by-path/ip-X.X.X.X:3260-iscsi-iqn.2010-12.org.example:libvirt-lun-0
</pre>
<p>切り終えたらホスト側でXenのものと今作成したパーティションをフォーマット、mountして <tt class="docutils literal">rsync</tt> などを使ってファイルをコピーします。
iSCSI側のパーティションは <tt class="docutils literal"><span class="pre">/dev/disk/by-path/ip-X.X.X.X:3260-iscsi-iqn.2010-12.org.example:libvirt-lun-0-partX</span></tt> として見えます。</p>
</div><div class="section" id="vm">
<h3>VMの作成</h3>
<p>VMの作成は <tt class="docutils literal"><span class="pre">virt-install</span></tt> コマンドが便利です。複数台の場合は最初の1台をこのコマンドで作り、あとはXMLをコピーして修正するほうが早いと思います。
<tt class="docutils literal"><span class="pre">virt-install</span></tt> の使い方は <a class="reference external" href="http://d.hatena.ne.jp/ymotongpoo/20100806/1281084634">10分で始めるKVM</a> が参考になります(virsh, libvirt使い必読)。iSCSIなストレージを使うポイントは <tt class="docutils literal"><span class="pre">--disk</span></tt> への引数です。</p>
<p><a class="reference external" href="http://berrange.com/tags/virt-install/">Provisioning KVM virtual machines on iSCSI the hard way (Part 2 of 2)</a> が参考になります。つまり、 <tt class="docutils literal"><span class="pre">--disk</span> <span class="pre">vol=pool-name/vol-name</span></tt> と指定します。
今回の例だと <tt class="docutils literal"><span class="pre">--disk</span> <span class="pre">vol=aoi-iscsi/8.0.0.0</span></tt> のようになるでしょう。</p>
<p>iSCSI側へ予めコピーが完了したとします。 <tt class="docutils literal"><span class="pre">virt-install</span></tt> コマンドでVMを作成し、grubインストール用に <a class="reference external" href="http://www.sysresccd.org/Main_Page">SystemRescueCd</a> で起動します。</p>
<pre class="literal-block">
$ virt-install --name base-gentoo --connect qemu:///system --ram=512 --vcpus=2 --os-variant=virtio26 --hvm --virt-type=kvm --vnc \
--cdrom /home/nabeken/tmp/systemrescuecd-x86-2.0.1.iso --network bridge=br0 --arch=x86_64 --disk vol=aoi-iscsi/8.0.0.5
</pre>
<p>VNC経由で接続すると SystemRescueCd の画面が見えるはずです。 <tt class="docutils literal">/dev/vda</tt> として先程XenのディスクからコピーしたiSCSI領域が見えているはずです。</p>
<p>通常の <tt class="docutils literal">grub</tt> では <tt class="docutils literal">/dev/vda</tt> を認識できないのでデバイスの対応を <tt class="docutils literal">/boot/grub/device.map</tt> へ記述します。
今回は <tt class="docutils literal">vda1</tt> が <tt class="docutils literal">/boot</tt> 、 <tt class="docutils literal">vda2</tt> が <tt class="docutils literal">/</tt> になります。</p>
<pre class="literal-block">
# cat /boot/grub/device.map
(fd0) /dev/fd0
(hd0) /dev/vda
</pre>
<p><tt class="docutils literal">grub</tt> をMBRへインストールします。</p>
<pre class="literal-block">
# grub --device-map=/boot/grub/device.map
grub# root (hd0,0)
grub# setup (hd0)
</pre>
<p>インストールできたら <tt class="docutils literal">menu.lst</tt> を編集します。</p>
<pre class="literal-block">
# mount /dev/vda1 /mnt/gentoo
# vi /mnt/gentoo/grub/menu.lst
</pre>
<p><tt class="docutils literal">root=</tt> を適切なルートパーティションに設定します。最後に <tt class="docutils literal">fstab</tt> を修正します。</p>
<pre class="literal-block">
# umount /mnt/gentoo
# mount /dev/vda2 /mnt/gentoo
# vi /mnt/gentoo/etc/fstab
# umount /mnt/gentoo
</pre>
<p>(他にもinittabを編集している場合も修正が必要です。hvc0をtty1へ修正します。)</p>
<p>SystemRescueCd での作業は以上です。シャットダウンします。virshで今回インストールしたVMが見えていることを確認します。</p>
<pre class="literal-block">
virsh# list --all
</pre>
<p>起動します。</p>
<pre class="literal-block">
virsh# start XXX
virsh# vncdisplay XXX
</pre>
<p>出てきたディスプレイ番号 + 5900 番ポートでVNCにアクセスできます。GRUBが立ち上がって起動することを確認してください。忘れないうちにautostartも仕込みます。</p>
<pre class="literal-block">
virsh# autostart XXX
</pre>
<p>お疲れ様でした。</p>
</div><div class="section" id="lun">
<h3>LUNを増やしたら</h3>
<p>iSCSI target側でLUNを追加してrestartしただけではiscsi initiatorには反映されません。libvirt側でrefreshが必要です。</p>
<pre class="literal-block">
virsh# pool-refresh aoi-iscsi
</pre>
<p>その後、 <tt class="docutils literal"><span class="pre">vol-list</span></tt> コマンドを実行すると新しいLUNが追加されているのが確認できます。</p>
</div><div class="section" id="id2">
<h3>最後に</h3>
<p>libvirt + virshのおかげで <tt class="docutils literal">kvm</tt> を直に触る必要がなくなり大変管理が楽になっています。virshはssh経由でも操作できます。</p>
<pre class="literal-block">
$ virsh -c qemu+ssh://hoge.example.com/sysytem
</pre>
<p>現在5台のVMがiSCSi上で動いています。やはり標準カーネルで動くのは安心できます。</p>
</div>
2011-03-20T19:56:08+09:00