CoreOSが提供するetcdの動作をお手軽に試してみました。
なお、etcdとは、分散Key-Valuesストアを使い,各種設定をノード間で共有するメカニズムだそうです。
etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines.
It’s open-source and available on GitHub. etcd gracefully handles master elections during network partitions
and will tolerate machine failure, including the master.
◼️ まずは、環境準備から ...
まずは、golang環境を準備しておきます。
Getting Started - The Go Programming Language
そして、Mac OS X環境で、etcdを動作させる場合、こちらのGetting Startedに従って作業します。
github.com
$ curl -L https://github.com/coreos/etcd/releases/download/v2.2.2/etcd-v2.2.2-darwin-amd64.zip -o etcd-v2.2.2-darwin-amd64.zip $ unzip etcd-v2.2.2-darwin-amd64.zip $ cd etcd-v2.2.2-darwin-amd64 $ ./etcd 2015-12-27 15:42:15.142251 I | etcdmain: etcd Version: 2.2.2 2015-12-27 15:42:15.142330 I | etcdmain: Git SHA: b4bddf6 2015-12-27 15:42:15.142346 I | etcdmain: Go Version: go1.5.1 2015-12-27 15:42:15.142349 I | etcdmain: Go OS/Arch: darwin/amd64 2015-12-27 15:42:15.142360 I | etcdmain: setting maximum number of CPUs to 8, total number of available CPUs is 8 2015-12-27 15:42:15.142364 W | etcdmain: no data-dir provided, using default data-dir ./default.etcd 2015-12-27 15:42:15.142982 I | etcdmain: listening for peers on http://localhost:2380 2015-12-27 15:42:15.143166 I | etcdmain: listening for peers on http://localhost:7001 2015-12-27 15:42:15.143335 I | etcdmain: listening for client requests on http://localhost:2379 2015-12-27 15:42:15.143499 I | etcdmain: listening for client requests on http://localhost:4001 2015-12-27 15:42:15.144404 I | etcdserver: name = default 2015-12-27 15:42:15.144433 I | etcdserver: data dir = default.etcd 2015-12-27 15:42:15.144447 I | etcdserver: member dir = default.etcd/member 2015-12-27 15:42:15.144451 I | etcdserver: heartbeat = 100ms 2015-12-27 15:42:15.144453 I | etcdserver: election = 1000ms 2015-12-27 15:42:15.144467 I | etcdserver: snapshot count = 10000 2015-12-27 15:42:15.144474 I | etcdserver: advertise client URLs = http://localhost:2379,http://localhost:4001 2015-12-27 15:42:15.144478 I | etcdserver: initial advertise peer URLs = http://localhost:2380,http://localhost:7001 2015-12-27 15:42:15.144487 I | etcdserver: initial cluster = default=http://localhost:2380,default=http://localhost:7001 2015-12-27 15:42:15.145942 I | etcdserver: starting member ce2a822cea30bfca in cluster 7e27652122e8b2ae 2015-12-27 15:42:15.146367 I | raft: ce2a822cea30bfca became follower at term 0 2015-12-27 15:42:15.146404 I | raft: newRaft ce2a822cea30bfca [peers: [], term: 0, commit: 0, applied: 0, lastindex: 0, lastterm: 0] 2015-12-27 15:42:15.146415 I | raft: ce2a822cea30bfca became follower at term 1 2015-12-27 15:42:15.146776 I | etcdserver: starting server... [version: 2.2.2, cluster version: to_be_decided] 2015-12-27 15:42:15.147874 N | etcdserver: added local member ce2a822cea30bfca [http://localhost:2380 http://localhost:7001] to cluster 7e27652122e8b2ae 2015-12-27 15:42:15.147934 E | etcdserver: cannot monitor file descriptor usage (cannot get FDUsage on darwin) 2015-12-27 15:42:15.548221 I | raft: ce2a822cea30bfca is starting a new election at term 1 2015-12-27 15:42:15.548284 I | raft: ce2a822cea30bfca became candidate at term 2 2015-12-27 15:42:15.548299 I | raft: ce2a822cea30bfca received vote from ce2a822cea30bfca at term 2 2015-12-27 15:42:15.548316 I | raft: ce2a822cea30bfca became leader at term 2 2015-12-27 15:42:15.548330 I | raft: raft.node: ce2a822cea30bfca elected leader ce2a822cea30bfca at term 2 2015-12-27 15:42:15.548736 I | etcdserver: published {Name:default ClientURLs:[http://localhost:2379 http://localhost:4001]} to cluster 7e27652122e8b2ae 2015-12-27 15:42:15.548760 I | etcdserver: setting up the initial cluster version to 2.2 2015-12-27 15:42:15.550378 N | etcdserver: set the initial cluster version to 2.2
◼️ オープンソース"go-etcd"を活用して、etcdの分散Key-Valuesストアを試してみる
それでは、オープンソース"go-etcd"を活用して、golangから、etcdを試してみます。
0. etcdのKey-Valuesストアを確認する
別ターミナルから、etcdctlコマンドで、etcdのストアデータを確認してみます。
まだ、etcdを起動したばかりなので、何も表示されないですけど。
$ ./etcdctl --peers "http://127.0.0.1:4001" ls
1. etcdにサンプルデータをセットしてみる
オープンソース"go-etcd"を活用して、手軽にKey-Valuesストアをセットできるサンプルコードを準備しておきます。
package main import ( "github.com/coreos/go-etcd/etcd" "log" ) var etcdServers = []string{ "http://127.0.0.1:4001", } func SetStatus_for_server(client *etcd.Client, status string){ // Set "active" to path of "/state/server" _, err := client.Set("/state/server", status, 0) if err != nil { log.Fatal(err) } } func SetStatus_for_network(client *etcd.Client, status string){ // Set "active" to path of "/state/network" _, err := client.Set("/state/network", status, 0) if err != nil { log.Fatal(err) } } func main() { // Create etcd client client := etcd.NewClient(etcdServers) SetStatus_for_server(client, "active") SetStatus_for_network(client, "down") }
サンプルコードを実行して、etcdにサンプルデータをセットしてみます。
エラーが表示されなければOKです。
$ go run go-etcd-set.go
2. etcdctlコマンドで、再度、Key-Valuesストアを確認する
今度は、"/state"という結果が表示されました。
$ ./etcdctl --peers "http://127.0.0.1:4001" ls /state
ちなみに、etcdのKey-Valuesストアデータは、ディレクトリ構造(=パス)で管理されております。
/state配下のパスを確認する場合は、"--recursive"を指定します。
$ ./etcdctl --peers "http://127.0.0.1:4001" ls --recursive /state /state/server /state/network
続いて、Key-ValuesストアのValuesを確認してみます。
まずは、"server"が"active"の状態であることを確認します。
$ ./etcdctl --peers "http://127.0.0.1:4001" get /state/server active
つぎに、"network"が"down"の状態であることを確認します。
$ ./etcdctl --peers "http://127.0.0.1:4001" get /state/network down
3. もっと、お手軽にKey-ValuesストアのValuesを確認してみる
オープンソース"go-etcd"を活用して、手軽にKey-Valuesストアを確認できるサンプルコードを準備しておきます。
package main import ( "github.com/coreos/go-etcd/etcd" "log" "fmt" ) var etcdServers = []string{ "http://127.0.0.1:4001", } func main() { client := etcd.NewClient(etcdServers) resp, err := client.Get("/state", false, true) if err != nil { log.Fatal(err) } for _, n := range resp.Node.Nodes { fmt.Printf("%s: %s\n", n.Key, n.Value) } }
サンプルコードを実行して、Key-ValuesストアのValuesを確認してみます。
$ go run go-etcd-get.go /state/server: active /state/network: down
4. etcdのKey-ValuesストアのValuesを監視してみる
ここからは、応用編です。
Key-ValuesストアのValuesが外部要因によって変更された場合、そのValuesをモニタ監視するサンプルコードを準備しておきます。
package main import ( "github.com/coreos/go-etcd/etcd" "log" ) var etcdServers = []string{ "http://127.0.0.1:4001", } func main() { etcdResponseChan := make(chan *etcd.Response) client := etcd.NewClient(etcdServers) go func(){ _, err := client.Watch("/state", 0, true, etcdResponseChan, nil) if err != nil { log.Fatal(err) } }() log.Println("Waiting for an update...") response := <-etcdResponseChan log.Printf("Got updated state : path=[%s], value=[%s]\n", response.Node.Key, response.Node.Value) }
サンプルコードを実行して、Valuesをモニタ監視できるよう準備しておきます。
$ go run ./go-etcd-watch.go 2015/12/27 16:46:16 Waiting for an update...
続いて、別ターミナルから、"network"を"active"の状態に更新します。
更新方法は、なんでも良いのですが、curlコマンドで更新してみます。
$ curl -L http://127.0.0.1:4001/v2/keys/state/network -XPUT -d value='active' {"action":"set","node":{"key":"/state/network","value":"active","modifiedIndex":6,"createdIndex":6},"prevNode":{"key":"/state/network","value":"down","modifiedIndex":5,"createdIndex":5}}
すると、先ほどモニタ監視として実行しておいたサンプルコードの起動画面にて、"network"が"active"の状態に更新されたことが検出できました。
$ go run ./go-etcd-watch.go 2015/12/27 16:46:16 Waiting for an update... 2015/12/27 16:47:07 Got updated state : path=[/state/network], value=[active]
事後確認として、Key-ValuesストアのValuesを確認してみます。
$ go run go-etcd-get.go /state/server: active /state/network: active