Carpe Diem

備忘録

bindアドレスとadvertiseアドレス

概要

ConsulやVaultのクラスタ構成をしていると

  • bind address
  • advertise address

という2つのアドレスを設定する必要が出てきます。
この2つをしっかり理解しておかないとクラスタ構成で思わぬ落とし穴にハマったりするので今回はこれを紹介します。

bindアドレスって?

サーバを立ち上げる時に指定するアドレスです。
これまではふわっとした知識で

  • 127.0.0.1だとローカルからのみアクセスできる
  • 0.0.0.0だとどこからでもアクセスできる
  • Elasticsearchとかはデフォルトは127.0.0.1になってる

くらいの理解でした。

bindアドレスは名札みたいなもの

例えば「田中」という名札をしていれば、「田中」と呼ばれれば返事します「山田」と呼ばれても返事しませんよね。
番号②という名札をもらったら、「②番の方〜」と呼ばれれば返事しますが、「①番の方〜」と呼ばれても返事しませんよね。

そんな感じでbindアドレスを127.0.0.1と設定すれば

$ curl 127.0.0.1

ではレスポンスを返しますが、仮にそのマシンがローカルアドレス192.168.1.10を持っていたとしても

$ curl 192.168.1.10

ではレスポンスを返しません。

0.0.0.0ワイルドカード

ただしそれだとどのIPが割り振られるか分からない環境では不便なので、どんな呼ばれ方でも返事するワイルドカード的なアドレスが0.0.0.0です。
この場合はLANに加えてWANwww.hoge.comみたいなアドレスを持っていたとしても

$ curl 127.0.0.1
$ curl 192.168.1.10
$ curl www.hoge.com

のどれでもレスポンスを返します。

検証

Goで簡単に検証してみます。

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World")
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe("BIND_ADDR:8080", nil)
}

こんな感じのコードを用意して、BIND_ADDRを変えてみます。

127.0.0.1

まずはループバックアドレスを設定してみます。

$ curl 127.0.0.1:8080
Hello, World

ちゃんと返りますが、

$ curl 192.168.1.22:8080
curl: (52) Empty reply from server

こちらは返りません。

LAN (192.168.xxx.xxx)

では今度はLANアドレス192.168.1.22を設定してみます。

$ curl 192.168.1.22:8080
Hello, World

今度はこちらが返りますが、

$ curl 127.0.0.1:8080
curl: (7) Failed to connect to 127.0.0.1 port 8080: Connection refused

ループバックアドレスではレスポンスが返りません。

0.0.0.0

最後は0.0.0.0です。

$ curl 127.0.0.1:8080
Hello, World
$ curl 192.168.1.22:8080
Hello, World

どちらもレスポンスが返ります。

bindまとめ

このようにListenerの名札として機能するのがbindでした。

advertiseアドレスって?

advertiseを辞書で調べると「広告・告知する」といった意味です。

ConsulやVaultは複数のサーバでクラスタを組むため、他のノードに対して「私のIPはこれですよー。このIPでアクセスしてねー」と伝える必要があります。
そのための設定というわけですね。

ちょっと前のクラスタというのは全ノードのリストを固定で持つことでノードを把握し構成されるものでしたが、Consulのように動的にノードが変わるようなクラスタは変化に対応できるようこのような設定になったのだと思われます。

マシンは複数のIPを持つ

なぜ他のノードにIPを指定して教える必要があるのかと言うと、マシンはループバックアドレスの他にNICの数によって複数のIPアドレス(eth0、eth1、ens3などなど)を持つためです。

ノードAからノードBにアクセスしたいのに、当然ながらループバックアドレスでは無理ですし、NICのアドレスによってはAとBのネットワークが繋がってないこともありえます。

なのでAとBがネットワーク的に繋がっているアドレスをadvertiseする必要があります。

具体的な設定

LANで繋がっている場合

ノード LAN IP
A 192.168.1.5
B 192.168.1.10

であれば、それぞれ

ノード 設定
A consul agent -advertise "192.168.1.5"
B consul agent -advertise "192.168.1.10"

とすればOKです。

LANで繋がっていない場合

この場合WANで繋げる必要があるので、

ノード WAN IP
A 13.52.1.5
B 53.108.1.10

のようにそれぞれGlobalIPを用意して、

ノード 設定
A consul agent -advertise-wan "13.52.1.5"
B consul agent -advertise-wan "53.108.1.10"

という設定になると思います。

advertiseまとめ

マシンは複数のIPを持つため、クラスタが互いに通信するためのIPを指定するための設定がadvertiseということでした。

ソース