CoreOS 上の Docker コンテナのサービス情報を registrator を使って SkyDNS2 に自動登録する


## 概要
registrator というサービス検出・登録・削除専用コンテナを使って、CoreOS 上に起動する Docker サービス（rails や redis, elasticsearch などポートを外部にさらすもの）を skydns2 へ自動登録するという話

registrator の基本については

* [CoreOS 上の Docker コンテナのサービス情報を registrator を使って etcd へ自動登録する](http://qiita.com/spesnova/items/ab1c5ccc996f8d681839)

skydns の基本については

* [CoreOS クラスタ上で SkyDNS2 を使ってサービスディスカバリする](http://qiita.com/spesnova/items/bdaa125220992115528d)

を参照

## registrator で Docker サービス を skydns2 へ自動登録する

### skydns2 コンテナの起動

```bash
# on CoreOS machine
# SkyDNS2 の Docker イメージ作成
core@core-01 ~ $ git clone https://github.com/skynetservices/skydns.git
core@core-01 ~ $ cd skydns
core@core-01 ~ $ docker build -t skydns2 .

# SkyDNS のデフォルト設定を etcd にセット
core@core-01 ~ $ curl -L -XPUT http://172.17.8.101:4001/v2/keys/skydns/config -d value='{"nameservers": ["8.8.8.8:53","8.8.4.4:53"]}'

# SkyDNS2 コンテナ起動
# SkyDNS2 の UDP 53 ポートをホストの Private IPの 53 ポートに bind 
core@core-01 ~/skydns $ docker run \
  -d \
  --name skydns2 \
  -p 172.17.8.101:53:53/udp \
  -e ETCD_MACHINES='172.17.8.101:4001,172.17.8.102:4001,172.17.8.103:4001' \
  skydns2:latest \
  -addr=0.0.0.0:53
```

### SkyDNS2 を backend にした registrator コンテナの起動

```bash
core@core-01 ~ $ docker run \
  -d \
  --name registrator \
  -h $HOSTNAME \
  -v /var/run/docker.sock:/tmp/docker.sock \
  progrium/registrator \
  -ip=172.17.8.101 skydns2://172.17.8.101:4001/skydns.local
```

registry-url の詳細については [SkyDNS2 backend - progrium/registrator README](https://github.com/progrium/registrator#skydns-2-backend) を参照

### redis コンテナを起動してみる

```bash
core@core-01 ~ $ docker run -d --name redis.1 -e SERVICE_ID=1 -p 6379:6379 redis
```

redis コンテナを起動すると registrator がそれを検知して skydns2 が参照する etcd のパスに key-value をセットしてくれる

```bash
core@core-01 ~ $ etcdctl ls --recursive /skydns/local
/skydns/local
/skydns/local/skydns
/skydns/local/skydns/redis
/skydns/local/skydns/redis/redis-1
```

### CoreOS マシンで使う DNS を skydns2 に変更する

```
core@core-01 ~ $ cat /etc/resolv.conf
# This file is managed by systemd-resolved(8). Do not edit.
#
# Third party programs must not access this file directly, but
# only through the symlink at /etc/resolv.conf. To manage
# resolv.conf(5) in a different way, replace the symlink by a
# static file or a different symlink.

#nameserver 10.0.2.3
nameserver 172.17.8.101 # -> 書き換え
```

直に変更してもしばらくすると戻るので注意。永続的に変更するには cloud-config を利用すること。

### ping してみる

```bash
core@core-01 ~ $ ping 1.redis.skydns.local
PING 1.redis.skydns.local (172.17.8.101) 56(84) bytes of data.
64 bytes from 172.17.8.101: icmp_seq=1 ttl=64 time=0.027 ms
64 bytes from 172.17.8.101: icmp_seq=2 ttl=64 time=0.021 ms
^C
--- 1.redis.skydns.local ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.021/0.024/0.027/0.003 ms
```

```bash
core@core-01 ~ $ ping redis.skydns.local
PING redis.skydns.local (172.17.8.101) 56(84) bytes of data.
64 bytes from 172.17.8.101: icmp_seq=1 ttl=64 time=0.027 ms
64 bytes from 172.17.8.101: icmp_seq=2 ttl=64 time=0.042 ms
64 bytes from 172.17.8.101: icmp_seq=3 ttl=64 time=0.019 ms
^C
--- redis.skydns.local ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.019/0.029/0.042/0.010 ms
```

## 簡単に解説
#### ドメイン名
registrator の引数に渡した `skydns2://172.17.8.101:4001/skydns.local` の `skydns.local` の部分が SkyDNS に権威があるドメインで、etcd には以下のようにセットされる


```
/skydns/local/skydns
```

registrator `skydns2://172.17.8.101:4001/staging.skydns.local` を渡して起動すれば、

```
/skydns/local/skydns/staging/
```

とセットされる。

#### サービス名
Docker のイメージがサービス名として利用される。 redis イメージを利用すると

```
/skydns/local/skydns/redis
```

のようにセットされ、logspout という名前のイメージを利用すると

```
/skydns/local/skydns/logspout
```

とセットされる。これで、

`redis.skydns.local` が利用可能になる

#### サービス ID
コンテナ起動時の環境変数 `SERVICE_ID` の値がサービス ID として利用される。さきほどの例のように 

```bash
core@core-01 ~ $ docker run -d --name redis.1 -e SERVICE_ID=1 -p 6379:6379 redis
```

と起動すると、

```bash
/skydns/local/skydns/redis/1
```

がセットされる。これで、

`1.redis.skydns.local` が利用可能になる

## Cloud-Config から SkyDNS2 backend の registrator を起動する

```yaml
coreos:
  units:
    - name: registrator.service
      command: start
      content: |     
        [Unit]
        Description=Registrator
        After=docker.service
        Requires=docker.service

        [Service]
        TimeoutStartSec=0
        ExecStartPre=-/usr/bin/docker kill registrator
        ExecStartPre=-/usr/bin/docker rm registrator
        ExecStartPre=/usr/bin/docker pull progrium/registrator:latest
        ExecStart=/usr/bin/docker run --name registrator -h %H -v /var/run/docker.sock:/tmp/docker.sock progrium/registrator:latest -ip=$private_ipv4 skydns2://$private_ipv4:4001/skydns.local
        ExecStop=/usr/bin/docker stop registrator

        [Install]
        WantedBy=multi-user.target
```

## REF

* [progrium/registrator](https://github.com/progrium/registrator)
* [skynetservices/skydns](https://github.com/skynetservices/skydns)
* [CoreOS 上の Docker コンテナのサービス情報を registrator を使って etcd へ自動登録する](http://qiita.com/spesnova/items/ab1c5ccc996f8d681839)
* [CoreOS クラスタ上で SkyDNS2 を使ってサービスディスカバリする](http://qiita.com/spesnova/items/bdaa125220992115528d)