k8s學習筆記-etcd介紹和集群搭建


前言

隨着kubernetes項目的日益火熱,該項目中用到的etcd組件作為一個高可用強一致性的服務發現存儲倉庫,漸漸的被開發人員所關注。

在雲計算時代,如何讓服務快速、透明的接入到計算集群中,如何讓共享配置信息快速被集群中的所有節點發現,如何構建一套高可用、安全、易於部署以及快速響應的服務集群成為了需要解決的問題。

Etcd為解決這類問題帶來便捷。

官方地址: https://coreos.com/etcd/

項目地址: https://github.com/coreos/etcd

Etcd是什么

Etcd是一個高可用的鍵值存儲系統,主要用於共享配置和服務發現,它通過Raft一致性算法處理日志復制以保證強一致性,我們可以理解它為一個高可用強一致性的服務發現存儲倉庫

在kubernetes集群中,etcd主要用於配置共享和服務發現

Etcd主要解決的是分布式系統中數據一致性的問題,而分布式系統中的數據分為控制數據和應用數據,etcd處理的數據類型為控制數據,對於很少量的應用數據也可以進行處理。

Etcd和Zookeeper的比較

Zookeeper有如下缺點

  1. 1.復雜。ZooKeeper的部署維護復雜,管理員需要掌握一系列的知識和技能;而Paxos強一致性算法也是素來以復雜難懂而聞名於世(ETCD使用[Raft]協議, ZK使用ZAB,類PAXOS協議);另外,ZooKeeper的使用也比較復雜,需要安裝客戶端,官方只提供了Java和C兩種語言的接口。

  2. 2.Java編寫。這里不是對Java有偏見,而是Java本身就偏向於重型應用,它會引入大量的依賴。而運維人員則普遍希望保持強一致、高可用的機器集群盡可能簡單,維護起來也不易出錯。

  3. 3.發展緩慢。Apache基金會項目特有的“Apache Way”在開源界飽受爭議,其中一大原因就是由於基金會龐大的結構以及松散的管理導致項目發展緩慢。

相較之下,Etcd

      1.簡單。使用Go語言編寫部署簡單;使用HTTP作為接口使用簡單;使用Raft算法保證強一致性讓用戶易於理解

  1. 2.數據持久化。etcd默認數據一更新就進行持久化。

  2. 3.安全。etcd支持SSL客戶端安全認證。

Etcd的架構與術語

 

流程分析

通常一個用戶的請求發送過來,會經過HTTP Server轉發給Store進行具體的事務處理,如果涉及到節點的修改,則需要交給Raft模塊進行狀態的變更,日志的記錄。

然后再同步給別的etcd節點確認數據提交,最后進行數據提交,再次同步。

工作原理

Etcd使用Raft協議來維護集群內各個節點狀態的一致性。簡單說,ETCD集群是一個分布式系統,由多個節點相互通信構成整體對外服務,每個節點都存儲了完整的數據,並且通過Raft協議保證每個節點維護的數據是一致的。

Etcd主要分為四個部分

  1. HTTP Server: 用於處理用戶發送的API請求以及其他etcd節點的同步與心跳信息請求

  2. Store:  用於處理 etcd 支持的各類功能的事務,包括數據索引、節點狀態變更、監控與反饋、事件處理與執行等等,是 etcd 對用戶提供的大多數 API 功能的具體實現。

  3. Raft: Raft 強一致性算法的具體實現,是 etcd 的核心。

  4. WAL:Write Ahead Log(預寫式日志/日志先行),是 etcd 的數據存儲方式,也是一種實現事務日志的標准方法。etcd通過 WAL 進行持久化存儲,所有的數據提交前都會事先記錄日志。Snapshot 是為了防止數據過多而進行的狀態快照;Entry 表示存儲的具體日志內容。

服務發現

服務發現要解決的也是分布式系統中最常見的問題之一,即在同一個分布式集群中的進程或服務,要如何才能找到對方並建立連接。本質上來說,服務發現就是想要了解集群中是否有進程在監聽 udp 或 tcp 端口,並且通過名字就可以查找和連接。要解決服務發現的問題,需要具備以下三點:

 

1.一個強一致性、高可用的服務存儲目錄。基於 Raft 算法的 etcd 天生就是這樣一個強一致性高可用的服務存儲目錄。

2.一種注冊服務和監控服務健康狀態的機制。用戶可以在 etcd 中注冊服務,並且對注冊的服務設置key TTL,定時保持服務的心跳以達到監控健康狀態的效果。

3.一種查找和連接服務的機制。通過在 etcd 指定的主題下注冊的服務也能在對應的主題下查找到。為了確保連接,我們可以在每個服務機器上都部署一個 Proxy 模式的 etcd,這樣就可以確保能訪問 etcd 集群的服務都能互相連接。
例如隨着 Docker 容器的流行,多種微服務共同協作,構成一個相對功能強大的架構的案例越來越多。透明化的動態添加這些服務的需求也日益強烈。通過服務發現機制,在 etcd 中注冊某個服務名字的目錄,在該目錄下存儲可用的服務節點的 IP。在使用服務的過程中,只要從服務目錄下查找可用的服務節點去使用即可。

 

Etcd集群中的術語

 

  • Raft: etcd所采用的保證分布式系統強一致的算法

  • Node: 一個Raft狀態機實例

  • Member: 一個etcd實例,管理一個Node,可以為客戶端請求提供服務

  • Cluster: 多個Member構成的可以協同工作的etcd集群

  • Peer: 同一個集群中,其他Member的稱呼

  • Client: 向etcd集群發送HTTP請求的客戶端

  • WAL: 預寫日志,是etcd用於持久化存儲的日志格式

  • Snapshot: etcd防止WAL文件過多而設置的快照,存儲etcd數據狀態

  • Proxy: etcd的一種模式,可以為etcd提供反向代理服務

  • Leader: Raft算法中通過競選而產生的處理所有數據提交的節點

  • Follower: Raft算法中競選失敗的節點,作為從屬節點,為算法提供強一致性保證

  • Candidate: Follower超過一定時間接收不到Leader節點的心跳的時候,會轉變為Candidate(候選者)開始Leader競選

  • Term: 某個節點稱為Leader到下一次競選開始的時間周期,稱為Term(任界,任期)

  • Index: 數據項編號, Raft中通過Term和Index來定位數據

     

Raft算法

Raft 是一種為了管理復制日志的一致性算法。它提供了和 Paxos 算法相同的功能和性能,但是它的算法結構和 Paxos 不同,使得 Raft 算法更加容易理解並且更容易構建實際的系統。一致性算法允許一組機器像一個整體一樣工作,即使其中一些機器出現故障也能夠繼續工作下去。正因為如此,一致性算法在構建可信賴的大規模軟件系統中扮演着重要的角色。

Raft算法分為三部分

Leader選舉、日志復制和安全性

Raft算法特性:

1.強領導者: 和其他一致性算法相比,Raft 使用一種更強的領導能力形式。比如,日志條目只從領導者發送給其他的服務器。這種方式簡化了對復制日志的管理並且使得 Raft 算法更加易於理解。

2.領導選舉: Raft 算法使用一個隨機計時器來選舉領導者。這種方式只是在任何一致性算法都必須實現的心跳機制上增加了一點機制。在解決沖突的時候會更加簡單快捷。

3.成員關系調整: Raft 使用一種共同一致的方法來處理集群成員變換的問題,在這種方法下,處於調整過程中的兩種不同的配置集群中大多數機器會有重疊,這就使得集群在成員變換的時候依然可以繼續工作。

Leader選舉

Raft 狀態機

Raft集群中的每個節點都處於一種基於角色的狀態機中。具體來說,Raft定義了節點的三種角色: Follower、Candidate和Leader。

1.Leader(領導者): Leader節點在集群中有且僅能有一個,它負責向所有的Follower節點同步日志數據

2.Follower(跟隨者): Follower節點從Leader節點獲取日志,提供數據查詢功能,並將所有修改請求轉發給Leader節點

3.Candidate(候選者): 當集群中的Leader節點不存在或者失聯之后,其他Follower節點轉換為Candidate,然后開始新的Leader節點選舉

這三種角色狀態之間的轉換,如下圖:

 

 一個 Raft 集群包含若干個服務器節點;通常是 5 個,這允許整個系統容忍 2 個節點的失效。在任何時刻個服務器節點都處於這三個狀態之一:領導人、跟隨者或者候選人。在通常情況下,系統中只有一個領導人並且其他的節點全部都是跟隨者。跟隨者都是被動的:他們不會發送任何請求,只是簡單的響應來自領導者或者候選人的請求。領導人處理所有的客戶端請求(如果一個客戶端和跟隨者聯系,那么跟隨者會把請求重定向給領導人)

在節點初始啟動的時候,所有節點的Raft狀態機都會處於Follower狀態。當Follower在一定的時間周期內沒有收到來自Leader節點的心跳數據包的時候,節點會將自己的狀態切換為Candidate,並向集群中其他Follower節點發送投票請求,Follower都會將自己的票投給收到的第一個投票請求節點。當Candidate收到來自集群中超過半數節點的投票后,會成為新的Leader節點。

Leader節點將接受並保存用戶發送的數據,並向其他的Follower節點同步日志。

Follower只響應來自其他服務器的請求。如果Follower接收不到消息,那么他就會變成候選人並發起一次選舉。獲得集群中大多數選票的候選人將成為Leader。在一個任期(Term)內,領導人一直都會是領導人直到自己宕機了。

Leader節點依靠定時向所有Follower發送心跳數據來保持地位。當急群眾的Leader節點出現故障的時候,Follower會重新選舉新的節點,保證整個集群正常運行。  

每次成功的選舉,新的Leader的Term(任期)值都會比之前的Leader增加1。當集群中由於網絡或者其他原因出現分裂后又重新合並的時候,集群中可能會出現多於一個的Leader節點,此時,Term值更高的節點才會成為真正的Leader。

Raft算法中的Term(任期)

關於Term,如下圖:

 

Raft會把時間分割成任意長度的任期。並且任期用連續的整數來標記。每一段任期都是從一次選舉開始一個或者多個候選人嘗試成為領導者。如果一個候選人贏得選舉,然后他就會在接下來的任期中充當Leader的職責。在某些情況下,一次選舉會造成選票瓜分,這樣,這一個任期將沒有Leader。如果沒有Leader,那么新的一輪選舉就馬上開始,也就是新的任期就會開始。Raft保證了在一個Term任期內,有且只有一個Leader。

日志復制

所謂日志復制,是指主節點將每次操作形成日志條目,並持久化到本地磁盤,然后通過網絡IO發送給其他節點。

一旦一個領導人被選舉出來,他就開始為客戶端提供服務。客戶端的每一個請求都包含一條被復制狀態機執行的指令領導人把這條指令作為一條新的日志條目附加到日志中去,然后並行的發起附加條目 RPCs 給其他的服務器,讓他們復制這條日志條目。

Raft 算法保證所有已提交的日志條目都是持久化的並且最終會被所有可用的狀態機執行。當主節點收到包括自己在內超過半數節點成功返回,那么認為該日志是可提交的(committed),並將日志輸入到狀態機,將結果返回給客戶端。

在正常的操作中,領導人和跟隨者的日志保持一致性,所以附加日志 RPC 的一致性檢查從來不會失敗。然而,領導人崩潰的情況會使得日志處於不一致的狀態(老的領導人可能還沒有完全復制所有的日志條目)。這種不一致問題會在一系列的領導人和跟隨者崩潰的情況下加劇。跟隨者的日志可能和新的領導人不同的方式。跟隨者可能會丟失一些在新的領導人中有的日志條目,他也可能擁有一些領導人沒有的日志條目,或者兩者都發生。丟失或者多出日志條目可能會持續多個任期。這就引出了另一個部分,就是安全性

安全性

截止此刻,選主以及日志復制並不能保證節點間數據一致。試想,當一個某個節點掛掉了,一段時間后再次重啟,並當選為主節點。而在其掛掉這段時間內,集群若有超過半數節點存活,集群會正常工作,那么會有日志提交。這些提交的日志無法傳遞給掛掉的節點。當掛掉的節點再次當選主節點,它將缺失部分已提交的日志。在這樣場景下,按Raft協議,它將自己日志復制給其他節點,會將集群已經提交的日志給覆蓋掉。這顯然是錯誤的

其他協議解決這個問題的辦法是,新當選的主節點會詢問其他節點,和自己數據對比,確定出集群已提交數據,然后將缺失的數據同步過來。這個方案有明顯缺陷,增加了集群恢復服務的時間(集群在選舉階段不可服務),並且增加了協議的復雜度。Raft解決的辦法是,在選主邏輯中,對能夠成為主的節點加以限制,確保選出的節點已定包含了集群已經提交的所有日志。如果新選出的主節點已經包含了集群所有提交的日志,那就不需要從和其他節點比對數據了。簡化了流程,縮短了集群恢復服務的時間。

這里存在一個問題,加以這樣限制之后,還能否選出主呢?答案是:只要仍然有超過半數節點存活,這樣的主一定能夠選出。因為已經提交的日志必然被集群中超過半數節點持久化,顯然前一個主節點提交的最后一條日志也被集群中大部分節點持久化。當主節點掛掉后,集群中仍有大部分節點存活,那這存活的節點中一定存在一個節點包含了已經提交的日志了。

Etcd的代理節點(proxy)

Etcd針對Raft的角色模型進行了擴展,增加了Proxy角色proxy模式的本職就是啟一個HTTP代理服務器把客戶發到這個服務器的請求轉發給別的 etcd 節點。

作為Proxy角色的節點不會參與Leader的選舉,只是將所有接收到的用戶查詢和修改請求轉發到任意一個Follower或者Leader節點上。

Proxy節點可以在啟動Etcd的時候通過"--proxy on"參數指定。在使用了"節點自發現"服務的集群中,可以設置一個固定的"參選節點數目",超過這個數目的成員自動轉換為Proxy節點。

一旦節點成為Proxy之后,便不再參與所有Leader選舉和Raft狀態變化。除非將這個節點重啟並指定為成員的Follower節點

etcd 作為一個反向代理把客戶的請求轉發給可用的 etcd 集群。這樣,你就可以在每一台機器都部署一個 Proxy 模式的 etcd 作為本地服務,如果這些 etcd Proxy 都能正常運行,那么你的服務發現必然是穩定可靠的。

完整的Etcd角色狀態轉換過程如下圖:

 

kubernetes項目中,Etcd用來做什么,為什么選擇它

etcd在kubernetes集群是用來存放數據並通知變動的

Kubernetes中沒有用到數據庫,它把關鍵數據都存放在etcd中,這使kubernetes的整體結構變得非常簡單。

在kubernetes中,數據是隨時發生變化的,比如說用戶提交了新任務、增加了新的Node、Node宕機了、容器死掉了等等,都會觸發狀態數據的變更。狀態數據變更之后呢,Master上的kube-scheduler和kube-controller-manager,就會重新安排工作,它們的工作安排結果也是數據。這些變化,都需要及時地通知給每一個組件。etcd有一個特別好用的特性,可以調用它的api監聽其中的數據,一旦數據發生變化了,就會收到通知。有了這個特性之后,kubernetes中的每個組件只需要監聽etcd中數據,就可以知道自己應該做什么。kube-scheduler和kube-controller-manager呢,也只需要把最新的工作安排寫入到etcd中就可以了,不用自己費心去逐個通知了

試想一下,如果沒有etcd,那么要怎樣做?這里的本質是:數據的傳遞有兩種方式,一種是消息的方式,比如說NodeA有了新的任務,Master直接給NodeA發一個消息,中間不經過任何人;一種是輪詢的方式,大家都把數據寫到同一個地方,每個人自覺地盯着看,及時發現變化。前者演化出rabbitmq這樣的消息隊列系統,后者演化出一些有訂閱功能的分布式系統。

第一種方式的問題是,所有要通信的組件之間都要建立長連接,並且要處理各種異常情況,比例如連接斷開、數據發送失敗等。不過有了消息隊列(message queue)這樣的中間件之后,問題就簡單多了,組件都和mq建立連接即可,將各種異常情況都在mq中處理。

那么為什么kubernetes沒有選用mq而是選用etcd呢?mq和etcd是本質上完全不同的系統,mq的作用消息傳遞,不儲存數據(消息積壓不算儲存,因為沒有查詢的功能,etcd是個分布式存儲(它的設計目標是分布式鎖,順帶有了存儲功能),是一個帶有訂閱功能的key-value存儲。如果使用mq,那么還需要引入數據庫,在數據庫中存放狀態數據。

選擇etcd還有一個好處,etcd使用raft協議實現一致性,它是一個分布式鎖,可以用來做選舉。如果在kubernetes中部署了多個kube-schdeuler,那么同一時刻只能有一個kube-scheduler在工作,否則各自安排各自的工作,就亂套了。怎樣保證只有一個kube-schduler在工作呢?那就是前文說到的通過etcd選舉出一個leader

上面的介紹轉發下面的文章https://blog.51cto.com/13210651/2358716 感謝作者分享,為方便閱讀重新復制了一遍

下面介紹集群的安裝

環境

系統centos 7.6 

etcd01 10.211.55.11

etcd02 10.211.55.12

etcd02  10.211.55.13

安裝方式:

wget https://github.com/etcd-io/etcd/releases/download/v3.3.13/etcd-v3.3.13-linux-amd64.tar.gz

還有一種方式是通過系統YUM 安裝

我這邊用的是YUM 安裝

 

yum install etcd -y 

 

vim /etc/etcd/etcd.conf
ETCD_DATA_DIR="/data/etcd/"
ETCD_LISTEN_CLIENT_URLS="https://0.0.0.0:2379"
ETCD_NAME="etcd01"
ETCD_LISTEN_PEER_URLS="https://0.0.0.0:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://10.211.55.11:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://10.211.55.11:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://10.211.55.11:2380,etcd02=https://10.211.55.12:2380,etcd03=https://10.211.55.13:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_CERT_FILE="/etc/ssl/kubernetes/kubernetes.pem"
ETCD_KEY_FILE="/etc/ssl/kubernetes/kubernetes-key.pem"
ETCD_TRUSTED_CA_FILE="/etc/ssl/kubernetes/ca.pem"
ETCD_PEER_CERT_FILE="/etc/ssl/kubernetes/kubernetes.pem"
ETCD_PEER_KEY_FILE="/etc/ssl/kubernetes/kubernetes.pem"
ETCD_PEER_TRUSTED_CA_FILE="/etc/ssl/kubernetes/ca.pem"

這里面涉及到證書,有相關文章介紹了,可以參考上一篇文章,這里不在多說了,證書統一放到/etc/ssl/kubernetes/下面

參數說明
--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
新建集群的標志,初始化狀態使用 new,建立之后改此值為 existing

修改服務啟動腳本 

[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
EnvironmentFile=-/etc/etcd/etcd.conf
ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/bin/etcd \
--name=${ETCD_NAME} \
--listen-client-urls=${ETCD_LISTEN_CLIENT_URLS} \
--listen-peer-urls=${ETCD_LISTEN_PEER_URLS} \
--advertise-client-urls=${ETCD_ADVERTISE_CLIENT_URLS} \
--initial-advertise-peer-urls=${ETCD_INITIAL_ADVERTISE_PEER_URLS} \
--initial-cluster=${ETCD_INITIAL_CLUSTER} \
--initial-cluster-token=${ETCD_INITIAL_CLUSTER_TOKEN} \
--initial-cluster-state=new \

--client-cert-auth=true \

--cert-file=${ETCD_CERT_FILE} \
--key-file=${ETCD_KEY_FILE} \
--peer-cert-file=${ETCD_PEER_CERT_FILE} \
--peer-key-file=${ETCD_PEER_KEY_FILE}\
--trusted-ca-file=${ETCD_TRUSTED_CA_FILE} \
--peer-trusted-ca-file=${ETCD_PEER_TRUSTED_CA_FILE}"
User=etcd
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

注: 啟動的時候注意給/data/etcd 賦予權限

chown etcd.etcd /data/etcd 

systemctl daemon-reload 

service etcd start

chkconfig etcd on 

查看日志

tail -f /var/log/message

其他節點也是這種部署方式,唯一的區別是修改為本機IP ,和修改ETCD_NAME,上面配置文件紅色部分就是需要修改的

全部啟動成功以后,驗證一下

etcdctl \
--ca-file=/etc/ssl/kuberneters/ca.pem --cert-file=/etc/ssl/kuberneters/kuberneters.pem --key-file=/etc/ssl/kuberneters/kuberneters-key.pem \
--endpoints="https://10.211.55.11:2379,https://10.211.55.12:2379,https://10.211.55.13:2379"  member list
344a57bb34515764: name=etcd01 peerURLs=https://10.211.55.11:2380 clientURLs=https://10.211.55.11:2379 isLeader=true
f9c27963788aad6e: name=etcd02 peerURLs=https://10.211.55.12:2380 clientURLs=https://10.211.55.12:2379 isLeader=false
ff2f490dbe25f877: name=etcd03 peerURLs=https://10.211.55.13:2380 clientURLs=https://10.211.55.13:2379 isLeader=false

可以看到etc01 是leader  

注:其實集群內部不用證書驗證通信可以,可以對peerurls 只用http ,外部客戶端用TSL 驗證

 

新增加新的節點

etcdctl --ca-file=/etc/ssl/kubernetes/ca.pem --cert-file=/etc/ssl/kubernetes/kubernetes.pem --key-file=/etc/ssl/kubernetes/kubernetes-key.pem --endpoints="https://k8s-etcd1:2379" member add k8s-etcd4 http://k8s-etcd4:2380

然后去新的節點配置

 

新增加節點的conf文件注意 ETCD_INITIAL_CLUSTER_STATE="existing"

啟動etcd 即可觀察

etcdctl --ca-file=/etc/ssl/kubernetes/ca.pem --cert-file=/etc/ssl/kubernetes/kubernetes.pem --key-file=/etc/ssl/kubernetes/kubernetes-key.pem --endpoints="https://k8s-etcd1:2379" member list

etcd升級遇到的問題

1 conflicting environment variable "ETCD_NAME" is shadowed by corresponding command-line flag (either unset environment variable or disable flag)

原因:ETCD3.4版本會自動讀取環境變量的參數,所以EnvironmentFile文件中有的參數,不需要再次在ExecStart啟動參數中添加,二選一,如同時配置,會觸發以下類似報錯
etcd: conflicting environment variable "ETCD_NAME" is shadowed by corresponding command-line flag (either unset environment variable or disable flag)
解決:剔除ExecStart中和配置文件重復的內容即可
2 cannot access data directory: directory "/application/kubernetes/data/","drwxr-xr-x" exist without desired file permission "-rwx------".

解決:將權限設置為700即可

3、Failed at step CHDIR spawning /usr/bin/etcd: No such file or directory

原因:etcd.service服務配置文件中設置的工作目錄WorkingDirectory=/var/lib/etcd/必須存在,否則會報以上錯誤

Etcd v3.3 升級到 v3.4

flannel 使用 v0.10.0 版本

遇到的問題
Etcd 需要升級到 v3.4.7 版本,從 v3.3.9 直接升級到 v3.4.7 是沒有問題的。但升級完成后,在查看 flannel 日志時,發現日志不斷報 E0714 14:49:48.309007 2887 main.go:349] Couldn't fetch network config: client: response is invalid json. The endpoint is probably not valid etcd cluster endpoint. 錯誤。

剛開始以為是 flannel 版本過低導致,后面把 flannel 升級到最新版本 v0.12.0,但是問題還是一樣。

問題原因
后面仔細通過排查,發現是連接不上 Etcd,當時很疑惑 Etce 連接不上,可 kube-apiserver 連接是正常的,后面才想起來,kube-apiserver 使用 Etcd v3接口,而 flannel 使用 v2接口。
懷疑在升級 Etcd 時默認沒有開啟 v2接口。最后查閱官方 Etcd v3.4 發布說明,從 3.4 版本開始,默認已經關閉 v2 接口協議,才導致上面報錯。
解決方法
直接在 Etcd 啟動參數添加 --enable-v2

 

etcd2和etcd3是不兼容的,兩者的api參數也不一樣,詳細請查看 etcdctl -h 。
可以使用api2 和 api3 寫入 etcd3 數據,但是需要注意,使用不同的api版本寫入數據需要使用相應的api版本讀取數據。

api 2 使用方法

ETCDCTL_API=2 etcdctl ls /
api 3 使用方法

ETCDCTL_API=3 etcdctl get /

 

修改flaneld 為host-gw 模式 因為flanneld 用的是v2版本 所以需要切換到V2 版本設置

export ETCDCTL_API=2

etcdctl --ca-file=/etc/ssl/kubernetes/ca.pem --cert-file=/etc/ssl/kubernetes/kubernetes.pem --key-file=/etc/ssl/kubernetes/kubernetes-key.pem --endpoints="https://k8s-etcd1:2379"   set /coreos.com/network/config '{ "Network": "172.17.0.0/16", "Backend": {"Type": "host-gw"}}'

etcd 的備份和恢復 

https://www.imooc.com/article/275606

下面是我們生產環境中的備份腳本, V2  和V3 都備份

#!/bin/bash
date_time=`date +%Y%m%d`

function etcd_backup(){

ETCDCTL_API=2 etcdctl --ca-file=/etc/ssl/kubernetes/ca.pem --cert-file=/etc/ssl/kubernetes/kubernetes.pem --key-file=/etc/ssl/kubernetes/kubernetes-key.pem --endpoints="https://k8s-etcd1:2379" backup --data-dir /data/etcd --backup-dir /data/tmp/ &> /dev/null
ETCDCTL_API=3 etcdctl --cacert=/etc/ssl/kubernetes/ca.pem --cert=/etc/ssl/kubernetes/kubernetes.pem --key=/etc/ssl/kubernetes/kubernetes-key.pem --endpoints="https://k8s-etcd1:2379" snapshot save /data/tmp/v3 &>/dev/null
tar cvzf etcd-${date_time}.tar.gz * &> /dev/null
}

function sendmsg() {
sign=`echo -n "backup${msg}zcD3xseDxJvvevvv"|md5sum|cut -d ' ' -f1`
curl "http://ctu.xxx.com/alarm/weixin?from=backup&msg=${msg}&sign=${sign}"
}

function ftp_init(){
printf "set ftp:passive-mode on
set net:max-retries 2
set net:reconnect-interval-base 10
set net:reconnect-interval-max 10
set net:reconnect-interval-multiplier 2
set net:limit-rate 8000000:8000000" > ~/.lftprc
lftp -e "put etcd-${date_time}.tar.gz;exit" ftp://ftp:ftppwd@192.168.1.1/etcd/ &>/dev/null
if [ $? -ne 0 ]
then
msg="etcd lftp put fail"
sendmsg
fi

}

mkdir /data/tmp && cd /data/tmp
ftp_init
etcd_backup
if [ $? -ne 0 ]
then
msg="etcd backup fail"
sendmsg
fi

rm -rf /data/tmp 

 

 

ETCDCTL_API=3 etcdctl --cacert=/etc/ssl/kubernetes/ca.pem --cert=/etc/ssl/kubernetes/kubernetes.pem --key=/etc/ssl/kubernetes/kubernetes-key.pem --endpoints="https://k8s-etcd1:2379" snapshot restore etcbackup  -data-dir /data/etcd

版本2 的數據直接拷貝目錄,重新啟動集群就可以了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM