vagrant+docker搭建consul集群開發(fā)環(huán)境

HashiCorp 公司推出的Consul是一款分布式高可用服務(wù)治理與服務(wù)配置的工具兆旬。關(guān)于其配置與使用可以參考這篇文章 consul 簡介與配置說明抄瓦。

一般彼妻,我們會在多臺主機(jī)上安裝并啟動 consul其爵,在開發(fā)時(shí)這可能會比較不方便咖耘,所以這里介紹如何使用 vagrant 和 docker 來簡化開發(fā)環(huán)境的搭建。

利用 vagrant 創(chuàng)建虛擬機(jī)


Vagrant 是 HashiCorp 公司的產(chǎn)品蜀踏, 用于創(chuàng)建和部署虛擬化開發(fā)環(huán)境维蒙,支持常見的操作系統(tǒng)。由于其安裝比較簡單果覆,參照官方文檔即可颅痊,此處不再贅述。

安裝完成后局待,我們創(chuàng)建文件夾consul八千,在consul文件夾下創(chuàng)建一個(gè)文件Vagrantfile,內(nèi)如如下:

# -*- mode: ruby -*-
# vi: set ft=ruby :

$script = <<SCRIPT
echo "Installing dependencies ..."
# 使用阿里云鏡像
sudo sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
sudo apt-get update
sudo apt-get install -y unzip curl jq
SCRIPT

# Specify a custom Vagrant box for the demo
DEMO_BOX_NAME = "ubuntu/xenial64"

# Vagrantfile API/syntax version.
# NB: Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = DEMO_BOX_NAME

  config.vm.provision "shell",
                          inline: $script

  config.vm.define "n1" do |n1|
      n1.vm.hostname = "n1"
      n1.vm.network "private_network", ip: "172.20.20.10"
  end

  config.vm.define "n2" do |n2|
      n2.vm.hostname = "n2"
      n2.vm.network "private_network", ip: "172.20.20.11"
  end

  config.vm.define "n3" do |n3|
      n3.vm.hostname = "n3"
      n3.vm.network "private_network", ip: "172.20.20.12"
  end
end

這里我們創(chuàng)建了三個(gè)虛擬機(jī)燎猛,hostname為 n1恋捆,n2,n3重绷;ip分別為 172.20.20.10沸停,172.20.20.11,172.20.20.10昭卓,使用鏡像 ubuntu/xenial64愤钾,并且將鏡像更新為了阿里云瘟滨,安裝了一些必須的軟件。

編輯好該文件能颁,在命令行運(yùn)行 vagrant up杂瘸,出去喝杯咖啡,你的機(jī)器上就會啟動三臺對應(yīng)的虛擬機(jī)了伙菊。如果你不想使用ubuntu 16.04败玉,還可以更換其他的操作系統(tǒng)。

在 consul 文件夾下使用 vagrant ssh命令镜硕,就可以登錄到對應(yīng)的虛擬機(jī)了:

?  consul vagrant ssh n2
Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-66-generic x86_64)

0 packages can be updated.
0 updates are security updates.

Last login: Tue Mar 28 04:13:00 2017 from 10.0.2.2
ubuntu@n2:~$

配置運(yùn)行consul的docker容器


docker的安裝請參照這里docker安裝运翼。需要注意,鑒于 dockerhub 在國內(nèi)喪心病狂的訪問速度兴枯,我們一般會選擇使用國內(nèi)的鏡像血淌,如阿里云、網(wǎng)易蜂巢等财剖。

安裝好了docker后悠夯,我們以 n1 虛擬機(jī)為例,說明如何在虛擬機(jī)上使用docker容器來運(yùn)行consul躺坟。

首先疗疟,創(chuàng)建一個(gè)consul文件夾,然后編輯 Dockerfile

FROM phusion/baseimage:latest

MAINTAINER millions <chenzhesp@gmail.com>

RUN DEBIAN_FRONTEND=noninteractive
RUN locale-gen en_US.UTF-8

ENV LANGUAGE=en_US.UTF-8
ENV LC_ALL=en_US.UTF-8
ENV LC_CTYPE=UTF-8
ENV LANG=en_US.UTF-8
ENV TERM xterm

RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list

RUN apt-get update -y
RUN apt-get upgrade -y

RUN apt-get -qq install curl unzip

ADD https://releases.hashicorp.com/consul/0.7.5/consul_0.7.5_linux_amd64.zip /tmp/consul.zip
RUN cd /usr/sbin && unzip /tmp/consul.zip  && chmod +x /usr/sbin/consul && rm /tmp/consul.zip
ADD consul.json /config/

ADD https://releases.hashicorp.com/consul/0.7.5/consul_0.7.5_web_ui.zip /tmp/webui.zip

RUN mkdir /webui  && unzip /tmp/webui.zip -d /webui/ && rm /tmp/webui.zip

EXPOSE 8300 8301 8301/udp 8302 8302/udp 8400 8500 53/udp

VOLUME ["/data"]

ENTRYPOINT [ "/usr/sbin/consul", "agent", "-config-dir=/config" ]
CMD []

大約解釋一下上面的Dockerfile。首先,我們選擇phusion/baseimage為基礎(chǔ)構(gòu)建docker容器褪贵。然后設(shè)置使用阿里云鏡像亏吝,安裝各種工具,下載 consul 并創(chuàng)建 consul 使用的 ui 文件夾裹刮。然后聲明暴露8個(gè) consul 需要使用的 tcp 或 udp 端口音榜,并將 /data 設(shè)置為一個(gè) VOLUME (通過--volumes-from可以在容器之間共享數(shù)據(jù))。 最后捧弃,注意 ENTRYPOINT 聲明了容器啟動時(shí)執(zhí)行的命令赠叼,而在啟動容器時(shí)加上的命令會被添加在 ENTRYPOINT 指定的命令后,比如ENTRYPOINT為 [ "/usr/sbin/consul", "agent", "-config-dir=/config" ]违霞,啟動鏡像時(shí)的命令為 sudo docker run <鏡像名稱> XXXX嘴办,則容器啟動時(shí)執(zhí)行的命令為 /usr/sbin/consul agent -config-dir=/config XXXX

另外买鸽,為了使用 consul涧郊,我們也需要編輯其配置文件 consul.json。這里我們使用一個(gè)比較簡單的配置眼五,有特殊需要的請參閱 consul 官方文檔的配置說明妆艘。

{
  "data_dir": "/data",
  "ui_dir": "/webui",
  "client_addr": "0.0.0.0",
  "ports": {
    "dns": 53
  },
  "recursor": "8.8.8.8"
} 

編輯好這2個(gè)文件后彤灶,在consul文件夾下執(zhí)行命令 sudo docker build -t millions/consul . 即可創(chuàng)建鏡像 millions/consul,通過 docker images 命令可以查看批旺。

ubuntu@n1:~/consul$ sudo docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
millions/consul            latest              5fc1597b91cf        23 hours ago        372 MB
phusion/baseimage          latest              b6b482650b50        7 days ago          247 MB

而后在其他虛擬機(jī)使用同樣方法創(chuàng)建鏡像幌陕。為了方便啟動 docker 鏡像,我們再在每臺虛擬機(jī)上創(chuàng)建以下環(huán)境變量:

# 在 Vagrantfile 中指定的ip汽煮,對于n1為172.20.20.10
export PUBLIC_IP="$(ifconfig enp0s8 | awk -F ' *|:' '/inet addr/{print $4}')"

而后搏熄,由于我們打算用n1做 bootstrap 時(shí)的leader,所以在 n2逗物、n3 上創(chuàng)建環(huán)境變量:

export JOIN_IP=172.20.20.10

接下來搬卒,我們就可以準(zhǔn)備啟動 consul 實(shí)例們啦~

啟動 consul 實(shí)例

注意啟動時(shí)需要使用 -h $HOSTNAME 指定容器的hostname。首先我們啟動 n1翎卓,由于用其做 bootstrap契邀, 所以我們使用了 -bootstrap-expect 3。其他相關(guān)啟動參數(shù)如果不熟悉的話可以查看 consul 的文檔失暴,這里不做詳細(xì)解釋坯门。比較重要的是需要額外設(shè)置dns,首先使用本地 docker0 來使用 consul 解析 DNS逗扒,然后使用 8.8.8.8解析其他請求的dns,最后為 consul 的查詢指定搜索域矩肩。

sudo docker run -d -h $HOSTNAME -p 8300:8300  \
 -p 8301:8301 -p 8301:8301/udp -p 8302:8302  \
 -p 8302:8302/udp -p 8400:8400 -p 8500:8500  \
 -p 53:53/udp --name n1 \
--dns 172.17.0.1 --dns 8.8.8.8 \
 --dns-search 'service.consul' millions/consul   \
-server -advertise $PUBLIC_IP -bootstrap-expect 3

這是查看 n1 的輸出發(fā)現(xiàn)其已經(jīng)啟動黍檩,但是還無法組成集群:

ubuntu@n1:~/consul$ sudo docker logs n1
==> WARNING: Expect Mode enabled, expecting 3 servers
==> Starting Consul agent...
==> Starting Consul agent RPC...
==> Consul agent running!
           Version: 'v0.7.5'
           Node ID: 'cedd93d8-4ff4-4bde-8bb4-391f5a129ed4'
         Node name: 'n1'
        Datacenter: 'dc1'
            Server: true (bootstrap: false)
       Client Addr: 0.0.0.0 (HTTP: 8500, HTTPS: -1, DNS: 53, RPC: 8400)
      Cluster Addr: 172.20.20.10 (LAN: 8301, WAN: 8302)
    Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
             Atlas: <disabled>

接下來喳逛,我們來啟動 n2 還有 n3(注意修改 --name 參數(shù)):

sudo docker run -d -h $HOSTNAME \
-p 8300:8300 -p 8301:8301 -p 8301:8301/udp \
-p 8302:8302 -p 8302:8302/udp -p 8400:8400 \
-p 8500:8500 -p 53:53/udp --name n2 \
-dns 172.17.0.1 --dns 8.8.8.8 \
 --dns-search 'service.consul' millions/consul   \
-server -advertise $PUBLIC_IP -join $JOIN_IP

這里作為后來加入者我們使用 -join參數(shù)而不是 bootstrap-expect润文。都完成啟動后在物理機(jī)上訪問 http://172.20.20.10:8500 即可看到熟悉的consul web-ui 界面典蝌。至此赠法,我們的 consul 集群開發(fā)環(huán)境就搭建完成了砖织,我們可以使用其他各種程序?qū)⒆约鹤鳛榉?wù)注冊到 consul 集群中,并且訪問集群獲取其他服務(wù)地址新锈。

測試


為了測試集群是否可以正常工作妹笆,我們再創(chuàng)建其他2個(gè)docker 鏡像拳缠。

distributed_app

Dockerfile為:

ROM phusion/baseimage:latest

MAINTAINER millions <chenzhesp@gmail.com>

RUN DEBIAN_FRONTEND=noninteractive
RUN locale-gen en_US.UTF-8

ENV LANGUAGE=en_US.UTF-8
ENV LC_ALL=en_US.UTF-8
ENV LC_CTYPE=UTF-8
ENV LANG=en_US.UTF-8
ENV TERM xterm

RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
RUN apt-get update -y
RUN apt-get upgrade -y

RUN apt-get -qq install ruby-dev git libcurl4-openssl-dev curl build-essential python
RUN gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
RUN gem install --no-ri --no-rdoc uwsgi sinatra

RUN mkdir -p /opt/distributed_app
WORKDIR /opt/distributed_app
RUN uwsgi --build-plugin https://github.com/unbit/uwsgi-consul

ADD uwsgi-consul.ini /opt/distributed_app/
ADD config.ru /opt/distributed_app/

ENTRYPOINT [ "uwsgi", "--ini", "uwsgi-consul.ini", "--ini", "uwsgi-consul.ini:server1", "--ini", "uwsgi-consul.ini:server2" ]
CMD []

config.ru 的內(nèi)容為:

require 'rubygems'
require 'sinatra'

get '/' do
  "Hello World!"
end

run Sinatra::Application

uwsgi-consul.ini 的內(nèi)容為:

[uwsgi]
plugins = consul
socket = 127.0.0.1:9999
master = true
enable-threads = true

[server1]
consul-register = url=http://%h.node.consul:8500,name=distributed_app,id=server1,port=2001
mule = config.ru

[server2]
consul-register = url=http://%h.node.consul:8500,name=distributed_app,id=server2,port=2002
mule = config.ru

而后創(chuàng)建鏡像:

sudo docker build -t millions/distributed_app .

我們創(chuàng)建好鏡像后绵疲,在 n1 和 n2 上分別啟動該容器:

sudo docker run -h $HOSTNAME -d --name n1-distributed \
--dns 172.17.0.1 --dns 8.8.8.8 \
 --dns-search 'service.consul'  millions/distributed_app

完成之后可以在 web-ui 上看到 n1 和 n2 上各有2個(gè)名為distributed_app的服務(wù)盔憨。

web-ui

我們使用一個(gè)腳本來進(jìn)行測試郁岩,為了再溫習(xí)一下 docker问慎,我們還是將其放在一個(gè) docker 容器中運(yùn)行蝴乔,Dockerfile 如下薇正,注意我們替換了使用了淘寶的 ruby source 來加速:

FROM phusion/baseimage:latest

MAINTAINER millions <chenzhesp@gmail.com>

RUN DEBIAN_FRONTEND=noninteractive
RUN locale-gen en_US.UTF-8

ENV LANGUAGE=en_US.UTF-8
ENV LC_ALL=en_US.UTF-8
ENV LC_CTYPE=UTF-8
ENV LANG=en_US.UTF-8
ENV TERM xterm

RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
RUN apt-get update -y
RUN apt-get upgrade -y

RUN apt-get -qq install ruby ruby-dev build-essential
RUN gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
RUN gem install --no-ri --no-rdoc json

RUN mkdir -p /opt/distributed_client
ADD client.rb /opt/distributed_client/

WORKDIR /opt/distributed_client

ENTRYPOINT [ "ruby", "/opt/distributed_client/client.rb" ]
CMD []

ruby 腳本如下,分別使用了http和dns兩種方式來獲取服務(wù):

require "rubygems"
require "json"
require "net/http"
require "uri"
require "resolv"

empty = "There are no distributed applications registered in Consul"

uri = URI.parse("http://consul.service.consul:8500/v1/catalog/service/distributed_app")

http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)

while true
  response = http.request(request)
  if response.body == "{}"
    puts empty
    sleep(1)
  elsif
    result = JSON.parse(response.body)
    result.each do |service|
      puts "Application #{service['ServiceName']} with element #{service["ServiceID"]} on port #{service["ServicePort"]} found on node #{service["Node"]} (#{service["Address"]})."
      sleep(1)
    end
  end
end

創(chuàng)建好鏡像:

sudo docker build -t millions/distributed_client .

運(yùn)行之:

sudo docker run -h $HOSTNAME -d --name n3-distributed \
 --dns 172.17.0.1 --dns 8.8.8.8  \
 --dns-search 'service.consul' millions/distributed_client

使用 sudo docker logs n3-distributed 命令,可以查看到:

ubuntu@n3:~$ sudo docker logs n3-distributed
Application distributed_app with element server1 on port 2001 found on node n1 (172.20.20.10).
Application distributed_app with element server2 on port 2002 found on node n1 (172.20.20.10).
Application distributed_app with element server1 on port 2001 found on node n2 (172.20.20.11).
Application distributed_app with element server2 on port 2002 found on node n2 (172.20.20.11).

或者可以使用 dns 來向 consul 查詢 ip 以及 port疾渣,我們利用 dig 命令查看 dns 的結(jié)果榴捡,可以看到獲取了 port 以及 n1 和 n2 的 ip:

ubuntu@n3:~$ dig @172.17.0.1 distributed_app.service.consul SRV

; <<>> DiG 9.10.3-P4-Ubuntu <<>> @172.17.0.1 distributed_app.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30551
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 2

;; QUESTION SECTION:
;distributed_app.service.consul.    IN  SRV

;; ANSWER SECTION:
distributed_app.service.consul. 0 IN    SRV 1 1 2001 n2.node.dc1.consul.
distributed_app.service.consul. 0 IN    SRV 1 1 2001 n1.node.dc1.consul.
distributed_app.service.consul. 0 IN    SRV 1 1 2002 n1.node.dc1.consul.

;; ADDITIONAL SECTION:
n2.node.dc1.consul. 0   IN  A   172.20.20.11
n1.node.dc1.consul. 0   IN  A   172.20.20.10

;; Query time: 0 msec
;; SERVER: 172.17.0.1#53(172.17.0.1)
;; WHEN: Tue Mar 28 14:41:34 UTC 2017
;; MSG SIZE  rcvd: 155

總結(jié)


至此吊圾,我們的consul 集群開發(fā)環(huán)境就搭建好了项乒。關(guān)機(jī)前不要忘記用 vagrant halt 或者 vagrant suspend 關(guān)閉或暫停你的虛擬機(jī)哦~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市埃碱,隨后出現(xiàn)的幾起案子砚殿,更是在濱河造成了極大的恐慌似炎,老刑警劉巖羡藐,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瘩扼,居然都是意外死亡垃僚,警方通過查閱死者的電腦和手機(jī)谆棺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門碍岔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來付秕,“玉大人询吴,你說我怎么就攤上這事唠摹」蠢” “怎么了藕赞?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長砚偶。 經(jīng)常有香客問我均芽,道長掀宋,這世上最難降的妖魔是什么劲妙? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任涛舍,我火速辦了婚禮掸驱,結(jié)果婚禮上毕贼,老公的妹妹穿的比我還像新娘陶贼。我一直安慰自己拜秧,他們只是感情好枉氮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布培廓。 她就那樣靜靜地躺著医舆,像睡著了一般爷速。 火紅的嫁衣襯著肌膚如雪惫东。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機(jī)與錄音坪稽,去河邊找鬼黍判。 笑死,一個(gè)胖子當(dāng)著我的面吹牛贬墩,可吹牛的內(nèi)容都是我干的趴腋。 我是一名探鬼主播优炬,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎坪仇,沒想到半個(gè)月后杂腰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡椅文,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年喂很,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蜡镶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡恤筛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出芹橡,到底是詐尸還是另有隱情毒坛,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布林说,位于F島的核電站煎殷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏腿箩。R本人自食惡果不足惜豪直,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望珠移。 院中可真熱鬧弓乙,春花似錦、人聲如沸钧惧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽浓瞪。三九已至懈玻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間乾颁,已是汗流浹背涂乌。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留英岭,地道東北人湾盒。 一個(gè)月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像诅妹,于是被迫代替她去往敵國和親历涝。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容