2015/08/15

lxcのlxdeをvncする

前回はlxcで仮想ubuntuを立ち上げてみるところまでやってみた。IPアドレスもdnsmasqで名前解決できるようになった。
そこで思い立ったのが、ホストの環境を汚さずに、デスクトップ環境のためのコンテナを作って、そこへ外部からVNC接続してみようかなと。飽きたらポイっとまるごと捨てればいいし。

lxcクローン
$ lxc-clone master ubu01

なにか構築したいなって時にすぐ始められるように、予め必要最低限のことを終わらせてあるubuntuコンテナをmasterとして作っておいて、lxc-cloneする。

起動
$ lxc-start -n ubu01 -d

sshログイン
$ ssh ubuntu@ubu01

lxdeインストール
$ sudo apt-get install lxde

ubuntu-desktopじゃなくてlxde。メモリもディスクも少ないShuttleではlxdeの方が小さくてよい。
それでも500MB位は消費してしまうが。

vncserver インストール
$ sudo apt-get install vnc4server

他にも色々VNCサーバーはあるようだけれど、扱いが簡単なvnc4server。

~/.vnc/xstartup作成 (っていうか、デフォルトをリンクしておくだけ)
$ mkdir ~/.vnc
$ ln -s /etc/X11/Xsession ~/.vnc/xstartup

vncserver起動(vncserverでもvnc4serverでもいっしょ)
$ vncserver :0

最初の起動時には、xauthのパスワード設定を要求してきます。適当に設定。
vncが 5900 で待ち受け状態になりました。


ホストの5900ポートを ubu01:5900 へルーティングする
(ホスト側で)
$ sudo iptables -t nat -A PREROUTING -p tcp --dport 5900 -j DNAT --to ubu01:5900

ホストとコンテナ間でのプライベートネットワークへ外部からアクセスできるようにするのに
一番お手軽な方法。

そしたら、外からホストの5900へVNC接続するとubu01:5900へルーティングされて、
めでたくlxdeのデスクトップへ到達します。

日本語化!

忘れてました。いつも端末ばっかりだったので、GUIには日本語化ってのがありました。
そもそも lxc で作った ubuntuコンテナってロケールがen_US.UTF-8だし・・・そこからか。

日本語フォント インストール(IPA入れとけばいいっしょ)
$ sudo apt-get install fonts-ipafont

とりあえずフォントさえ入れれば、lxdeで日本語が表示されます。

日本語パッケージインストール
$ sudo apt-get install language-pack-ja

ロケール設定
$ sudo update-locale LANG=ja_JP.UTF-8

/etc/default/localeに書き込まれる。が、今のシェルの環境変数はen_US.UTF-8のままです。

インプットメソッド
$ sudo apt-get install ibus-anthy

mozcの方が評判いいらしいが、自分にはぴんとこなかった。
ibusじゃなくてfcitxか?とも思って入れてみたけど、??な感じ。ibus-anthyで十分っす。

タイムゾーン変更(日本語化というより日本時間でってだけだけど)
$ sudo dpkg-reconfigure tzdata

CUIメニュー操作でAsiaからTokyo選ぶ

ここまでやったら、一度コンテナを再起動したほうが良い。環境変数とか変わるんで。
(ホストでリブート)
$ lxc-stop -n ubu01 -r

そしたら改めてコンテナ上で vncserver を起動して、そとからVNC接続すると lxdeデスクトップ自体も日本語表示になって、IMもibusで動いている状態に。


後処理
$ sudo iptables -t nat -D PREROUTING 1

遊び終わったら、DNAT設定を消しておこう。
コンテナも終わらせるか、vncserverを $ vncserver -kill :0 しておこう。
油断していると外から潜り込まれちゃうのでね。


2015/08/14

lxcのdnsmasqでコンテナのIPアドレス管理

lxc楽しくて、調子に乗って何個も作るとコンテナのIPアドレスでアクセスするのが面倒になってくる。
コンテナ側で固定IP設定するのもいいけど、lxc-cloneして使う場合、外側で管理しないと辛い。

ということで、コンテナ内はデフォルトのDHCP設定のままで、ホスト側で制御したい。

一番本家っぽいところを読む・・・
https://help.ubuntu.com/lts/serverguide/lxc.html#lxc-network

やっぱり、ありますね。方法が。

/etc/default/lxc-net ファイルの以下の記述があるんで、コメント外す
LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf
LXC_DOMAIN="lxc" ←必要かなぁ。dnsmasqが使うかな。

/etc/lxc/dnsmasq.conf を作成して以下のように記述
dhcp-host=ubu01,10.0.3.11
dhcp-host=ubu02,10.0.3.12
dhcp-host=ubu03,10.0.3.13
もしくは
dhcp-hostsfile=/etc/lxc/dnsmasq-hosts.conf
と書いて、別ファイルにまとめることも出来るそうな。

$ sudo service lxc-net stop
$ sudo service lxc-net start
とかじゃなくてホスト再起動のほうがいいかも。

その後、コンテナを起動すると、指定アドレスになった。DHCP側で管理できるってことだね。
楽ちん。

ホスト側から名前でアクセスしたい

IP管理するんだったら全部 hosts ファイルに書くっていう手もあるが、それすら面倒くさい。
本家のドキュメントを読むと
server=/lxc/10.0.3.1 を /etc/dnsmasq.conf に書き加えろとか書いてあるんだけど、効果なし。
あちこちの記事でも書き加える場所とか説明がまちまちで、よくわからん。

DNS in Ubuntu + LXC が参考になりました。

/etc/resolvconf/resolv.conf.d/head とか /etc/network/interface当たりに
nameserver 10.0.3.1を加えればいいだけだった。

$ sudo resolveconf -u
更新して

$ ping ubu01
$ ping ubu01.lxc

が出来るようになった。これで、dhcp-hostでIP指定してなくても名前解決が出来るんで
更に楽ちん。


https://github.com/jeremiahsnapp/dev-lxc
これも面白そう。高度すぎ?

2015/08/13

lxcを入れてVM構築

LinuxContainers.org Infrastructure for container projects というLinuxカーネルのコンテナ技術を使って軽量VM環境を構築できるらしいものを最近知りました。

VMWare、Xen、KVM、もっと大きなのでは AWS とかが、VMの世界だと思っておりましたが、それら全部が openstack (cloud softwre) ファミリーだったのね。

ということで、軽量でメモリもディスクもあまり使わなそうな lxc でVMっぽいものをやってみた。
lxcの先には Docker とかいうものが控えているようだけれど、まずは基礎から。

lxcの勉強には LXCで学ぶコンテナ入門 を参考にさせてもらいました。

lxcインストール

$ sudo apt-get install lxc

すると
 /etc/lxc/ 設定
 /usr/share/lxc/ ディストーション設定やテンプレート
 /var/lib/lxc/ ルート権限のコンテナ格納場所
 /etc/init/lxc-**.conf 自動起動やらネットワーク設定やら
が作られて
 upstart-file-bridge
 upstart-socket-bridge
 upstart-udev-bridge
 cgmanager
 dnsmasq
がデーモンで動き始めました。

ifconfig すると、lxcbr0 っていうコンテナのネットワークをブリッジするインターフェースが追加されているのを確認。

root権限でコンテナ作って動かしてみる
$ sudo lxc-create -t ubuntu -n uc01

/var/lib/lxc/uc01にuc01という名前のubuntuが作られた。

起動!
$ sudo lxc-start -n uc01

動いた~。デフォルトのubuntuユーザでログインしてみた。ふむふむ。sshが出来る状態なのね。
えーと、コンソールから抜けるのは??? Ctrol+a qだそうな。やってみたけど抜けられぬ。。

停止(ホスト側で)
$ sudo lxc-stop -n uc01

コンソールから抜けられなかったので、外から殺しました。

デーモン起動して
$ sudo lxc-start -n uc01 -d

コンソール起動
$ sudo lxc-console -n uc01

おぉ? 今度は Ctrl+a q で抜けられた!まあいいか。次へ進む。
どうやらlxc-startをフォアグラウンドで起動した時のコンソールではダメで、lxc-consoleで起動したコンソールならば抜けられるようだ。

ネットワークタイプをmacvlanへ変更
デフォルトだと、仮想ネットワークが構築されて、それがホストに作られたブリッジインターフェース経由で外に出られるようになっていて、ホストから ssh 接続ができる状態。
これだと、外から uc01 へsshしたりは出来ない。

/var/lib/lxc/uc01/configを以下のように変更
 lxc.network.type = veth
 lxc.network.link = lxcbr0
 ↓
 lxc.network.type = macvlan
 lxc.network.link = em1 ← 普通はeth0とかになるところ。自分のShuttleではem1なのだ。

ホストの物理インターフェースに接続される。dhcpもいつものルータが担う。
ホストと同じように固定IP設定も普通にできる。

再起動
$ sudo lxc-stop -r -n uc01

確認
$ sudo lxc-ls -f
ふむ。IPアドレスが 192.168.1.31 とかになった。
コンテナから外に出れる。外部から コンテナ(uc01)へssh出来る。
ただし! ホストからはsshもpingも出来ない。
macvlanモード設定でコンテナ同士でのアクセスは出来るようになる。が、ホストはダメです。

コンテナ削除
$ sudo lxc-destroy -n uc01

なくなりました。
ここまでは全然何の問題もないっすね。あっけない。けど、裏ではものすごい技術の集合体です。

----

ユーザ権限でコンテナ作成

いくつかホスト側で設定が必要らしいが、ubuntu 14.04 だとそのほとんどは済んでいて、簡単な設定ファイルを用意するだけでよいようだ。

ユーザホームディレクトリ
$ mkdir .config/lxc
$ cp /etc/lxc/default.conf .config/lxc
$ echo "lxc.id_map = u 0 100000 65536" >> .conifig/lxc/default.conf
$ echo "lxc.id_map = g 0 100000 65536" >> .conifig/lxc/default.conf

lxc.id_mapへは、/etc/subuid と /etc/subgid に書かれているユーザのサブIDを設定する。
このsubuidとかはubuntuでは普通にユーザを作成すると作られている情報。

/etc/lxc/lxc-usernet ファイルに追記
$ sudo echo "user veth lxcbr0 10" >> /etc/lxc/lxc-usernet

"user"にvethでlxcbr0を使うコンテナを10個作れる。という特権を与える設定。
vethしかダメらしい。

作成(ユーザコンテナの場合、テンプレートには download しか選べない)
$ lxc-create -n ubu01 -t download

すると、どのディストリビューション入れる?って対話で聞いてくるので、それにそって入れても良いし、分かっているなら以下のようにオプション指定してもいい。

$ lxc-create -n ubu01 -t download -d ubuntu -r trusty -a amd64
ってな感じ。
ダウンロードイメージは毎日ビルドされているものをwgetで取得してくるようだ。

起動
$ lxc-start -n ubu01 -d

$ ps aux でプロセスを見てみると、UIDが100000位上のプロセスが10数個立つ。これがユーザコンテナのプロセスだろう。lxcはホストのカーネルプロセスの一部として動くので混ざるわけだ。

実はこの時ちゃんと起動しなくて、cgmanagerがエラーを出してクラッシュした。
何か設定が悪いのか?と調べてみたところ、lxcかcgmanagerのちょっとしたバグ?なのだろうか
ホストを再起動したら、直った。

起動してもログイン出来ないよ
ルート用テンプレートとは違い、sshdも入らないし、ubuntuユーザに初期パスワード設定されていないので、起動してもログイン出来ないのだ。これはセキュリティのための対処らしい。

ubuntuユーザにパスワード設定
$ lxc-attach -n ubu01 -- sudo passwd ubuntu

lxc-attachはコンテナにデフォルトユーザでログインしたつもりで外からコマンドを実行出来る。
親切にもダウンロードコンテナ作成するとその辺のガイドとかが表示される。

書いておきながら何だけど、デフォのubuntuユーザは触らずに、新たに作ったほうがいいと思う。

$ lxc-attach -n ubu01 -- sudo adduser user1
$ lxc-attach -n ubu01 -- sudo adduser user1 sudo

な感じで。

因みに、ユーザ起動コンテナのネットワークタイプはデフォルトの veth じゃないとだめらしい。
外に出れる。ホストからアクセスできる。が、外からはアクセス出来ないってこと。
セキュリティ的には良いが、外からアクセス出来ないとちょっとつまらないので、何とかしよう。

2015/08/05

svnrdump で uuid 取得できるね

今日は、実務の中でちょっとした発見ができたので、書き残しておくと思う。
世間にとっては既知なのかもしれないが・・・

日頃仕事でリポジトリ管理にオープン系の Svn と Git を扱っている。
Svnリポジトリの引っ越しやらバックアップやらで svnsync を使って同期状態にすることが多いが
「再配置(relocate)」が出来るようにするためには、リポジトリの UUID を同じにしておく必要がある。

svnsyncが出来るまでの基本手順
$ svnadmin create dest_repo_path
$ echo "#!/bin/sh" > dest_repo_path/hooks/pre-revprop-change
$ echo "exit 0" >> dest_repo_path/hooks/pre-revprop-change
$ chmod +x  dest_repo_path/hooks/pre-revprop-change
svnadminはローカルパスを指定する必要があるし、pre-revprop-changeファイル作成が必要
なので同期したいサーバー側で実行する必要があるかと思う。
実際の同期処理の、svnsync init と svnsync sync は、リモートから実行可能なので
アクセス可能なところから適当に。

本題はそこではなくて、再配置(relocate)可能な同期リポジトリにするためには先ほど書いたように
UUID を同じにしておく必要がある。

どうやって同期元リポジトリのUUIDを取得するか?

$ svnlook uuid src_repo_path とか
$ cat src_repo_path/db/uuid とか?

どちらにせよURLではなくファイルパス指定なので、

1.同期元リポジトリが存在するサーバー上で実行してコピペ?
2.NFSとかSambaとかsshfsとか使ってマウントしてuuidコピー?

手順のスクリプト化には厄介な話だ。自分はちょっと前まで実際に sshfs で元サーバーのリポジトリをマウントしてuuidコピーする手順をスクリプト化していた。苦肉の策。

すげー簡単な方法があった! やったーと思っているのは自分だけかも・・・
$ svnrdump dump -r 0 {src_repo_URL} | awk -e '/UUID/ { print $2 }' > uuid_file_path
これで取れる。しかも1ラインで。
svnrdump は、svndump をリモートから出来るようにしたコマンドなので、同期したい側から元リポジトリのURL指定でダンプが取れる。

ありがたいことに、どのリビジョンを取得してもダンプ情報の3行目に元のUUIDが記述されている。
UUIDを取り出したいだけなので、0番取得としている。Rev#0は属性情報だけなのでどんな
リポジトリでも一瞬でダンプが取れる。

取れさえすれば、直接uuidファイルに書き込んでもよし、svnadmin setuuid を使ってもよし。

ということで、チェックアウトせずにリモート操作で、しかも簡単にuuidを取得する方法でした。