Etcd叢集的介紹和選主應用

360雲端計算發表於2022-12-06

女主宣言

ETCD作為開源、分散式、高可用、強一致性的key-value儲存系統,提供了配置共享和服務發現等眾多功能。目前已廣泛應用在kubernetes、ROOK、CoreDNS、M3以及openstack等領域。本文作者基於公司內部的場景需求,對etcd進行了介紹,並對選主機制進行了實踐,下來就跟隨作者一起學習下吧。


Etcd叢集的介紹和選主應用


背景介紹

在實際生產環境中,有很多應用在同一時刻只能啟動一個例項,例如更新資料庫的操作,多個例項同時更新不僅會降低系統效能,還可能導致資料的不一致。但是單點部署也使得系統的容災性減弱,比如程式異常退出。目前程式保活,也有很多方案,如supervisor和systemd。但是,如果宿主機down掉呢?所有的程式保活方法都會無濟於事。本文基於etcd自帶的leader選舉機制,輕鬆的使服務具備了高可用性。


Etcd簡介

Etcd是一個開源的、高度一致的分散式key-value儲存系統。由Go語言實現,具有很好的跨平臺性。主要用於配置共享和服務發現。透過raft演算法維護叢集中各個節點的通訊和資料一致性,節點之間是對等的關係,即使leader節點故障,會很快選舉出新的leader,保證系統的正常執行。目前已廣泛應用在kubernetes、ROOK、CoreDNS、M3、openstack等領域。

Etcd叢集的介紹和選主應用
特性:
  1. 介面操作簡單,提供了http+json和grpc介面。
  2. 可選的ssl客戶端認證,支援https訪問。
  3. 每個例項支援1000的QPS,適用於儲存資料量小但更新和訪問頻繁的資料。
  4. 資料按照檔案系統的方式,分層儲存,資料持久化。
  5. 監視特定的鍵或目錄的變化,並對值的更改做出響應,適用於訊息的釋出和訂閱。


Etcd架構及工作原理

架構


Etcd的架構如下圖所示,主要分為四部分。HTTP server、Store、Raft和WAL。

Etcd叢集的介紹和選主應用
  • HTTP server:為使用者提供的Api請求。
  • Store:用於處理 etcd 支援的各類功能的事務,包括資料索引、節點狀態變更、監控與反饋、事件處理與執行等等。
  • Raft:利用raft演算法,保證節點之間資料的強一致性。
  • WAL:資料儲存方式。透過 WAL 進行資料持久化儲存。Snapshot 儲存資料的狀態快照;Entry 表示儲存的具體日誌內容。

工作原理



Etcd叢集的介紹和選主應用

ETCD叢集是一個分散式系統,每個ETCD節點都維護了一個狀態機,並且儲存了完整的資料,任意時刻至多存在一個有效的主節點。主節點處理所有來自客戶端的讀寫操作。其中狀態機的狀態轉換規則如下:

Etcd叢集的介紹和選主應用

ETCD中每個節點的狀態集合為(Follower、Candidate、Leader),叢集初始化時候,每個節點都是Follower角色,當Follower在一定時間內沒有收到來自主節點的心跳,會將自己角色改變為Candidate,併發起一次選主投票;當收到包括自己在內超過半數節點贊成後,選舉成功;當收到票數不足半數選舉失敗,或者選舉超時。若本輪未選出主節點,將進行下一輪選舉。當某個Candidate節點成為Leader後,Leader節點會透過心跳與其他節點同步資料,同時參與競選的Candidate節點進入Follower角色。


Etcd叢集搭建及基本應用

部署環境



三臺系統為centos7的虛機,IP地址如下:
10.143.74.108
10.202.252.147
10.202.254.213
下來以10.143.74.108為例,介紹安裝與配置步驟。

一鍵安裝etcd



1、建立安裝指令碼build.sh。

ETCD_VER=v3.4.7# choose either URLGOOGLE_URL={GITHUB_URL}rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gzrm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-testcurl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gztar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/etcd-download-test --strip-components=1rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gzcp /tmp/etcd-download-test/etcd /usr/binetcd --versioncp /tmp/etcd-download-test/etcdctl /usr/binetcdctl version

2、或者執行以下命令,指令碼已上傳到公網S3儲存。

wget -qO- | bash

etcd配置和systemd保活



1、 建立etcd配置檔案/etc/etcd/etcd.conf。

ETCD_NAME=instance01ETCD_DATA_DIR="/usr/local/etcd/data"ETCD_LISTEN_CLIENT_URLS="

註釋:
  • ETCD_NAME:本member的名稱;
  • ETCD_DATA_DIR:儲存資料的目錄;
  • ETCD_LISTEN_CLIENT_URLS:用於監聽客戶端etcdctl或者curl連線;
  • ETCD_ADVERTISE_CLIENT_URLS: 本機地址, 用於通知客戶端,客戶端透過此IPs與叢集通訊;
  • ETCD_INITIAL_ADVERTISE_PEER_URLS:本機地址,用於通知叢集member,與member通訊;
  • ETCD_LISTEN_PEER_URLS:用於監聽叢集中其它member的連線;
  • ETCD_INITIAL_CLUSTER:描述叢集中所有節點的資訊,本member根據此資訊去聯絡其他member;
  • ETCD_INITIAL_CLUSTER_STATE:叢集狀態,新建叢集時候設定為new,若是想加入某個已經存在的叢集設定為existing。
2、 建立etcd的systemd配置檔案 /usr/lib/systemd/system/etcd.service。
[Unit]
Description=Etcd Server
After=network.target
[Service]
Type=simple
WorkingDirectory=/var/lib/etcd/
EnvironmentFile=-/etc/etcd/etcd.conf
ExecStart=/usr/bin/etcd
KillMode=process
Restart=always
RestartSec=3
LimitNOFILE=655350
LimitNPROC=655350
PrivateTmp=false
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target

3、 啟動etcd。

systemctl daemon-reload

systemctl enable etcd.service

systemctl start etcd.service


4、 檢視etcd叢集狀態。

HOST_1=10.143.74.108

HOST_2=10.202.253.147

HOST_3=10.202.254.213

ENDPOINTS=$HOST_1:2379,$HOST_2:2379,$HOST_3:2379

etcdctl -w table --endpoints=$ENDPOINTS endpoint status


Etcd叢集的介紹和選主應用

5、 讀寫以及刪除操作。

Etcd叢集的介紹和選主應用

6、 watch監聽操作。

Etcd叢集的介紹和選主應用

至此,在10.143.74.108主機上,我們已經成功安裝、啟動etcd服務,並測試了基本的功能。其他兩臺機器的配置類似,在此不再做介紹。



Etcd選主在Go中的實踐

什麼是選主機制呢?舉個例子,在軍事演習中,我們總會發現某架預警機周圍分佈著多架戰鬥機和殲擊機,他們統一聽從預警機的排程,有序的完成消滅敵軍的任務。那麼在這個叢集中,預警機就類似於我們選主中的master,某個叢集有且只有一個master,完成任務的分發等工作,其他節點配合行動,當這個master節點掛掉之後,要能夠立刻選出新的節點作為master。

下來我們一起看下專案中如何利用etcd的選主機制來實現應用的高可用吧。


1、安裝clientv3。
go get "github.com/coreos/etcd/clientv3"


2、新增常量。

const prefix = "/nanoPing"
const prop = "local"
var leaderFlag bool


3、編寫client節點競選函式campaign。


func campaign(c *clientv3.Client, election string, prop string) {

   for {

      //gets the leased session for a client

      s, err := concurrency.NewSession(c, concurrency.WithTTL(15))

      if err != nil {

         log.Println(err)

         continue

      }

      //returns a new election on a given key prefix

      e := concurrency.NewElection(s, election)

      ctx := context.TODO()

      //Campaign puts a value as eligible for the election on the prefix key.

      //Multiple sessions can participate in the election for the same prefix,

      //but only one can be the leader at a time

      if err = e.Campaign(ctx, prop); err != nil {

         log.Println(err)

         continue

      }

      log.Println("elect: success")

      leaderFlag = true

      select {

      case <-s.Done():

         leaderFlag = false

         log.Println("elect: expired")

      }

   }

}


4、新增競選成功後執行的動作run。

func run() {
      log.Println("[info] Service master")
      log.Println("[info] Task start.")
}


5、編寫入口函式,建立client節點,參與競選master,競選成功,執行任務。

func Start() {

   donec := make(chan struct{})

   //create a client

   cli, err := clientv3.New(clientv3.Config{Endpoints: g.Config().Etcd.Addr,Username:g.Config().Etcd.User,Password:g.Config().Etcd.Password})

   if err != nil {

      log.Fatal(err)

   }

   defer cli.Close()

   go campaign(cli, prefix, prop)

   go func() {

      ticker := time.NewTicker(time.Duration(10) * time.Second)

      for {

         select {

         case <-ticker.C:

            {

               if leaderFlag == true{

                  run()

                  return

               }else{

                  log.Println("[info] Service is not master")

               }

            }

         }

      }

   }()

   <-donec

}


6、 測試執行結果。
選主成功的節點輸出:
Etcd叢集的介紹和選主應用

選主失敗的節點輸出:

Etcd叢集的介紹和選主應用

Master節點程式退出後,之前的非master節點,自動競選為master節點。

Etcd叢集的介紹和選主應用



總結

透過etcd中的選主機制,我們實現了服務的高可用。同時利用systemd對etcd本身進行了保活,只要etcd服務所在的機器沒有當機,程式就具備了容災性。當然,一個etcd叢集,不僅僅可以對一個服務提供高可用,我們可以將多個服務註冊在一個etcd叢集中,同時利用etcd所提供的共享配置和服務發現,此外,etcd還有很多值得深入研究的技術,比如raft一致性演算法等等,希望和大家能夠一起深入交流。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69966971/viewspace-2687644/,如需轉載,請註明出處,否則將追究法律責任。

相關文章