dockerの仕組みとiij社内での利用例
TRANSCRIPT
© 2014 Internet Initiative Japan Inc.
Dockerの仕組みとIIJ社内での利用例
maebashi @ IIJ
© 2014 Internet Initiative Japan Inc. 2
本日の話
• Dockerのコンテナ起動の仕組みについて(概略のみ)
• IIJ社内での利用例
特に断りがない限り、本資料の説明は CentOS 6.6 + docker 1.3.2を前提としている
この資料のURL: http://www.slideshare.net/maebashi/dockeriij
© 2014 Internet Initiative Japan Inc. 3
Docker とは?
• Docker Engine + Docker Hub のプラットフォーム – Docker Engine – コンテナ管理ソフトウェア – Docker Hub – Dockerのイメージを共有するためのクラウドサービス
© 2014 Internet Initiative Japan Inc. 4
コンテナとは何か?
• Linux標準機能を複数組み合わせて実現する隔離されたプロセス
Namespaces ネットワーク環境やファイルシステム等の分離
Cgroups メモリやCPUなどのリソース制限
Capabilities 権限降格
iptables ネットワークパケットフィルタ and NAT
© 2014 Internet Initiative Japan Inc. 5
docker run
• 指定イメージを元に新しいコンテナを作ってコマンドを実行する
# docker run centos:centos6 echo Hello, world Hello, world #
イメージ名 (リポジトリ名:タグ名)
コマンドと引数
© 2014 Internet Initiative Japan Inc. 6
Docker client と daemon
Host
Docker daemon docker pull docker run docker ... container container container
Docker client HTTP
Unix domain socket または TCP
Docker Hub
pull
push
© 2014 Internet Initiative Japan Inc. 7
Dockerの実装
• Go言語で記述 – ごく一部 C言語で記述 (libcontainerの一部)
• client と daemon は同一バイナリ – 起動時オプションで動作を切り替える – 実行バイナリとしては docker 本体と、もうひとつ
dockerinit がある
• execdriver, graphdriverを選べる
© 2014 Internet Initiative Japan Inc. 8
execdriver, graphdriver
• execdriver – コンテナを実行するドライバ
• lxc – lxc-* コマンド群を利用 • native – libcontainer を利用
• graphdriver – ディスクイメージ管理
• aufs • btrfs • devmapper • vfs
この資料では execdriver = native、graphdriver = devmapper を前提とする
© 2014 Internet Initiative Japan Inc. 9
コンテナ起動の流れ
image snapshot snapshot
process create start
動いている コンテナ
止まっている コンテナ
run Docker Hub
pull
(ひな形)
# docker run centos:centos6 echo Hello, world
© 2014 Internet Initiative Japan Inc. 10
コンテナ起動の流れ
image snapshot snapshot
process create start
動いている コンテナ
止まっている コンテナ
run Docker Hub
pull
(ひな形)
© 2014 Internet Initiative Japan Inc. 11
イメージの格納場所
• 上記dataファイルがブロックプール – data(とmetadata)の中に複数のイメージを格納 – devicemapper(dm)により論理デバイスとして使える
– dmで論理デバイスのスナップショットを作れる
# cd /var/lib/docker/devicemapper/devicemapper/ # ls -lh total 550M -rw-------. 1 root root 100G Nov 4 14:59 data -rw-------. 1 root root 2.0G Nov 4 14:59 metadata #
CentOS 6 の場合 /var/lib/docker/devicemapper/devicemapper/
© 2014 Internet Initiative Japan Inc. 12
dockerのイメージ管理
• 階層化され、子は親との差分を管理 • 各イメージはそれをbuildしたコンテナの情報を持つ
docker images --viz!でGraphviz用dotファイルを 出力
© 2014 Internet Initiative Japan Inc. 13
管理情報
• dockerのイメージIDとdevicemapperの論理デバイスとの対応
• 各イメージの親子関係、作成時刻、buildコンテナの情報等
/var/lib/docker/devicemapper/metadata/<ID>
/var/lib/docker/graph/<ID>/json
© 2014 Internet Initiative Japan Inc. 14
コンテナ起動の流れ
image snapshot snapshot
process create start
動いている コンテナ
止まっている コンテナ
run Docker Hub
pull
(ひな形)
© 2014 Internet Initiative Japan Inc. 15
docker create
• config生成
• 指定イメージからコンテナ用ファイルシステム作成 – イメージから<ID>-initというsnapshotを作成 – SetupInitLayer – <ID>-initから<ID>というsnapshotを作成
# docker create centos:centos6 echo Hello, world 13fd39df5f742cd90ce703852af274c98c00c7c559d236.....
/var/lib/docker/containers/<ID>/config.json hostconfig.json
© 2014 Internet Initiative Japan Inc. 16
コンテナ起動の流れ
image snapshot snapshot
process create start
動いている コンテナ
止まっている コンテナ
run Docker Hub
pull
(ひな形)
© 2014 Internet Initiative Japan Inc. 17
docker start
• 設定ファイル生成 – resolv.conf, hosts など
• コンテナ用ファイルシステムを一旦ホスト側の以下のディレクトリにマウント – /var/lib/docker/devicemapper/mnt/<ID>
• 新規 Namespace で、外部コマンド dockerinit プロセスを起動
(つづく)
# docker start –a 13fd39df5f74 13fd39df5f74 Hello, World
© 2014 Internet Initiative Japan Inc. 18
Namespace
• コンテナ実現のための中核となる機能 • プロセスが動作する空間を分離する
– いくつかの種類がある • Network Namespace – ネットワーク環境の分離 • Mount Namespace – ファイルシステムの分離 • PID Namespace – プロセステーブルの分離 • UTS Namespace – hostnameの分離 • IPC Namespace – IPCの分離 • User Namespace – UID/GIDの分離(docker 1.3では未使用)
© 2014 Internet Initiative Japan Inc. 19
dockerinit プロセス起動
• 起動コマンド
– コマンドライン引数例
– 親プロセス: docker daemon、子: dockerinit
• 外部コマンド(dockerinit)を起動する → cloneシステムコールの呼び出し
/var/lib/docker/init/dockerinit-1.3.2
native –console ”” –pipe 3 –root /var/lib/docker/execdriver/native/<ID> -- echo Hello, world
© 2014 Internet Initiative Japan Inc. 20
clone で新規Namespace
• docker daemonがdockerinitコマンドを起動する時のcloneのフラグを指定
CLONE_NEWNS!CLONE_NEWUTS!CLONE_NEWIPC!CLONE_NEWPID!CLONE_NEWNET!
c.ProcessConfig.SysProcAttr = &syscall.SysProcAttr{ Cloneflags: uintptr( namespaces.GetNamespaceFlags(container.Namespaces)), }
daemon/execdriver/native/driver.go
これらの OR をとったものをフラグとして指定
(詳細は man 2 clone 参照)
© 2014 Internet Initiative Japan Inc. 21
dockerinit 起動後
• 親(docker daemon) – 子プロセスのPIDを元にcgroup設定 – ネットワーク設定
• 子(dockerinit) – 子のPID Namespaceの中で PID=1で起動 – ネットワーク設定 – ファイルシステム関連設定(rootfsをマウント) – 本来コンテナ内で実行するコマンドを execv
© 2014 Internet Initiative Japan Inc. 22
コンテナのネットワーク
• コンテナ毎にNetwork Namespaceを分離 – 分離しないこともできる(ホストと共有)
eth0
Network Namespace
コンテナ1
eth0
Network Namespace
コンテナ2
eth0
Network Namespace
コンテナ3
vethXX vethYY vethZZ
docker0(仮想ブリッジ)
NIC
IPマスカレード
ホスト
ネットワーク
Network Namespace
veth (仮想NICのペア)
© 2014 Internet Initiative Japan Inc. 23
コンテナのファイルシステム
• Mount Namespaceでコンテナ毎に分離
docker create
/.../mnt/<ID>/ ! lost+found/ ! rootfs/ ! bin/ ! etc/ ! home/ ! ... !ホスト Mount Namespace
コンテナ Mount Namespace
コンテナ起動毎に スナップショットを作成
ホストLinuxの /var/lib/docker/devicemapper/mnt/<ID>/ !にマウント
コンテナの新規Mount Namespace内 で、その root に rootfs/ 以下をマウント
/ ! bin/ ! etc/ ! home/ ! ... !
mount
mount
snapshot image
docker start
コンテナ
ホスト
© 2014 Internet Initiative Japan Inc. 24
cgroups
• プロセスグループのリソース(CPU、メモリ、ディスクI/Oなど)の利用を制限 – dockerではcpu(set), memoryについて制限可
– デバイスへのアクセスも制限
• リソース使用状況の統計値がとれる
© 2014 Internet Initiative Japan Inc. 25
おまけ: docker exec
• 指定コンテナの中でコマンドを実行 – つまり、指定コンテナ(プロセス)と同じ
Namespaceでコマンドを実行 • 既存Namespaceに切り替えるには
setnsシステムコールを使う – Goのプロセスモデルとあまり相性が良くない
– main()に到達する前にCで書かれたinit()でなんとかしているっぽい
© 2014 Internet Initiative Japan Inc. 26
ここまでのまとめ
• dockerのコンテナはLinux標準機能のNamespaces, cgroups等を使用して実現
© 2014 Internet Initiative Japan Inc.
IIJ社内での利用例
継続的インテグレーション クラスタリング モニタリング
© 2014 Internet Initiative Japan Inc. 28
継続的インテグレーション(CI)
• drone – オープンソースの CI サーバ – dockerコンテナ内のクリーンな環境でビルド、テストを実行する
– GitHub/GitHub Enterprise/GitLab等と連携
© 2014 Internet Initiative Japan Inc. 29
継続的インテグレーション: 流れ
push drone 開発者
build"test"notify"deploy
clone
rpm
serf
event 社内IRC
社内yumリポジトリ
結果 docker"container
© 2014 Internet Initiative Japan Inc. 30
コンテナのクラスタリング
• 多数のDockerホスト上の多数のコンテナを管理したい
Docker Daemon Docker Daemon Docker Daemon
空き
Container
Container
Container
Container
Container
Container
Container
Container
クラスタ1
クラスタ2
クラスタ3
Host
© 2014 Internet Initiative Japan Inc. 31
クラスタ管理ツール
• fig – 開発環境用、ホスト1台のみ対象
• Apache Mesos – 複数ホストのリソース管理
• Kubernetes – Google Container Engineで使われている
• flynn, dokku – PaaS用
© 2014 Internet Initiative Japan Inc. 32
IIJ内製 docker manager 構成図
Docker Daemon
Container
Container
Container
slave
構成情報DB
master
request/response
CLI, Web UI など
Docker Remote API
API dockerホスト群
使用可能ホスト リソース空き情報
IPアドレス空き情報 etc
© 2014 Internet Initiative Japan Inc. 33
dockerコンテナのモニタリング
• 個々のコンテナのメトリクスを収集したいがコンテナ毎にsnmpdやその他エージェントを入れたくない
• dockerコンテナのメトリクス収集 – http://blog.docker.com/2013/10/gathering-lxc-docker-containers-metrics/
– cgroupsの統計情報を使うことにより、ホスト上で(コンテナの外から)メトリクスを収集可能
– コンテナのNetwork Namespaceに切り替えて /proc/net/devを参照することでネットワークの統計情報を得られる
© 2014 Internet Initiative Japan Inc. 34
docker-metricsd
• 各dockerホストに常駐、dockerコンテナの情報(cgroupsの統計情報等)を収集して返す – 似たようなもの: Google cAdvisor等
• githubで公開中 – https://github.com/maebashi/docker-metricsd
• Docker Hubでも公開中 – インストール & 実行
# docker run -v /usr/local/bin:/target maebashi/docker-metricsd # /usr/local/bin/docker-metricsd &
© 2014 Internet Initiative Japan Inc. 35
docker-metricsdはメトリクスをJSON形式で返す "memory": { "failcnt": 0, "stats": { "unevictable": 0, "total_unevictable": 0, "total_swap": 0, "total_rss": 380928, "total_pgpgout": 681084, "total_pgpgin": 697086, "total_mapped_file": 1433600, "total_inactive_file": 38936576, "mapped_file": 1433600, "inactive_file": 38936576, "inactive_anon": 0, "hierarchical_memsw_limit": 9223372036854776000, "hierarchical_memory_limit": 9223372036854776000, "cache": 102838272, "active_file": 63901696, "active_anon": 380928, "pgpgin": 697086, "pgpgout": 681084, "rss": 380928, "swap": 0, "total_active_anon": 380928, "total_active_file": 63901696, "total_cache": 102838272, "total_inactive_anon": 0 }, "max_usage": 139268096, "usage": 104189952 }, "interfaces": { "outpackets.0": 3021223,
"inbytes.0": 8228044607, "indrop.0": 0, "inerrs.0": 0, "inpackets.0": 6429687, "name.0": "eth0", "outbytes.0": 199687042, "outdrop.0": 0, "outerrs.0": 0 }, "cpuacct": { "throlling_data": {}, "cpu_usage": { "usage_in_usermode": 2.668e+10, "usage_in_kernelmode": 8.181e+10, "percpu_usage": [ 22599918565, 987624379, 65146098, 36705600, 18221767943, 5890326, 22768005795, 4033968, 218211598, 4302652, 5437296326, 23781278563, 18992360915, 18712487134, 55742891, 18522722054 ] } }
© 2014 Internet Initiative Japan Inc. 36
定期的にメトリクスを収集してGrafanaでグラフ化
container container container
dockerホスト群
docker-metricsd メトリクス収集 ツール(内製)
InfluxDB Docker Daemon
© 2014 Internet Initiative Japan Inc. 37
結果 ↓CPU Accounting
Memory→
↓Network traffic