LoginSignup
12
11

More than 5 years have passed since last update.

DockerCon EU 2015のオーケストレーションハンズオン on Azure

Posted at

Docker Orchestration Toolsのチュートリアル

この度DockerCon EU 2015に参加してきました。
12281685_1065455416827609_1024759276_o.jpg
のハンズオンラボの内容が面白そうだったのですが、私は自社で出店していたブースのお守りもあったため、当日はあまりできませんでした。ですので、帰国後自分で楽しんでみることにしました。

今回はAzureで動作させるときの手順を書いてみたいと思います。

12281855_1065456156827535_719777253_o.jpg

Lab 2 : Docker Orchestrationこれが、Docker社が公開していた、ハンズオンです。
Swarm、Compose、そしてInterlockを使って、Swarmの環境にスケールするWeb-DBアプリケーションをデプロイするデモです。いろいろはまりましたが楽しかったです。

1. インスタンスの準備

実はこのチュートリアル、本来はAWSでインスタンスが提供されるようになっていました。
環境を作ってわかったのですが、そこまで行くのが結構めんどくさいからでした。

普通だと、docker-machineでちょろっとインスタンス用意したらDockerの環境環境構築など簡単です。ところが、本チュートリアルは、TLSを使わない前提になっているのですが、最新のdocker-machineはTLSをオフにすることができないようです。

つまり、TLSを使わないDocker環境を作らないといけないわけです。

また、チュートリアルでは3つのインスタンスを使いますが、最後の一つのインスタンスはスケールアウトするときにポートをたくさん使います。ですので、ポートをレンジで開ける必要がありますが、例えばAzureのクラシックVMはこれが得意ではありません。実際にやろうと思うと、PowerShellでちょろっとやらないといけないようです。

また、最初は、Ubuntu 14.04(LTS)を使うつもりでしたが、Dockerの標準のインストール手順で実施すると、その通りにできない感じでしたので、これを機会に、15.04に取り組んで見ることにしました。

Ubuntu 15.04のVMをブートすればよいですが、classic VMではなく、ResourceManagerのVMをブートしましょう。classic VMだと、たくさんのポートを開けるのは面倒ですが、ResourceManagerのVMを使うと、ポートを範囲指定することができます。

Screen Shot 2015-11-23 at 19.03.53.png

Screen Shot 2015-11-23 at 22.47.54.png

わたしはこのチュートリアルのためにswarm-master, swarm-agent-01, swarm-agent-02というインスタンスを3台起動しました。

2. Dockerのインストール

Dockerのインストールは下記の手順に従うとあっさりできました。

Docker / Ubuntu

わたしが実施した内容をメモとして書いておきます。3台のマシンとも同じ手順です。

apt-getのリポジトリに使うキーを取得

$ sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D

apt-getのリポジトリを追加

/etc/apt/sources.list.d/docker.listファイルを下記のようにする

# Ubuntu Vivid 15.04
deb https://apt.dockerproject.org/repo ubuntu-vivid main

リポジトリを更新しておく

$ sudo apt-get update

おすすめパッケージ群のインストール

$ sudo apt-get install linux-image-extra-$(uname -r)

Docker Engineのインストール

$ sudo apt-get update
$ sudo apt-get install docker-engine
$ sudo service docker start

動作確認

$ sudo docker run hello-world

これでまずはあっさり動きました。

3. Dockerを他のマシンから使えるようにするための設定

Swarmを使うときは、Dockerを他のマシンから使えるようにする必要があります。今回実施したチュートリアルは、TLSを使わないようになっているので、TLSを使わずにdockerの設定をします。一般的に出回っているのは、Ubuntu 14.04の手順なので、Ubuntu 15.04だと若干手順が異なります。

これは、Ubuntu 15.04からUpstartの代わりにSystemdが使われるようになったからです。大抵のインターネットの手順には次のように書いています。これは15.04では、動作しない方法です。デーモンを動かすときに、ソケットと、2375ポートをリッスンするようにしています。

$ sudo nano /etc/default/docker
# Use DOCKER_OPTS to modify the daemon startup options
DOCKER_OPTS="-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --label=environment=staging"

代わりに次の手順を使います。

/etc/systemd/system/docker-tcp.socketというファイルを作ります。systemdでは
このようにファイルを作って、ポートのリッスンを有効にします。

[Unit]
Description=Docker Socket for the API  
[Socket]
ListenStream=2375  
BindIPv6Only=both  
Service=docker.service  
[Install]
WantedBy=sockets.target  

その後

$ sudo systemctl enable docker-tcp.socket
$ sudo systemctl enable docker.socket
$ sudo systemctl stop docker
$ sudo systemctl start docker-tcp.socket
$ sudo systemctl start docker

テストは次のようにすると、ネットワーク経由で、dockerがアクセスできるようになっているかを確認できます。

$ docker -H tcp://127.0.0.1:2375 ps

手元のクライアントから、このdockerホストを操作指定場合、クラウドを利用しているときなど2375ポートをオープンする必要があります。なおこの設定ができていたらお手元のクライアントから。

$ export DOCKER_HOST=xxxxxxx:2375

を設定することで、リモートからdockerを操作することができます。
ただし、平文で通信していますので、実際の運用ではTLSを使ってください。TLSを使っている場合、ポート番号は2376になります。

Setting Docker’s DOCKER_OPTS on Ubuntu 15.04
Enable Remote API on Docker hosts running systemd (like Ubuntu 15.04)

4. SwarmとComposerのインストール

swarm-masterのサーバーに、SwarmとComposerをインストールします。

Composerのインストール (swarm-master)

Composerのインストールはとても簡単です。dockerを外部から使える設定
にしている場合は、お手元のコンピュータにインストールしても結構です。

Install Docker Compose

今回は、swarm-masterのサーバーにインストールしてみました。

master $ sudo -i
master # curl -L https://github.com/docker/compose/releases/download/1.5.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
master # chmod +x /usr/local/bin/docker-compose
master # exit
master $ docker-compose --version
docker-compose version: 1.5.1

agentサーバーへ環境のラベルを設定する (swarm-agent-0x)

今回の環境では、

  • swarm-master : Swarmのマスター
  • swarm-agent-01 : Staging環境
  • swarm-agent-02 : Production環境

となっています。これらの環境の区別をするために、swarm-agent-01, swarm-agent-02でそれぞれ次の設定を行います。

それぞれの環境にdockerデーモン起動時に--label=environment=staging--label=environment=productionのラベルをつけます。そのためには、先ほどのsystemdを利用します。

/lib/systemd/system/docker.serviceのファイルを次のように編集します。ポイントは、EnvironmentFileの追加と、ExecStartのところへの $DOCKER_OPTSの追加です。

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target docker.socket
Requires=docker.socket

[Service]
Type=notify
EnvironmentFile=/etc/default/docker
ExecStart=/usr/bin/docker daemon -H fd:// $DOCKER_OPTS
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity

[Install]
WantedBy=multi-user.target

/etc/default/dockerファイルにも次の行を追加します

swarm-agent-01サーバ

DOCKER_OPTS="--label=environment=staging"

swarm-agent-02サーバ

DOCKER_OPTS="--label=environment=production"

その上で、swarm-agent-01, swarm-agent-02の両方のサーバーでdockerデーモンを再起動します。止めようとすると、エラーが出るときがありますが、そのエラーメッセージにかかれている、systemctlコマンド(systemctl daemon-reload)を実行すると問題なくなります。

$ sudo systemctl stop docker-tcp.socket
$ sudo systemctl daemon-reload
$ sudo systemctl stop docker
$ sudo systemctl start docker-tcp.socket
$ sudo systemctl start docker

swarm-masterでswarmのインストール

swarmのトークンを振り出します。このトークンはクラスタを区別するためのユニークな識別子です。そして、下記の指定でswarmのマネージサーバーを起動します。これ自体がdockerのコンテナです。尚、本チュートリアルでは、3375ポートはオープンする必要があります。

master $ export DOCKER_HOST=127.0.0.1:2375
master $ export TOKEN=$(docker run --rm swarm create)
master $ docker run -d -p 3375:2375 swarm manage token://$TOKEN

エージェントサーバーのswarmへの追加

2台のエージェントサーバーをswarmに追加します。2台のエージェントサーバーのプライベートアドレスを記入します。Resource Managerを利用してVMを起動したときのプライベートアドレスの発見方法はAzureの新ポータルからswarm-masterの場合

swarm-master > Settings > Network interfaces でパブリックと、プライベートのポートを見ることができます。プライベートIPは同じリソースグループの間であればInboundポートの設定をしなくてもアクセス可能です。

master $ docker run -d swarm join --addr=<swarm-agent-01_private_ip:2375> token://$TOKEN
master $ docker run -d swarm join --addr=<swarm-agent-02_private_ip:2375> token://$TOKEN

動作確認。エージェントサーバーが追加されていることがわかります。下記のように認識されないケースは、docker logs などで原因を探ってください。わたしは、token://$TOKENのところを間違えてtoken//$TOKENとしていて、エラーがでないため、ちょっとはまりました。

$ docker -H tcp://0.0.0.0:3375 info
Containers: 0
Images: 0
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 2
 node-1: ************.compute.amazonaws.com:2375
  └ Containers: 3
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 3.859 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.19.0-26-generic, operatingsystem=Ubuntu 14.04.3 LTS, storagedriver=aufs
 node-2: *****************.eu-central-1.compute.amazonaws.com:2375
  └ Containers: 2
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 3.859 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.19.0-26-generic, operatingsystem=Ubuntu 14.04.3 LTS, storagedriver=aufs
CPUs: 2
Total Memory: 7.718 GiB
Name: 5dc162006656

5. デプロイの実施

今はdockerコンテナとして、swarm managerが動作しているので、DockerHostを変更しておきます。

master $ export DOCKER_HOST={swarm-master-PrivateIP}:3375

今回dockerから、サンプルが提供されているのでそれを使ってみます。適当なディレクトリで下記のファイルを展開してください。

master $ git clone https://github.com/nicolaka/dockchat.git

このような感じになっています。

master $ cd dockchat/
swarm-master:~/dockchat$ tree
.
├── docker-compose.yml
├── Dockerfile
├── README.md
├── requirements.txt
├── static
│   └── style.css
├── templates
│   └── form_action.html
└── webapp.py

本家のチュートリアルでは、docker-composeのみで動作させる手順も載っていますが、割愛して、いきなりswarmの用の手順を書いておきます。

最初にDockerHubにログインしてください。

master $ docker login

DockerHubのユーザ名+dockchatというアプリ名をつけてタグをつけます。そして、DockerHubにpushします。

master $ docker build -t {Your_Docker_Hub_username}/dockchat:v1 .
master $ docker push {Your_Docker_Hub_username}/dockchat:v1

次に、docker-compose.ymlを、staging.docker-compose.ymlとしてコピーして次のように変更します。environmentがdbとwebに追加されているのと、web:の次の行が、build: . からimageに変更されて、先ほどDockerHubにあげたイメージを取得するようになっています。

# Mongo DB
db:
  image: mongo
  expose:
    - 27017
  command: --smallfiles
  environment:
   - "constraint:environment==staging"
# Python App
web:
  image: <your_Docker_Hub_username>/dockchat:v1
  ports:
    - "5000:5000"
  links:
   - db:db
  environment:
   - "constraint:environment==staging"

stagingへのデプロイ

ステージングへデプロイしてみましょう。

master $ docker-compose -f staging.docker-compose.yml -p dockchat_staging pull
master $ docker-compose -f staging.docker-compose.yml -p dockchat_staging up -d

Creating dockchatstaging_db_1
Creating dockchatstaging_web_1

master $ docker-compose -f staging.docker-compose.yml -p dockchat_staging ps

        Name                      Command             State             Ports
---------------------------------------------------------------------------------------
dockchatstaging_db_1    /entrypoint.sh --smallfiles   Up      27017/tcp
dockchatstaging_web_1   python webapp.py              Up      10.0.10.77:5000->5000/tcp

これでステージング(swarm-agent-01)へデプロイがなされました。興味があればswarm-agent-01のinboundの5000番ポートを開けると、swarm-agent-01のパブリックIP:5000でチャットアプリの画面が見れます。

productionへのデプロイ

同じく、production.docker-compose.ymlを作成します。本番では、interlockのHAProxyプラグインを使って、スケールと、負荷分散を実装します。

# Mongo DB
db:
  image: mongo
  expose:
   - 27017
  command: --smallfiles
  environment:
   - "constraint:environment==production"
# Python App
web:
  image: nicolaka/dockchat:v1
  ports:
   - "5000"
  links:
   - db:db
  environment:
   - "constraint:environment==production"
   - INTERLOCK_DATA={"hostname":"dockchat.com","domain":"dockchat.com"}
interlock:
  image: ehazlett/interlock:latest
  ports:
    - "80:80"
  volumes:
    - /var/lib/docker:/etc/docker
  environment:
   - "constraint:environment==production"
  command: "--swarm-url tcp://$DOCKER_HOST --debug --plugin haproxy start"

同じようにプロダクションにもデプロイします。その前に、ポートを公開しておきましょう。Interlockは、どうやら、30000以上のポートを使うようなので、そこはAzureの新ポータルで公開しておきましょう。

Screen Shot 2015-11-23 at 22.28.58.png

わたしは30000-65535を公開してみました。swarm-agent-02 > Settings > inbound security rules で、次のように設定しました。これは、Resource ManagerのVMでしかレンジ設定できないので注意が必要です。同様に、80番ポートも公開しておきます。Interlockは、HAProxyなので、このポートから実際のポートに割り振りを行います。ちなみに本当は、2375のポートを開ける必要は本来ありません。

Name : Swarm
Priority : 1200
Protocol : TCP
Source port range : *
Destination port range : 30000-65535
Action : Allow
master $ docker-compose -f production.docker-compose.yml -p dockchat_production pull
master $ docker-compose -f production.docker-compose.yml -p dockchat_production up -d
master $ Creating dockchatproduction_db_1
Creating dockchatproduction_web_1
Creating dockchatproduction_interlock_1

master $ docker-compose -f production.docker-compose.yml -p dockchat_production ps
             Name                           Command               State               Ports
--------------------------------------------------------------------------------------------------------
dockchatproduction_db_1          /entrypoint.sh --smallfiles      Up      27017/tcp
dockchatproduction_interlock_1   /usr/local/bin/interlock - ...   Up      443/tcp, 10.0.11.50:80->80/tcp
dockchatproduction_web_1         python webapp.py                 Up      10.0.11.50:32769->5000/tcp

手元のマシンの、/etc/hostsを下記のように書き換えます。プロダクションサーバーの
IPアドレス(swarm-agent-02のアドレス)をdockchat.comとして指定してみてください。

mylaptop$ vim /etc/hosts

(+) {PUBLIC_IP_OF_NODE-2}   dockchat.com

最後にスケールアップします。注意事項としては、このスケールアウトでは、ポートが自動で割り振られ
ます。スケールアウト時にこのポートが空いている必要があります。そうすれば、Interlockが認識してくれます。
そうでないと、せっかくスケールアウトしても、Interlockが認識してくれません。

machine $ docker-compose -f production.docker-compose.yml -p dockchat_production scale web=10

Creating and starting 2 ... done
Creating and starting 3 ... done
Creating and starting 4 ... done
Creating and starting 5 ... done
Creating and starting 6 ... done
Creating and starting 7 ... done
Creating and starting 8 ... done
Creating and starting 9 ... done
Creating and starting 10 ... done


machine $ docker-compose -f production.docker-compose.yml -p dockchat_production ps

             Name                           Command               State               Ports
--------------------------------------------------------------------------------------------------------
dockchatproduction_db_1          /entrypoint.sh --smallfiles      Up      27017/tcp
dockchatproduction_interlock_1   /usr/local/bin/interlock - ...   Up      443/tcp, 10.0.11.50:80->80/tcp
dockchatproduction_web_1         python webapp.py                 Up      10.0.11.50:32769->5000/tcp
dockchatproduction_web_10        python webapp.py                 Up      10.0.11.50:32771->5000/tcp
dockchatproduction_web_2         python webapp.py                 Up      10.0.11.50:32770->5000/tcp
dockchatproduction_web_3         python webapp.py                 Up      10.0.11.50:32775->5000/tcp
dockchatproduction_web_4         python webapp.py                 Up      10.0.11.50:32777->5000/tcp
dockchatproduction_web_5         python webapp.py                 Up      10.0.11.50:32774->5000/tcp
dockchatproduction_web_6         python webapp.py                 Up      10.0.11.50:32773->5000/tcp
dockchatproduction_web_7         python webapp.py                 Up      10.0.11.50:32772->5000/tcp
dockchatproduction_web_8         python webapp.py                 Up      10.0.11.50:32776->5000/tcp
dockchatproduction_web_9         python webapp.py                 Up      10.0.11.50:32778->5000/tcp

さて、お手元のブラウザで dockchat.comにアクセスしてみてください。リロードごとに違うインスタンスが使われているのがわかると思います。

Screen Shot 2015-11-23 at 22.28.20.png
Screen Shot 2015-11-23 at 22.28.33.png

 また、dockchat.com/haproxy?statsを見ると、管理画面を見ることができます。
ちなみにユーザ/パスワードを聞かれたら stats/interlockです。
Screen Shot 2015-11-23 at 22.25.23.png

6. 障害時には?

さて、スケールアウトのときになぜか画面が出てこないとかの問題に出会ったら、先の管理画面にちゃんとサーバーが認識されているか?というのと、ログを見ることをしてみましょう。

master $ docker-compose -f production.docker-compose.yml -p dockchat_production logs

という感じでログを見ることができます。

ではみなさまハッピーコーディングを!

12
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
11