Docker for Mac で Rancher を動かす

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/1db61554-c349-be77-7fb0-7faedc882068.png)



Rancher が Docker for Mac をサポートしていないらしいのですが、Virtualboxで別なDockerを無駄に立ち上げたくないし、なぜMacだと駄目なのか納得もできなかったので試してみました。:kissing:
動かすことができたら、そのRancherを使って簡単なサービスを構築してみたいと思います。

先ずは以下の記載。Docker for Mac はサポートされてないと明記されていますが、理由は書いてありません。。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/2fd0b4b4-73f0-83d5-f58d-c5247fb73fa4.png)
see: [Quick Start Guide - docs.rancher.com](https://docs.rancher.com/rancher/v1.3/en/quick-start-guide/)

# Docker for Mac で Rancher を動かす

## 結論
結論から言うと動きました。これと言って問題は出ていません。

気を付ける所は、以下ぐらいでした。

- `rancher/server` コンテナのMac側ボリュームマウントPATHを変更する
- Rancherのホスト登録URLに `127.0.0.1` は使わない（Docker for Mac の原因かは未だ確かめてません）


## 環境

- Mac: OS X EI Capitan (Version 10.11.6)
- Docker for Mac: 1.12.6 (14937)
- Rancher: v1.3.0

## Rancherサーバーのインストールと設定

[Quick Start Guide - docs.rancher.com](https://docs.rancher.com/rancher/v1.3/en/quick-start-guide/) を参考に進めていきます。

### Rancherサーバーの起動

Rancher自身もコンテナとして動くので起動させます。

```bash
$ sudo docker run -d -p 8080:8080 rancher/server
```
※ 正式手順では、`--restart=unless-stopped` オプションをつけますが、Mac上で立ち上げて置く必要もないので省略しています。


### 登録URLを設定する

Rancherサーバーが起動したら、ブラウザで http://localhost:8080 を開きいて`Host Registration URL`を設定します。設定ページは、「ADMIN」->「Settings」にあります。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/fa2d3cd9-5d70-32dc-b9ba-4f7385a60135.png)

今回は、`http://172.31.0.1:8080` に設定しました。
このURLは、Rancherエージェント（また別なコンテナ）がRancherサーバーへ接続するAPIエンドポイントとして使われます。このURLが`localhost`や`127.0.0.1`だったりコンテナから接続できないアドレスだとエージェントからの接続が失敗してしまいます。

#### Tips - 専用のIPを用意する

MacだとWi-FiネットワークでIPアドレスが環境によって変わってしまうことが多いと思います。これだと登録URLも変わり都合が悪いのでMacで固定IPを設定しました。

- Network設定（メニューバーのWiFi -> Open Network Preferences..）を開きます。
- 左下の「＋」ボタンでネットワークを追加します。
- Interfaceに「Wi-Fi」を選択して作成します。名前は任意で。
- 作成したネットワークを選択し「Advanced...」の設定項目に入ります。
- 「TCP/IP」タブを選び固定IPを設定します。以下参照。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/1ce0df9c-3eb1-4be3-88a9-67b86d9b8adf.png)

ターミナルで以下の様になっていれば成功です。

```bash:Macターミナルでインターフェースの確認
$ ifconfig en0
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
  ether 3c:15:c2:d3:5e:34 
  inet6 fe80::3e15:c2ff:fed3:5e34%en0 prefixlen 64 scopeid 0x4 
  inet 172.31.0.1 netmask 0xffffff00 broadcast 172.31.0.255
  inet 192.168.3.7 netmask 0xffffff00 broadcast 192.168.3.255
  nd6 options=1<PERFORMNUD>
  media: autoselect
  status: active
```

#### Tips - もっと簡単なIPをつかう

実は、`Host Resistration URL`のIPのはMacのIPでなくて良いので、以下でRancherコンテナのIPを調べてそれを設定することもできます。ただし再起動すると変わってしまうので注意が必要です。

```bash
$ docker inspect --format '{{ .NetworkSettings.IPAddress }}' <rancherのコンテナ名>
172.17.0.2
```



## Rancherホストの追加

次にRancherが管理するホストを登録します。

UIの「INFRASTRUCTURE」->「Hosts」->「Add Host」画面で、Rancherエージェントのコンテナ作成用のコマンドをコピーします。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/90ff8a37-05c4-0f0e-04d0-32d4d762c9ba.png)

コピーしたまま実行すると起動に失敗するので、以下の様に変更して実行します。

```bash
$ sudo docker run -d --privileged \
> -v /var/run/docker.sock:/var/run/docker.sock \
> -v $HOME/rancher:/var/lib/rancher \ # ここを"-v /var/lib/rancher:/var/lib/rancher"から変更する
> rancher/agent:v1.1.3 \
> http://172.31.0.1:8080/v1/scripts/EE883A8F4ED4B48F6B1E:1484319600000:FRYynPCEDcMyiIo14lxJSxYD4TM
```
※ `$HOME/rancher`の部分は環境に応じて変更してください。

実行後、1−2分して以下の様にホストが現れていたら成功です。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/37578c6f-feab-9fda-c3ee-b31533e52016.png)

`docker ps`で見ると複数のコンテナが起動されていると思います。

```bash
$ docker ps
CONTAINER ID        IMAGE                               COMMAND                  CREATED             STATUS              PORTS                              NAMES
e5fb926d81a1        rancher/scheduler:v0.5.0            "/.r/r /rancher-entry"   18 hours ago        Up 15 minutes                                          r-scheduler-scheduler-1-03c7f2af
17e0bd3e7ce4        rancher/healthcheck:v0.2.0          "/.r/r /rancher-entry"   42 hours ago        Up 15 minutes                                          r-healthcheck-healthcheck-1-446e005c
de6689305148        rancher/net:v0.8.1                  "/rancher-entrypoint."   42 hours ago        Up 15 minutes                                          r-ipsec-ipsec-router-1-d3790cf3
4da693010709        rancher/net:holder                  "/.r/r /rancher-entry"   42 hours ago        Up 15 minutes                                          r-ipsec-ipsec-1-c3301785
557a9cf4a039        rancher/net:v0.8.1                  "/rancher-entrypoint."   42 hours ago        Up 16 minutes                                          r-ipsec-ipsec-cni-driver-1-752a7b7c
ca94e20b39f1        rancher/dns:v0.13.0                 "/rancher-entrypoint."   42 hours ago        Up 16 minutes                                          r-network-services-metadata-dns-1-7e74b995
8025f2e8a471        rancher/metadata:v0.7.0             "/rancher-entrypoint."   42 hours ago        Up 16 minutes                                          r-network-services-metadata-1-e80cec1f
3178f95f3a73        rancher/network-manager:v0.4.0      "/rancher-entrypoint."   42 hours ago        Up 16 minutes                                          r-network-services-network-manager-1-d3660993
efeb30cfc331        rancher/agent:v1.1.3                "/run.sh run"            42 hours ago        Up 17 minutes                                          rancher-agent
5c19194b6ee8        rancher/server                      "/usr/bin/entry /usr/"   43 hours ago        Up 17 minutes       3306/tcp, 0.0.0.0:8080->8080/tcp   rancher-server
```

### なぜ標準のPATHだと駄目なのか

標準のPATHのまま実行すると以下の様なエラーが出ます。

```bash
$ sudo docker run -d --privileged \
> -v /var/run/docker.sock:/var/run/docker.sock \
> -v /var/lib/rancher:/var/lib/rancher \
> rancher/agent:v1.1.3 \
> http://172.31.0.1:8080/v1/scripts/EE883A8F4ED4B48F6B1E:1484319600000:FRYynPCEDcMyiIo14lxJSxYD4TM

...省略...

docker: Error response from daemon: Mounts denied: 
The path /var/lib/rancher is not shared from OS X and is not known to Docker.
You can configure shared paths from Docker -> Preferences... -> File Sharing.
See https://docs.docker.com/docker-for-mac/osxfs/#namespaces for more info.
..
```

`/var/lib/rancher` は駄目と言われています。これはDockerのFile Sharing設定がされてないからです。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/4067998a-951f-f897-9442-ac47e2450f77.png)

ただし、 `/var` を追加しようとしてもエラーになり使えません。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/2111258b-322b-d45f-69e6-afbaccec8fd7.png)

ここまでが Docker for Mac で Rancher を動かす内容でした。次はこの Rancher on Docker for Mac でサービスを作ってみたいと思います。 :smiley: 


# Rancherで簡単なシステム構築

##  作るもの

構成は以下の様なものを作ります。

```
          +----------+    +----------+    +----------+
(Mac)-----|    lb    |----|rancher-lb|----|  webapp  | 
          +----------+    +----------+    +----------+
```

作成したStack（後述）は以下の様になります。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/af737f87-c88d-1d06-0dfc-2b22b4292bbc.png)

なぜ、ロードバランサー(lbとrancher-lb)が2つあるのかと言うと、rancherが提供するロードバランサー（rancher-lb）はホストのインターフェースIPをバインド出来ないからです。 :scream: 

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/d54b43f3-37d5-7ea2-9b49-ea85acef9f2a.png)
see: [Load Balancers - docs.rancher.com](https://docs.rancher.com/rancher/v1.3/en/cattle/adding-load-balancers/)

MacのIPアドレスをバインドさせるhaproxyを作り、その分散先としてrancher-lbを登録し、さらにそのrancher-lbの分散先をwebappにして最終的にwebappのクラスタ（Rancherでいうサービス）へ分散する構成にしています。


## 単語の定義説明
UIが分かりやすく出来ているので余り迷うことはないと思いますが、Rancherで使われている単語や定義を簡単に説明します。

- Service・・用途別のコンテナをグループ化する（Docker Image 単位）。web, application, dbなどのTierを想定。
- Stack・・Serviceのグループ化。一連のアプリケーションを関連付け。一つのサービスやシステムを想定。 
- Environment・・環境。Production, Staging, Developmentなどの使い分けが想定を想定。

## Stackの作成
`Stack`を作成しておきます。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/bfd6cb79-9b1b-56a4-aa17-a356066245a0.png)



## webappサービスを作成
Webサーバーを作成します。アクセスされたコンテナによって表示を出し分けたいので一番簡単そうなApache＋PHPで作成します。

予めindex.phpを準備しておきます。

```bash:index.php
<?php

echo date("Y-m-d H:i:s");
echo " hostname: ";
echo gethostname();
echo "\n";

?>
```

以下の様なレスポンスを期待しています。コンテナ名を表示してどのコンテナにアクセスしたか分かるようにするのが目的です。

```text:期待するHTTPレスポンス
YYYY-MM-DD HH:mm:ss hostname: container_hostname
```

先ほど作成したStackで「Add Service」して、必要な情報を指定して作成します。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/4fcfbacb-9d97-65da-818f-fd19d1643e87.png)



```yaml:webappサービスの設定
Name: webapp
Select Image: php:7.0-apache
Volumes: /Users/user/rancher/webapp/index.php:/var/www/html/index.php:ro # 作ったindex.phpをマウント。
```

コンテナに入って確認してみます。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/f9b5fb8c-d19e-ae3d-b380-72788537210d.png)


![image](https://qiita-image-store.s3.amazonaws.com/0/142397/62ad0cfd-448c-8668-8f56-a40f196311e7.png)

上手く動きました :tada: 
「Execute Shell」便利ですね〜 :thumbsup: 

## rancher-lbサービスの作成

rancher-lbは、Rancherが管理してくれるロードバランサー機能で作成します。SSL TerminationやURL分散などUIから設定することが出来き、必要十分な機能が使えます。さらに、haproxy.cfgをアップロードもできるので全ての機能を使うこともできます。

「Add Load Balancer」を選択して作成します。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/1311a40b-19c3-81f9-0cbf-b4673d8ecd85.png)

```yaml:rancher-lbの設定
Name: rancher-lb
Access: public
Protocol: HTTP
Port: 81 # rancher-lbのリッスンポート
Target: webapp # 先ほど作ったwebappサービスを選択
Port: 80 # コンテナのポート
```

## LBサービスの作成

haproxyでMacのIPとrancher-lbを接続するサービスを作ります。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/6f3b29ad-ebf3-f1af-92a8-8866a6983dff.png)

```yaml:lbサービスの作成
Name: lb
Select Image: haproxy:latest
Port Map - Public Host Port: 80
Port Map - Private Container Port: 80
Port Map - Protocol: TCP
Volumes: /Users/user/rancher/lb/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
Networking - Network: Bridge
```

haproxy.cfgは以下を使いました。

```py:haproxy.cfg
global
    daemon
    maxconn 4096
    maxpipes 1024

defaults
    maxconn 4096
    mode tcp
    option forwardfor
    option http-server-close
    option redispatch
    retries 3

resolvers rancher
nameserver dnsmasq 169.254.169.250:53

frontend 80
bind *:80
mode http
default_backend 81

backend 81
acl forwarded_proto hdr_cnt(X-Forwarded-Proto) eq 0
acl forwarded_port hdr_cnt(X-Forwarded-Port) eq 0
    http-request add-header X-Forwarded-Port %[dst_port] if forwarded_port
    http-request add-header X-Forwarded-Proto https if { ssl_fc } forwarded_proto
mode http
server rancher-lb 172.17.0.1:81 # rancher-lbサービスのIPとポート
```

これでMacから接続出来るようになりました。 :clap: 

```bash:MacターミナルからHTTPアクセス
$ curl localhost
2017-01-13 17:21:06 hostname: bea4f484cef5
```

## スケールさせてみる

Rancherではサービス毎にスケールが簡単にできるので、HTTPリクエストのレスポンスを見てコンテナが増えるのを確認してみます。

webappサービスの画面に入りScaleの「＋」を押してコンテナ数を増やします。

![image](https://qiita-image-store.s3.amazonaws.com/0/142397/9febf88c-1e46-bc52-944b-a911d04be228.png)

スケールするときに連続してHTTPアクセスをしておきながら、コンテナ名が変わるのを確認します。

```bash:MacコンソールからHTTP連続アクセス
$ while true; do curl localhost ; sleep 2 ; done
2017-01-13 17:28:12 hostname: bea4f484cef5
2017-01-13 17:28:14 hostname: bea4f484cef5
2017-01-13 17:28:16 hostname: bea4f484cef5
2017-01-13 17:28:21 hostname: ad20c7329672 # 1個増えた
2017-01-13 17:28:23 hostname: bea4f484cef5
2017-01-13 17:28:25 hostname: cbdefcc553be # 2個目も増えた
2017-01-13 17:28:27 hostname: ad20c7329672
2017-01-13 17:28:29 hostname: bea4f484cef5
2017-01-13 17:28:31 hostname: cbdefcc553be
```

分散先が増えてるのが分かります。 :smirk:

# 最後に

コンテナをサービスとして導入するにはどうやって運用管理や監視をしていくことが課題になってくると思います。Rancherは、分かりやすいUIがあり、かつ、オペレーションをよく考えられて作られているのでとても魅力的です。 :heart_eyes:


それでは :smile: