3C科技 娛樂遊戲 美食旅遊 時尚美妝 親子育兒 生活休閒 金融理財 健康運動 寰宇綜合

Zi 字媒體

2017-07-25T20:27:27+00:00
加入好友
本文源自3月30『高效開發運維』微信群的在線分享,轉載請在文章開頭註明來自『高效開發運維』公眾號。加群學習請關注『高效開發運維』公眾號,並點擊菜單中的「加群學習」或直接回復「加群」。隨著微服務概念深入人心,越來越多的解決方案選擇使用微服務架構,這類架構的共同點是服務數量多,因此種類繁多的服務之間如何互相訪問就變成了一個很現實的問題。目前比較流行的分散式存儲有:Consul, etcd, ZooKeeper。今天主要分享下如何基於Consul來實現服務發現。關於服務發現及Consul 將應用部署到集群時,服務IP或埠是動態分配的,用戶訪問時不知道後端的IP及埠在訪問這些服務時,使用一定的機制動態發現服務的IP及埠就是服務發現(Service Discovery)。Consul是一個服務發現和配置管理的工具,是具有分散式、高可用、高度可擴展的服務。Consul的特性 服務發現Consul客戶端可以提供其他服務的服務發現功能,使用dns和http,服務發現問題很容易被解決。監控檢查使用Consul可以提供任意數量的健康檢查功能,無論是服務狀態(web伺服器返回 http 200)還是本地節點的信息(內存利用率超過90%),這些信息都可以由操作員進行設置,並由服務發現組件將服務流量從不健康的組件中移開。key/value存儲Consul的kv存儲功能,通過http api可以很容易完成動態配置管理、協調服務、主選舉、功能標記等服務。跨中心部署Consul支持多數據中心感知,可以支撐任意數量的區域無需複雜配置。節點 節點類型server服務發現、健康檢查、數據一致性存儲,leader選舉機制,所以奇數部署agent健康檢查Consul節點退出正常退出(至關重要)節點通過信號正常關閉,接到信號的Consul會通知其他節點,正常離開後上面的服務和健康檢查將被移除異常退出沒有通過信號正常關閉的節點,其他節點會由於沒有接到信號,認為這個節點還是正常的,也不會移除其服務和健康檢查。本文主要分享服務發現和健康檢查兩個特性。ansible批量部署Consul 為了更加方便快捷的部署,採用Consul進行docker化的方式實現,Consul本身安裝很簡單,只安裝二進位的包即可使用。首先從組件下載頁找到合適系統的二進位包下載,下載后將二進位的包拷貝安裝在對應的可被執行的目錄里,如:~/bin 或者 /usr/local/bin。Consul 還有web_ui,需要單獨下載,並在啟動指定目錄即可。dockerfile集群運行Consul可以運行client和server 兩種節點模式,每個數據中心必須有一個server節點,但如果高可用,需要部署3個以上。其它Consul全部運行在client模式。客戶端連接會有一個非常輕的註冊過程,運行健康檢查併發給server節點。client運行在每個節點上。ansible批量部署Consul server (agent與server類似) Consul server ansible模板片段Consul agent ansible模板片段上面啟動的信息中每台主機啟動的參數不同的主要是IP,所以使用ansbile的時候就用到了一個小技巧,在ansible的hosts配置文件中給每條主機信息添加一個變數 ansible_ssh_host,在ansible運行中直接引用hosts配置中的變數,其它相對來說比較固定的參數,填寫到ansible的全局變數文件ansible/inventory/group_vars/all中,或執行playbook時傳入就可以了。ansible hosts配置示例base-Consul-master ansible role 片段base-Consul-master playbook調用playbook的執行腳本調用playbook是可以指定主機或主機組部署Consul master指定ansible role中的tag 執行任務ansible批量註冊服務健康檢查到Consul Consul服務定義 Consul中的服務可以在啟動前就定義 ,提前寫好定義服務的配置文件放置到 Consul配置目錄Consul.d中, 如果這種方式需要更新,則需要重啟或發送SIGHUP信號給Consul ,不太方便操作,因此推薦使用Consul api的方式來註冊服務。註冊服務的信息主要包含id, name, port, address, check每個服務可以由多個ip可以有多個埠的服務組成。需要注意的是:每個服務可以有多個check,check可以是埠檢查、http檢查、腳本檢查。其中檢查腳本通常是自由做任何事情,以確定檢查的狀態。唯一的限制是,該退出代碼都必須遵守此約定:Exit code 0 - 檢查結果是 passingExit code 1 - 檢查結果是 warning其它 Exit code - 檢查結果是 failing註冊服務通常是通過agent來註冊,因為服務的健康檢查與所在Consul agent是綁定的,如果 Consul agent所有宿主機掛掉,就認為這台主機上的服務也是掛的。Consul健康檢查參考:ansible註冊服務及健康檢查到Consul agent模板reg_Consul.sh片段 註冊的服務有問題,需要刪除調用deregistry介面 刪除一個服務刪除一個檢查agent api 參考:注意:同一個服務 每個實例的id唯一同一個服務 每個檢查項的id唯一ansible批量註冊服務到Consul 服務發現 Consul啟動后,並且服務集群狀態正常,就可以對外提供DNS或者HTTP API來查詢服務了。http api 通過Consul server查詢服務列表信息通過Consul server查詢單個服務信息通過agent查詢服務服務只查詢健康的服務(不加passing參數會包含warning的服務,不包含critical的服務)agent操作api參考 https://www.consul.io/docs/agent/http/agent.htmlConsul dns服務發現 Consul自帶一套dns 服務,所以可以處理簡單的服務發現。通過dig命令查詢Consul dns中的服務解析, critical的服務不會解析使用dnsmasp轉發Consul dnsConsul默認的dns服務埠是8600,常用的dns服務默認的埠為53,所以如果使用8600,不太方便,而且Consul 0.7.0版本后才支持修改默認Consul dns埠,就算可以修改Consul dns埠,但又可能會跟其它的dns服務衝突。可以使用centos7自帶的服務dnsmasp來轉發Consul dns和其它dns服務在/etc/dnsmasq.d/dns-hosts.conf中添加 Consul dns地址配置NetworkManager 在resolv.conf中添加search service.Consul和默認的dns server指定到本機,這樣即可直接在宿主機使用dns訪問到Consul中的服務了,而且可以使用短域名訪問,例如:使用registrator實現自動註冊服務 registrator通過在容器啟動時檢查容器來自動註冊和註銷任何Docker容器的服務。registrator支持自動註冊的服務包括Consul,etcd和SkyDNS 2github地址:直接使用官方鏡像即可。docker run方法服務自動註冊的id name check等需要在被註冊的服務啟動環境變數指定。例如:docker run -d --net host -p 5014:5014 -e SERVICE_5014_ID=cadivisor -e SERVICE_5014_NAME=cadivisor cadivisor注意:使用Consul做服務發現一般為host模式啟動的服務,埠是固定的。由於埠問題,一台宿主機也只部署一個實例。host模式一般不添加 -p 或 --publish參數,但registrator 的默認註冊規則,是有--publish都會自動註冊到Consul, 所以host 模式 就算是不需要埠映射,也需要添加--publish參考指定埠,這樣registrator 就會把服務註冊到Consul了。參考 :haproxy配合Consul dns實現服務發現 haproxy做為PaaS平台服務的負載均衡服務,對外服務;配置backend服務時,配置的是Consul中的服務域名。這裡有個坑,原來使用haproxy 1.5版本, 後端服務使用域名時,啟動后只解析一次(和nginx類似),這時如果解析到的服務掛掉,訪問haproxy頁面時會503。查詢官網得知haproxy 1.6支持了動態dns 域名解析的配置,后升級為haproxy 1.6。下面是動態DNS解析相關的配置內容:用戶訪問haproxy就會動態解析訪問後端Consul中的服務。基於Consul dns,實現mysql高可用切換 數人云最初的Mysql主從切換是基於 haproxy+keepalived 來做高可用的。這種機制下,Mysql主從切換的簡單需求需要引入2個開源組件,架構上也非常複雜。為了減輕架構複雜度和可維護性,將主從切換改為了使用Consul進行主從切換。Mysql是安裝了兩台,一主一從,設置許可權時,主是讀寫的,從是普通用戶只讀許可權。通過將服務註冊到Consul來做健康檢查,Mysql Master和Slave註冊四個服務到Consul, 如下代碼:正常情況mysql-vip.service.Consul解析到 主mysql ip。這裡分兩種情況切換到從解析:— 主Mysql掛掉后,ip解析到從mysql ip,mysql-vip 切換到從Mysql IP 。— 主庫的Consul 掛掉也會導致服務無法解析,即使 mysql-master正常,如果Consul掛掉也會被激活切換。請注意:因為Mysql從是只讀的,相當於降級服務。接下來再分享一下Consul實踐中遇到的一些坑。Consul實踐遇到的坑 調用deregistry介面刪除Consul服務后,詭異的出現了 初期進行http api 調試測試時,註冊了一些服務到Consul, 後來想刪除就調用,ip:8500/v1/catalog/deregister 介面進行刪除,調用該介面返回成功。但過一會兒去web ui查詢, 發現剛才刪除的服務還在,後來查詢官方文檔,原來server端catalog和 agent端都有deregister介面,我們的服務都是通過agent註冊的,所以在catalog 刪除不生效,只能通過agent的 deregistry介面來刪除。清理Consul持久化數據異常 測試Consul server服務的高可用,先停止其中一台Consul server節點的容器,並清理Consul 的持久化數據,其它服務的Consul節點正常,達到預期結果,後來嘗試恢復這個Consul server,恢復后發現從Consul ui查發現 少了一些服務節點,查詢過後,正好是清理數據的這台Consul server上的服務在 Consul 中消失了,因此又重新在這個節點進行相應的服務註冊才真正恢復正常。健康檢查狀態碼的坑 健康檢查腳本中使用grep檢查結果內容,如果匹配則正常,不匹配為異常,例如: echo result|grep ok,有一次,一個服務節點異常,grep也沒有匹配,當時認為這樣就不會被解析了,後來發現這個服務ip還是會被解析,查詢問題發現grep 不匹配的error code 為1 ,code 1 只是warning ,還是會被解析,所以修改檢查腳本內容,如果不匹配,手動返回error code 2,之後這個異常服務才不解析。使用registrator自動註冊的坑 在數人云的PaaS平台發布的服務,一般服務容器名稱都是隨機的,registrator 默認的自動註冊規則是把容器名註冊為 Consul中的service id,這樣在Consul就有可能同一個服務被註冊多次,實際上是同 個服務不同實例。所以需要在啟動容器的環境變數中指定SERVICE_xxx_NAME ,這樣registrator註冊的時候就不會同是有多個相同的服務但server name 的不同 ,同理,如果需要consul 中的 service id 保持 致,則需要啟動容 時指定SERVICE_xxx_ID。registrator 默認 自動註冊的服務在consul中 帶健康檢查的,所以容器實例掛掉,consul的 頁面上是看不 出的,會導致consul dns解析到異常的容器實例 上,所以需要在啟動容 時需 要添加類似下面的環境變數。Consul agent節點異常 部署客戶環境時遇到一個詭異的問題,有兩個節點總是異常,健康檢查這兩個節點時好時壞,大部分時間是壞的,少部分時間顯示正常狀態。排查問題時,發現主機之間響應時間很快,Consul server 與Consul agnet 之間的Consul埠都是可以通的。查詢Consul server日誌,看到 server 日誌中有error以為是有埠漏開放了,telnet 測試后,發現Consul server到agent都是通的,谷歌下這個錯誤,發現有可能是因為沒有開通udp埠導致的,後來又使用nmap測試Consul相關的udp埠是不是開放的,測試后發現udp 果然沒有開通。於是就向客戶申請開通相應的udp埠,開通后,再進行測試,發現問題還是存在。這就不得不再想其它辦法,後來又查詢異常的Consul agent節點日誌發現,發現Consul agent 也報類似的錯誤,乍一看跟server端的日誌是一樣的,但仔細研究發現關鍵問題,異常節點的agent報了很多訪問其它agent節點8301埠的 time out的日誌:才發現agent不僅訪問server, 還需要訪問同級的其它agent 8301埠進行健康檢查,後來開放8301所有Consul節點的埠訪問后才正常。比起另外兩個同樣流行的分散式存儲etcd和ZooKeeper, Consul從設計上就考慮到了很多服務發現的需求, 比如說健康檢查, 服務註冊, DNS等。所以基於Consul來實現服務發現的功能還是有很多的想象空間的。QA環節 Q1:感謝老師!Consul, etcd, ZooKeeper能比較一下嗎?為什麼沒有選用后兩者呢?A1:ZooKeeper 處理數據 不支持 resf api , 需要操作的時候比較繁瑣,功能也比較單一,etcd 服務功能也相對單一,需要依賴其它 組件 配合使用Consul 本身自帶服務發現、健康檢查 、dns解析 功能相對來說強大一些,不需要依賴其它的組件就可能實現很多功能Q2:就服務發現和zk相比,會有多大的延遲?A2: 就服務發現來說,Consul 支持 api 和 dns 兩個方式獲取 服務, dns 解析基本無消耗。 api 操作的話,具體的數據我沒有進行嚴格測試,但zk是java服務本身需要的內存比較多,java gc 垃圾回收也會影響一些性能。Consul 是go 語言開發性能會有一些優勢。Q3: 這裡問一個不是很相關的問題,老師怎麼看待Docker和微服務更配這樣的說法?A3: 以前是所有功能集成到一個服務中,微服務本身需要拆分服務,需要部署、更新、維護的服務數量會幾何增加,如果是傳統的方式運維的話,操作起來就是個挑戰,Docker化之後,部署、遷移、交付都會變簡單。Q4:Consul最大承受多大規模,有瓶頸嗎?Q4: 我沒有針對 Consul服務 做過壓力測試,我們一般是會對服務進行壓力測試,就現在我們部署的集群規模而言,支持幾百來的Consul 節點是沒有問題的。理論上可以更多。Q5:內部的web服務怎麼註冊?用後台腳本周期性地檢測web服務正常后,再請求介面註冊服務嗎?失敗取消A5: 如果 使用了 registrator ,docker服務啟動時,添加相應的環境變數,就會自動註冊到Consul,也會自動刪除,不過registrator偶爾異常情況會有不同步的現象,我們在 registrator 啟動時添加同步參數定時同步,如果沒有使用 registrator ,就需要自己處理註冊和刪除的邏輯,例如我們使用marathon /mesos 做為調試的核心基礎組件,可以監聽marathon 的事件獲取 容器實例 啟動在哪,刪除了哪些,就可以相應對 Consul做操作Consul 也支持異常服務定時清理,在註冊添加時添加DeregisterCriticalServiceAfter 參數 就可以Q6:「每個數據中心必須有一個server節點,但如果高可用,需要部署3個以上」為啥一定要三個以上A6: Consul server 節點也分為 leader 和 follower 節點,leader 選舉一般為基數選舉,1個就不是高可用了,所以最少3個,遵循2N+1 原則,支持宕機 N 個節點。Q7: Consul能夠支撐多大的高併發系統?A7: 這個問題跟上面的問題稍有些重合,其實高併發是指的業務,業務一般在 啟動、停止、遷移 、或業務之間相互訪問時 Consul 才會有些數據交互 ,Consul的健康檢查 和 訪問都是分攤到每個宿主機上, Consul 的壓力 對比業務來說可以忽略不計。作者介紹劉金燁,數人云運維工程師。早期做 Java 開發,後轉職為運維開發,曾就職於仙掌軟體、金山西山居,現就職於數人云。負責數人雲平台 Mesos/Marathon/Docker 環境維護、運維自動化建設。

本文由yidianzixun提供 原文連結

寫了 5860316篇文章,獲得 23313次喜歡
精彩推薦