［入門編］etcdでクラスタを構築する

# はじめに
etcdには、あらかじめマシン数が決まっている場合に静的にクラスタを組む方法とDiscoveryと呼ばれている動的にクラスタを組む方法の2パターンがありますが、ここでは静的にクラスタを組む方法を説明します。
etcdバージョン2を使用します。cloud-config.ymlを使って構築します。
CoreOSの公式ドキュメントは[こちら](https://coreos.com/etcd/docs/latest/clustering.html)です。

# ポートに関して
etcdは、基本的な通信にポート2379番を使い、クラスタとしての通信にはポート2380番を使います。前バージョンではそれぞれ4001番、7001番が使われていました。CoreOSの公式ドキュメントを見ると、cloud-config.ymlの説明などの場合に、4001, 7001の記述がありますが、etcdバージョン２を使用する場合には、4001, 7001の記述は必要ありません。

# フラグに関して
cloud-config.ymlに設定する listen-client-url などの項目はフラグと呼ばれます。
フラグ名にclientが付くものは、etcdの基本的な通信に関する項目です。フラグ名にpeerが付くものは、etcdのクラスタに関する通信を設定する項目です。initialがプレフィックスとして付くフラグは、メンバが新規に起動されるときのみに実行され、リスタート時などには実行されません。これはメンバを追加・削除するときに意味があります。
以下は静的にクラスタを組む場合に必要になるフラグです。

- [ ] **name**: 各メンバを識別するための固有の任意名を付けます。ここで付けた名前がinitial-clusterフラグで使用されます。
例: name: "member001"

- [ ] **listen-client-url**: etcdの基本的な通信において、受け付けるクライアントからのトラフィックを指定します。
メンバのインターナルIPとループバックアドレスをURL形式で指定します。
0.0.0.0を指定することで、すべてのインターフェースにおける指定したportを開けることができるます。これを使ってインターナルIPとループバックアドレスの両方を指定することを省略することができます。
例: listen-client-url: "http://0.0.0.0:2379" 
または、listen-client-url: "http://192.168.0.11:2379,http://127.0.0.1:2379"

- [ ] **advertise-client-urls**: etcdの基本的な通信において、ほかのメンバに公開するURLを指定します。
メンバのインターナルIPを指定します。
例: advertise-client-urls: "http://192.168.0.11:2379"

- [ ] **listen-peer-urls**: クラスタの通信において、受け付けるURLを指定します。
メンバのインターナルIPを指定します。peerはクラスタに関する通信なのでポートは2380番です。
例: listen-peer-urls: "http://192.168.0.11:2380"

- [ ] **initial-advertise-peer-urls**: クラスタの通信において、ほかのメンバに公開するURLを指定します。
メンバのインターナルIPを指定します。
例: initial-advertise-peer-urls: "http://192.168.0.11:2380"

- [ ] **initial-cluster**: クラスタを組む各メンバのURLをメンバ名=URLの形式で指定します。ここで指定するURLは、initial-advertise-peer-urlsフラグで指定したURLとイコールとなります。
静的にクラスタを組む時にのみ必要となるフラグです。
例: initial-cluster: "member001=192.168.0.11:2380,member002=192.168.0.12,member003=192.168.0.13"

- [ ] **initial-cluster-token**: クラスタを識別するためのトークンです。1つのクラスタ内の各メンバに対して同じトークンを設定します。トークンは任意の文字列です。
静的にクラスタを組む時にのみ必要となるフラグです。
例: initial-cluster-token: "cluster001"

- [ ] **initial-cluster-state**: newとexistingを指定でき、newはクラスタを新規に作成する場合に指定します。existingは、既存のクラスタにメンバを追加する場合に使用します。
例: initial-cluster-state: "new"

# クラスタを組む
マシン３台を使ってクラスタを組みます。


| name       | IP Address  |
|:-----------|:------------|
| member001  | 192.168.0.11|
| member002  | 192.168.0.12| 
| member003  | 192.168.0.13| 

etcdの設定を読み込ませるためにcloud-config.ymlをマシンごとに準備します。以下のフラグの値はマシンごとに修正してください。他のフラグの値は３つのマシンで共通です。
- hostname
- name
- advertise-client-urls
- listen-peer-urls
- initial-advertise-peer-urls

cloud-config.ymlファイルは, `/usr/share/oem/`ディレクトリに保存する必要があります。このディレクトリに保存しなければ、CoreOSを起動した時に読み込まれません。

etcdでクラスタを組む場合の最小限のcloud-config.yml設定です。
member001の場合。cloud-config.ymlをマシンごとにそれぞれ作成します。

```lang:/usr/share/oem/cloud-config.yml
hostname: "member001"
coreos:
  etcd2:
    name: "member001"
    advertise-client-urls: "http://192.168.0.11:2379"
    listen-client-urls: "http://0.0.0.0:2379"
    listen-peer-urls: "http://192.168.0.11:2380"
    initial-advertise-peer-urls: "http://192.168.0.11:2380"
    initial-cluster-token: "cluster001"
    initial-cluster: "member001=http://192.168.0.11:2380,member002=http://192.168.0.12:2380,member003=http://192.168.0.13:2380"
    initial-cluster-state: "new"

  units:
    - name: "etcd2.service"
      command: "start"

```

それぞれのマシンで`coreos-cloudinit`コマンドを実行し、`cloud-config.yml`を読み込みます。すべてのマシンで`cloud-config.yml`の読み込みが完了するとetcdはマシン間で通信を開始し、クラスタを構築します。どのマシンでもよいので`etcdctl cluster-health`コマンドを実行し、以下のようにcluster is healthyと出るとクラスタの構築は完了です。

```
$ coreos-cloudinit --from-file=/usr/share/oem/cloud-config.yml
$ etcdctl cluster-health
cluster is healthy
member 6e3bd23ae5f1eae0 is healthy
member 924e2e83e93f2560 is healthy
member a8266ecf031671f3 is healthy
```

# クラスタを作り直そうとしたときに、マシン情報が残ってエラーになるとき
etcdが読み込んでいるメンバのIPアドレスなどの情報が保存されているディレクトリを削除してください。
削除し、再起動すれば正常に機能するようになります。

```lang:coreos
rm -rf /var/lib/etcd2/member
```


# 最後に
クラスタの構築が完了すれば、次はスケジューリングの構築です。CoreOS社は`fleet`という名前のスケジューリングソフトウェアを提供していますが、githubを見ると最近のコミットは頻度が高くなく、etcdバージョン2が出ているのに対してまだ1にも達していません。fleetは簡単なスケジューリング機能だけを提供しているので入門編にはちょうど良いですが、メインで使っていくスケジューリングソフトウェアは、[Kubernetes](http://kubernetes.io/)がおすすめです。