Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

すごく分かるwarden

6,980 views

Published on

Cloud Foundryで用いられるコンテナシステム「Warden」の動作について、ソースコードを交えた紹介を行います。

第8回CloudFoundry輪読会で発表を行いました:http://atnd.org/events/30614

  • Be the first to comment

すごく分かるwarden

  1. 1. すごく分かるWarden岩嵜 雄大NTT Software Innovation Center2012-07-26 NTT Software Innovation Center
  2. 2. Warden(ウォードン)とは https://github.com/cloudfoundry/warden DEA上でアプリケーションを隔離する仕組み2012-07-26 NTT Software Innovation Center 2
  3. 3. Outline  なぜWardenが必要なのか  Wardenの動作原理2012-07-26 NTT Software Innovation Center 3
  4. 4. なぜWardenが必要なのか2012-07-26 NTT Software Innovation Center 4
  5. 5. なぜWardenが必要なのか ユーザ権限で 動作 App App App DEAホスト(OS)  Appはユーザが自由に開発する – 悪意のあるAppの可能性もある  現在はUNIX UserによりAppを隔離2012-07-26 NTT Software Innovation Center 5
  6. 6. Unix Userの問題点 App App App  脆弱性に弱い – 特権昇格 DEAホスト(OS) App A p A p  他のAppの影響を受ける – CPU、メモリ、IO、etc. p p DEAホスト(OS) App App App  情報が他Appに伝わる – PID、CPU、メモリ、etc. – 気持ち悪い DEAホスト(OS)2012-07-26 NTT Software Innovation Center 6
  7. 7. 求められるもの App App App 制限 DEAホスト 一方通行  App環境の隔離  リソース制限の導入  操作用API2012-07-26 NTT Software Innovation Center 7
  8. 8. FAQ  AppごとにVM建てればいいのでは? – パフォーマンス的に難しい  chroot jailではダメ? – マウントポイントしか隠ぺいできない  LXCではダメ? – 初期のWardenはLXCを利用していたが… – Linuxでしか動かない – 機能過多2012-07-26 NTT Software Innovation Center 8
  9. 9. Wardenの動作原理2012-07-26 NTT Software Innovation Center 9
  10. 10. 基本方針  コンテナ – 環境の隔離:Namespaces – リソース制限:Cgroups – /sbin/init起動によるシステムコンテナ  操作用API – Wardenサーバがコンテナを管理 – Warden Protocl経由でサーバにアクセス2012-07-26 NTT Software Innovation Center 10
  11. 11. Cgroups  Linux Kernel 2.6.24から  プロセスをグループに分離 – メモリ使用量、CPU・IOの優先度 書いてあるよ!2012-07-26 NTT Software Innovation Center 11
  12. 12. Namepaces  プロセスの名前空間を分離 – PID、Network, Mount、UTS、IPC、User – unshare(1), clone(2)  マウント状況も分離される – 高級版chroot jail  ネットワークも分離される – 仮想NIC(veth)を使用2012-07-26 NTT Software Innovation Center 12
  13. 13. Wardenの概要 Warden クライアント ②コンテナの起動 EMサーバ シェル (Ruby) スクリプト群 Linux クラス clone.c DEA コンテナ ①コンテナの生成 ジョブ sshd ③ジョブの起動 OS2012-07-26 NTT Software Innovation Center 13
  14. 14. サーバ本体 Warden クライアント ②コンテナの起動 EMサーバ シェル (Ruby) スクリプト群 Linux クラス clone.c DEA コンテナ ①コンテナの生成 ジョブ sshd ③ジョブの起動 OS2012-07-26 NTT Software Innovation Center 14
  15. 15. サーバ本体  /lib/warden  命令を受け取ってコンテナの操作を行う – EMがListen – OS・環境ごとのクラスに委譲  Linuxクラス – シェルスクリプトに処理を委託2012-07-26 NTT Software Innovation Center 15
  16. 16. サーバ本体  /lib/warden/container/linux.rb 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 コンテナの起動 (コンテナは常時起動)2012-07-26 NTT Software Innovation Center 16
  17. 17. シェルスクリプト部分 Warden クライアント ②コンテナの起動 EMサーバ シェル (Ruby) スクリプト群 Linux クラス clone.c DEA コンテナ ①コンテナの生成 ジョブ sshd ③ジョブの起動 OS2012-07-26 NTT Software Innovation Center 17
  18. 18. シェルスクリプト部分  /root/linux  コンテナの生成・削除  Skeleton – ファイルがコンテナごとにコピーされる2012-07-26 NTT Software Innovation Center 18
  19. 19. シェルスクリプト部分(コンテナ生成)  /root/linux/create.sh # インスタンスごとのディレクトリ target="instances/${1}" mkdir -p instances … cp -r skeleton "${target}“ unshare -m "${target}"/setup.sh – スケルトンをコピー – マウント名前空間をunshareしてsetup.shを実行  /root/linux/skeleton/setup.sh – 設定を/etc内に書きだす – /etc/ssh, /etc/init.d, /etc/hosts, etc.2012-07-26 NTT Software Innovation Center 19
  20. 20. シェルスクリプト部分(コンテナ起動)  /root/linux/skeleton/start.sh env -i unshare -n ../../../../src/clone/clone – network名前空間をunshareしてclone.cを実行2012-07-26 NTT Software Innovation Center 20
  21. 21. シェルスクリプト部分 Warden クライアント ②コンテナの起動 EMサーバ シェル (Ruby) スクリプト群 Linux クラス clone.c DEA コンテナ ①コンテナの生成 ジョブ sshd ③ジョブの起動 OS2012-07-26 NTT Software Innovation Center 21
  22. 22. clone.c  /src/clone/clone.c  システムコールによるコンテナ生成 – clone(2)2012-07-26 NTT Software Innovation Center 22
  23. 23. clone.c  /src/clone/clone.c 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");2012-07-26 NTT Software Innovation Center 23
  24. 24. clone.c  /src/clone/clone.c 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");2012-07-26 NTT Software Innovation Center 24
  25. 25. skeletonに寄り道  /root/linux/skeleton/hook-parent-before-clone.sh setup_fs  /root/linux/skeleton/common.sh: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} – コンテナごとのファイルをループバックマウント – OSが入っているベースにオーバーレイ • ベースは書き込み禁止状態で共有2012-07-26 NTT Software Innovation Center 25
  26. 26. clone.c  /src/clone/clone.c 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");2012-07-26 NTT Software Innovation Center 26
  27. 27. clone.c 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); … }2012-07-26 NTT Software Innovation Center 27
  28. 28. clone.c 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); … }2012-07-26 NTT Software Innovation Center 28
  29. 29. clone.c  /src/clone/clone.c 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");2012-07-26 NTT Software Innovation Center 29
  30. 30. skeletonに寄り道  /root/linux/skeleton/hook-parent-after-clone.sh # 新しい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} > tasks2012-07-26 NTT Software Innovation Center 30
  31. 31. ジョブの起動 Warden クライアント ②コンテナの起動 EMサーバ シェル (Ruby) スクリプト群 Linux クラス clone.c DEA コンテナ ①コンテナの生成 ジョブ sshd ③ジョブの起動 OS2012-07-26 NTT Software Innovation Center 31
  32. 32. ファイルの送受信とコマンドの実行  DEA用の特別な仕掛けは見当たらない – ファイルの送受信(rsync) – コマンドの実行(ssh) • ジョブとして入出力を管理2012-07-26 NTT Software Innovation Center 32
  33. 33. ジョブの起動  /lib/warden/container/linux.rb 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) …2012-07-26 NTT Software Innovation Center 33
  34. 34. ファイルの送受信  /lib/warden/container/linux.rb 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 end2012-07-26 NTT Software Innovation Center 34
  35. 35. まとめ  WardenはApp隔離用のコンテナ  LinuxではCgroupsとNamespacesを使用  サーバがコンテナの操作を行う  ファイルを転送してコマンドを実行する2012-07-26 NTT Software Innovation Center 35

×