ラズパイ2で動く docker paas
TRANSCRIPT
ラズパイ 2 で動く Docker PaaS
Tetsuhiro Sato
2
自己紹介
佐藤 哲大( tetz ) 某ネットワークベンダで、 SDN (っぽい)仕
事をしてます ネットワークプログラマビリティ勉強会の企画、
運営をしてますhttp://network-programmability.connpass.com/
3
TL;DR ラズパイ2で動く Docker PaaS を自作し
てみたので、その仕組みを紹介します (時間に余裕があれば、)自作した PaaS
を CI (継続的インテグレーション)してみたので、その仕組みを紹介します
4
デモ①
<paas_name> は、既存の Linux コマンドと Linux ユーザとコンフリクトしなければ、なんでも可
<paas_name> は、ユーティリティコマンドと git リモートリポジトリの名前に使われる <paas_name> scale web=3 git push <paas_name> master
$ wget http://raw.github.com/tetsusat/raspaas/master/bootstrap.sh $ chmod +x bootstrap.sh$ sudo ./bootstrap.sh <paas_name>
5
そもそも Docker PaaS のうれしさDocker PaaS従来の PaaS
ハードウェア
ハイパーバイザ
OS
ハードウェア
OS
Docker エンジン
実行環境(言語、ライブラ
リ、ミドルウェア)
実行環境(言語、ライブラ
リ、ミドルウェア)
アプリケーション アプリケーション
実行環境が多様化すると、 PaaS ユーザはうれしいが、 PaaS 事業者はメンテナンスが大変
PaaS ユーザは Docker コンテナで動作させられる言語、ライブラリ、ミドルウェアを自由に利用できる
PaaS 事業者は Docker コンテナが動作する環境を用意すればいい
どちらもハッピー
6
なぜ、ラズパイ2で Docker PaaS ?
建前 ラズパイ2からクアッドコアに。これをカツカツに使いた
い 本音
x86 だと、すでにすぐれた Docker PaaS がかなりある(>_<)
PaaS のデファクト - Heroku キャッチーでポップなワークフローにより一世風靡
7
$ heroku createCreating polar-inlet-4930... done, stack is cedar-14http://polar-inlet-4930.herokuapp.com/ | https://git.heroku.com/polar-inlet-4930.gitGit remote heroku added
$ heroku scale web=2Scaling dynos... done, now running web at 2:standard-1x
$ git push heroku masterFetching repository, done.Counting objects: 10, done.Delta compression using up to 4 threads.Compressing objects: 100% (6/6), done.Writing objects: 100% (6/6), 876 bytes | 0 bytes/s, done.Total 6 (delta 4), reused 0 (delta 0)....
8
Heroku Inspired なDocker PaaS?
最小公倍数的な特徴(私見)ワークフローが Heroku っぽい
<heroku> creategit push <heroku> master<heroku> scale web=3
Buildpack 対応(後述) 具体例
シングルノードで動作する Dokkuマルチノードで動作する Deis 、 Flynn
9
Raspaashttps://github.com/tetsusat/raspaas
利用可能な環境 x86_64
Ubuntu14.04 / Docker 1.6 # Vagrantfile 参照 ARMv7
Hypriot Docker Image for Raspberry Pi (Version 0.4) http://blog.hypriot.com/downloads/
Scaleway (www.scaleway.com) できること
git push … で Docker コンテナが立ち上がる オートスケーリング (heroku scale web=3 みたいなやつ )
10
ちなみに Buildpack
アプリケーションを自動で検知し、実行する環境を用意する Heroku の仕組み
[ 参考 ] Buildpack Adventure 2 (http://ba2.herokuapp.com/)
11
Heroku Inspired なDocker PaaS 比較(不完全版)
Dokku Raspaas
CPU アーキテクチャ x86_64 x86_64 x86_64 x86_64 / ARMv7
OS CoreOS Ubuntu Ubuntu Ubuntu
ノード マルチ マルチ シングル シングル
アプリケーションのデプロイ方式
BuildpackDocker イメージDockerfile
BuildpackDocker イメージ
BuildpackDockerfile
Buildpack-likeDockerfile
12
デモ(つづき)
$ git clone https://github.com/tetsusat/ruby-sample.git $ teroku create$ git push teroku master$ teroku scale web=3
13
利用コンポーネント gitreceive (https://github.com/progrium/gitreceive/)
git push した際の git フックを仕掛けるためのユーティリティ Consul (https://www.consul.io/)
サービスディスカバリ Registrator (https://hub.docker.com/r/gliderlabs/registrator/)
Docker API からサービスを検知して Consul へ登録 Consul Template (https://github.com/hashicorp/consul-template)
Consul イベントを検知して Nginx の設定を更新 Nginx (http://nginx.org/)
ルータ( HTTP リクエストをロードバランス) Docker Compose (https://docs.docker.com/compose/)
Docker コンテナ管理のユーティリティ
14
git push でデプロイできる仕組み
Git Repogit push teroku master
① git clone …
③ docker build ….
④ docker run …
② Dockerfile の作成(なければ)
15
Buildpack-like
https://github.com/tetsusat/buildpack-like
Raspaas 向けの Builpack っぽい仕掛け 以下の言語に対応
Ruby (2.2.2) Python (2.7.10) Node.js (0.12.7)
言語毎に 2 つのスクリプトからなる detect compile
やってること( Ruby の場合)
#!/bin/bash
if [ -f "$1/Gemfile" ]; then echo "Ruby" exit 0fi
exit 1
detect
ファイルから言語を検知 Gemfile があれば Ruby requiremts.txt があれば Python package.json があれば Node.js
本家 Buildpack と同じ
17
やってること( Ruby の場合)
#!/bin/bash
省略
# generate Dockerfileecho "FROM raspaas/$LANG:$VERSION" > $1/Dockerfile
# generate docker-compose.ymlCMD=$(get_procfile_cmd $1/Procfile)APP=$(get_app_name $1)cat << EOF > $1/docker-compose.ymlweb: image: $2/$APP command: $CMD ports: - 5000EOF
compile
Dockerfile を作成 言語: detect スクリプトで検知 バージョン: Gemfile から
docker-compose.yml を作成 CMD : Procfile から ポート番号 : 5000 決め打ち
18
compile でできる DockerfileFROM ruby:2.2.2
ENV PORT 5000 EXPOSE 5000
RUN mkdir /app WORKDIR /app ONBUILD ADD ./Gemfile Gemfile ONBUILD ADD ./Gemfile.lock Gemfile.lock ONBUILD RUN bundle install
ONBUILD ADD . /appFROM raspaas/ruby:2.2.2
compile スクリプトが作成する Dockerfile
raspaas/ruby:2.2.2
compile スクリプトは FROM 文一行からなる Dockerfile を作成
継承する親 Dockerfile は Automated Build で管理 https://hub.docker.com/r/raspaas/ なので、 ARM では Buildpack-like が使えません (>_<)
19
オートスケーリングの仕組み
Docker エンジン
registrator
① 登録
Nginx +consul template
app
consul② 設定更新
teroku scale web=3
app app
Docker コンテナ(システム)
Docker コンテナ(ユーザ)
HTTP リクエスト
Docker API
20
Consul Template
{{range services}}upstream {{.Name}} { {{range service .Name}}server 10.0.2.15:{{.Port}}; {{else}}server 127.0.0.1:65535; # force a 502{{end}}}{{end}}
server { listen 80; {{range services}}location /{{.Name}} { proxy_pass http://{{.Name}}/; }{{end}}}
upstream ruby-sample { server 10.0.2.15:32768; server 10.0.2.15:32769; server 10.0.2.15:32770;}
server { listen 80; }location /ruby-sample { proxy_pass http://ruby-sample/; }}
/etc/nginx/conf.d/service.conf(一部のみ)/templates/service.ctmpl
Consul のイベントをトリガーにテンプレートから特定のファイル(設定ファイルなど)を動的に生成し、アクション(サービスのリローなど)を実行
21
Consul と Registrator Registrator は Docker API 経由で Docker の起動を検知
し、 Consul に登録してくれる
$ docker run -d -v /var/run/docker.sock:/tmp/docker.sock --restart=always --name registrator -h registrator gliderlabs/registrator consul://$DOCKER_IP:8500
$ docker run -d -p 8400:8400 -p 8500:8500 -p 8600:53/udp --restart=always --name consul -h consul progrium/consul -server -advertise $DOCKER_IP -bootstrap -ui-dir /ui
22
Scaleway ARM ベースのベアメタルクラウドサービス 4 コア CPU + 50GB SSD で € 2.99
(安っ!)
23
Drone+Gitlab+Vagrant でPaaS の CI 環境を構築してみた
24
drone.io
Travis CI 、 Circle CI のように、 Github 等の Git ホスティングサービスと連携できるホスティング型の CI ツール
ホスティング版だけでなく、オンプレ環境で動作するオープンソース版がある
Drone + Gitlab + Vagrant で PaaS の CI 環境をオンプレに無料で作れそう。。。
25
PaaS の CI
Drone Host Vagrant/Virtualbox
DroneDocker Engine
app app app
① Gitlab へ git push② Gitlab から Drone を呼び出し③ Drone がテスト用に Docker コンテナを生成④ Ansible で Vagrant VM の起動⑤ Ansible で PaaS (raspaas) のインストール⑥ Ansible で App (ruby-sample) のインストール⑦ Infrataster でテスト⑧ Ansible で App のオートスケーリング⑨ Infrataster でテスト⑩ Ansible で Vagrant VM の廃棄
④
⑩
⑤ ⑥ ⑧
⑦ ⑨
Docker コンテナ
VirtualBox VM
Infrataster
Ansible
①
②
③
26
Serverspec と Infrataster
[ 参考 ] Introduction Infrataster(https://speakerdeck.com/ryotarai/introducing-infrataster)
.drone.yml
27
image: "tetz/drone-npstudy"git: path:$$GITLAB/tetsusat/raspaasscript: - rm $HOME/.ssh/id_rsa - echo 'StrictHostKeyChecking=no' > $HOME/.ssh/ssh-config - ssh-keygen -f $HOME/.ssh/id_rsa -t rsa -q -N '' - sshpass -p $$VAGRANT_HOST_PASS ssh-copy-id $$VAGRANT_HOST_USER@$$VAGRANT_HOST - echo 'vagrant-host ansible_ssh_host=$$VAGRANT_HOST ansible_ssh_user=$$VAGRANT_HOST_USER' > hosts - echo 'vagrant-guest ansible_ssh_port=22222 ansible_ssh_host=$$VAGRANT_HOST ansible_ssh_user=$$VAGRANT_USER' >> hosts - ansible-playbook -i hosts playbooks/vagrant-up.yml - sshpass -p vagrant ssh-copy-id 'vagrant@$$VAGRANT_HOST -p 22222' - ansible-playbook -i hosts playbooks/raspaas-setup.yml - ansible-playbook -i hosts playbooks/app-setup.yml - cd tests - rspec spec/raspaas_app_spec.rb - ansible-playbook -i ../hosts ../playbooks/app-auto-scale.yml - rspec spec/raspaas_auto_scale_spec.rb - ansible-playbook -i ../hosts ../playbooks/vagrant-destroy.yml
Ansible インベントリ作成
Ansible Playbook 実行
Infrataster 実行
28
Ansible PlaybooksRaspaas のセットアップ
- hosts: vagrant-guest tasks: - name: restart docker engine command: sudo service docker restart - name: download bootstrap.sh command: wget http://raw.github.com/tetsusat/raspaas/master/bootstrap.sh - name: chmod +x bootstrap.sh command: chmod +x bootstrap.sh - name: start bootstrap script command: sudo ./bootstrap.sh teroku
playbooks/raspaas-setup.yml
29
Ansible Playbooksサンプル App のセットアップ
- hosts: vagrant-guest tasks: - name: change ssh config for git push shell: echo 'StrictHostKeyChecking no' > $HOME/.ssh/config - name: git clone command: git clone https://github.com/tetsusat/ruby-sample.git - name: teroku create command: teroku create args: chdir: ruby-sample/ - name: git push command: git push teroku master args: chdir: ruby-sample/
playbooks/app-setup.yml
30
Infrastater Spec ファイルサンプル App のテスト
require 'spec_helper'
describe server(:vagrant_host) do describe http('http://<vagrant_host>:8080/ruby-sample') do it "responds content including 'Hello, world'" do expect(response.body).to include('Hello, world') end endend
tests/spec/raspaas_app_spec.rb
31
Infrastater Spec ファイルオートスケーリングのテスト
require 'spec_helper'
seen = []
describe server(:vagrant_host) do 3.times do describe http('http://<vagrant_host>:8080/ruby-sample') do it "responds content including 'Hello, world' from unseen container" do see = "" if response.body =~ /Hello, world from (\w+)/ see = $1 end expect(seen).not_to include(see) seen << see end end endend
tests/spec/raspaas_auto_scale_spec.rb
32
実行イメージ
失敗 成功
33
おわり
ご清聴、ありがとうございました m(_ _)m