From e446ce1852df7efcea6aa93475cabd5fb3bf3d68 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Mon, 4 Jul 2016 12:10:53 -0700 Subject: [PATCH 1/7] Add discovery/README.md --- .gitignore | 1 - discovery/README.md | 167 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 discovery/README.md diff --git a/.gitignore b/.gitignore index ea79c21..669eded 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,4 @@ *.gz *.etcd etcd* -discovery* *.log diff --git a/discovery/README.md b/discovery/README.md new file mode 100644 index 0000000..3fc85cc --- /dev/null +++ b/discovery/README.md @@ -0,0 +1,167 @@ +\# etcd 机群和 Discovery + +在这个试验里,我们启动一个有四个node的Vagrant虚拟机群。我们在其中第一个node上运行一个单进程的etcd机群,用它作为discovery service,来在剩下三个nodes上启动一个三进程的etcd机群。 + + + +## Vagrant 虚拟机群 + +CoreOS提供了一个[Github repo](https://github.com/coreos/coreos-vagrant)来配置一个简单的CoreOS虚拟机群。我们用它来启动一个四个node的虚拟机群。 + +``` +git clone https://github.com/coreos/coreos-vagrant +cd coreos-vagrant +``` + +编辑 `Vagrantfile`,引入两个修改: + +1. `$num_instances = 1` 改成 `$num_instances = 4`,这样机群里有四个nodes。 +1. `$vm_memory = 1024` 改成 `$vm_memory = 2048`,这样每个node有4GB内存。 + +这样我们就可以启动机群了: + +``` +vagrant up +vagrant status +``` + +我们可以用以下命令查看每个虚拟机的eth1网卡的IP地址: + +``` +for ((i = 1; i <= 4; i++ )); do vagrant ssh core-0$i -c "ifconfig eth1"; done +``` + +应该看到IP地址从`172.17.8.101`到`172.17.8.104`。 + + + +## 单进程etcd机群 + +我们在名为 core-01 (IP地址是172.17.8.101)的虚拟机上启动一个单进程的etcd机群: + +运行 `vagrant ssh core-01` 可以登录到 core-01 上。运行 `etcdctl --version`可以看到本机的etcdctl的版本。我的是`2.3.2`。接下来可以通过 Docker 启动一个对应版本的 etcd container: + +``` +docker run --net=host --rm --name etcd quay.io/coreos/etcd:v2.3.2 +``` + +注意,CoreOS虽然自带etcd程序,但是不要用,因为[版本很老](#don't-use-coreos's-etcd)。关于在Docker里启动etcd,我碰到[一个问题](#在docker里运行etcd)。 + + + +## Pitfalls + +### 在Docker里运行etcd + +我本来是按照这个[tutorial](https://coreos.com/etcd/docs/latest/docker_guide.html)中的办法来启动etcd container的: + +``` +docker run -p 4001:4001 -p 7001:7001 -p 2379:2379 -p 2380:2380 --name learn-etcd --rm quay.io/coreos/etcd:v2.3.2 +``` + +但是 `etcdctl ls /` 抱怨说 + +> Error: read tcp 127.0.0.1:4001: connection reset by peer” + +我搜到[这个页面](https://github.com/coreos/etcd/blob/master/Documentation/op-guide/container.md#docker)里介绍的方法的启发,改用`--net=host`,而不是export各个port,`etcctl -ls /`就可以工作了。 + +李鹏棒我分析的时候看了`netstat -lntp`的输出: +``` +core@core-01 ~ $ netstat -lntp +(Not all processes could be identified, non-owned process info + will not be shown, you would have to be root to see it all.) +Active Internet connections (only servers) +Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name +tcp6 0 0 :::22 :::* LISTEN - +tcp6 0 0 :::7001 :::* LISTEN - +tcp6 0 0 :::4001 :::* LISTEN - +tcp6 0 0 :::2379 :::* LISTEN - +tcp6 0 0 :::2380 :::* LISTEN - +``` + +可以看到,IP地址都用的是IPv6的格式。而用`docker run --net=host --rm +--name etcd quay.io/coreos/etcd:v2.3.2`的时候,IP地址都是IPv4的形式: + +``` +core@core-01 ~ $ netstat -lntp +(Not all processes could be identified, non-owned process info + will not be shown, you would have to be root to see it all.) +Active Internet connections (only servers) +Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name +tcp 0 0 127.0.0.1:7001 0.0.0.0:* LISTEN - +tcp 0 0 127.0.0.1:4001 0.0.0.0:* LISTEN - +tcp 0 0 127.0.0.1:2379 0.0.0.0:* LISTEN - +tcp 0 0 127.0.0.1:2380 0.0.0.0:* LISTEN - +tcp6 0 0 :::22 :::* LISTEN - +``` + +借着这个线索,我找到这个 +[讨论](https://github.com/docker/docker/issues/2174)。我采取了一种一种 +做法:在docker命令里明确指明IPv4地址格式: + +``` +docker run -p 127.0.0.1:4001:4001 -p 127.0.0.1:7001:7001 -p 127.0.0.1:2379:2379 -p 127.0.0.1:2380:2380 --name learn-etcd --rm quay.io/coreos/etcd:v2.3.2 +``` + +这样一来,`netstat -lntp`的输出里显示的地址都是IPv4的形式了。但是`etcdctl`报错: + +``` +core@core-01 ~ $ etcdctl --endpoints=127.0.0.1:4001,127.0.0.1:2379 ls / +Error: EOF +``` + +### Don't Use CoreOS's etcd + +不知道为什么,CoreOS自带的etcd和etcdctl的版本不一致。而且etcd的版本很 +老。所以确实得用Docker运行最新的image。 + +``` +core@core-01 ~ $ cat /etc/os-release +NAME=CoreOS +ID=coreos +VERSION=899.17.0 +VERSION_ID=899.17.0 +BUILD_ID=2016-05-03-2151 +PRETTY_NAME="CoreOS 899.17.0" +ANSI_COLOR="1;32" +HOME_URL="https://coreos.com/" +BUG_REPORT_URL="https://github.com/coreos/bugs/issues" +core@core-01 ~ $ etcd --version +etcd version 0.4.9 +core@core-01 ~ $ etcdctl --version +etcdctl version 2.2.3 +``` + +``` +core@core-01 ~ $ cat /etc/os-release +NAME=CoreOS +ID=coreos +VERSION=1097.0.0 +VERSION_ID=1097.0.0 +BUILD_ID=2016-07-02-0145 +PRETTY_NAME="CoreOS 1097.0.0 (MoreOS)" +ANSI_COLOR="1;32" +HOME_URL="https://coreos.com/" +BUG_REPORT_URL="https://github.com/coreos/bugs/issues" +core@core-01 ~ $ etcd --version +etcd version 0.4.9 +core@core-01 ~ $ etcdctl --version +etcdctl version 2.3.2 +``` + +``` +core@core-01 ~ $ cat /etc/os-release +NAME=CoreOS +ID=coreos +VERSION=899.17.0 +VERSION_ID=899.17.0 +BUILD_ID=2016-05-03-2151 +PRETTY_NAME="CoreOS 899.17.0" +ANSI_COLOR="1;32" +HOME_URL="https://coreos.com/" +BUG_REPORT_URL="https://github.com/coreos/bugs/issues" +core@core-01 ~ $ etcd --version +etcd version 0.4.9 +core@core-01 ~ $ etcdctl --version +etcdctl version 2.2.3 +``` From 6c849a7ef29a2ae43862ba5662926924debe158a Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Mon, 4 Jul 2016 14:08:21 -0700 Subject: [PATCH 2/7] It works if we run etcdctl in Docker image --- README.md | 24 ++++++++++++++++++------ discovery/README.md | 16 ++++++++++++++-- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index be08c05..70a8826 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,23 @@ # 玩转`etcd` -`etcd`事实上是Hadoop Zookeeper的替代。而Zookeeper是Google Chubby的开源 -仿制。对Chubby的描述见 -[这篇论文](http://research.google.com/archive/chubby.html)。文中说 -Chubby是一个*lock service*,实际上简单的理解是Chubby是一个key-value存 -储系统,和分布式文件系统(如GFS)类似,只是为了性能考虑,每个etcd维护 -的文件大小尽量小于1MB。 +`etcd`是Hadoop Zookeeper的替代。而Zookeeper是Google Chubby的开源仿制。 +对Chubby的描述见 +[这篇论文](http://research.google.com/archive/chubby.html)。 + +etcd是一个key-value存储系统,通常由多个进程协同工作。如果其中一个进程 +挂了,剩下的进程会互相讨论选出一个新的首领。这些互相讨论的协议被称为 +Paxos。etcd实现的是Paxos的一个变种,称为Raft。 + +因为一个etcd机群利用Raft协议可以做到永远不死,我们可以借助etcd的这个特 +性,设计自己的“不死”的分布式系统。一个简单的做法是:我们的分布式系统中 +的每个进程都把自己注册到etcd机群里去,并且每个进程每隔一秒种更新自己的 +状态,否则让etcd把自己的记录删除。这样etcd机群里总是存储着我们的系统中 +活着的进程的状态。任何时候,我们都可以取其中进程名字的hash值最小的,作 +为我们的分布式系统中各个进程的首领。 + +Kubernetes和在其上运行的很多分布式系统,都利用了etcd进群的“不死”的特性 +(而不是自己实现Raft协议)来实现自己的“不死”。所以etcd是机群系统中特别 +基础特别重要的一环。在了解Kubernetes之前,得先了解etcd。 ## 文档 diff --git a/discovery/README.md b/discovery/README.md index 3fc85cc..3486f07 100644 --- a/discovery/README.md +++ b/discovery/README.md @@ -1,7 +1,12 @@ -\# etcd 机群和 Discovery +# etcd 机群和 Discovery 在这个试验里,我们启动一个有四个node的Vagrant虚拟机群。我们在其中第一个node上运行一个单进程的etcd机群,用它作为discovery service,来在剩下三个nodes上启动一个三进程的etcd机群。 + * [Vagrant 虚拟机群](#vagrant-虚拟机群) + * [单进程etcd机群](#单进程etcd机群) + * [Pitfalls](#pitfalls) + * [在Docker里运行etcd](#在docker里运行etcd) + * [Don't Use CoreOS's etcd](#dont-use-coreoss-etcd) ## Vagrant 虚拟机群 @@ -45,7 +50,7 @@ for ((i = 1; i <= 4; i++ )); do vagrant ssh core-0$i -c "ifconfig eth1"; done docker run --net=host --rm --name etcd quay.io/coreos/etcd:v2.3.2 ``` -注意,CoreOS虽然自带etcd程序,但是不要用,因为[版本很老](#don't-use-coreos's-etcd)。关于在Docker里启动etcd,我碰到[一个问题](#在docker里运行etcd)。 +注意,CoreOS虽然自带etcd程序,但是不要用,因为[版本很老](#dont-use-coreoss-etcd)。关于`--net=host`参数,请参见我碰到的[一个问题](#在docker里运行etcd)。 @@ -110,6 +115,13 @@ core@core-01 ~ $ etcdctl --endpoints=127.0.0.1:4001,127.0.0.1:2379 ls / Error: EOF ``` +最后尝试运行Docker image里面的etcdctl,这样就OK了: + +``` +core@core-01 ~ $ docker exec learn-etcd /etcdctl set /foo bar +bar +``` + ### Don't Use CoreOS's etcd 不知道为什么,CoreOS自带的etcd和etcdctl的版本不一致。而且etcd的版本很 From 99685e6eaf1abbe0fba647932998d9bea9d91e0f Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 5 Jul 2016 15:14:23 -0700 Subject: [PATCH 3/7] Update README.md --- discovery/README.md | 140 ++++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 64 deletions(-) diff --git a/discovery/README.md b/discovery/README.md index 3486f07..28988c2 100644 --- a/discovery/README.md +++ b/discovery/README.md @@ -18,10 +18,11 @@ git clone https://github.com/coreos/coreos-vagrant cd coreos-vagrant ``` -编辑 `Vagrantfile`,引入两个修改: +编辑 `Vagrantfile`,引入几个修改: +1. `$update_channel = "alpha"` 改成 `$update_channel = "stable"` 1. `$num_instances = 1` 改成 `$num_instances = 4`,这样机群里有四个nodes。 -1. `$vm_memory = 1024` 改成 `$vm_memory = 2048`,这样每个node有4GB内存。 +1. `$vm_memory = 1024` 改成 `$vm_memory = 2048`,这样每个node有2GB内存。 这样我们就可以启动机群了: @@ -42,17 +43,84 @@ for ((i = 1; i <= 4; i++ )); do vagrant ssh core-0$i -c "ifconfig eth1"; done ## 单进程etcd机群 -我们在名为 core-01 (IP地址是172.17.8.101)的虚拟机上启动一个单进程的etcd机群: +### 在host上运行 -运行 `vagrant ssh core-01` 可以登录到 core-01 上。运行 `etcdctl --version`可以看到本机的etcdctl的版本。我的是`2.3.2`。接下来可以通过 Docker 启动一个对应版本的 etcd container: +我们在名为 core-01 (IP地址是172.17.8.101)的虚拟机上启动一个单进程的etcd机群很容易: ``` -docker run --net=host --rm --name etcd quay.io/coreos/etcd:v2.3.2 +vagrant ssh core-04 +etcd2 ``` -注意,CoreOS虽然自带etcd程序,但是不要用,因为[版本很老](#dont-use-coreoss-etcd)。关于`--net=host`参数,请参见我碰到的[一个问题](#在docker里运行etcd)。 +在另一个terminal里可以运行 +``` +etcdctl ls / +``` + +来连接本机的 etcd2 进程。注意 `etcdctl ls /`相当于`etcdctl --endpoints=127.0.0.1:4001,127.0.0.1:2379 ls /`。 + +CoreOS里 `/usr/bin/etcd2` 和 `/usr/bin/etcdctl` 的版本是一致的,而 `/usr/bin/etcd` 通常是一个很老的版本。 + +### 在container里运行 + +我们也可以通过 Docker 启动一个对应版本的 etcd container: + +``` +docker run --net=host --rm --name learn-etcd quay.io/coreos/etcd:v2.3.1 +``` + +或者 + +``` +docker run -p 4001:4001 -p 7001:7001 -p 2379:2379 -p 2380:2380 --name learn-etcd --rm quay.io/coreos/etcd:v2.3.1 +``` + +对应的,也可以在 container 里运行 etcdctl: + +``` +docker exec learn-etcd /etcdctl ls / +``` +### 让其他机器可以访问 + +etcd的默认命令行参数是把和peer通信的port以及和client通信的port都绑定在127.0.0.1上的。所以只有在本机上可以用etcdctl访问etcd服务。为了让其他机器上的程序也能访问本机上的etcd服务,我们需要把ports绑定在本机网卡对应的IP地址上。比如我们在core-01上执行以下命令: + +``` +etcd2 --name etcd01 \ +--initial-advertise-peer-urls http://172.17.8.101:2380 \ +--listen-peer-urls http://172.17.8.101:2380 \ +--listen-client-urls http://172.17.8.101:2379,http://127.0.0.1:2379 \ +--advertise-client-urls http://172.17.8.101:2379 \ +--initial-cluster-token etcd-cluster-1 \ +--initial-cluster etcd01=http://172.17.8.101:2380 \ +--initial-cluster-state new +``` + +随后可以在core-02上用etcdctl访问: + +``` +etcdctl --endpoints=http://172.17.8.101:2379,http://172.17.8.102:4001 ls / +``` + + +## 多进程机群 + +上面例子可以拓展到配置一个三个节点的etcd机群。打开3个terminal,在每一个terminal里登陆到一台虚拟机,比如在第一个terminal里执行 `vagrant ssh core-01`。 + +分别用如下命令启动 + +``` +INDEX=1 +THIS_IP=172.17.8.10$INDEX +etcd2 --name etcd01 --initial-advertise-peer-urls http://10.0.1.10:2380 \ + --listen-peer-urls http://10.0.1.10:2380 \ + --listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \ + --advertise-client-urls http://10.0.1.10:2379 \ + --initial-cluster-token etcd-cluster-1 \ + --initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \ + --initial-cluster-state new +``` ## Pitfalls @@ -70,7 +138,7 @@ docker run -p 4001:4001 -p 7001:7001 -p 2379:2379 -p 2380:2380 --name learn-etcd 我搜到[这个页面](https://github.com/coreos/etcd/blob/master/Documentation/op-guide/container.md#docker)里介绍的方法的启发,改用`--net=host`,而不是export各个port,`etcctl -ls /`就可以工作了。 -李鹏棒我分析的时候看了`netstat -lntp`的输出: +李鹏帮我分析的时候看了`netstat -lntp`的输出: ``` core@core-01 ~ $ netstat -lntp (Not all processes could be identified, non-owned process info @@ -101,8 +169,7 @@ tcp6 0 0 :::22 :::* LISTEN ``` 借着这个线索,我找到这个 -[讨论](https://github.com/docker/docker/issues/2174)。我采取了一种一种 -做法:在docker命令里明确指明IPv4地址格式: +[讨论](https://github.com/docker/docker/issues/2174)。我采取了一种做法:在docker命令里明确指明IPv4地址格式: ``` docker run -p 127.0.0.1:4001:4001 -p 127.0.0.1:7001:7001 -p 127.0.0.1:2379:2379 -p 127.0.0.1:2380:2380 --name learn-etcd --rm quay.io/coreos/etcd:v2.3.2 @@ -122,58 +189,3 @@ core@core-01 ~ $ docker exec learn-etcd /etcdctl set /foo bar bar ``` -### Don't Use CoreOS's etcd - -不知道为什么,CoreOS自带的etcd和etcdctl的版本不一致。而且etcd的版本很 -老。所以确实得用Docker运行最新的image。 - -``` -core@core-01 ~ $ cat /etc/os-release -NAME=CoreOS -ID=coreos -VERSION=899.17.0 -VERSION_ID=899.17.0 -BUILD_ID=2016-05-03-2151 -PRETTY_NAME="CoreOS 899.17.0" -ANSI_COLOR="1;32" -HOME_URL="https://coreos.com/" -BUG_REPORT_URL="https://github.com/coreos/bugs/issues" -core@core-01 ~ $ etcd --version -etcd version 0.4.9 -core@core-01 ~ $ etcdctl --version -etcdctl version 2.2.3 -``` - -``` -core@core-01 ~ $ cat /etc/os-release -NAME=CoreOS -ID=coreos -VERSION=1097.0.0 -VERSION_ID=1097.0.0 -BUILD_ID=2016-07-02-0145 -PRETTY_NAME="CoreOS 1097.0.0 (MoreOS)" -ANSI_COLOR="1;32" -HOME_URL="https://coreos.com/" -BUG_REPORT_URL="https://github.com/coreos/bugs/issues" -core@core-01 ~ $ etcd --version -etcd version 0.4.9 -core@core-01 ~ $ etcdctl --version -etcdctl version 2.3.2 -``` - -``` -core@core-01 ~ $ cat /etc/os-release -NAME=CoreOS -ID=coreos -VERSION=899.17.0 -VERSION_ID=899.17.0 -BUILD_ID=2016-05-03-2151 -PRETTY_NAME="CoreOS 899.17.0" -ANSI_COLOR="1;32" -HOME_URL="https://coreos.com/" -BUG_REPORT_URL="https://github.com/coreos/bugs/issues" -core@core-01 ~ $ etcd --version -etcd version 0.4.9 -core@core-01 ~ $ etcdctl --version -etcdctl version 2.2.3 -``` From 947bcdb31fa880980a7285d270e062dc94303245 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Wed, 6 Jul 2016 08:44:08 -0700 Subject: [PATCH 4/7] Update --- discovery/README.md | 60 +++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/discovery/README.md b/discovery/README.md index 28988c2..b9eab77 100644 --- a/discovery/README.md +++ b/discovery/README.md @@ -84,44 +84,66 @@ docker exec learn-etcd /etcdctl ls / ### 让其他机器可以访问 -etcd的默认命令行参数是把和peer通信的port以及和client通信的port都绑定在127.0.0.1上的。所以只有在本机上可以用etcdctl访问etcd服务。为了让其他机器上的程序也能访问本机上的etcd服务,我们需要把ports绑定在本机网卡对应的IP地址上。比如我们在core-01上执行以下命令: +etcd的默认命令行参数是把和peer通信的port以及和client通信的port都绑定在127.0.0.1上的。所以只有在本机上可以用etcdctl访问etcd服务。为了让其他机器上的程序也能访问本机上的etcd服务,我们需要把ports绑定在本机网卡对应的IP地址上。比如我们在core-04上执行以下命令: ``` -etcd2 --name etcd01 \ ---initial-advertise-peer-urls http://172.17.8.101:2380 \ ---listen-peer-urls http://172.17.8.101:2380 \ ---listen-client-urls http://172.17.8.101:2379,http://127.0.0.1:2379 \ ---advertise-client-urls http://172.17.8.101:2379 \ ---initial-cluster-token etcd-cluster-1 \ ---initial-cluster etcd01=http://172.17.8.101:2380 \ +THIS_IP=$(ifconfig | grep 172.17.8. | awk '{print $2;}') +etcd2 --name boot01 \ +--initial-advertise-peer-urls http://$THIS_IP:2380 \ +--listen-peer-urls http://$THIS_IP:2380 \ +--listen-client-urls http://$THIS_IP:2379,http://127.0.0.1:2379 \ +--advertise-client-urls http://$THIS_IP:2379 \ +--initial-cluster-token bootstrap \ +--initial-cluster boot01=http://$THIS_IP:2380 \ --initial-cluster-state new ``` -随后可以在core-02上用etcdctl访问: +随后可以在其他任何一台机器上用etcdctl访问: ``` -etcdctl --endpoints=http://172.17.8.101:2379,http://172.17.8.102:4001 ls / +etcdctl --endpoints=http://172.17.8.104:2379,http://172.17.8.104:4001 ls / ``` ## 多进程机群 -上面例子可以拓展到配置一个三个节点的etcd机群。打开3个terminal,在每一个terminal里登陆到一台虚拟机,比如在第一个terminal里执行 `vagrant ssh core-01`。 +### 固定大小明确IP -分别用如下命令启动 +上面例子可以拓展到配置一个三个节点的etcd机群。打开3个terminal,在每一个terminal里登陆到一台虚拟机,比如在第一个terminal里执行 `vagrant ssh core-01`。重复三次之后就ssh到三台虚拟机上了。在每个terminal窗口里输入以下同一组命令: ``` -INDEX=1 -THIS_IP=172.17.8.10$INDEX -etcd2 --name etcd01 --initial-advertise-peer-urls http://10.0.1.10:2380 \ - --listen-peer-urls http://10.0.1.10:2380 \ - --listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \ - --advertise-client-urls http://10.0.1.10:2379 \ +CLUSTER="etcd1=http://172.17.8.101:2380,etcd2=http://172.17.8.102:2380,etcd3=http://172.17.8.103:2380" +THIS_IP=$(ifconfig | grep 172.17.8. | awk '{print $2;}') +INDEX=$(echo $THIS_IP | tail -c 2) +etcd2 --name etcd$INDEX \ + --initial-advertise-peer-urls http://$THIS_IP:2380 \ + --listen-peer-urls http://$THIS_IP:2380 \ + --listen-client-urls http://$THIS_IP:2379,http://127.0.0.1:2379 \ + --advertise-client-urls http://$THIS_IP:2379 \ --initial-cluster-token etcd-cluster-1 \ - --initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \ + --initial-cluster $CLUSTER \ --initial-cluster-state new ``` +然后登陆到 core-04 上验证往一个节点里写的内容可以从其他节点读出来: + +``` +vagrant ssh core-04 +core@core-04 ~ $ etcdctl --endpoints=http://172.17.8.101:2379 ls / +core@core-04 ~ $ etcdctl --endpoints=http://172.17.8.101:2379 set /foo bar +bar +core@core-04 ~ $ etcdctl --endpoints=http://172.17.8.101:2379 get /foo +bar +core@core-04 ~ $ etcdctl --endpoints=http://172.17.8.102:2379 get /foo +bar +core@core-04 ~ $ etcdctl --endpoints=http://172.17.8.103:2379 get /foo +bar +``` + +### 利用Discovery服务 + +很多时候,我们并不能提前知道host的IP地址,比如,当host都是通过DHCP获取IP地址的时候。 + ## Pitfalls ### 在Docker里运行etcd From 56a9f4edb98e86306ccde19d10ae64eb4e794edc Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Fri, 8 Jul 2016 10:56:27 -0700 Subject: [PATCH 5/7] Response to comments from Li Peng --- discovery/README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/discovery/README.md b/discovery/README.md index b9eab77..2bb8bce 100644 --- a/discovery/README.md +++ b/discovery/README.md @@ -45,7 +45,7 @@ for ((i = 1; i <= 4; i++ )); do vagrant ssh core-0$i -c "ifconfig eth1"; done ### 在host上运行 -我们在名为 core-01 (IP地址是172.17.8.101)的虚拟机上启动一个单进程的etcd机群很容易: +我们在任何一台虚拟机上启动一个单进程的etcd机群很容易: ``` vagrant ssh core-04 @@ -67,13 +67,22 @@ CoreOS里 `/usr/bin/etcd2` 和 `/usr/bin/etcdctl` 的版本是一致的,而 `/ 我们也可以通过 Docker 启动一个对应版本的 etcd container: ``` -docker run --net=host --rm --name learn-etcd quay.io/coreos/etcd:v2.3.1 +docker run \ + --net=host \ + --name learn-etcd \ + --rm quay.io/coreos/etcd:v2.3.1 ``` 或者 ``` -docker run -p 4001:4001 -p 7001:7001 -p 2379:2379 -p 2380:2380 --name learn-etcd --rm quay.io/coreos/etcd:v2.3.1 +docker run \ + -p 127.0.0.1:4001:4001 \ + -p 127.0.0.1:7001:7001 \ + -p 127.0.0.1:2379:2379 \ + -p 127.0.0.1:2380:2380 \ + --name learn-etcd \ + --rm quay.io/coreos/etcd:v2.3.1 ``` 对应的,也可以在 container 里运行 etcdctl: From 13a00f9799ef9faed722f9056cbc018c7da53885 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Fri, 8 Jul 2016 10:56:54 -0700 Subject: [PATCH 6/7] Add .gitignore --- discovery/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 discovery/.gitignore diff --git a/discovery/.gitignore b/discovery/.gitignore new file mode 100644 index 0000000..1ab9962 --- /dev/null +++ b/discovery/.gitignore @@ -0,0 +1 @@ +coreos-vagrant From 6dbd8f35941682bd43368e918ce8a66969258e1f Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Fri, 8 Jul 2016 11:32:49 -0700 Subject: [PATCH 7/7] Add bootstraping using discovery service --- discovery/README.md | 74 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/discovery/README.md b/discovery/README.md index 2bb8bce..73bf103 100644 --- a/discovery/README.md +++ b/discovery/README.md @@ -21,7 +21,7 @@ cd coreos-vagrant 编辑 `Vagrantfile`,引入几个修改: 1. `$update_channel = "alpha"` 改成 `$update_channel = "stable"` -1. `$num_instances = 1` 改成 `$num_instances = 4`,这样机群里有四个nodes。 +1. `$num_instances = 1` 改成 `$num_instances = 6`,这样机群里有6个nodes。 1. `$vm_memory = 1024` 改成 `$vm_memory = 2048`,这样每个node有2GB内存。 这样我们就可以启动机群了: @@ -34,10 +34,10 @@ vagrant status 我们可以用以下命令查看每个虚拟机的eth1网卡的IP地址: ``` -for ((i = 1; i <= 4; i++ )); do vagrant ssh core-0$i -c "ifconfig eth1"; done +for ((i = 1; i <= 6; i++ )); do vagrant ssh core-0$i -c "ifconfig eth1"; done ``` -应该看到IP地址从`172.17.8.101`到`172.17.8.104`。 +应该看到IP地址从`172.17.8.101`到`172.17.8.106`。 @@ -91,6 +91,7 @@ docker run \ docker exec learn-etcd /etcdctl ls / ``` + ### 让其他机器可以访问 etcd的默认命令行参数是把和peer通信的port以及和client通信的port都绑定在127.0.0.1上的。所以只有在本机上可以用etcdctl访问etcd服务。为了让其他机器上的程序也能访问本机上的etcd服务,我们需要把ports绑定在本机网卡对应的IP地址上。比如我们在core-04上执行以下命令: @@ -118,7 +119,7 @@ etcdctl --endpoints=http://172.17.8.104:2379,http://172.17.8.104:4001 ls / ### 固定大小明确IP -上面例子可以拓展到配置一个三个节点的etcd机群。打开3个terminal,在每一个terminal里登陆到一台虚拟机,比如在第一个terminal里执行 `vagrant ssh core-01`。重复三次之后就ssh到三台虚拟机上了。在每个terminal窗口里输入以下同一组命令: +上面例子可以拓展到配置一个(比如三个节点的)etcd机群。打开3个terminal,在每一个terminal里登陆到一台虚拟机,比如在第一个terminal里执行 `vagrant ssh core-01`。重复三次之后就ssh到三台虚拟机上了。在每个terminal窗口里输入以下同一组命令: ``` CLUSTER="etcd1=http://172.17.8.101:2380,etcd2=http://172.17.8.102:2380,etcd3=http://172.17.8.103:2380" @@ -149,10 +150,73 @@ core@core-04 ~ $ etcdctl --endpoints=http://172.17.8.103:2379 get /foo bar ``` + ### 利用Discovery服务 -很多时候,我们并不能提前知道host的IP地址,比如,当host都是通过DHCP获取IP地址的时候。 +很多时候,我们并不能提前知道host的IP地址,比如,当host都是通过DHCP获取IP地址的时候。这时我们可以利用一个已经存在的etcd机群来帮助一个新机群里的members互相建立联系。原理如下: + +1. 为新etcd机群标志一个uuid; +1. 在已有etcd机群里创建一个以这个uuid为名字的directory; +1. 启动新机群的etcd members的时候,通过命令行参数告诉它们这个uuid; +1. 新机群的etcd members都可以向已有etcd机群的这个uuid里注册自己的信息,从而互相找到。 + +这里有一个细节,我们在已有机群里写uuid的时候,也写入我们期待的新etcd机群里的members数量。这样如果有超出members数量的etcd进程注册自己,这些多余的etcd进程就成为新机群的 proxy,而不是members。 + +接下来我们来验证一下这套机制: + +1. 首先,按照[上面例子](#让其他机器可以访问),在 core-01 上启动一个单节点的etcd机群。 + +2. 然后,我们利用这个小机群在 core-02 到 core-04 上启动一个有三个members的新etcd机群: + + 1. 在任何一台机器上(Linux或者MacOSX),运行`uuidgen`可以得到一个uuid。比如 `8D527FB2-B3CB-4FDB-A70A-AF35E38D5A80`。 + + 1. 在老etcd机群里创建一个以此uuid为名字的目录,并且把期待的新etcd机群的members数量(3)写进去。为此我们可能要登录到虚拟机群里某一台机器: + + ``` + vagrant core-02 + curl -X PUT http://172.17.8.101:2379/v2/keys/discovery/8D527FB2-B3CB-4FDB-A70A-AF35E38D5A80/_config/size -d value=3 + ``` + + 为了验证是否写入了,我们可以执行: + + ``` + etcdctl --endpoints=http://172.17.8.101:2379 get /discovery/8D527FB2-B3CB-4FDB-A70A-AF35E38D5A80/_config/size + ``` + +1. 我们在 core-02 到 core-04 上启动三个 etcd 进程,利用 core-01 上的单节点etcd机群,来帮助这三个新进程互相认识,并组成一个新etcd机群。打开三个terminal窗口,分别用`vagrant ssh`登录到上述三台虚拟机,然后在这些窗口里粘贴如下命令: + + ``` +THIS_IP=$(ifconfig | grep 172.17.8. | awk '{print $2;}') +INDEX=$(echo $THIS_IP | tail -c 2) +etcd2 --name etcd$INDEX \ + --initial-advertise-peer-urls http://$THIS_IP:2380 \ + --listen-peer-urls http://$THIS_IP:2380 \ + --listen-client-urls http://$THIS_IP:2379,http://127.0.0.1:2379 \ + --advertise-client-urls http://$THIS_IP:2379 \ + --discovery http://172.17.8.101:2379/v2/keys/discovery/8D527FB2-B3CB-4FDB-A70A-AF35E38D5A80 + ``` +1. 验证新机群可以工作。在core-05上执行以下命令: + + ``` +core@core-05 ~ $ etcdctl --endpoints=http://172.17.8.102:2379 ls / +core@core-05 ~ $ etcdctl --endpoints=http://172.17.8.102:2379 set /foo bar +bar +core@core-05 ~ $ etcdctl --endpoints=http://172.17.8.102:2379 get /foo +bar + ``` + +1. 把步骤3中的命令,在 core-05 上再粘贴一次,从而启动一个 proxy。 + +1. 在 core-06 上验证可以通过 core-05 上的 proxy 访问新机群: + + ``` +core@core-06 ~ $ etcdctl --endpoints=http://172.17.8.105:2379 ls / +/foo +core@core-06 ~ $ etcdctl --endpoints=http://172.17.8.105:2379 get /foo +bar + ``` + ## Pitfalls ### 在Docker里运行etcd