徹底搞懂 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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...