本文将介紹在專有網絡vpc(virtual private cloud)網絡環境下,基于資源編排服務,快速部署高可用的dubbox服務的過程。dubbox服務采用的注冊中心是主備高可用redis伺服器kvstore。做這件事情的意義在于:節約部署dubbox的時間,降低部署dubbox過程中出錯的風險。
ros 阿裡雲資源編排(resource orchestration)是一種簡單易用的雲計算資源管理和自動化運維服務。使用者通過模闆描述多個雲計算資源的依賴關系、配置等,并自動完成所有資源的建立和配置,以達到自動化部署、運維等目的。編排模闆同時也是一種标準化的資源和應用傳遞方式,并且可以随時編輯修改,使基礎設施即代碼(infrastructure as code)成為可能。 ansible ansible是一個簡單的自動化it工具。引用ansible官網的介紹就是:“deploy apps.manage systems.crush complexity.ansible helps you build a strong foundation for devops.”。 dubbox
本文将從兩個方面展開介紹:
安裝ansible和ros sdk
vpc網絡環境下快速部署dubbox服務
首先申請一個vpc,并在這個vpc下面建立一個vswitch,然後在這個vpc和vswitch下申請一台ecs作為ansible主機,給這台機器綁定公網ip,友善通路外網。ecs系統版本資訊如下:
此版本的ecs已經安裝了python 2.7.5。
dubbox服務的部署需要通過ansible來完成,本文采用了yum來安裝ansible:
注意:如果采用的是ubuntu系統,安裝ansible過程如下:
ros提供了restful api和sdk,本文将介紹用python的方式來調用ros sdk建立資源。
使用pip安裝aliyun-python-sdk-core:
使用pip安裝ros sdk:
如果ansible主機未安裝pip,可使用以下指令安裝pip:
根據ros api的調用方式,在python檔案中定義ros資源模闆。模闆包括以下資源類型:
<a href="https://ros.console.aliyun.com/#/resourcetype/detail/aliyun::ecs::instancegroup/metadata">"type": "aliyun::ecs::instancegroup"</a>
定義了包含兩台ecs的instancegroup
<a href="https://ros.console.aliyun.com/#/resourcetype/detail/aliyun::redis::instance/metadata">"type": "aliyun::redis::instance"</a>
定義一台kvstore,作為dubbox服務的注冊中心
<a href="https://ros.console.aliyun.com/#/resourcetype/detail/aliyun::slb::loadbalancer/metadata">"type": "aliyun::slb::loadbalancer"</a>
建立一台slb
<a href="https://ros.console.aliyun.com/#/resourcetype/detail/aliyun::slb::backendserverattachment/metadata">"type": "aliyun::slb::backendserverattachment"</a>
給slb添加後端伺服器
<a href="https://ros.console.aliyun.com/#/resourcetype/detail/aliyun::slb::listener/metadata">"type": "aliyun::slb::listener"</a>
slb監聽兩台ecs的8080端口,并配置了<code>healthcheck</code>
<a href="https://ros.console.aliyun.com/#/resourcetype/detail/aliyun::ecs::securitygroup/metadata">"type": "aliyun::ecs::securitygroup"</a>
定義安全組
<code>"outputs"</code> 資源棧輸出,包括:ecs的private ip,kvstore的private ip,slb的公網ip以及kvstore port
在vpc網絡環境下,要給ecs和kvstore配置設定vpc和vswtich,并且需要保證和anisble主機處在同一個vpc和vswitch下,資源棧輸出定義為:ecs的private ip,kvstore的private ip,slb的公網ip以及kvstore port。
定義ros資源模闆的python檔案<code>generate_vpc_ros_template.py</code>:
初始化sdk用戶端對象:
構造建立資源棧的請求:
指定請求資源region:
構造請求體的内容,包括:棧名、過期時間戳、ros資源模闆
說明:其中template是通過調用<code>generate_vpc_ros_template.generate_template</code>方法生成的ros資源模闆對象,調用方式如下:
發送請求,建立資源棧:
擷取資源棧資訊:
資源棧建立好以後,我們再次調用ros api擷取資源棧的輸出資訊。方法如下:
資源棧的輸出格式如下:
我們将以上輸出定義為<code>outputs</code>。
根據<code>outputs</code>,擷取ecs内網ip。方法如下:
由于ecs登入密碼在配置檔案中已經給出,可以直接使用,使用者預設為root使用者,根據這些資訊編輯<code>/etc/ansible/hosts</code>檔案,即通常我們所說的ansible inventory檔案。方法如下:
生成inventory檔案,即<code>/etc/ansible/hosts</code>檔案。檔案内容如下:
inventory檔案中定義了遠端主機組<code>vpc_dubbox</code>,并指明了該主機組下雲主機的登入位址、登入協定(預設是 ssh )、登入端口、登入使用者名和密碼。
根據<code>outputs</code>,擷取kvstore host。方法如下:
根據<code>outputs</code>,擷取kvstore port。方法如下:
根據<code>outputs</code>,擷取slb 公網ip。方法如下:
在<code>/etc/ansible</code>目錄下建立檔案夾<code>vpc_dubbox</code>,并在此檔案夾下生成playbook的執行檔案<code>vpc_dubbox.yml</code>。生成<code>vpc_dubbox.yml</code>的方法如下:
生成的<code>vpc_dubbox.yml</code>檔案内容如下:
檔案中的屬性解釋如下:
hosts
遠端主機組名稱,和inventory檔案中的遠端主機組相對應。
vars
配置參數,提供給<code>install_jdk.sh</code> <code>install_jetty.sh</code> <code>deploy_admin.sh</code>這三個腳本使用。
roles
指定要執行的playbook為 <code>vpc_dubbox_playbook</code>。
<code>vpc_dubbox_playbook</code>定義好後會被傳到阿裡雲oss,運作python腳本會将<code>vpc_dubbox_playbook</code>下載下傳至<code>/etc/ansible/vpc_dubbox</code>目錄下。下載下傳playbook到ansible主機的方法如下:
<code>vpc_dubbox_playbook</code>目錄結構如下:
關于<code>vpc_dubbox_playbook</code>結構的說明:
files
存放<code>install_jdk.sh</code> <code>install_jetty.sh</code> <code>deploy_admin.sh</code>三個檔案,這三個檔案分别用來安裝jdk、jetty以及部署dubbox服務。
tasks
存放要執行的yml檔案 <code>install.yml</code>,檔案内容如下:
name: add config
template:
name: run install jdk
script: install_jdk.sh
name: run install jetty
script: install_jetty.sh
name: run deploy admin
script: deploy_admin.sh
templates
存放配置檔案模闆config.j2,檔案内容如下:
配置檔案config.j2中的參數值從<code>vpc_dubbox.yml</code>檔案中擷取,然後在通過ansible執行playbook的過程中在每一台遠端主機<code>/root</code>目錄下生成<code>config</code>檔案,提供給<code>install_jdk.sh</code> <code>install_jetty.sh</code> <code>deploy_admin.sh</code>這三個腳本讀取配置資訊。
ansible是通過ssh指令連接配接遠端主機,并執行playbook的。首次執行playbook前,由于目前ansible主機并沒有記錄遠端主機的rsa key,會彈出确認對話框,輸入yes,回車:
可通過python腳本實作上述過程:
注意:由于用到了pexpect這個子產品,在執行腳本前,使用pip安裝pexpect子產品:
vpc網絡環境下未給ecs配置設定公網ip,是以每台ecs無法下載下傳安裝包。因為ansible主機和每台ecs在同一個vswitch下面,是以可以通過scp指令将安裝包從ansible主機傳到每台ecs上,具體過程如下:
首先将jdk,jetty以及dubbox控制台的安裝包上傳至阿裡雲oss,擷取object位址。
傳入object位址,運作python腳本,下載下傳安裝包至ansible主機。方法如下:
def wget_files():
将安裝包拷貝到每台ecs。方法如下:
def scp_files_from_ansible_host_to_ecs(host_ips):
最後執行ansible。指令如下
運作ansible以後會進行dubbox服務的部署。
dubbox服務的部署,主要分為以下三個步驟:
安裝jdk的檔案為<code>install_jdk.sh</code>,内容如下:
安裝jdk過程中,首先需要檢查目前ecs是否存在java環境,存在就跳過安裝過程,反之則安裝jdk。
聲明:jdk安裝包請從oracle官網下載下傳,并下載下傳本文指定的jdk版本。由于從本文連結中下載下傳jdk帶來的任何問題,和本文作者無關。
安裝jetty的檔案為<code>install_jetty.sh</code>,内容如下:
安裝jetty過程,主要包括:讀取配置檔案,設定jetty安裝目錄,修改jetty的配置檔案。jetty安裝目錄的選擇包括以下幾種情形:
未指定jetty安裝目錄,則選擇預設目錄進行安裝
指定了jetty安裝目錄并且目錄不存在,則建立目錄并安裝jetty
指定了jetty安裝目錄并且目錄已經存在
如果配置了強制執行選項,則覆寫目錄并安裝jetty
如果沒有配置強制執行選項,程式強制退出
部署dubbox服務的檔案為<code>deploy_admin.sh</code>,内容如下:
部署dubbox服務過程,主要包括:檢查設定是否合理,将dubbox服務部署到jetty,設定dubbox服務注冊中心為redis,修改dubbo.properties配置檔案,設定控制台的登入密碼。
在部署dubbox服務的過程中,有幾個需要注意的問題:
當通路dubbox服務時,需要通路伺服器的8080端口,由于防火牆的原因,外部可能無法通路到伺服器的dubbox服務,是以需要修改防火牆的設定。我建立的ecs系統為centos 7,為了簡單起見,我直接關閉了系統的防火牆:
systemctl stop firewalld.service
通過ansible控制遠端伺服器組啟動jetty服務時,ansible指令執行結束以後,jetty服務也自動退出,這是我們不想看到的結果。可通過nohup指令以守護程序的方式啟動jetty服務,可以解決jetty服務自動退出的問題,啟動jetty指令如下:
nohup $jetty_home/bin/jetty.sh start &
dubbox服務支援redis注冊中心加密的方式,配置檔案dubbo.properties中的格式為:
dubbo.registry.address=redis://user:password@ip:port
<code>user</code>可随便填寫,但是不能為空,<code>password</code>為redis服務的登入密碼,redis服務預設<code>port</code>為6379
dubbox服務部署好了以後,可通過以下位址通路dubbox服務控制台:
注意:在vpc網絡下,ip指的是slb的公網ip
輸入使用者名密碼,點選登入:

dubbox服務控制台如下:
現在,我們可以使用dubbox服務了。
最終,基于資源編排快速部署出來的高可用dubbox服務架構如下圖所示:
dubbox服務的高可用,主要展現在兩個方面:
注冊中心的高可用
注冊中心采用了kvstore,kvstore其實是一個主備雙機的高可用redis伺服器。
dubbox服務控制台的高可用
建立兩台ecs執行個體并分别部署dubbox服務,然後建立一個slb,将之前建立的兩台ecs執行個體作為slb的後端伺服器,最後給這個slb添加監聽,并設定健康檢查。外部通過slb來通路dubbox服務。