基於linux7的ectd安裝與部署
- 系統環境
iostat Linux 3.10.0-693.17.1.el7.x86_64 (swarm1) 2018年03月28日 _x86_64_ (2 CPU) cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) getenforce Disabled
- etcd簡介
etcd是CoreOS團隊於2013年6月發起的開源項目,它的目標是構建一個高可用的分佈式鍵值(key-value)數據庫。etcd內部採用raft協議作爲一致性算法,etcd基於Go語言實現。
etcd作爲服務發現系統,有以下的特點:
(1)簡單:安裝配置簡單,而且提供了HTTP API進行交互,使用也很簡單
(2)安全:支持SSL證書驗證
(3)快速:根據官方提供的benchmark數據,單實例支持每秒2k+讀操作
(4)可靠:採用raft算法,實現分佈式系統數據的可用性和一致性
etcd項目地址:https://github.com/coreos/etcd/ - etcd應用場景
etcd比較多的應用場景是用於服務發現,服務發現(Service Discovery)要解決的是分佈式系統中最常見的問題之一,即在同一個分佈式集羣中的進程或服務如何才能找到對方並建立連接。
從本質上說,服務發現就是要了解集羣中是否有進程在監聽upd或者tcp端口,並且通過名字就可以進行查找和鏈接。
要解決服務發現的問題,需要下面三大支柱,缺一不可。
(1)一個強一致性、高可用的服務存儲目錄。
基於Ralf算法的etcd天生就是這樣一個強一致性、高可用的服務存儲目錄。
(2)一種註冊服務和健康服務健康狀況的機制。
用戶可以在etcd中註冊服務,並且對註冊的服務配置key TTL,定時保持服務的心跳以達到監控健康狀態的效果。
(3)一種查找和連接服務的機制。
通過在etcd指定的主題下注冊的服務業能在對應的主題下查找到。爲了確保連接,我們可以在每個服務機器上都部署一個proxy模式的etcd,這樣就可以確保訪問etcd集羣的服務都能夠互相連接。 - etcd安裝
etcd在生產環境中一般推薦集羣方式部署。etcd目前默認使用2379端口提供HTTP API服務,2380端口和peer通信(這兩個端口已經被IANA官方預留給etcd);在之前的版本中可能會分別使用4001和7001,在使用的過程中需要注意這個區別。
因爲etcd是go語言編寫的,安裝只需要下載對應的二進制文件,並放到合適的路徑就行。 - etcd下載與啓動
##etcd下載 mkdir -p /opt/etcd && cd /opt/etcd curl -L https://github.com/coreos/etcd/releases/download/v3.3.2/etcd-v3.3.2-linux-amd64.tar.gz -o etcd-v3.3.2-linux-amd64.tar.gz ##解壓後是一些文檔和兩個二進制文件etcd和etcdctl。etcd是server端,etcdctl是客戶端。 tar zxf etcd-v3.3.2-linux-amd64.tar.gz mv etcd-v3.3.2-linux-amd64 etcd pwd /opt/etcd cd etcd ls etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md ##如果在測試環境,啓動一個單節點的etcd服務,只需要運行etcd命令就行。 ./etcd 如下: ##前臺運行,直接佔用了當前終端。 2018-03-28 17:46:23.082655 I | etcdmain: etcd Version: 3.3.2 2018-03-28 17:46:23.082753 I | etcdmain: Git SHA: c9d46ab37 2018-03-28 17:46:23.082769 I | etcdmain: Go Version: go1.9.4 2018-03-28 17:46:23.082783 I | etcdmain: Go OS/Arch: linux/amd64 2018-03-28 17:46:23.082817 I | etcdmain: setting maximum number of CPUs to 2, total number of available CPUs is 2 。。。。。。 ##從上面的輸出中,我們可以看到很多信息。以下是幾個比較重要的信息: (1)name表示節點名稱,默認爲default。 (2)data-dir 保存日誌和快照的目錄,默認爲當前工作目錄default.etcd/目錄下。 (3)在http://localhost:2380和集羣中其他節點通信。 (4)在http://localhost:2379提供HTTP API服務,供客戶端交互。 (5)heartbeat爲100ms,該參數的作用是leader多久發送一次心跳到followers,默認值是100ms。 (6)election爲1000ms,該參數的作用是重新投票的超時時間,如果follow在該時間間隔沒有收到心跳包,會觸發重新投票,默認爲1000ms。 (7)snapshot count爲10000,該參數的作用是指定有多少事務被提交時,觸發截取快照保存到磁盤。 (8)集羣和每個節點都會生成一個uuid。 (9)啓動的時候會運行raft,選舉出leader。 ##添加etcd啓動路徑 cat >> /etc/profile << EOF ##etcd export PATH=/opt/etcd/etcd:$PATH export ETCDCTL_API=3 EOF source /etc/profile ##查看下etcd路徑 echo $PATH /opt/etcd/etcd:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin 說明:如果不設置 ETCDCTL_API=3,則默認是的API版本是2: etcdctl version etcdctl version: 3.3.2 API version: 2 正確設置後,API版本變成3: etcdctl version etcdctl version: 3.3.2 API version: 3.3 ##上面的方法只是簡單的啓動一個etcd服務,但要長期運行的話,還是做成一個服務好一些。下面將以systemd爲例,介紹如何建立一個etcd服務。
- 建立etcd服務
##設定etcd配置文件,建立相關目錄 mkdir -p /var/lib/etcd/ mkdir -p /opt/etcd/config/ ##創建etcd配置文件 cat <<EOF | sudo tee /opt/etcd/config/etcd.conf #節點名稱 ETCD_NAME=$(hostname -s) #數據存放位置 ETCD_DATA_DIR=/var/lib/etcd EOF ##創建systemd配置文件 cat <<EOF | tee /etc/systemd/system/etcd.service [Unit] Description=Etcd Server Documentation=https://github.com/coreos/etcd After=network.target [Service] User=root Type=notify EnvironmentFile=/opt/etcd/config/etcd.conf ExecStart=/opt/etcd/etcd/etcd Restart=on-failure RestartSec=10s LimitNOFILE=40000 [Install] WantedBy=multi-user.target EOF ##啓動etcd systemctl daemon-reload && systemctl enable etcd && systemctl start etcd
- etcd基本使用
etcdctl是一個命令行客戶端,它能提供一些簡潔的命令,供用戶直接跟etcd服務打交道,而無需基於 HTTP API方式。可以方便我們在對服務進行測試或者手動修改數據庫內容。建議剛剛接觸etcd時通過etdctl來熟悉相關操作。這些操作跟HTTP API基本上是對應的。
etcd項目二進制發行包中已經包含了etcdctl工具,etcdctl支持的命令大體上分爲數據庫操作和非數據庫操作兩類。##查看etcd版本 etcd --version etcd Version: 3.3.2 Git SHA: c9d46ab37 Go Version: go1.9.4 Go OS/Arch: linux/amd64 ##etcdctl參數和選項 etcdctl -h ##數據庫操作 數據庫操作圍繞對鍵值和目錄的CRUD完整生命週期的管理。 etcd在鍵的組織上採用了層次化的空間結構(類似於文件系統中目錄的概念),用戶指定的鍵可以爲單獨的名字,如:testkey,此時實際上放在根目錄/下面,也可以爲指定目錄結構,如/cluster1/node2/testkey,則將創建相應的目錄結構。 說明:CRUD即Create,Read,Update,Delete是符合REST風格的一套API操作。 (1)put etcdctl put foo "hello world" OK etcdctl put /root/wtf "datagrand" OK (2)get etcdctl get foo foo hello world etcdctl get /root/wtf /root/wtf datagrand ##當鍵不存在時,則會報錯。例如: etcdctl get /testdir/testkey2 Error: 100: Key not found (/testdir/testkey2) [5]
- 集羣及go安裝優化
##單獨集羣:只有一臺服務器的集羣。 部署etcd集羣作爲單獨集羣是直截了當的。僅用一個命令啓動它 etcd或 systemctl daemon-reload && systemctl enable etcd && systemctl start etcd ##本地多成員集羣 多成員集羣:有多臺臺服務器的集羣。 提供 Procfile 用於簡化搭建本地多成員集羣。通過少量命令來啓動多成員集羣: ##使用go get **** 命令安裝程序 yum install -y go 系統會安裝golang-1.8.3-1.el7.x86_64(按實際版本) ##執行 go version,查看當前 go 的當前版本 go version go version go1.8.3 linux/amd64 ##執行 go env,查看當前 go 的環境變量 go env GOARCH="amd64" GOBIN="" GOEXE="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOOS="linux" GOPATH="/root/go" GORACE="" GOROOT="/usr/lib/golang" GOTOOLDIR="/usr/lib/golang/pkg/tool/linux_amd64" 說明:golang1.8默認情況下,在 GOPATH 沒有設置的情況下,使用的默認路徑是 /root/go 。這個是非常不好的,因爲 /root 目錄權限非常特殊。 因此最好能自己設置 GOPATH,比如設置到自己的工作區目錄。 mkdir -p /usr/local/go ##修改 /etc/profile,將go加入到path中 cat >> /etc/profile << EOF export GOPATH=/usr/local/go export PATH=/usr/local/go/bin:$PATH EOF source /etc/profile ##執行 go env,查看當前 go 的GOPATH GOPATH="/usr/local/go" 說明:之後再通過 go get **** 命令安裝程序時,新的程序就會被安裝到 GOPATH/bin 下,然後由於GOPATH/bin 已經加入到 PATH,因此就可以很方便的使用新安裝的程序。
- 多成員集羣(一個node多個port)
##安裝goreman go get github.com/mattn/goreman ##查看下安裝路徑 which goreman /usr/local/go/bin/goreman ##編輯Procfile文件 cat >> Procfile << EOF ##Use goreman to run `go get github.com/mattn/goreman` 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 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 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 EOF ##查看當前監控端口 netstat -lnp|grep etcd tcp 0 0 127.0.0.1:2379 0.0.0.0:* LISTEN 32618/etcd tcp 0 0 127.0.0.1:2380 0.0.0.0:* LISTEN 32618/etcd ##啓動多成員集羣 goreman -f /root/Procfile start ##查看監控端口 netstat -lnp|grep etcd tcp 0 0 127.0.0.1:22379 0.0.0.0:* LISTEN 53932/etcd tcp 0 0 127.0.0.1:2379 0.0.0.0:* LISTEN 32618/etcd tcp 0 0 127.0.0.1:22380 0.0.0.0:* LISTEN 53932/etcd tcp 0 0 127.0.0.1:2380 0.0.0.0:* LISTEN 32618/etcd tcp 0 0 127.0.0.1:32379 0.0.0.0:* LISTEN 53926/etcd tcp 0 0 127.0.0.1:12379 0.0.0.0:* LISTEN 53925/etcd tcp 0 0 127.0.0.1:32380 0.0.0.0:* LISTEN 53926/etcd tcp 0 0 127.0.0.1:12380 0.0.0.0:* LISTEN 53925/etcd 說明:啓動的成員各自在 localhost:12379, localhost:22379, 和 localhost:32379 上監聽客戶端請求。 ##通過使用 etcdctl 來查看已經啓動的集羣 etcdctl --write-out=table --endpoints=localhost:12379 member list
- etcd存取數據測試
##向其中以port寫入數據 etcdctl --endpoints=localhost:12379 put name "my name is wtf" OK ##用其port提取數據 etcdctl --endpoints=localhost:22379 get name name my name is wtf etcdctl --endpoints=localhost:32379 get name name my name is wtf
- etcd的容錯性
##kill某個成員 goreman run stop etcd2 說明: 使用etcdctl --write-out=table --endpoints=localhost:12379 member list查看時,etcd2還在,但netstat -lnp|grep etcd監控的端口已經停掉了,使用ps -ef | grep etcd | grep 127.0.0.1:22379查看下ectd2的pid爲空。 ##put數據 etcdctl --endpoints=localhost:12379 put key hello OK ##get數據 etcdctl --endpoints=localhost:12379 get key hello ##試圖從被殺掉的成員獲取key etcdctl --endpoints=localhost:22379 get key 報錯:Error: dial tcp [::1]:22379: getsockopt: connection refused ##重啓被殺掉的成員 goreman run restart etcd2 ##從重啓的成員獲取key etcdctl --endpoints=localhost:22379 get key hello