徹底搞懂 etcd 系列文章(三):etcd 集群運維部署

来源:https://www.cnblogs.com/aoho/archive/2020/06/06/13054681.html
-Advertisement-
Play Games

0 專輯概述 etcd 是雲原生架構中重要的基礎組件,由 CNCF 孵化托管。etcd 在微服務和 Kubernates 集群中不僅可以作為服務註冊與發現,還可以作為 key-value 存儲的中間件。 《徹底搞懂 etcd 系列文章》將會從 etcd 的基本功能實踐、API 介面、實現原理、源碼分 ...


0 專輯概述

etcd 是雲原生架構中重要的基礎組件,由 CNCF 孵化托管。etcd 在微服務和 Kubernates 集群中不僅可以作為服務註冊與發現,還可以作為 key-value 存儲的中間件。

《徹底搞懂 etcd 系列文章》將會從 etcd 的基本功能實踐、API 介面、實現原理、源碼分析,以及實現中的踩坑經驗等幾方面具體展開介紹 etcd。預計會有 20 篇左右的文章,筆者將會每周持續更新,歡迎關註。

1 etcd 集群部署

在生產環境中,為了整個集群的高可用,etcd 正常都會集群部署,避免單點故障。本節將會介紹如何進行 etcd 集群部署。引導 etcd 集群的啟動有以下三種機制:

  • 靜態
  • etcd 動態發現
  • DNS 發現

靜態啟動 etcd 集群要求每個成員都知道集群中的另一個成員。 在許多情況下,群集成員的 IP 可能會提前未知。在這些情況下,可以在發現服務的幫助下引導 etcd 群集。

下麵我們將會分別介紹這幾種方式。

2 靜態方式啟動 etcd 集群

單機安裝

如果想要在一臺機器上實踐 etcd 集群的搭建,可以通過 goreman 工具。

goreman 是一個 Go 語言編寫的多進程管理工具,是對 Ruby 下廣泛使用的 foreman 的重寫(foreman 原作者也實現了一個 Go 版本:forego,不過沒有 goreman 好用)。

我們需要確認 Go 安裝環境,然後直接執行:

go get github.com/mattn/goreman

編譯後的文件放在 $GOPATH/bin 中,$GOPATH/bin目錄已經添加到了系統 $PATH 中,所以我們可以方便執行命令 goreman 命令。下麵就是編寫 Procfile 腳本,我們啟動三個 etcd,具體對應如下:

HostName | ip | 客戶端交互埠 | peer 通信埠
:-: | :-: | :-: | :-:
infra1 | 127.0.0.1 | 12379 | 12380 |
infra2 | 127.0.0.1| 22379 | 22380 |
infra3 | 127.0.0.1| 32379 | 32380 |

Procfile 腳本如下:

etcd1: etcd --name infra1 --listen-client-urls http://127.0.0.1:12379 --advertise-client-urls http://127.0.0.1:12379 --listen-peer-urls http://127.0.0.1:12380 --initial-advertise-peer-urls http://127.0.0.1:12380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380' --initial-cluster-state new --enable-pprof --logger=zap --log-outputs=stderr
etcd2: etcd --name infra2 --listen-client-urls http://127.0.0.1:22379 --advertise-client-urls http://127.0.0.1:22379 --listen-peer-urls http://127.0.0.1:22380 --initial-advertise-peer-urls http://127.0.0.1:22380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380' --initial-cluster-state new --enable-pprof --logger=zap --log-outputs=stderr
etcd3: etcd --name infra3 --listen-client-urls http://127.0.0.1:32379 --advertise-client-urls http://127.0.0.1:32379 --listen-peer-urls http://127.0.0.1:32380 --initial-advertise-peer-urls http://127.0.0.1:32380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380' --initial-cluster-state new --enable-pprof --logger=zap --log-outputs=stderr

配置項說明:

  • --name:etcd集群中的節點名,這裡可以隨意,可區分且不重覆就行
  • --listen-peer-urls:監聽的用於節點之間通信的url,可監聽多個,集群內部將通過這些url進行數據交互(如選舉,數據同步等)
  • --initial-advertise-peer-urls:建議用於節點之間通信的url,節點間將以該值進行通信。
  • --listen-client-urls:監聽的用於客戶端通信的url,同樣可以監聽多個。
  • --advertise-client-urls:建議使用的客戶端通信 url,該值用於 etcd 代理或 etcd 成員與 etcd 節點通信。
  • --initial-cluster-token: etcd-cluster-1,節點的 token 值,設置該值後集群將生成唯一 id,併為每個節點也生成唯一 id,當使用相同配置文件再啟動一個集群時,只要該 token 值不一樣,etcd 集群就不會相互影響。
  • --initial-cluster:也就是集群中所有的 initial-advertise-peer-urls 的合集。
  • --initial-cluster-state:new,新建集群的標誌

註意上面的腳本,etcd 命令執行時需要根據本地實際的安裝地址進行配置。下麵我們啟動 etcd 集群。

goreman -f /opt/procfile start

使用如上的命令啟動啟動 etcd 集群,啟動完成之後查看集群內的成員。

$ etcdctl --endpoints=http://localhost:22379  member list

8211f1d0f64f3269, started, infra1, http://127.0.0.1:12380, http://127.0.0.1:12379, false
91bc3c398fb3c146, started, infra2, http://127.0.0.1:22380, http://127.0.0.1:22379, false
fd422379fda50e48, started, infra3, http://127.0.0.1:32380, http://127.0.0.1:32379, false

我們在單機搭建的偽集群成功,需要註意的是在集群啟動時,我們是通過靜態的方式指定集群的成員,在實際環境中,集群成員的 ip 可能不會提前知道。這時候就需要採用動態發現的機制。

docker 啟動集群

etcd 使用 gcr.io/etcd-development/etcd 作為容器的主要加速器, quay.io/coreos/etcd 作為輔助的加速器。可惜這兩個加速器我們都沒法訪問,如果下載不了,可以使用筆者提供的地址:

docker pull bitnami/etcd:3.4.7

然後將拉取的鏡像重新 tag:

docker image tag bitnami/etcd:3.4.7 quay.io/coreos/etcd:3.4.7

鏡像設置好之後,我們啟動 3 個節點的 etcd 集群,腳本命令如下:

REGISTRY=quay.io/coreos/etcd

# For each machine
ETCD_VERSION=3.4.7
TOKEN=my-etcd-token
CLUSTER_STATE=new
NAME_1=etcd-node-0
NAME_2=etcd-node-1
NAME_3=etcd-node-2
HOST_1= 192.168.202.128
HOST_2= 192.168.202.129
HOST_3= 192.168.202.130
CLUSTER=${NAME_1}=http://${HOST_1}:2380,${NAME_2}=http://${HOST_2}:2380,${NAME_3}=http://${HOST_3}:2380
DATA_DIR=/var/lib/etcd

# For node 1
THIS_NAME=${NAME_1}
THIS_IP=${HOST_1}
docker run \
  -p 2379:2379 \
  -p 2380:2380 \
  --volume=${DATA_DIR}:/etcd-data \
  --name etcd ${REGISTRY}:${ETCD_VERSION} \
  /usr/local/bin/etcd \
  --data-dir=/etcd-data --name ${THIS_NAME} \
  --initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://0.0.0.0:2380 \
  --advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://0.0.0.0:2379 \
  --initial-cluster ${CLUSTER} \
  --initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}

# For node 2
THIS_NAME=${NAME_2}
THIS_IP=${HOST_2}
docker run \
  -p 2379:2379 \
  -p 2380:2380 \
  --volume=${DATA_DIR}:/etcd-data \
  --name etcd ${REGISTRY}:${ETCD_VERSION} \
  /usr/local/bin/etcd \
  --data-dir=/etcd-data --name ${THIS_NAME} \
  --initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://0.0.0.0:2380 \
  --advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://0.0.0.0:2379 \
  --initial-cluster ${CLUSTER} \
  --initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}

# For node 3
THIS_NAME=${NAME_3}
THIS_IP=${HOST_3}
docker run \
  -p 2379:2379 \
  -p 2380:2380 \
  --volume=${DATA_DIR}:/etcd-data \
  --name etcd ${REGISTRY}:${ETCD_VERSION} \
  /usr/local/bin/etcd \
  --data-dir=/etcd-data --name ${THIS_NAME} \
  --initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://0.0.0.0:2380 \
  --advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://0.0.0.0:2379 \
  --initial-cluster ${CLUSTER} \
  --initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}

註意,上面的腳本是部署在三台機器上面,每台機器執行對應的腳本即可。在運行時可以指定 API 版本:

docker exec etcd /bin/sh -c "export ETCDCTL_API=3 && /usr/local/bin/etcdctl put foo bar"

docker 的安裝方式比較簡單,讀者根據需要可以定製一些配置。

3 動態發現啟動 etcd 集群

如前面所述,在實際環境中,集群成員的 ip 可能不會提前知道。在這種情況下,需要使用自動發現來引導 etcd 集群,而不是指定靜態配置,這個過程被稱為發現。我們啟動三個 etcd,具體對應如下:

HostName | ip | 客戶端交互埠 | peer 通信埠
:-: | :-: | :-: | :-:
etcd1 | 192.168.202.128 | 2379 | 2380 |
etcd2 | 192.168.202.129| 2379 | 2380 |
etcd3 | 192.168.202.130| 2379 | 2380 |

協議的原理

Discovery service protocol 幫助新的 etcd 成員使用共用 URL 在集群引導階段發現所有其他成員。

該協議使用新的發現令牌來引導一個唯一的 etcd 集群。一個發現令牌只能代表一個 etcd 集群。只要此令牌上的發現協議啟動,即使它中途失敗,也不能用於引導另一個 etcd 集群。

提示:Discovery service protocol 僅用於集群引導階段,不能用於運行時重新配置或集群監視。

Discovery protocol 使用內部 etcd 集群來協調新集群的引導程式。首先,所有新成員都與發現服務交互,並幫助生成預期的成員列表。之後,每個新成員使用此列表引導其伺服器,該列表執行與 --initial-cluster 標誌相同的功能,即設置所有集群的成員信息。

獲取 discovery 的 token

生成將標識新集群的唯一令牌。 在以下步驟中,它將用作發現鍵空間中的唯一首碼。 一種簡單的方法是使用uuidgen:

UUID=$(uuidgen)

指定集群的大小

獲取令牌時,必須指定群集大小。 發現服務使用該大小來瞭解何時發現了最初將組成集群的所有成員。

curl -X PUT http://10.0.10.10:2379/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83/_config/size -d value=3

我們需要把該 url 地址 http://10.0.10.10:2379/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83 作為 --discovery 參數來啟動 etcd。

節點會自動使用 http://10.0.10.10:2379/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83 目錄進行 etcd 的註冊和發現服務。

公共發現服務

當我們本地沒有可用的 etcd 集群,etcd 官網提供了一個可以公網訪問的 etcd 存儲地址。我們可以通過如下命令得到 etcd 服務的目錄,並把它作為 --discovery 參數使用。

公共發現服務 discovery.etcd.io 以相同的方式工作,但是有一層修飾,可以提取醜陋的 URL,自動生成 UUID,並提供針對過多請求的保護。公共發現服務在其上仍然使用 etcd 群集作為數據存儲。

$ curl http://discovery.etcd.io/new?size=3

http://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de

以動態發現方式啟動集群

etcd 發現模式下,啟動 etcd 的命令如下:

# etcd1 啟動
$ /opt/etcd/bin/etcd  --name etcd1 --initial-advertise-peer-urls http://192.168.202.128:2380 \
  --listen-peer-urls http://192.168.202.128:2380 \
  --data-dir /opt/etcd/data \
  --listen-client-urls http://192.168.202.128:2379,http://127.0.0.1:2379 \
  --advertise-client-urls http://192.168.202.128:2379 \
  --discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de

# etcd2 啟動
 /opt/etcd/bin/etcd  --name etcd2 --initial-advertise-peer-urls http://192.168.202.129:2380 \
  --listen-peer-urls http://192.168.202.129:2380 \
  --data-dir /opt/etcd/data \
  --listen-client-urls http://192.168.202.129:2379,http://127.0.0.1:2379 \
  --advertise-client-urls http://192.168.202.129:2379 \
  --discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de

# etcd3 啟動
 /opt/etcd/bin/etcd  --name etcd3 --initial-advertise-peer-urls http://192.168.202.130:2380 \
    --listen-peer-urls http://192.168.202.130:2380 \
    --data-dir /opt/etcd/data \
    --listen-client-urls http://192.168.202.130:2379,http://127.0.0.1:2379 \
    --advertise-client-urls http://192.168.202.130:2379 \
    --discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de

需要註意的是,在我們完成了集群的初始化後,這些信息就失去了作用。當需要增加節點時,需要使用 etcdctl 進行操作。為了安全,每次啟動新 etcd 集群時,都使用新的 discovery token 進行註冊。另外,如果初始化時啟動的節點超過了指定的數量,多餘的節點會自動轉化為 Proxy 模式的 etcd。

結果驗證

集群啟動好之後,進行驗證,我們看一下集群的成員:

$ /opt/etcd/bin/etcdctl member list
# 結果如下
    40e2ac06ca1674a7, started, etcd3, http://192.168.202.130:2380, http://192.168.202.130:2379, false
    c532c5cedfe84d3c, started, etcd1, http://192.168.202.128:2380, http://192.168.202.128:2379, false
    db75d3022049742a, started, etcd2, http://192.168.202.129:2380, http://192.168.202.129:2379, false

結果符合預期,再看下節點的健康狀態:

$ /opt/etcd/bin/etcdctl  --endpoints="http://192.168.202.128:2379,http://192.168.202.129:2379,http://192.168.202.130:2379"  endpoint  health
# 結果如下
    http://192.168.202.128:2379 is healthy: successfully committed proposal: took = 3.157068ms
    http://192.168.202.130:2379 is healthy: successfully committed proposal: took = 3.300984ms
    http://192.168.202.129:2379 is healthy: successfully committed proposal: took = 3.263923ms


可以看到,集群中的三個節點都是健康的正常狀態。以動態發現方式啟動集群成功。

 

4 DNS自發現模式

etcd 還支持使用 DNS SRV 記錄進行啟動。實際上是利用 DNS 的 SRV 記錄不斷輪訓查詢實現。DNS SRV 是 DNS 資料庫中支持的一種資源記錄的類型,它記錄了電腦與所提供服務信息的對應關係。

Dnsmasq 安裝

這裡使用 Dnsmasq 創建 DNS 服務。Dnsmasq 提供 DNS 緩存和 DHCP 服務、Tftp 服務功能。作為功能變數名稱解析伺服器,Dnsmasq 可以通過緩存 DNS 請求來提高對訪問過的網址的連接速度。Dnsmasq 輕量且易配置,適用於個人用戶或少於 50 台主機的網路。此外它還自帶了一個 PXE 伺服器。

當接受到一個 DNS 請求時,Dnsmasq 首先會查找 /etc/hosts 這個文件,然後查找 /etc/resolv.conf 中定義的外部 DNS。配置 Dnsmasq 為 DNS 緩存伺服器,同時在 /etc/hosts 文件中加入本地內網解析,這樣使得內網機器查詢時就會優先查詢 hosts 文件,這就等於將 /etc/hosts 共用給全內網機器使用,從而解決內網機器互相識別的問題。相比逐台機器編輯 hosts 文件或者添加 Bind DNS 記錄,可以只編輯一個 hosts 文件。

基於筆者使用的 Centos 7 的主機,首先安裝 Dnsmasq:

yum install dnsmasq

安裝好之後,進行配置,所有的配置都在一個文件中完成 /etc/dnsmasq.conf。我們也可以在 /etc/dnsmasq.d 中自己寫任意名字的配置文件。

配置上游伺服器地址

resolv-file 配置 Dnsmasq 額外的上游的 DNS 伺服器,如果不開啟就使用 Linux 主機預設的 /etc/resolv.conf 里的 nameserver。

$ vim /etc/dnsmasq.conf

# 增加如下的內容:
resolv-file=/etc/resolv.dnsmasq.conf
srv-host=_etcd-server._tcp.blueskykong.com,etcd1.blueskykong.com,2380,0,100
srv-host=_etcd-server._tcp.blueskykong.com,etcd2.blueskykong.com,2380,0,100
srv-host=_etcd-server._tcp.blueskykong.com,etcd3.blueskykong.com,2380,0,100

在 dnsmasq.conf 中相應的功能變數名稱記錄,配置了我們所涉及的三台伺服器,分別對應 etcd1,etcd2,etcd3。

在指定文件中增加轉發 DNS 的地址
$ vim /etc/resolv.dnsmasq.conf

nameserver 8.8.8.8
nameserver 8.8.4.4

這兩個免費的 DNS服務,大家應該不陌生。讀者可以根據本地實際網路進行配置。

本地啟用 Dnsmasq 解析
$ vim /etc/resolv.conf

nameserver 127.0.0.1

將 Dnsmasq 解析配置到本地,這很好理解。

添加解析記錄

分別為各個功能變數名稱配置相關的 A 記錄指向 etcd 核心節點對應的機器 IP。添加解析記錄有三種方式:使用系統預設 hosts、使用自定義 hosts 文件、使用自定義 conf。這裡我們使用比較簡單的第一種方式。

$ vim /etc/hosts

# 增加如下的內容解析
192.168.202.128 etcd1.blueskykong.com
192.168.202.129 etcd2.blueskykong.com
192.168.202.130 etcd3.blueskykong.com

啟動服務

service dnsmasq start

啟動好之後,我們進行驗證:

  • DNS 伺服器上 SRV 記錄查詢,查詢到的結果如下:

    <span class="katex"><annotation encoding="application x-tex"=""> dig @192.168.202.128 +noall +answer SRV _etcd-server._tcp.blueskykong.com

    _etcd-server._tcp.blueskykong.com. 0 IN SRV     100 2380 etcd2.blueskykong.com.
    _etcd-server._tcp.blueskykong.com. 0 IN SRV     100 2380 etcd1.blueskykong.com.
    _etcd-server._tcp.blueskykong.com. 0 IN SRV     100 2380 etcd3.blueskykong.com.
    </code></pre></li>
    <li><p>使查詢功能變數名稱解析結果</p>
    <pre><code><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"><span class="mord mathit">d<span class="mord mathit">i<span class="mord mathit" style="margin-right:0.03588em;">g<span class="mord">@<span class="mord">1<span class="mord">9<span class="mord">2<span class="mord">.<span class="mord">1<span class="mord">6<span class="mord">8<span class="mord">.<span class="mord">2<span class="mord">0<span class="mord">2<span class="mord">.<span class="mord">1<span class="mord">2<span class="mord">8<span class="mspace" style="margin-right:0.2222222222222222em;"><span class="mbin">+<span class="mspace" style="margin-right:0.2222222222222222em;"><span class="base"><span class="strut" style="height:0.77777em;vertical-align:-0.08333em;"><span class="mord mathit">n<span class="mord mathit">o<span class="mord mathit">a<span class="mord mathit" style="margin-right:0.01968em;">l<span class="mord mathit" style="margin-right:0.01968em;">l<span class="mspace" style="margin-right:0.2222222222222222em;"><span class="mbin">+<span class="mspace" style="margin-right:0.2222222222222222em;"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"><span class="mord mathit">a<span class="mord mathit">n<span class="mord mathit">s<span class="mord mathit" style="margin-right:0.02691em;">w<span class="mord mathit">e<span class="mord mathit" style="margin-right:0.02778em;">r<span class="mord mathit" style="margin-right:0.05764em;">S<span class="mord mathit" style="margin-right:0.00773em;">R<span class="mord mathit" style="margin-right:0.22222em;">V<span class="mord">¨<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord">9<span class="mord">5<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord mathit">e<span class="mord mathit">t<span class="mord mathit">c<span class="mord mathit">d<span class="mord">¨<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord">4<span class="mord">5<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord mathit">s<span class="mord mathit">e<span class="mord mathit" style="margin-right:0.02778em;">r<span class="mord mathit" style="margin-right:0.03588em;">v<span class="mord mathit">e<span class="mord mathit" style="margin-right:0.02778em;">r<span class="mord">.<span class="mord">¨<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord">9<span class="mord">5<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord mathit">t<span class="mord mathit">c<span class="mord mathit">p<span class="mord">.<span class="mord mathit">b<span class="mord mathit" style="margin-right:0.01968em;">l<span class="mord mathit">u<span class="mord mathit">e<span class="mord mathit">s<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit" style="margin-right:0.03588em;">y<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit">o<span class="mord mathit">n<span class="mord mathit" style="margin-right:0.03588em;">g<span class="mord">.<span class="mord mathit">c<span class="mord mathit">o<span class="mord mathit">m<span class="mord">¨<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord">9<span class="mord">5<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord mathit">e<span class="mord mathit">t<span class="mord mathit">c<span class="mord mathit">d<span class="mord">¨<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord">4<span class="mord">5<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord mathit">s<span class="mord mathit">e<span class="mord mathit" style="margin-right:0.02778em;">r<span class="mord mathit" style="margin-right:0.03588em;">v<span class="mord mathit">e<span class="mord mathit" style="margin-right:0.02778em;">r<span class="mord">.<span class="mord">¨<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord">9<span class="mord">5<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord mathit">t<span class="mord mathit">c<span class="mord mathit">p<span class="mord">.<span class="mord mathit">b<span class="mord mathit" style="margin-right:0.01968em;">l<span class="mord mathit">u<span class="mord mathit">e<span class="mord mathit">s<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit" style="margin-right:0.03588em;">y<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit">o<span class="mord mathit">n<span class="mord mathit" style="margin-right:0.03588em;">g<span class="mord">.<span class="mord mathit">c<span class="mord mathit">o<span class="mord mathit">m<span class="mord">.<span class="mord">0<span class="mord mathit" style="margin-right:0.07847em;">I<span class="mord mathit" style="margin-right:0.10903em;">N<span class="mord mathit" style="margin-right:0.05764em;">S<span class="mord mathit" style="margin-right:0.00773em;">R<span class="mord mathit" style="margin-right:0.22222em;">V<span class="mord">0<span class="mord">1<span class="mord">0<span class="mord">0<span class="mord">2<span class="mord">3<span class="mord">8<span class="mord">0<span class="mord mathit">e<span class="mord mathit">t<span class="mord mathit">c<span class="mord mathit">d<span class="mord">2<span class="mord">.<span class="mord mathit">b<span class="mord mathit" style="margin-right:0.01968em;">l<span class="mord mathit">u<span class="mord mathit">e<span class="mord mathit">s<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit" style="margin-right:0.03588em;">y<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit">o<span class="mord mathit">n<span class="mord mathit" style="margin-right:0.03588em;">g<span class="mord">.<span class="mord mathit">c<span class="mord mathit">o<span class="mord mathit">m<span class="mord">.<span class="mord">¨<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord">9<span class="mord">5<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord mathit">e<span class="mord mathit">t<span class="mord mathit">c<span class="mord mathit">d<span class="mord">¨<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord">4<span class="mord">5<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord mathit">s<span class="mord mathit">e<span class="mord mathit" style="margin-right:0.02778em;">r<span class="mord mathit" style="margin-right:0.03588em;">v<span class="mord mathit">e<span class="mord mathit" style="margin-right:0.02778em;">r<span class="mord">.<span class="mord">¨<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord">9<span class="mord">5<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord mathit">t<span class="mord mathit">c<span class="mord mathit">p<span class="mord">.<span class="mord mathit">b<span class="mord mathit" style="margin-right:0.01968em;">l<span class="mord mathit">u<span class="mord mathit">e<span class="mord mathit">s<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit" style="margin-right:0.03588em;">y<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit">o<span class="mord mathit">n<span class="mord mathit" style="margin-right:0.03588em;">g<span class="mord">.<span class="mord mathit">c<span class="mord mathit">o<span class="mord mathit">m<span class="mord">.<span class="mord">0<span class="mord mathit" style="margin-right:0.07847em;">I<span class="mord mathit" style="margin-right:0.10903em;">N<span class="mord mathit" style="margin-right:0.05764em;">S<span class="mord mathit" style="margin-right:0.00773em;">R<span class="mord mathit" style="margin-right:0.22222em;">V<span class="mord">0<span class="mord">1<span class="mord">0<span class="mord">0<span class="mord">2<span class="mord">3<span class="mord">8<span class="mord">0<span class="mord mathit">e<span class="mord mathit">t<span class="mord mathit">c<span class="mord mathit">d<span class="mord">1<span class="mord">.<span class="mord mathit">b<span class="mord mathit" style="margin-right:0.01968em;">l<span class="mord mathit">u<span class="mord mathit">e<span class="mord mathit">s<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit" style="margin-right:0.03588em;">y<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit">o<span class="mord mathit">n<span class="mord mathit" style="margin-right:0.03588em;">g<span class="mord">.<span class="mord mathit">c<span class="mord mathit">o<span class="mord mathit">m<span class="mord">.<span class="mord">¨<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord">9<span class="mord">5<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord mathit">e<span class="mord mathit">t<span class="mord mathit">c<span class="mord mathit">d<span class="mord">¨<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord">4<span class="mord">5<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord mathit">s<span class="mord mathit">e<span class="mord mathit" style="margin-right:0.02778em;">r<span class="mord mathit" style="margin-right:0.03588em;">v<span class="mord mathit">e<span class="mord mathit" style="margin-right:0.02778em;">r<span class="mord">.<span class="mord">¨<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord">9<span class="mord">5<span class="mord mathit" style="margin-right:0.05764em;">E<span class="mord mathit">t<span class="mord mathit">c<span class="mord mathit">p<span class="mord">.<span class="mord mathit">b<span class="mord mathit" style="margin-right:0.01968em;">l<span class="mord mathit">u<span class="mord mathit">e<span class="mord mathit">s<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit" style="margin-right:0.03588em;">y<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit">o<span class="mord mathit">n<span class="mord mathit" style="margin-right:0.03588em;">g<span class="mord">.<span class="mord mathit">c<span class="mord mathit">o<span class="mord mathit">m<span class="mord">.<span class="mord">0<span class="mord mathit" style="margin-right:0.07847em;">I<span class="mord mathit" style="margin-right:0.10903em;">N<span class="mord mathit" style="margin-right:0.05764em;">S<span class="mord mathit" style="margin-right:0.00773em;">R<span class="mord mathit" style="margin-right:0.22222em;">V<span class="mord">0<span class="mord">1<span class="mord">0<span class="mord">0<span class="mord">2<span class="mord">3<span class="mord">8<span class="mord">0<span class="mord mathit">e<span class="mord mathit">t<span class="mord mathit">c<span class="mord mathit">d<span class="mord">3<span class="mord">.<span class="mord mathit">b<span class="mord mathit" style="margin-right:0.01968em;">l<span class="mord mathit">u<span class="mord mathit">e<span class="mord mathit">s<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit" style="margin-right:0.03588em;">y<span class="mord mathit" style="margin-right:0.03148em;">k<span class="mord mathit">o<span class="mord mathit">n<span class="mord mathit" style="margin-right:0.03588em;">g<span class="mord">.<span class="mord mathit">c<span class="mord mathit">o<span class="mord mathit">m<span class="mord">.<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="mrel"><<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"><span class="mord">/<span class="mord mathit">c<span class="mord mathit">o<span class="mord mathit">d<span class="mord mathit">e<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="mrel">><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"><span class="mrel"><<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"><span class="mord">/<span class="mord mathit">p<span class="mord mathit" style="margin-right:0.02778em;">r<span class="mord mathit">e<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="mrel">><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"><span class="mrel"><<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"><span class="mord">/<span class="mord mathit" style="margin-right:0.01968em;">l<span class="mord mathit">i<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="mrel">><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"><span class="mrel"><<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="base"><span class="strut" style="height:0.73354em;vertical-align:-0.0391em;"><span class="mord mathit" style="margin-right:0.01968em;">l<span class="mord mathit">i<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="mrel">><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"><span class="mrel"><<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="base"><span class="strut" style="height:0.7335400000000001em;vertical-align:-0.19444em;"><span class="mord mathit">p<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="mrel">><span class="mspace" style="margin-right:0.2777777777777778em;"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"><span class="mord cjk_fallback">使<span class="mord cjk_fallback">查<span class="mord cjk_fallback">詢<span class="mord cjk_fallback">域<span class="mord cjk_fallback">名<span class="mord cjk_fallback">解<span class="mord cjk_fallback">析<span class="mord cjk_fallback">結<span class="mord cjk_fallback">果<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="mrel"><<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"><span class="mord">/<span class="mord mathit">p<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="mrel">><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"><span class="mrel"><<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="base"><span class="strut" style="height:0.7335400000000001em;vertical-align:-0.19444em;"><span class="mord mathit">p<span class="mord mathit" style="margin-right:0.02778em;">r<span class="mord mathit">e<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="mrel">><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"><span class="mrel"><<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="base"><span class="strut" style="height:0.73354em;vertical-align:-0.0391em;"><span class="mord mathit">c<span class="mord mathit">o<span class="mord mathit">d<span class="mord mathit">e<span class="mspace" style="margin-right:0.2777777777777778em;"><span class="mrel">> dig @192.168.202.128 +noall +answer etcd1.blueskykong.com etcd2.blueskykong.com etcd3.blueskykong.com

    etcd1.blueskykong.com.  0       IN      A       192.168.202.128
    etcd2.blueskykong.com.  0       IN      A       192.168.202.129
    etcd3.blueskykong.com.  0       IN      A       192.168.202.130

至此,我們已成功安裝好 Dnsmasq。下麵我們基於 DNS 發現啟動 etcd 集群。

啟動集群

做好了上述兩步 DNS 的配置,就可以使用 DNS 啟動 etcd 集群了。需要刪除ETCD_INITIAL_CLUSTER 配置(用於靜態服務發現),並指定 DNS SRV 功能變數名稱(ETCD_DISCOVERY_SRV)。配置 DNS 解析的 url 參數為 -discovery-srv,其中 etcd1 節點地啟動命令如下:

$ /opt/etcd/bin/etcd   --name etcd1 \
--discovery-srv blueskykong.com \
--initial-advertise-peer-urls http://etcd1.blueskykong.com:2380 \
--initial-cluster-token etcd-cluster-1 \
--data-dir /opt/etcd/data \
--initial-cluster-state new \
--advertise-client-urls http://etcd1.blueskykong.com:2379 \
--listen-client-urls http://0.0.0.0:2379 \
--listen-peer-urls http://0.0.0.0:2380

etcd 群集成員可以使用功能變數名稱或 IP 地址進行廣播,啟動的過程將解析 DNS 記錄。--initial-advertise-peer-urls 中的解析地址必須與 SRV 目標中的解析地址匹配。etcd 成員讀取解析的地址,以查找其是否屬於 SRV 記錄中定義的群集。

我們驗證基於 DNS 發現啟動集群的正確性,查看集群的成員列表:

$ /opt/etcd/bin/etcdctl member list

# 結果如下:
40e2ac06ca1674a7, started, etcd3, http://192.168.202.130:2380, http://etcd3.blueskykong.com:2379, false
c532c5cedfe84d3c, started, etcd1, http://192.168.202.128:2380, http://etcd1.blueskykong.com:2379, false
db75d3022049742a, started, etcd2, http://192.168.202.129:2380, http://etcd2.blueskykong.com:2379, false

可以看到,結果輸出 etcd 集群有三個成員,符合預期。下麵我們使用 IP 地址的方式,繼續驗證集群節點的狀態。

$ /opt/etcd/bin/etcdctl  --endpoints="http://192.168.202.128:2379,http://192.168.202.129:2379,http://192.168.202.130:2379"  endpoint  health

# 結果如下:
http://192.168.202.129:2379 is healthy: successfully committed proposal: took = 2.933555ms
http://192.168.202.128:2379 is healthy: successfully committed proposal: took = 7.252799ms
http://192.168.202.130:2379 is healthy: successfully committed proposal: took = 7.415843ms

更多的 etcd 集群操作,讀者可以自行嘗試,筆者不在此一一展開。

5 小結

本文在上一篇文章單機安裝 etcd 的基礎上進行了補充,主要介紹了 etcd 集群的多種安裝啟動方式:靜態單體,靜態 docker,動態發現以及 DNS 發現的啟動方式。這麼多的安裝姿勢,都是為了我們實際的使用,下一篇我們將具體進入 etcdctl 的使用講解。

訂閱最新文章,歡迎關註我的公眾號

推薦閱讀

  1. etcd 與 Zookeeper、Consul 等其它 k-v 組件的對比
  2. 徹底搞懂 etcd 系列文章(一):初識 etcd
  3. 徹底搞懂 etcd 系列文章(二):etcd 的多種安裝姿勢

參考

etcd docs


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在使用avue表單時,若想在表單中進行數據請求時,可以使用下麵的方法: { label: "補貼類型", prop: "sub_type_msg", search: true, type: "select", dicUrl: "/admin/hadoop/not_auth/subType", dic ...
  • 在做一個公眾號商城,遇到了跨域問題。 後端用了beego框架 ctx.ResponseWriter.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS") ctx.ResponseWriter.Header(). ...
  • 前端開發學習路線知識點彙總,學習前端要熟練掌握前端開發HTML、CSS、JavaScript等核心技術,熟練掌握Vue、React、Angular三大流行框架;使用面向對象思想進行編程,掌握應對業務編程的能力以及常見相容性方案;前後端分工開發流程、原生Ajax請求流程與細節,掌握常見跨域技巧等相關知 ...
  • 動態組件 & 非同步組件 切換組件保持組件的原狀態 1.使用 is 進行組件的切換顯示 <component v-bind:is="currentTabComponent"></component> 這樣是重新創建了組件 如果要保持組件的狀態,比如打開的菜單欄還是保持展開的 ,就可以這樣 <!-- 失 ...
  • 1、圓角邊框 定義圓角邊框後,可以將盒子定義為圓角的 (1)長度方式 <html> <head> <meta charset="utf-8"> <title>盒子模型外邊距</title> <style> div{ width: 200px; height: 100px; background-co ...
  • 13.5 記憶體和性能 Javascript 中函數都是對象,過多被添加到事件的處理程式都會占用記憶體,記憶體中對象越多性能就越差。其次,事先指定好所有事件處理程式而導致的DOM訪問次數也會延遲整個頁面的交互就緒時間 對付“事件處理程式過多”的方案就是事件委托,事件委托利用了事件冒泡只指定一個事件處理程式 ...
  • 前面幾章蜻蜓點水的介紹了elasticsearch、apm相關的內容。本片主要介紹怎麼使用ELK Stack幫助我們打造一個支撐起日產TB級的日誌監控系統 背景 在企業級的微服務環境中,跑著成百上千個服務都算是比較小的規模了。在生產環境上,日誌扮演著很重要的角色,排查異常需要日誌,性能優化需要日誌, ...
  • 消息中間件作為分散式系統的重要成員,各大公司及開源均有許多解決方案。目前主流的開源解決方案包括RabbitMQ、RocketMQ、Kafka、ActiveMQ等。消息這個東西說簡單也簡單,說難也難。簡單之處在於好用方便,接入簡單使用簡單,非同步操作能夠解耦系統間的依賴,同時失敗後也能夠追溯重試。難的地 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...