このエントリーをはてなブックマークに追加

rancherというものを使ってみる

前置き

自宅のGiga HUBがちょっと前に壊れて、100M HUBで代用してたけど、今度はブロードバンドルータが壊れた。 なので、ブロードバンドルータ買いに行こうと思ったけど、ネットワーク構成をよくよく眺めてみると、 過去に作ったESXi環境のgatewayにしてたSEIL/x86を、そのままブロードバンドルータ変わりにすればいい気がしてきた。

さらに、ESXi環境はvcenter serverがなくて、管理が個別のESXiに繋がないといけなくてだるかったけど、 dockerとrancherなら、ぽこぽこコンテナ上げられるみたいなことを会社の隣の席の人が言ってたから、 いい感じになるかもしれないと思って、安直に乗っかってみた。

始める前に

以下のサポートバージョンのdockerが入ったlinuxならよさげ、 RancherOS, ubuntu, CentOS 7 がよさげ

調べた時点では、

  • CentOS -> 1.12.6
  • ubuntu -> 17.03

RancherOS amd64なら17.03がデフォルトっぽい。自由に切り替えれるっぽいけど。

たぶん、defaultが不安定ということはないだろうから、ubuntuがベストか?

RancherOS使えよとかいわれそうだけど、よくわかってないからやめといた。 RancherOSはinitがシステムコンテナでその上でユーザコンテナとか書いてあった。

隣の席の人がRancherOSいいよ!って言ったら使ってみる。

構成

../../../_images/rancher.png

グローバルアドレスは伏せてます。

ubuntu Aはいつもの開発サーバなので、OS変えたりはしない。ubuntu B,CがESXiだったやつ。Dは成り行きで(間違って)増えた。

コンテナ通信用にローカルセグメント172.16.60.0/24を用意してみたけど、正直使うかどうか謎。

全てのノードにアドレスを振っているのはESXiと違って、rancherはoverlay networkを構築して必要に応じてポートを出すだけだから。

さくらVPSもrancherで管理する。ノリ的にはさくらVPSが本番環境、自宅が開発環境。趣味なのでステージングとかはない。 rancherのenvironmentsで環境ごとにホストの登録ができる。また、managed network(overlay network)も環境ごとに作られるとドキュメントにある。

あと、今回はちょっとチャレンジをしていて、 “自宅環境はグローバルにoverlay network作ると、172.16.51.0/24側の物理結線したネットワークもったいなくね?将来ローカルを10Gにして、 分散ファイルシステムでトラフィックたくさん流すかもしれないよ!” という天のお告げが降ってきたの、さくらVPSと自宅環境どちらもローカル側にoverlay networkを作ってみます。

たぶん、rancherは素直に、どちらもglobalにoverlayネットワーク作ることを想定していると思う。敢えて想定外のことをやってみる。 ちなみに、コンテナが外からのアクセスを受けるときはiptablesのPREROUTINGでDNATするので基本ポートが合えば何でも食べれるので問題ないと思う。 アドレス指定したらその限りじゃないけど。。。

尚、今回の作業はすべてPCからやっています。

esxiを消してubuntuにする

ESXiさようなら。ubuntuこんにちは。

ネットワーク構成変更

頑張る

dockerに関連する設定

dockerを使うのでip_forwardは1にしておく必要がある。

# vi /etc/sysctl.conf
.
.
net.ipv4.ip_forward=1
.
.
# sysctl -p

ubuntu Aでdockerインストール

ドキュメント

リポジトリから入れてみる

# sudo apt-get install \
>     apt-transport-https \
>     ca-certificates \
>     curl \
>     software-properties-common

# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# sudo apt-key fingerprint 0EBFCD88

#  sudo add-apt-repository \
>    "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
>    $(lsb_release -cs) \
>    stable"

# sudo apt-get update

# sudo apt-get install docker-ce

rancher serverを起動

ドキュメント

listenポート番号は10080にしてみました。

とりあえず、rancher serverを立てるとWEBでアクセスできるようになる。 そして、WEBからホスト追加しようとすると、各ホストでこのコマンドうてみたいなのを教えてくれる。 そのコマンドを実行すると、rancher agentがrancher serverに登録しにいく。

グローバルから入ってくる場合はSSLを終端するために、nginxで20080にアクセスしたものを10080にリバースプロキシするようにした。 オレオレ証明書だとうまくいかなかったのでlet’s encryptで証明書を取得した。

enginxの設定はこんな感じ。これはドキュメントのまんま。 https://docs.rancher.com/rancher/v1.5/en/installing-rancher/installing-server/basic-ssl-config/

upstream rancher {
        server X.X.X.D:10080;
}

server {
        listen       X.X.X.D:20080 ssl spdy;
        server_name  hogehoge.potix.jp;

        ssl_certificate      /etc/letsencrypt/live/hogehoge.potix.jp/fullchain.pem;
        ssl_certificate_key  /etc/letsencrypt/live/hogehoge.potix.jp/privkey.pem;

        location / {
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header X-Forwarded-Port $server_port;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://rancher;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "Upgrade";
                proxy_read_timeout 900s;
        }
}

以下のコマンドをubuntu Aで実行。

# docker run -d --restart=unless-stopped -p X.X.X.D:10080:8080 -p 172.16.50.20:10080:8080 -p 172.31.1.130:10080:8080 --name rancher rancher/server

X.X.X.D:10080:8080 => globalからアクセスする先
172.16.50.20:10080:8080 => PC側からアクセスする先
172.31.1.130:10080:8080 => リモート管理側からアクセスする先

dockerの中見たいときは以下で

# docker exec  -it rancher  /bin/bash

これで、PCからブラウザでhttp://172.16.50.20:10080 にアクセスすれば、rancherの画面が見える。

../../../_images/disp1.png

Access Controll

Admin -> Access Control で ローカルを選んでユーザを登録する

defaultのenrironmentに自宅環境のhost追加

管理ホストを追加してみる。

infrastracture -> hosts -> Add Host

Host Registration URLの設定画面だ出てくる(最初の1回だけ、以後AdminのSettingから変更可)。 rancher agentがrancher serverにアクセスするURLを指定するらしい。

something else を選択して、https://hogehoge.potix.jp:20080 を入れてあげる。

どうもこのパラメータは環境ごとに切り替えられないようで、全部の環境で同じになるようにしてあげないと面倒。

また、このURLに対して定期的に通信が発生しているみたい(たぶんヘルスチェック?)。 そういう意味でも、グローバルを指定しておくのは正しいかも。 グローバルで制御不能 = サービスダウン的なノリ。

この後、Add Hostの画面になる。

Make sure any security groups or firewalls allow traffic:
From and To all other hosts on UDP ports 500 and 4500 (for IPsec networking)

とかいっていたので、overlay networkがルータやFWを超える場合はポートを開けてあげよう。 agentになるホストに関しては特に何もしなくても初期状態なら問題なさそう。IPSECも結局DNATで処理される。

ラベルは key = develop.host.no, value = 1 と入れておいた。 このラベルは割と重要で、スケジューラー設定で特定のホストに対して任意のコンテナを起動させたい場合に、このラベルと一致するかどうかでそのホストかどうか判定ができる。 ホストだけじゃなく、コンテナやサービスのラベルを使っても制御ができる。

次に、なんかよくわからないことを言われた。

Specify the public IP that should be registered for this host. If left empty, Rancher will auto-detect the IP to use. This generally works for machines with unique public IPs, but will not work if the machine is behind a firewall/NAT or if it is the same machine that is running the rancher/server container.

ドキュメントにはこうある

By default, the IP of a VM with a private IP and public IP will be set to match the IP specified in the registration URL. For example, if a private IP is used in the registration URL, then the host’s private IP will be used. If you wanted to change the host’s IP address, you’ll need to edit the command provided from the UI. In order for the Rancher agent container to be launched correctly, set the CATTLE_AGENT_IP environment variable to the desired IP address. All the hosts within Rancher will need to be on the same network as Rancher server.

説明がよくわからないんだけど。。。

軽く試した結果。ここに指定したアドレス側でoverlay networkを構築するみたい。 指定しないとregistration URLアドレスからアドレスを推測してoverlay networkが作られるだけだと思う。

というわけで、これを検証する意味も込めて、ここは敢えてpublic ipにprivateなアドレス172.16.51.1を入れる。 こうすると172.16.51.0/24側でoverlay networkを構築するはず。

コピペしてエージェント起動してみる。

# sudo docker run -e CATTLE_AGENT_IP="172.16.51.1"  -e CATTLE_HOST_LABELS='develop.host.no=1'  --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/rancher:/var/lib/rancher rancher/agent:v1.2.2 https://hogehoge.potix.jp:20080/v1/scripts/7FC97CCF075415608954:1483142400000:XcEE4ZCaeJ6A1XcQrD5ojzhmx8
 INFO: Running Agent Registration Process, CATTLE_URL=https://hogehoge.potix.jp:20080/v1
 INFO: Attempting to connect to: https://hogehgoe.potix.jp:20080/v1
 INFO: https://hogehoge.potix.jp:20080/v1 is accessible
 INFO: Inspecting host capabilities
 INFO: Boot2Docker: false
 INFO: Host writable: true
 INFO: Token: xxxxxxxx
 INFO: Running registration
 INFO: Printing Environment
 INFO: ENV: CATTLE_ACCESS_KEY=5EBB8DC739BF413EACCF
 INFO: ENV: CATTLE_AGENT_IP=172.16.51.1
 INFO: ENV: CATTLE_HOME=/var/lib/cattle
 INFO: ENV: CATTLE_HOST_LABELS=develop.host.no=1
 INFO: ENV: CATTLE_HOME=/var/lib/cattle
 INFO: ENV: CATTLE_HOST_LABELS=develop.host.no=1
 INFO: ENV: CATTLE_REGISTRATION_ACCESS_KEY=registrationToken
 INFO: ENV: CATTLE_REGISTRATION_SECRET_KEY=xxxxxxx
 INFO: ENV: CATTLE_SECRET_KEY=xxxxxxx
 INFO: ENV: CATTLE_URL=https://hogehgoe.potix.jp:20080/v1
 INFO: ENV: DETECTED_CATTLE_AGENT_IP=X.X.X.A
 INFO: ENV: RANCHER_AGENT_IMAGE=rancher/agent:v1.2.2
 INFO: Launched Rancher Agent: ebbe896d3b285a1d4a03a318113bb130af5b00fc388ba85d43d84db829ccc932

いけったっぽい。ubuntu C,Dも同じように登録してあげる。

../../../_images/disp2.png

enrironmentにproduction追加

manage environment -> add environment

cattleを選択して新規の環境を作る

productionのenrironmentにさくらVPSのhost追加

infrastracture -> hosts -> Add Host

ラベルは key = service.host.no, value = 1 と入れておいた。

public IPの欄は172.16.200.1を入れる。これで、172.16.200.0/24側にoverlay networkを構築するはず。

表示されたコマンドを実行して、hostを登録する。

F,Gも同じように登録してあげる。

../../../_images/disp3.png

overlay network確認

本当にローカル側にoverlay networkが構築されているか。 nat traversalのパケットをみてみる。 自宅環境側。

# ip addr show eno1
3: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 80:ee:73:ad:61:55 brd ff:ff:ff:ff:ff:ff
    inet 172.16.51.1/24 brd 172.16.51.255 scope global eno1
       valid_lft forever preferred_lft forever
    inet6 fe80::82ee:73ff:fead:6155/64 scope link
       valid_lft forever preferred_lft forever

# tcpdump -i eno1 -vvv -n -s 9999  port 4500 -c 5
tcpdump: listening on eno1, link-type EN10MB (Ethernet), capture size 9999 bytes
04:45:41.635501 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 124)
    172.16.51.1.4500 > 172.16.51.3.4500: [no cksum] UDP-encap: ESP(spi=0xc878fba4,seq=0x18f76), length 96
04:45:41.636227 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 124)
    172.16.51.3.4500 > 172.16.51.1.4500: [no cksum] UDP-encap: ESP(spi=0xc2562367,seq=0x11ab7), length 96
04:45:41.636379 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 116)
    172.16.51.1.4500 > 172.16.51.3.4500: [no cksum] UDP-encap: ESP(spi=0xc878fba4,seq=0x18f77), length 88
04:45:42.452258 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 124)
    172.16.51.1.4500 > 172.16.51.2.4500: [no cksum] UDP-encap: ESP(spi=0xcca3a348,seq=0x1894d), length 96
04:45:42.452535 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 124)
    172.16.51.2.4500 > 172.16.51.1.4500: [no cksum] UDP-encap: ESP(spi=0xc7b13622,seq=0x11ce1), length 96

ちゃんと流れてる。

さくらVPS側も見てみる。

# ip addr show ens4
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 9c:a3:ba:03:a0:9e brd ff:ff:ff:ff:ff:ff
    inet 172.16.200.1/24 brd 172.16.200.255 scope global ens4
       valid_lft forever preferred_lft forever
    inet6 fe80::9ea3:baff:fe03:a09e/64 scope link
       valid_lft forever preferred_lft forever

# tcpdump -i ens4 -vvv -n -s 9999  port 4500 -c 5
tcpdump: listening on ens4, link-type EN10MB (Ethernet), capture size 9999 bytes
04:50:22.984222 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 124)
    172.16.200.1.4500 > 172.16.200.2.4500: [no cksum] UDP-encap: ESP(spi=0xc8d5839f,seq=0x1277), length 96
04:50:22.984837 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 124)
    172.16.200.2.4500 > 172.16.200.1.4500: [no cksum] UDP-encap: ESP(spi=0xcdb79709,seq=0x93c), length 96
04:50:22.985150 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 116)
    172.16.200.1.4500 > 172.16.200.2.4500: [no cksum] UDP-encap: ESP(spi=0xc8d5839f,seq=0x1278), length 88
04:50:24.115459 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 124)
    172.16.200.1.4500 > 172.16.200.3.4500: [no cksum] UDP-encap: ESP(spi=0xc8ae6fbe,seq=0xfa7), length 96
04:50:24.116064 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 124)
    172.16.200.3.4500 > 172.16.200.1.4500: [no cksum] UDP-encap: ESP(spi=0xc14f34e4,seq=0x7d4), length 96

ちゃんと流れていることがわかる。

ネットワークの流れを、 以下のコマンドを駆使して調べると、

  • iptables -t nat -L -v -n
  • iptables -L -v -n
  • ip addr
  • ip route list
  • ip route get
  • brctl show
  • docker inspect
  • docker exec
  • docker network inspect
  • netstat -an
  • lsof
  • tcpdump

細かいところは、突っ込みあると思うけど、ざっくりこんなイメージ

../../../_images/guess.png

大雑把に言うと、各ホストで外から入ってきたのはDNATで食べてコンテナに流してあげる。 コンテナ発のパケットは各ホストのPOSTROUTINGのMASQUERADEで出ていく。

加えて、今回rancher serverでSSL終端して裏に流した関係で、DNATに食われなくて、docker-proxyが食べるルートがある。

この基本的なdockerのブリッジネットワーク上のコンテナに10.42.X.Xのアドレスを割り当てて、ipsecルータを作ってipsecでVPNを構築している。 なので、10.42.X.Xはoverlay上のホストということになり、10.42.X.X間はホストを超えて通信が可能になっている。

とは言っても、ホストを超えて通信できるようになったけど、相変わらずポートを外出しするところに変わりはない。

あと、IPSECって遅そうだから。AES-NI必須な気がしてならない。 気になったので参考程度にやってみた。

AES-NIのあるマシン

Model name:            Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz

# 暗号化しない
# dd if=/dev/zero count=100 bs=10M | cat > /dev/null
100+0 records in
100+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 0.509076 s, 2.1 GB/s

# 暗号化する
# dd if=/dev/zero count=100 bs=10M | openssl enc -e -aes-256-cbc -pass pass:foobar -out /dev/null
100+0 records in
100+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 3.03892 s, 345 MB/s

大体6倍ぐらい時間かかる。

AES-NIのないやつ

Model name:            Intel(R) Atom(TM) CPU D525   @ 1.80GHz

# 暗号化しない
# dd if=/dev/zero count=100 bs=10M | cat > /dev/null
100+0 records in
100+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 2.72433 s, 385 MB/s

# 暗号化する
# dd if=/dev/zero count=100 bs=10M | openssl enc -e -aes-256-cbc -pass pass:foobar -out /dev/null
100+0 records in
100+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 52.6625 s, 19.9 MB/s

大体20倍近い時間がかかる。

今回のこの環境、自宅とさくらVPSでenvironment分離したし、ローカル側にoverlay network作ったから、IPSECとかじゃなくて、GREとかIPIPでよかったんじゃ。。。 あ、でもIPだと何かと問題ありそうだから、IPSECしないL2TPv2とかL2TPv3とか。。。

今回はここまで。次回はrancherでコンテナを作るところから。

name:
email:
comment: