Skip to content

マルチホストdocker環境でのBlueGreenなデプロイメント

Posted on:2015-03-19 at 04:00 AM

Overview

dockerをそれなりに扱おうと思うと直面するのがマルチホスト環境でのdockerの構成。
大抵シングルホストのプリミティブな環境では問題無かったL3/L4の扱い、IPアドレス、ポート等のメタデータのリソース管理が問題になってくる。
前者に関しては、ルーティングコンテナ経由でのパケット交換、cgroup/namespaced、Open vSwtichなどでSDNを実装、
L3/L4を抽象化し仮想的に1つのネットワークとして扱えるようにすることで解決をしようという動きがある。 代表的なソリューションとしてはsocketplane, weave, pipework, flannel, Open vSwitch等のソリューションがある。

後者に関して分散Key Valueストアにコンテナのメタデータを登録し必要に応じてクラスタの構成情報を読み出す
ことで解決しようとする動きがある。 代表的なソリューションとしてはConsuletcdzookeeper等がある。

マルチホストdocker環境で辛いところ

やりたいこと

やったこと

weaveでホストごとに存在するdockerのプライベートネットワークをL3レベルで抽象化、複数のホストにまたがるdockerネットワークを一つのネットワークとして扱えるようにし、Consul/consul-template/registratorでメタデータの管理/configの自動書き換え及びBlueGreenなクラスタの切り替え、またコンテナのスケジューリング/ライフサイクル管理にdocker-swarm/docker-composeを使用しクラスタ全体を透過的に管理出来るようにした。
それぞれの構成要素は単体で落ちても他の構成要素には影響しないものとし、ホスト障害があってもクラスタ全体としては可用性を存続出来るようにする。 なお前提として各構成要素は全てコンテナのためOSは便宜的にCoreOSを使用しているがホストでdockerさえ動作すればどんな環境でも動作するようになっている。

構成イメージ

docker-weave-swarm

Requirements

Weave

dockerネットワークの抽象化にはWeaveを使う。
Weaveは各ホストに存在するローカルなdockerネットワークを抽象化し、1つのネットワークとして扱うことを可能にする。

sudo vim /etc/systemd/system/install-weave.service
[Unit]
After=network-online.target
After=docker.service
Description=Install Weave
Documentation=http://zettio.github.io/weave/
Requires=network-online.target
Requires=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/usr/bin/wget -N -P /opt/bin \
    https://raw.github.com/zettio/weave/master/weave 
ExecStartPre=/usr/bin/chmod +x /opt/bin/weave
ExecStartPre=/usr/bin/docker pull zettio/weave:latest
ExecStart=/bin/echo Wave Installed
sudo vim /etc/systemd/network/10-weave.network
[Match]
Type=bridge
Name=weave*

[Network]
Address=10.0.0.1/8
sudo vim /etc/systemd/network/10-weave.netdev
[NetDev]
Name=weave
Kind=bridge
sudo vim /etc/systemd/system/weave.service
[Unit]
After=install-weave.service
Description=Weave Network
Documentation=http://zettio.github.io/weave/
Requires=install-weave.service

[Service]
ExecStartPre=/opt/bin/weave launch
ExecStart=/usr/bin/docker attach weave
sudo systemctl restart systemd-networkd
sudo systemctl start install-weave.service
sudo systemctl start weave.service
sudo /opt/bin/weave create-bridge

Docker

docker用の管理ポートを開ける。

sudo vim /etc/systemd/system/docker-tcp.socket
[Unit]
Description=Docker Socket for the API

[Socket]
ListenStream=2375
BindIPv6Only=both
Service=docker.service

[Install]
WantedBy=sockets.target

dockerのデフォルトブリッジをweaveし、dockerから透過的にweaveネットワークを扱えるようにする。

sudo cp /usr/lib/systemd/system/docker.service /etc/systemd/system/
sudo vim /etc/systemd/system/docker.service
Environment=DOCKER_OPTS='--bridge=weave --fixed-cidr="10.0.0.0/8" --insecure-registry="0.0.0.0/0"'
sudo systemctl enable docker-tcp.socket
sudo systemctl stop docker
sudo systemctl start docker-tcp.socket
sudo systemctl start docker
# Accept a manage node
sudo iptables -A INPUT -s 10.0.0.1 -m tcp -p tcp --dport 2375 -j ACCEPT
# Drop other nodes
sudo iptables -A INPUT -s 0.0.0.0/0 -m tcp -p tcp --dport 2375 -j DROP

参照: https://coreos.com/docs/launching-containers/building/customizing-docker/

Swarm

docker run --rm swarm create
6856663cdefdec325839a4b7e1de38e8
docker run -d --name swarm_agent swarm join --addr=<node_ip:2375> token://<cluster_id>
docker run -d --name swarm_manager -p <swarm_port>:2375 swarm manage token://<cluster_id>
docker run --rm swarm list token://<cluster_id>
docker kill swarm_agent
docker kill swarm_manager

Compose

curl -L https://github.com/docker/compose/releases/download/1.1.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
mkdir nodes
cd nodes
vim docker-compose.yml
consul:
  command: --name consul -server -bootstrap -ui-dir /ui -data-dir ./data
  image: progrium/consul:latest
  ports:
  - "8300"
  - "8400"
  - "8500"
  - "8600/udp"
  environment:
  - "affinity:container!=nodes_consul_*"
  net: "host"

registrator:
  command: -internal consul://127.0.0.1:8500
  image: sttts/registrator:latest
  volumes:
  - "/var/run/docker.sock:/tmp/docker.sock"
  environment:
  - "affinity:container!=nodes_registrator_*"
  net: "host"

haproxy:
  image: shayashibara/docker-consul-template-haproxy
  environment:
  - "affinity:container!=nodes_haproxy_*"
  links:
    consul:consul
  ports:
  - "80:80"

apache:
  image: httpd
  environment:
  - "SERVICE_TAGS=production"
DOCKER_HOST=tcp://localhost:2375 docker-compose scale consul=3 registrator=3 haproxy=3 apache=6
DOCKER_HOST=tcp://localhost:2375 docker-compose ps

Consul / consul-template

Consulでコンテナのメタデータを管理し、Consul-templateでHAProxy配下のbackendを切り替える。

global
  log 127.0.0.1 local0
  log 127.0.0.1 local1 notice
  user haproxy
  group haproxy

defaults
  log global
  mode http
  option httplog
  option dontlognull
  balance roundrobin
  timeout connect 5000
  timeout client 50000
  timeout server 50000

listen stats
  bind *:8001
  option httpclose
  option forwardfor
  stats enable
  stats uri /haproxy?stats
  stats auth admin:123123q
  stats realm HAProxy\ Statistics

frontend web-app
  bind *:80
  default_backend {{key "backend/current"}}

backend default
  server s1 localhost:8080

{{range $tag, $services := service "apache-80" | byTag}}backend {{$tag}}
 balance roundrobin
{{range $services}} server {{.ID}} {{.Address}}:{{.Port}}
{{end}}{{end}}
pip install consulate
consulate --api-host 172.17.42.1:8500 kv set backend/current production
docker exec -it nodes_haproxy_1 cat /etc/haproxy/haproxy.cfg
DOCKER_HOST=tcp://localhost:2375 docker-compose kill
DOCKER_HOST=tcp://localhost:2375 docker-compose rm

Conclusion

マルチホストDocker環境でBlueGreenなデプロイを実現するためweaveでL3の抽象化とConsulによる分散Key-ValueストアでL3/L4リソースの管理、consul-templateで設定ファイルの動的書き換え、docker-swarm/composeによるコンテナのスケジューリング、ライフサイクル管理、BlueGreenなクラスタの切り替えを行った。
構成要素は多いものの各要素は疎結合でそれぞれ代替可能なツールが多い(weaveはpipeworkやflannel、Consulはetcdやzookeeper、consul-templateはconfd等ある)ので、要件に応じて構成要素は変えることが出来る。
dokkuやflynn、deis等のマイクロPaaSやCloud-FoundryやOpenShift等のフルスタックPaaSは単体で上記ツールチェインのほとんどの機能を備えている一方ロックインされやすいという面もあるため今回は既存の技術の組み合わせのみで構成した。

Docker誕生から2年を迎え牧歌的なシングルホストでのdon’t recommend in productionな状態からプロダクションでのマルチホスト環境を見据えたオーケストレーションツール群も大分整理統合されてきた感がある。
依然レポジトリの扱いやセキュリティ面等、実運用面で辛い箇所は残るものの徐々にプロダクション環境での現実的な解が見えてきたように思える。今年はdocker in productionの飛躍の年になることを願いたい。

解決していない課題

課題解決への布石

References