すごく分かるwarden
description
Transcript of すごく分かるwarden
NTT Software Innovation Center
すごく分かるWarden
岩嵜 雄大
NTT Software Innovation Center
2012-07-26
NTT Software Innovation Center
Warden(ウォードン)とは
DEA上でアプリケーションを隔離する仕組み
2012-07-26 2
https://github.com/cloudfoundry/warden
NTT Software Innovation Center
Outline
なぜWardenが必要なのか
Wardenの動作原理
2012-07-26 3
NTT Software Innovation Center
なぜWardenが必要なのか
2012-07-26 4
NTT Software Innovation Center
なぜWardenが必要なのか
Appはユーザが自由に開発する
– 悪意のあるAppの可能性もある
現在はUNIX UserによりAppを隔離
2012-07-26 5
DEAホスト(OS)
App App App
ユーザ権限で動作
NTT Software Innovation Center
Unix Userの問題点
脆弱性に弱い
– 特権昇格
他のAppの影響を受ける
– CPU、メモリ、IO、etc.
情報が他Appに伝わる
– PID、CPU、メモリ、etc.
– 気持ち悪い
2012-07-26 6
DEAホスト(OS)
App App App
DEAホスト(OS)
App App
App
DEAホスト(OS)
App App App
NTT Software Innovation Center
求められるもの
App環境の隔離
リソース制限の導入
操作用API
2012-07-26 7
DEAホスト
App App App
一方通行
制限
NTT Software Innovation Center
FAQ
AppごとにVM建てればいいのでは?
– パフォーマンス的に難しい
chroot jailではダメ?
– マウントポイントしか隠ぺいできない
LXCではダメ?
– 初期のWardenはLXCを利用していたが…
– Linuxでしか動かない
– 機能過多
2012-07-26 8
NTT Software Innovation Center
Wardenの動作原理
2012-07-26 9
NTT Software Innovation Center
基本方針
コンテナ
– 環境の隔離:Namespaces
– リソース制限:Cgroups
– /sbin/init起動によるシステムコンテナ
操作用API
– Wardenサーバがコンテナを管理
– Warden Protocl経由でサーバにアクセス
2012-07-26 10
NTT Software Innovation Center
Cgroups
Linux Kernel 2.6.24から
プロセスをグループに分離
– メモリ使用量、CPU・IOの優先度
2012-07-26 11
書いてあるよ!
NTT Software Innovation Center
Namepaces
プロセスの名前空間を分離
– PID、Network, Mount、UTS、IPC、User
– unshare(1), clone(2)
マウント状況も分離される
– 高級版chroot jail
ネットワークも分離される
– 仮想NIC(veth)を使用
2012-07-26 12
NTT Software Innovation Center
Wardenの概要
2012-07-26 13
EMサーバ (Ruby)
Warden クライアント
Linux クラス
シェル スクリプト群
clone.c DEA
②コンテナの起動
sshd
OS
ジョブ
コンテナ
①コンテナの生成
③ジョブの起動
NTT Software Innovation Center
サーバ本体
2012-07-26 14
EMサーバ (Ruby)
Warden クライアント
Linux クラス
シェル スクリプト群
clone.c DEA
②コンテナの起動
sshd
OS
ジョブ
コンテナ
①コンテナの生成
③ジョブの起動
NTT Software Innovation Center
サーバ本体
/lib/warden
命令を受け取ってコンテナの操作を行う
– EMがListen
– OS・環境ごとのクラスに委譲
Linuxクラス
– シェルスクリプトに処理を委託
2012-07-26 15
NTT Software Innovation Center
サーバ本体
/lib/warden/container/linux.rb
2012-07-26 16
def do_create sh "#{env_command} #{root_path}/create.sh #{handle}", :timeout => nil debug "container created" write_bind_mount_commands debug "wrote bind mount commands" sh "#{container_path}/start.sh", :timeout => nil debug "container started" end
コンテナの生成
コンテナの起動 (コンテナは常時起動)
NTT Software Innovation Center
シェルスクリプト部分
2012-07-26 17
EMサーバ (Ruby)
Warden クライアント
Linux クラス
シェル スクリプト群
clone.c DEA
②コンテナの起動
sshd
OS
ジョブ
コンテナ
①コンテナの生成
③ジョブの起動
NTT Software Innovation Center
シェルスクリプト部分
/root/linux
コンテナの生成・削除
Skeleton
– ファイルがコンテナごとにコピーされる
2012-07-26 18
NTT Software Innovation Center
シェルスクリプト部分(コンテナ生成)
/root/linux/create.sh
– スケルトンをコピー
– マウント名前空間をunshareしてsetup.shを実行
/root/linux/skeleton/setup.sh
– 設定を/etc内に書きだす
– /etc/ssh, /etc/init.d, /etc/hosts, etc.
2012-07-26 19
# インスタンスごとのディレクトリ
target="instances/${1}" mkdir -p instances … cp -r skeleton "${target}“ unshare -m "${target}"/setup.sh
NTT Software Innovation Center
シェルスクリプト部分(コンテナ起動)
/root/linux/skeleton/start.sh
– network名前空間をunshareしてclone.cを実行
2012-07-26 20
env -i unshare -n ../../../../src/clone/clone
NTT Software Innovation Center
シェルスクリプト部分
2012-07-26 21
EMサーバ (Ruby)
Warden クライアント
Linux クラス
シェル スクリプト群
clone.c DEA
②コンテナの起動
sshd
OS
ジョブ
コンテナ
①コンテナの生成
③ジョブの起動
NTT Software Innovation Center
clone.c
/src/clone/clone.c
システムコールによるコンテナ生成
– clone(2)
2012-07-26 22
NTT Software Innovation Center
clone.c
/src/clone/clone.c
2012-07-26 23
rv = unshare(CLONE_NEWNS); … # clone前のフック # コンテナ用のファイルシステムをマウントする
rv = run("./hook-parent-before-clone.sh"); … # コンテナ内のinitプロセスを起動する
rv = parent_clone_child(h); … # clone後のフック
rv = run("./hook-parent-after-clone.sh");
NTT Software Innovation Center
clone.c
/src/clone/clone.c
2012-07-26 24
rv = unshare(CLONE_NEWNS); … # clone前のフック # コンテナ用のファイルシステムをマウントする
rv = run("./hook-parent-before-clone.sh"); … # コンテナ内のinitプロセスを起動する
rv = parent_clone_child(h); … # clone後のフック
rv = run("./hook-parent-after-clone.sh");
NTT Software Innovation Center
skeletonに寄り道
/root/linux/skeleton/hook-parent-before-clone.sh
/root/linux/skeleton/common.sh:setup_fs()
– コンテナごとのファイルをループバックマウント
– OSが入っているベースにオーバーレイ
•ベースは書き込み禁止状態で共有
2012-07-26 25
setup_fs
if [ ! -f fs ]; then dd if=/dev/null of=fs bs=1M seek=${disk_size_mb} … fi mkdir -p rootfs ${target} mount -n -o loop fs rootfs … mount -n -t overlayfs -o rw,upperdir=rootfs,lowerdir=../../base/rootfs none ${target}
NTT Software Innovation Center
clone.c
/src/clone/clone.c
2012-07-26 26
rv = unshare(CLONE_NEWNS); … # clone前のフック # コンテナ用のファイルシステムをマウントする
rv = run("./hook-parent-before-clone.sh"); … # コンテナ内のinitプロセスを起動する
rv = parent_clone_child(h); … # clone後のフック
rv = run("./hook-parent-after-clone.sh");
NTT Software Innovation Center
clone.c
2012-07-26 27
int parent_clone_child(clone_helper_t *h) { … # 名前空間分離の設定
/* Setup namespaces */ flags |= CLONE_NEWIPC; flags |= CLONE_NEWNET; flags |= CLONE_NEWNS; flags |= CLONE_NEWPID; flags |= CLONE_NEWUTS; # start()から子プロセス起動
pid = clone(start, stack, flags, h); … }
NTT Software Innovation Center
clone.c
2012-07-26 28
int start(void *data) { … rv = run(hook_before_pivot … rv = run(hook_after_pivot); … # /sbin/initをexecvpして起動完了
char * const argv[] = { "/sbin/init", "--debug", NULL }; execvp(argv[0], argv); … }
NTT Software Innovation Center
clone.c
/src/clone/clone.c
2012-07-26 29
rv = unshare(CLONE_NEWNS); … # clone前のフック # コンテナ用のファイルシステムをマウントする
rv = run("./hook-parent-before-clone.sh"); … # コンテナ内のinitプロセスを起動する
rv = parent_clone_child(h); … # clone後のフック
rv = run("./hook-parent-after-clone.sh");
NTT Software Innovation Center
skeletonに寄り道
/root/linux/skeleton/hook-parent-after-clone.sh
2012-07-26 30
# 新しいcgroupを作って
mkdir -p /dev/cgroup/instance-${id} pushd /dev/cgroup/instance-${id} > /dev/null # 上限などを決め
cat ../cpuset.cpus > cpuset.cpus cat ../cpuset.mems > cpuset.mems # 子プロセスに値をコピーするコールバックを呼ぶ設定
echo 1 > cgroup.clone_children # cgroupsに現在のプロセスを登録
echo ${PID} > tasks
NTT Software Innovation Center
ジョブの起動
2012-07-26 31
EMサーバ (Ruby)
Warden クライアント
Linux クラス
シェル スクリプト群
clone.c DEA
②コンテナの起動
sshd
OS
ジョブ
コンテナ
①コンテナの生成
③ジョブの起動
NTT Software Innovation Center
ファイルの送受信とコマンドの実行
DEA用の特別な仕掛けは見当たらない
– ファイルの送受信(rsync)
– コマンドの実行(ssh)
•ジョブとして入出力を管理
2012-07-26 32
NTT Software Innovation Center
ジョブの起動
/lib/warden/container/linux.rb
2012-07-26 33
def create_job(request) user = request.privileged ? "root" : "vcap" # -T: Never request a TTY # -F: Use configuration from <container_path>/ssh/ssh_config args = ["-T", "-F", File.join(container_path, "ssh", "ssh_config"), "#{user}@container"] args << { :input => request.script } child = DeferredChild.new("ssh", *args) …
NTT Software Innovation Center
ファイルの送受信
/lib/warden/container/linux.rb
2012-07-26 34
def do_copy_in(request, response) src_path = request.src_path dst_path = request.dst_path perform_rsync(src_path, "vcap@container:#{dst_path}") nil end def do_copy_out(request, response) src_path = request.src_path dst_path = request.dst_path perform_rsync("vcap@container:#{src_path}", dst_path) if request.owner sh "chown", "-R", request.owner, dst_path end nil end private def perform_rsync(src_path, dst_path) ssh_config_path = File.join(container_path, "ssh", "ssh_config") # Build arguments args = ["rsync"] args += ["-e", "ssh -T -F #{ssh_config_path}"] args += ["-r"] # Recursive copy args += ["-p"] # Preserve permissions args += ["--links"] # Preserve symlinks args += [src_path, dst_path] # Add option hash args << { :timeout => nil } sh *args end
NTT Software Innovation Center
まとめ
WardenはApp隔離用のコンテナ
LinuxではCgroupsとNamespacesを使用
サーバがコンテナの操作を行う
ファイルを転送してコマンドを実行する
2012-07-26 35