paizaのオンラインジャッジを支えるdockerとその周辺
TRANSCRIPT
paizaのオンラインジャッジを支えるDockerとその周辺
Gino, paiza
吉岡恒夫http://paiza.jp/
E-Mail: [email protected]
Twitter: @yoshiokatsuneo
自己紹介 (吉岡恒夫)
• 2014年4月ジョイン(paizaでpaizaに転職しました)
• paizaのオンラインジャッジシステムの開発
• オンラインコーディング環境paiza.IOの開発
• Linux, Docker, Rails, AngularJS
仮想化の方法
• 仮想マシン(VMware, Xen)
• コンテナ仮想化(Googleは週に20億コンテナ)
•何もしない
→他の人のコードが見える❌
•ディレクトリのアクセスモード設定を分ける
→CPU等リソース制限がない
❌
仮想マシンとコンテナの違い
ホストマシン
ホストOS
仮想マシン
ゲストOS
プロセス
ホストマシン
ホストOS
仮想マシン
ゲストOS
コンテナ コンテナ
プロセス プロセス プロセス
プロセス プロセス プロセス プロセス
• 仮想マシン: 仮想環境ごとにOSが動作する• コンテナ: ホストと同一のOS上で動作
仮想マシン コンテナ
仮想マシン v.s. コンテナ
仮想マシン コンテナ
起動❌
(数分)
⚪︎
(1秒未満)
メモリ❌
(OS本体)
⚪︎
(必要なプロセス分)
のみ)
OSの自由度⚪︎
(任意)
❌
(ホストと共有)
コンテナは軽量!→ジャッジシステムで利用
Dockerのファイルシステム管理• Union File Systemを利用(Copy on Write)
• ファイルシステムを積み重ねる。読み込みは一番上のレイヤーから、書き込みは最上位のレイヤーに差分として記録。
• 共通のベースイメージを再利用できる
プロセス
/usr
/home
プロセス
/home
ユーザ環境 ユーザ環境
/homeベースイメージ(OS)
コンテナ コンテナ
Docker: リソース制限
• Linuxのcgroupsでコンテナ単位のプロセスグループを作成し、グループ内で利用するリソースを制限
メモリ
CPU
メモリプロセス
プロセス
プロセス
プロセス
プロセス
プロセス
プロセス
CPU CPU
コンテナ1 コンテナ2
Docker: Namespace隔離
1. プロセス(PID)
2. ネットワーク(virtual Ethernet)
3. ホスト名(UTS)
4. Mount
5. IPC
6. User
(Linuxの機能としてはあるが、Dockerでは利用できない)
コード実行の流れ
ベースイメージの作成(OS, ライブラリ)
実行コンテナ作成
実行コンテナ破棄
コード実行
実行ファイル
実行結果
# docker build
# docker run
# docker kill
# docker rm
サービス
CPUの利用管理
コンテナ1 コンテナ2
3 コンテナ4
コンテナ5
CPU-1
CPU-2
CPU-3
CPU-4
コンテナ1
コンテナ2
コンテナ3
サービス
CPUの量が運に左右される
コンテナ単位でCPUを割り当てる→コンテナのCPU数を制限→コンテナがCPUを独占→サービスとコンテナでCPUを分ける
何も考えずに複数のコンテナを同時実行した場合CPU単位でコンテナを割り当てた場合
CPU コア / CPU スレッド
• 個々のCoreは独立して並列実行できる
Quad-Core AMD Opteron processor (front view die, white background)
Attribution: Advanced Micro Devices, Inc. (AMD)
http://en.wikipedia.org/wiki/Opteron#mediaviewer/File:Quad-Core_AMD_Opteron_processor.jpg
Core Core
Core Core
プロセス1
CPUスレッド(ハイパースレッディング)• 物理的には1つのCPUコア
• ソフトウェアからは2つの(論理)CPU
• 物理CPUの実行ユニットを効率的に使うことで全体として高速化(30%程度)
物理CPUコア
論理CPU 論理CPU
実行ユニット
実行ユニット
実行ユニット
実行ユニット
プロセス1 プロセス2
ハードウェア
ソフトウェア
CPU CPU
CPUスレッドと公平性
• 1論理CPUを占有しても物理CPUの利用度で速度が変わる
論理CPU
コンテナ1 コンテナ2
実行ユニット
実行ユニット
論理CPU
物理CPUコア
実行ユニット
実行ユニット
コンテナ1
コンテナ1個に物理CPUコア1個(論理CPU2個)
CPU論理CPU
コンテナ3
実行ユニット
実行ユニット
物理CPUコア
実行ユニット
実行ユニット
論理CPU
コンテナ2
メモリの利用管理
• Docker/cgroupsの機能で512MBに制限
• 一部言語では言語単位のメモリ設定が必要
• Java: -Mxオプション指定しないとメモリ容量から自動的に設定
• PHP: memory_limit設定
プロセスの利用制限
• “fork爆弾”対策
• Docker自身にはfork数の制限はない
• カーネルメモリ制限→正確に把握できない→Dockerから直接利用できない
• Linuxのユーザ資源管理(RLIMIT_NPROC)により、ユーザ単位でプロセス数を制限
• 同時実行するコンテナごとに別ユーザを割り当てる
ネットワークの利用管理
• スキルチェックではネットワークは無効化→ テストケースの漏洩等防止
• ネットワークを利用するサービス(paiza.io)では、”bridge”でネットワーク仮想化
• NATのコネクション管理機能(ip_conntrack)を利用して利用状況を監視
実行時間の測定
• 正確に測定→ コンテナ内でtimeコマンド実行
• 改ざん防止→ timeコマンドはrootで、コードは一般ユーザで実行(rootでtimeコマンドを開始後、コード実行直前にユーザを一般ユーザに変更)
スケールアウト
• キュー(RabbitMQ)を経由して複数のジャッジサーバを接続
• ジャッジサーバを追加し、キューからの読み込みを増やすことでスケールアウト
• ジャッジサーバが停止した場合、キューの再送が行われることで冗長化
APIサーバ キュージャッジサーバ
ジャッジサーバ
ジャッジサーバ
APIサーバAPIサーバユーザ
8つのDocker利用目的
1. サーバ管理を簡単に! => コンテナはどこでも動作!
2. 開発環境依存の問題をなくす! => 開発者全員が同じコンテナを利用できる!
3. 開発・デプロイ環境の同一化! => 開発環境とデプロイ環境を同一コンテナ利用!
4. マイクロサービス化! => サービス間の依存性を減らす!
5. サーバリソースの節約! => 同一物理サーバ上で複数コンテナが軽量動作!
6. デバッグが簡単!=> いつでもスナップショット/コピーをとって解析できる!
7. 複数テナント! => 複数のサービスを1つの物理サーバ上でまとめて動作!
8. デプロイ高速化! => コンテナ起動は一瞬!
高速で軽量仮想化環境が作れることを利用!
超軽量コンテナを使ってより快適なサービス、環境に!
以上ありがとうございました!
Gino, paiza
吉岡恒夫http://paiza.jp/
E-Mail: [email protected]
Twitter: @yoshiokatsuneo