ホーム
企業情報
テックレポート - TechReport
テックレポート詳細
テックレポート - TechReport
Dockerによる開発環境から本番環境までの一貫した管理 2014年6月
執筆者
- 執筆者:
- 劉春来
- 所属部署:
- インフラ&コアテク本部
- 業務経歴:
- 2012年株式会社サイバーエージェント入社。プライベートクラウドの監視システムや自動化などのDevOpsを担当。現在はクラウドシステムのUI刷新とPaaS検証に従事。
概要
開発環境から本番環境までを Docker にて一貫性のある管理が可能であるかを検証しました。
尚、本レポートは Docker 管理に CoreOS を利用しております。
目次
1.タイトルについて
1-1.Docker
DockerはLinux Container技術のhigh levelツールです。VMはマシン仮想化に対してLinux Containerはプロセスの仮想化。
2013年3月にopen sourceしてから今や明らかにデベロッパコミュニティのスパースターになっています:
- githubにdockerのstar数: 13256, Fork数: 2315(2014年6月30日)
- githubのsearch結果の数:8429(2014年6月30日)
- googleのtrend
Linux Containerは最新の技術ではないですがなぜDockerは大人気を集まっているのか、LXCとの違いは?
Googleから十年程container運用実績の披露やGoogle Cloudのdockerの真剣対応など、 Docker熱をもっと上がっていると思います。
使いやすさの工夫とエコシステムを形成する能力を考えると、Dockerは今後の主流になっていくと見られる技術です。
1-2.CoreOS
単一ホスト(single-host)でdocker containerを管理するためのprocess managers(https://github.com/dotcloud/docker/blob/master/docs/sources/articles/host_integration.md):
- systemd
- upstart
- supervisor
multi-hostsの場合、dockerを一元管理できるツールが欲しいです(distributed systemd/upstart/supervisorみたい)。
このようなdocker管理ツールは以下の機能を求めています:
- コンテナの管理
- 分散スケジューリング
関連ツール:
- Kubernetes
- MesOS + Marathon
- CoreOS
上記三つツールからCoreOSをpickupしました:
- Kubernetesは今現在Google Cloud Platformしか使えません。
- MesOSは独自のcontainer技術をnative使っていますがMarathonというツールでdockerもサポートできるようになります。MesOS自体はサーバー全体のリソースの最適化を目指す、次世代のデータセンター管理ツールと言えます。
- CoreOSはDockerのための軽量OSです。普通のLinux distributionよりDockerのためのcluster frameworkという位置付けです。service discoveryやdistributed schedulingなどのCluster機能を持つ、osのatomic updateも目玉ポイントです。massive server deployを目指しています。
今回はDockerのためのCoreOSを検証してみよう。
本レポートはコンテナ管理と分散スケジューリングをメインにCoreOSの使い方をhandsonの形で検証してみます。
1-3.開発環境から本番環境まで
DockerはLinux ContainerだからLinux環境にしか動かないのでmac OS Xやwindowsの開発環境に以下の流行ツールはproxy vm(Virtual BoxでLinuxのVMを起動)の形でdockerを使えるようにする:
開発環境にdocker-osxを使う場合、figというツールを使ってdockerの管理をより簡単になります:
- fig: docker-osxを使ってYAMLファイルを書いて「fig up」コマンドで全部containerをsingle-hostに起動、非常に便利。
上記の開発環境は全部single-hostですがテスト環境と本番環境はほぼmulti-hostです。
multi-hostsのdocker管理は先ほど紹介した通り、CoreOSは得意ですのでsingle-host環境からmulti-hosts環境まで一貫性のあるworkflowできるかなと思いまして、本レポートは CoreOSでsingle-hostからmulti-hostsまでDockerを試すことになります。
つまり、タイトルにある「開発環境から本番環境まで」、大体イコール「single-hostからmulti-hostsまで」。
2.Coreosのhandson
handson_coreosというプロジェクトを作りました。
2-1.環境の準備
このhandsonに開発環境は「mac OS X」を想定しています。 勿論Linuxなら簡単にVirtualBox/Vagrant環境を構築できますのでLinux環境の構築はここに割愛します。
簡単な手順は:
1) VirtualBoxとVagrantのインストール
- VirtualBox(https://www.virtualbox.org/) 4.3.10 or greater.
- Vagrant(http://www.vagrantup.com/downloads.html) 1.6 or greater.
2) single-hostの開発環境:
$ git clone https://github.com/coreos/coreos-vagrant.git$ cd coreos-vagrant$ cp user-data.sample user-data$ vagrant up |
以上です。core-01というCoreOSのvmを起動しました。
dockerコマンドを使う:
- `vagrant ssh`でvmにログインしてdockerを使う
- local laptopで`brew install docker`でdockerのclientをinstall、環境変数のDOCKER_HOSTを設定してlocalから使える
dockerコマンドを直接使えますがCoreOSではdockerコマンドを触らなくでもいいです。
CoreOSにdocker管理や分散スケジューリングをやっているツールはfleetですのでこのHandsonは主にfleetコマンドの使い方です。
local laptopからCoreOSのClusterを管理できますのでlocal laptopの配置:
-
fleetのcommand line clientであるfleetctlをインストール
$ brewinstallfleetctlNOTES: fleet projectはactive devlopment状態なのでbrewのfleetctlのversionはCoreOSのfleetより古い時WARNINGが出ますので、https://github.com/coreos/fleet/releasesからmac用の最新zipファイルをdownloadしてbuildできます。 -
設定
$ssh-add ~/.vagrant.d/insecure_private_key$exportFLEETCTL_TUNNEL=127.0.0.1:2222
以上です。今はlocal laptopからfleetctlコマンドを使えました:
$ fleetctl list-machinesMACHINE IP METADATAe7a4172d... ${IPADDRESS1} - |
3) multi-hostsの開発環境:
handson02からCoreOSのパワーをフルに発揮できるようにvagrantで三つノードのClusterを構築しましょう。
NOTES: 理想なDockerの使い方はpublic portを指定しないで、インフラを意識しないで自由にdeployできるだから、実の開発環境はsingle-nodeでも複雑な構成が行けます。 このhandsonだけのためにclusterの構築は必要になります。
handson01はsingle-hostで試してもいいですから、今はとりあえずmulti-hostsを構築しなくでもいいです。 後でmulti-hostの環境を構築する時、ここを参照ください。
$ git clone https://github.com/coreos/coreos-vagrant.git$ cd coreos-vagrant$ cp user-data.sample user-data$ echo $(curl https://discovery.etcd.io/new) |
上記のcurlコマンドでclusterのためのtokenを取得してuser-dataファイルに以下の行を書き換え:
discovery: https://discovery.etcd.io/<token>
次は起動したいVMの数を設定する:
$ cp config.rb.sample config.rb |
config.rbに「$num_instances=3」を追加してから三つCoreOSのVMをlaunchする:
$ vagrant up |
以上です。core-01/core-02/core-03三つVMをlaunchできた。
local laptopのfleetctl設定はsingle-hostと同じ設定で行けます。single-host構築の時すでに設定済みの場合、不要です。 defaultではfleetctlが~/.fleetctl/known_hostsを使っていますのでもしknown_hostsの問題発生したらこのknown_hostsファイルから[127.0.0.1]:2222の行を削除してOKです。
fleetctlコマンドでも確認します:
$ fleetctl list-machinesMACHINE IP METADATAe7a4172d... ${IPADDRESS1} -34aa3ef6... ${IPADDRESS2} -ba04d7eb... ${IPADDRESS3} - |
2-2.handsonを試す
handson_coreosをgloneして:
$ git clone https://github.com/chuenlye/handson_coreos.git
handsonの詳細:
- handson01_basic : fleetctlコマンドの使い方
- handson02_scheduling : fleetctlコマンドで分散スケジューリング機能を試す
- handson03_using_template : templateファイルを使ってportが異なるcontainerを複数launchする
- handson04_sidekick_registry : classicな例です。LBはapp serversの情報を動的に取得、自動設定更新
- handson05_ambassador_pattern : containerの"Dynamic link" を試す
- handson06_yaml2coreos : fig2coreosツールでYAMLファイルから全部のserviceファイルを生成する
NOTES: clusterを体験するためこのhandsonはmulti-hostのclusterに設計したものですがhandson01/04/06はsingle-hostでも行けます。
2-2-1.handson01_basisc
まずsingle-hostでhandson01を試す:
$ cd handson01_basic |
ファイルの説明:
$ cat myfirst.service [Service]ExecStart=/usr/bin/docker run --rm --name bbox busybox /bin/sh -c "while true; do echo Hello World; sleep 3; done"ExecStop=/usr/bin/docker stop -t 3 bbox |
serviceの定義にExecStartとExecStopは実行したいdockerコマンドです。
次はこのサービスのdeploy:
$ fleetctl start myfirst.serviceJob myfirst.service launched on e7a4172d.../${IPADDRESS1} |
OK, fleetctl list-unitsで結果を確認しましょう:
$ fleetctl list-unitsUNIT STATE LOAD ACTIVE SUB DESC MACHINEmyfirst.service launched loaded active running - e7a4172d.../${IPADDRESS1} |
serviceは正常にlaunched, running状態です。
fleetctl statusで詳細statusと最新10行のlogを確認しましょう:
$ fleetctl status myfirst.service● myfirst.service Loaded: loaded (/run/fleet/units/myfirst.service; linked-runtime) Active: active (running) since Sun 2014-06-29 00:26:58 UTC; 5min ago Main PID: 1554 (docker) CGroup: /system.slice/myfirst.service └─1554 /usr/bin/docker run --rm --name bbox busybox /bin/sh -c while true; do echo Hello World; sleep 3; done Jun 29 00:32:17 core-01 docker[1554]: Hello World Jun 29 00:32:20 core-01 docker[1554]: Hello World Jun 29 00:32:23 core-01 docker[1554]: Hello World Jun 29 00:32:26 core-01 docker[1554]: Hello World Jun 29 00:32:29 core-01 docker[1554]: Hello World Jun 29 00:32:32 core-01 docker[1554]: Hello World Jun 29 00:32:35 core-01 docker[1554]: Hello World Jun 29 00:32:38 core-01 docker[1554]: Hello World Jun 29 00:32:41 core-01 docker[1554]: Hello World Jun 29 00:32:44 core-01 docker[1554]: Hello World |
serviceのlogを「tail -f」のように確認しましょう:
$ fleetctl journal -f myfirst.service(結果を省略する) |
fleetctl destroy *.serviceでclean環境になったら全部のhandsonを繰り返し実行できます
他のfleetctlコマンドはhandson01_basic/README.mdを参照ください
2-2-2.handson02_scheduling
handson02からmulti-hostで試しましょう。multi-host環境の構築は上の「3) multi-hostの開発環境」を参照ください。
ファイルの説明:
- app1.service: deploy先を指定します。e.g. core-02のサーバーにapp1.serviceをdeployする
- app2.service: 他のserviceと同居。e.g. app2はapp1と同じサーバーにdeployを求める
- app3.service: 他のserviceと別居。e.g. app3はapp1と異なるサーバーにdeployを求める
- app4.service: customized情報によりdeploy先を決めます。e.g. 「instanceType==large and diskType==ssd」のサーバーにdeployする
$ cd handson02_scheduling$ fleetctl start *.service$ fleetctl list-unitsUNIT STATE LOAD ACTIVE SUB DESC MACHINEapp1.service launched loaded active running app1 17b2ac84.../${IPADDRESS2}app2.service launched loaded active running app2 17b2ac84.../${IPADDRESS2}app3.service launched loaded active running app3 40172041.../${IPADDRESS3}app4.service launched loaded active running app4 17b2ac84.../${IPADDRESS2} |
app1.serviceは指定したvmにdeploy、app2はapp1と同居、app3はapp1/app2と別居
詳しくhandson02_scheduling/README.mdを参照ください
2-2-3.handson03_using_template
ファイルの説明:
- apache.service.template: reuseできるtemplateファイルです。以下の全部serviceファイルはこのtemplateファイルへのsymblic linkです。
$ cat apache.service.template[Unit]Description=Apache FrontendAfter=docker.serviceRequires=docker.service[Service]ExecStart=/usr/bin/docker run --rm --name apache_%i -p %i:80 coreos/apache /usr/sbin/apache2ctl -D FOREGROUNDExecStop=/usr/bin/docker stop -t 3 apache_%i[X-Fleet]X-Conflicts=*@%i.service |
- apache1@80.service: ln -s apache.service.template apache1@80.service
- apache2@80.service: ln -s apache.service.template apache2@80.service
- apache3@80.service: ln -s apache.service.template apache3@80.service
- apache4@8001.service: ln -s apache.service.template apache4@8001.service
- apache5@8001.service: ln -s apache.service.template apache5@8001.service
- apache6@8002.service: ln -s apache.service.template apache6@8002.service
このhandsonのtemplateファイルに「%i」というsystemdの変数を使ってportを柔軟に指定できるようになりました。
fleetctlで試しよう:
$ cd handson03_using_template$ fleetctl start *.service$ fleetctl list-unitsUNIT STATE LOAD ACTIVE SUB DESC MACHINEapache1@80.service launched loaded active running Apache Frontend 40172041.../${IPADDRESS3}apache2@80.service launched loaded active running Apache Frontend 17b2ac84.../${IPADDRESS2}apache3@80.service launched loaded active running Apache Frontend df4dae97.../${IPADDRESS1}apache4@8001.service launched loaded active running Apache Frontend 40172041.../${IPADDRESS3}apache5@8001.service launched loaded active running Apache Frontend df4dae97.../${IPADDRESS1}apache6@8002.service launched loaded active running Apache Frontend 17b2ac84.../${IPADDRESS2} |
OKです。六個Apacheサーバーをpublic portを指定してlaunchできました。
2-2-4.handson04_sidekick_registry
このhandsonはload balancerとapp serversの例です。app serverは複数、動的に変動。load balancerは自動設定が欲しい。
handson04はhandson03と違い、public portを指定しないので、ipとport両方の情報はCoreOS/Dockerにお任せ、柔軟性は一番高いですが自動化のためservice discoveryのような自動登録・自動発見は必要です。
ファイルの説明:
- apache-worker1.registry.service: apache-worker1の「ip + port」情報をお知らせるための補助serviceです。
- apache-worker1.service: apache container自体。
- apache-worker2.registry.service
- apache-worker2.service
- apache-worker3.registry.service
- apache-worker3.service
- lb-config-from-container.service: lb demoです(簡単に最新のworkers情報を出力だけ、本物のlbではない)
- lb-config-from-host.service: lb demoのもうひとつ実現です。CoreOSのhostから。上記のはlbのcontainer内部から。
fleetctlで試しよう:
まず、lb serverだけをdeploy、logを「journal -f」で監視:
$ cd handson04_sidekick_registry$ fleetctl start lb*.service$ fleetctl journal -f lb-config-from-host.service |
lbのlog:
Jun 29 15:38:30 core-03 sh[4869]: --------- Workers List ----------Jun 29 15:38:35 core-03 sh[4869]: --------- Workers List ---------- |
今はworkersがないです。
次はworker1とworker2をdeploy、lbのlogを確認:
$ fleetctl start apache-worker{1,2}*.service |
lbのlogを確認:
Jun 29 15:40:10 core-03 sh[4869]: --------- Workers List ----------Jun 29 15:40:10 core-03 sh[4869]: ${IPADDRESS1}:49153Jun 29 15:40:10 core-03 sh[4869]: ${IPADDRESS1}:49154Jun 29 15:40:15 core-03 sh[4869]: --------- Workers List ----------Jun 29 15:40:15 core-03 sh[4869]: ${IPADDRESS1}:49153Jun 29 15:40:15 core-03 sh[4869]: ${IPADDRESS1}:49154 |
最後はworker3をdeploy:
$ fleetctl start apache-worker3*.service |
lbのlogを確認:
Jun 29 15:41:15 core-03 sh[4869]: --------- Workers List ----------Jun 29 15:41:15 core-03 sh[4869]: ${IPADDRESS1}:49153Jun 29 15:41:15 core-03 sh[4869]: ${IPADDRESS1}:49154Jun 29 15:41:15 core-03 sh[4869]: ${IPADDRESS1}:49155Jun 29 15:41:20 core-03 sh[4869]: --------- Workers List ----------Jun 29 15:41:20 core-03 sh[4869]: ${IPADDRESS1}:49153Jun 29 15:41:20 core-03 sh[4869]: ${IPADDRESS1}:49154Jun 29 15:41:20 core-03 sh[4869]: ${IPADDRESS1}:49155 |
OKです。load balancerは自動的にworkers情報を取得できました。
このhandsonはapp serverのpublic portを指定しないのでsingle-hostの開発環境でも行けます。
2-2-5.handson05_ambassador_pattern
Ambassador_pattern: 今のdocker linkはsingle-host限定なので、multi-hostsでのdynamic linksはambassador_patternです。 例えば、app serverはdb serverへアクセスするためDBのipとportを知る必要です。ただDockerの世界、動的変動は普通なので動的に設定更新を以前より更に求めている。
簡単に言うと、以前はapp -> network -> dbですが、ambassador_patternは(app -> appのambassador) -> network-> (dbのambassador -> db)です。appとdbをlinkingする部分(設定やportのpublish)をambassadorのcontainerにお任せ、 つまり動的に設定更新はambassadorにお任せしました。技術的にはambassadorはport forwardingだけです。containerの形でservice containerの補助containerという役割と思います。
dockerのcreatorよりAmbassador patternはdockerのもう一つ貢献です。
このhandsonはoriginally from: Dynamic Docker links with an ambassador powered by etcd
ちょっと複雑なのでより簡単な例を考えています。
2-2-6.handson06_yaml2coreos
ここまでCoreOSで一番簡単なケースからより複雑なケースまで体験してみましたが使いやすさについては:
- サービスファイルを書くためにsystemdの知識は必要
- 簡単なケースでも複数サービスファイルを書くのは必要
紹介した「fig」より使いにくい(figはひとつだけのYAMLファイルを書いて、「fig up」でsingle-hostに自動deploy)。
使いやすさを改善するためfig2coreosというツールを検証しました。
使い方は:
figのYAMLファイルを書く --> fig2coreosでsystemdのservice fileへ変換 --> fleetctlで生成したservice filesをdeploy
ひとつのYAMLファイルだけを書く、systemdの知識も不要、より便利になります。
このhandsonには三つの例があります。一番簡単の例を例えます:
$ cat quickstart.yamlweb: image: ctlc/wordpress ports: - 80:80 environment: DB_USER: root DB_PASSWORD: qa1N76pWAri9 links: - dbdb: image: ctlc/mysql ports: - 3306:3306 environment: MYSQL_DATABASE: wordpress MYSQL_ROOT_PASSWORD: qa1N76pWAri9 |
systemdのservice fileに変換:
$ fig2coreos myapp quickstart.yaml quickstart$ cd quickstartdb-discovery.1.servicedb.1.serviceweb-discovery.1.serviceweb.1.service |
ただfig2coreosの制限があります:
今現在fig2coreosもsingle-hostしか使えませんのでmulti-host環境に行けないです。 multi-hosts環境での使いやすさを改善するため、multi-hostsの対応は必要になります。
とりあえずsingle-hostの開発環境にはfig2coreosのツールでCoreOSを使うと便利です。
3.まとめ
- single-host環境なら「fig」あるいはfig2coreosを使ってCoreOSでdockerを楽しめる、便利さはよい。
- multi-hosts環境ならCoreOSはDockerのcluster管理ツールとして大きく期待できると思います。
- single-host環境からmulti-hosts環境までCoreOSで一貫性のあるdocker管理には使いやすさの改善は必要、yaml2coreosのようなツールは解決案のひとつ。
CoreOSはまだActive development状態なので本番環境で使いたいならversion問題の取扱など要注意です。
4.参考文献
-
Docker Project : https://github.com/docker/docker
- CoreOS: https://coreos.com/
- etcd project: https://github.com/coreos/etcd
- fleet project: https://github.com/coreos/fleet
- coreos-vagrant project: https://github.com/coreos/coreos-vagrant
- fig: http://orchardup.github.io/fig/
- fig2coreos project: https://github.com/CenturyLinkLabs/fig2coreos
- article: http://stackoverflow.com/questions/17989306/what-does-docker-add-to-just-plain-lxc
- google keynote : http://www.slideshare.net/dotCloud/eric-brewer-dockercon-keynote
- Kubernetes project: https://github.com/GoogleCloudPlatform/kubernetes
- Mesos: http://mesos.apache.org/
- Marathon project: https://github.com/mesosphere/marathon.git
- boot2docker project: http://boot2docker.io/
- docker-osx: https://github.com/noplay/docker-osx
- ambassador pattern: https://coreos.com/blog/docker-dynamic-ambassador-powered-by-etcd/
- fig2coreos project: https://github.com/CenturyLinkLabs/fig2coreos