Upload
etsuji-nakai
View
507
Download
0
Embed Size (px)
DESCRIPTION
Citation preview
Ver1.0 2013/08/08Etsuji Nakai
NII dodai-deploy2.0 project
DCK Server プロトタイプ
2
NII dodai-deploy2.0 project
前回までのアイデア
3
NII dodai-deploy2.0 project
コンポーネントスタックの整理
IaaS Infra
dck
dckapp
libdck
dckemu
dcktool
libdck 本来はIaaS基盤が提供するべきだが、既存のIaaSでは未実装の機能を代替として提供するモジュール
AWS / OpenStack / Eucalyputus / Wakame VDCなどの既存の
IaaS基盤を前提とする
DCKを前提としたアプリケーション DCKを容易に利用するためのツール
Data Center Kernel本体
DCKを前提としたアプリケーション
DCKのAPIを呼び出すライブラリ
ユーザ
4
NII dodai-deploy2.0 project
dcinitとは?
複数VM間で連携するサービスを自立分散的に起動する仕組み dckが提供するインフラ機能を利用して、VM間の連携を実現する ここでは、dcinitを実現するために必要なdckのインフラ機能を考える
5
NII dodai-deploy2.0 project
VM間の連携方法
一般的な分類–Fork
• 新しいVMを起動して、実行中コードの指定関数の実行を開始する–Messaging
• pub/subモデルでイベント情報を交換する–Shared memory
• 複数VM間で情報共有するWhite Board機能• hostnameなどの基本情報をVM間で共有することができる
–Signal• 指定VMのイベントハンドラを起動する• Tomcatが追加されたらApacheに通知して負荷分散設定を変更する、など
の使い方ができる
6
NII dodai-deploy2.0 project
擬似コードイメージ
# dcinit web3tier start
fork apacheinstall apache
fork tomcatinstall apache
fork postgresqlinstall apache
main { global id = $$ # Uniq job ID shmget(id) shm_write(id, “controller:hostname”, $HOSTNAME) fork apache fork tomcat fork postgresql shm_read(id, “apache:ready”) # Blocking read shm_read(id, “tomcat:ready”) # Blocking read shm_read(id, “postgres:ready”) # Blocking read while (1) { fork tomcat if scaleout_is_required }}
apache { install apache shm_write(id, “apache:hostname”, $HOSTNAME) shm_write(id, “apache:reday”, true) event_loop}
# signal handler to modify apache conf for new tomcatadd_tomcat { tomcat_hosts=shm_read(id, “tomcat:hostlist”) update_apache_config(tomcat_hosts)}
tomcat { install tomcat shm_append(id, “tomcat:hostlist”, $HOSTNAME) pgsql=shm_read(id, “pgsql:hostname”) apache=shm_read(id, “apache:hostname”) notify “add_tomcat” $apache shm_write(id, “tomcat:ready”, true) event_loop}
postgres { install postgres shm_write(id, “postgres:hostname”, $HOSTNAME) shm_write(id, “postgres:ready”, true) event_loop}
7
NII dodai-deploy2.0 project
プロトタイプ実装DCK Server
8
NII dodai-deploy2.0 project
目的
とにかく一度、p.6のような擬似コードが実際に実行できる環境を作ってみる。
9
NII dodai-deploy2.0 project
構成
OpenStack
REST API
DCKサーバ
REST API
VMインスタンス
管理用PC
10
NII dodai-deploy2.0 project
「User Data」「メタデータ」「UUID」について
OpenStackでは、VM起動時にテキストの「User Data」を受け渡すことができます。特にスクリプトファイルを渡すと、ゲストOS起動後に自動実行されます。
– DCK Serverでは、「User Data」を利用して、VM連携処理の「ブートストラップ」を実施しています。
OpenStackでは、各VMに対して、「Key=Value」形式のメタデータを複数セットすることができます。
– DCK Serverでは、VM間でメタデータを相互参照することで、VM間のメッセージ伝達を行います。
OpenStackでは、起動中のVMにユニークなUUIDがアサインされます。– DCK Serverでは、UUIDをVMの識別子(プロセスID)として使用します。
11
NII dodai-deploy2.0 project
DCK ServerがREST APIで提供する機能
exec– 新規VMを起動する。
• 親VMのUUID、OSイメージ、User Dataを指定する。 fork
– 既存VMの「User Data」を再利用して、新規VMを起動する。• forkされたVMは、メタデータに「forked=true」がセットされる。
ps– 起動中VMの情報を取得する
ppid– 指定VMの親VMのUUIDを取得する
cpid– 指定VMの子VMのUUID(複数)を取得する
poke– 指定VMに指定のメタデータをセットする
peek– 指定VMのメタデータを取得する
delete– 指定VM(および、子VM)を停止・削除する
12
NII dodai-deploy2.0 project
libdck.shについて
DCK ServerのREST APIを簡便なコマンドで利用するためのライブラリ(シェルスクリプトの関数群)– User Dataなどから次のようにインクルードして使用する。– # curl -s http://<dckserver>:5000/dck/api/v1.0/libdck > /tmp/libdck.sh– # . /tmp/libdck.sh
exec # dck-exec <親VM UUID> <新規VM名> <イメージID> <User Dataファイル> fork # dck-fork <親VM UUID> <新規VM名> ps # dck-ps / # dck-ps <UUID> ppid # dck-ppid <UUID> cpid # dck-cpid <UUID> poke # dck-poke <UUID> <key> <value> peek # dck-peek <UUID> / # dck-peek <UUID> <key> delete # dck-delete <UUID>
その他補助関数– JSONから特定キーの値を取り出す
# json_elem <key> <JSON>
13
NII dodai-deploy2.0 project
forkを利用した簡単なUser Dataの例#!/bin/bashcurl -s http://192.168.101.9:5000/dck/api/v1.0/libdck > /tmp/libdck.sh. /tmp/libdck.shpid=$( json_elem "uuid" "$(curl -s http://169.254.169.254/openstack/latest/meta_data.json )" ) # 自分のUUIDforked=$(dck-peek $pid "forked") # forkした子VMか判断するためのメタデータ
function child { # 子VMの場合の処理 echo "I'm child" > /etc/motd dck-poke $pid "child_setup" "true" # 処理完了を自身のメタデータに記録}
function parent { # 親VMの場合の処理 for i in 1 2; do result=$(dck-fork $pid "child$i") # 子VMをfork cpids[i]=$(json_elem "pid" "$result") done for cpid in ${cpids[@]}; do # 子VMの処理完了をループで待つ while [[ ! $(dck-peek $cpid "child_setup") == "true" ]]; do sleep 10 done done echo "I'm parent" > /etc/motd}
# mainif [[ $forked == "true" ]]; then # 親VMと子VMで処理を分岐 childelse parentfiexit
14
NII dodai-deploy2.0 project
Forkを利用したスケールアウトWebサーバの例 (1/2)#!/bin/bashcurl -s http://192.168.101.9:5000/dck/api/v1.0/libdck > /tmp/libdck.sh. /tmp/libdck.shpid=$( json_elem "uuid" \ "$(curl -s http://169.254.169.254/openstack/latest/meta_data.json )" )forked=$(dck-peek $pid "forked")
function reload_lb { webservers_bak="" while [[ true ]]; do # 自身のメタデータから子VMのIPを取得して、ロードバランサに登録 webservers=$(dck-peek $pid | awk -F ': ' '/^ +"web/ { print $2 }' | sed 's/[\",]//g') if [[ $webservers != $webservers_bak ]]; then cat <<EOF > /etc/httpd/conf.d/proxy.conf<IfModule proxy_module>ProxyRequests OffProxyPass /balancer_test balancer://mycluster lbmethod=byrequests timeout=1<Proxy balancer://mycluster>BalancerMember http://127.0.0.1 loadfactor=1EOF for s in $webservers; do echo "BalancerMember http://$s loadfactor=1" >> /etc/httpd/conf.d/proxy.conf done cat <<EOF >> /etc/httpd/conf.d/proxy.conf</Proxy></IfModule>EOF webservers_bak=$webservers systemctl reload httpd.service fi sleep 10 done}
このUser DataでVMを起動するとロードバランサーとなる。
その後、このVMをforkすると、Webサーバーになって、ロードバランス対象に登録される。
15
NII dodai-deploy2.0 project
Forkを利用したスケールアウトWebサーバの例 (2/2)function prepare_httpd { setenforce 0 yum install -y httpd systemctl stop iptables systemctl start httpd.service hostname > /var/www/html/index.html}
function parent { # 親VMは、ロードバランサーとして動作 prepare_httpd reload_lb # 子VMを定期的にチェックして、新規の子VMをロードバランス先に登録}
function child { # 子VMは、Webサーバとして動作 prepare_httpd parent=$(dck-ppid $pid) ip=$(dck-pip $pid) dck-poke $parent "web-$ip" "$ip" # 親VMのメタデータの自身のIPアドレスを登録}
# mainif [[ $forked == "true" ]]; then childelse parentfiexit
Etsuji NakaiTwitter @enakai00
NII dodai-deploy2.0 project
Thank You!