HashiCorp 公司推出的Consul是一款分布式高可用服务治理与服务配置的工具。关于其配置与使用可以参考这篇文章 consul 简介与配置说明

一般,我们会在多台主机上安装并启动 consul,在开发时这可能会比较不方便,所以这里介绍如何使用 vagrant 和 docker 来简化开发环境的搭建。

利用 vagrant 创建虚拟机


Vagrant 是 HashiCorp 公司的产品, 用于创建和部署虚拟化开发环境,支持常见的操作系统。由于其安装比较简单,参照官方文档即可,此处不再赘述。

安装完成后,我们创建文件夹consul,在consul文件夹下创建一个文件Vagrantfile,内如如下:

# -*- 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

这里我们创建了三个虚拟机,hostname为 n1,n2,n3;ip分别为 172.20.20.10,172.20.20.11,172.20.20.10,使用镜像 ubuntu/xenial64,并且将镜像更新为了阿里云,安装了一些必须的软件。

编辑好该文件,在命令行运行 vagrant up,出去喝杯咖啡,你的机器上就会启动三台对应的虚拟机了。如果你不想使用ubuntu 16.04,还可以更换其他的操作系统。

在 consul 文件夹下使用 vagrant ssh命令,就可以登录到对应的虚拟机了:

➜  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:~$

配置运行consul的docker容器


docker的安装请参照这里docker安装。需要注意,鉴于 dockerhub 在国内丧心病狂的访问速度,我们一般会选择使用国内的镜像,如阿里云、网易蜂巢等。

安装好了docker后,我们以 n1 虚拟机为例,说明如何在虚拟机上使用docker容器来运行consul。

首先,创建一个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为基础构建docker容器。然后设置使用阿里云镜像,安装各种工具,下载 consul 并创建 consul 使用的 ui 文件夹。然后声明暴露8个 consul 需要使用的 tcp 或 udp 端口,并将 /data 设置为一个 VOLUME (通过--volumes-from可以在容器之间共享数据)。 最后,注意 ENTRYPOINT 声明了容器启动时执行的命令,而在启动容器时加上的命令会被添加在 ENTRYPOINT 指定的命令后,比如ENTRYPOINT为 [ "/usr/sbin/consul", "agent", "-config-dir=/config" ],启动镜像时的命令为 sudo docker run <镜像名称> XXXX,则容器启动时执行的命令为 /usr/sbin/consul agent -config-dir=/config XXXX

另外,为了使用 consul,我们也需要编辑其配置文件 consul.json。这里我们使用一个比较简单的配置,有特殊需要的请参阅 consul 官方文档的配置说明。

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

编辑好这2个文件后,在consul文件夹下执行命令 sudo docker build -t millions/consul . 即可创建镜像 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

而后在其他虚拟机使用同样方法创建镜像。为了方便启动 docker 镜像,我们再在每台虚拟机上创建以下环境变量:

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

而后,由于我们打算用n1做 bootstrap 时的leader,所以在 n2、n3 上创建环境变量:

export JOIN_IP=172.20.20.10

接下来,我们就可以准备启动 consul 实例们啦~

启动 consul 实例

注意启动时需要使用 -h $HOSTNAME 指定容器的hostname。首先我们启动 n1,由于用其做 bootstrap, 所以我们使用了 -bootstrap-expect 3。其他相关启动参数如果不熟悉的话可以查看 consul 的文档,这里不做详细解释。比较重要的是需要额外设置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 的输出发现其已经启动,但是还无法组成集群:

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 参数):

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参数而不是 bootstrap-expect。都完成启动后在物理机上访问 http://172.20.20.10:8500 即可看到熟悉的consul web-ui 界面。至此,我们的 consul 集群开发环境就搭建完成了,我们可以使用其他各种程序将自己作为服务注册到 consul 集群中,并且访问集群获取其他服务地址。

测试


为了测试集群是否可以正常工作,我们再创建其他2个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 的内容为:

require 'rubygems'
require 'sinatra' get '/' do
"Hello World!"
end run Sinatra::Application

uwsgi-consul.ini 的内容为:

[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

而后创建镜像:

sudo docker build -t millions/distributed_app .

我们创建好镜像后,在 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个名为distributed_app的服务。

web-ui

我们使用一个脚本来进行测试,为了再温习一下 docker,我们还是将其放在一个 docker 容器中运行,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两种方式来获取服务:

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

创建好镜像:

sudo docker build -t millions/distributed_client .

运行之:

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 的结果,可以看到获取了 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

总结


至此,我们的consul 集群开发环境就搭建好了。关机前不要忘记用 vagrant halt 或者 vagrant suspend 关闭或暂停你的虚拟机哦~

作者:millions_chan
链接:https://www.jianshu.com/p/52f4ea31aa1b
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

vagrant+docker搭建consul集群开发环境的更多相关文章

  1. 庐山真面目之十二微服务架构基于Docker搭建Consul集群、Ocelot网关集群和IdentityServer版本实现

    庐山真面目之十二微服务架构基于Docker搭建Consul集群.Ocelot网关集群和IdentityServer版本实现 一.简介      在第七篇文章<庐山真面目之七微服务架构Consul ...

  2. 如何基于Jupyter notebook搭建Spark集群开发环境

    摘要:本文介绍如何基于Jupyter notebook搭建Spark集群开发环境. 本文分享自华为云社区<基于Jupyter Notebook 搭建Spark集群开发环境>,作者:apr鹏 ...

  3. Docker学习-Docker搭建Consul集群

    1.环境准备 Linux机器三台 网络互通配置可以参考 https://www.cnblogs.com/woxpp/p/11858257.html 192.168.50.21 192.168.50.2 ...

  4. 使用Docker搭建consul集群+registrator实现服务自动注册。

    准备工作:10.173.16.83 master10.172.178.76 node110.171.19.139 node210.162.204.252 node3 一.安装consul-cluste ...

  5. docker搭建etcd集群环境

    其实关于集群网上说的方案已经很多了,尤其是官网,只是这里我个人只有一个虚拟机,在开发环境下建议用docker-compose来搭建etcd集群. 1.拉取etcd镜像 docker pull quay ...

  6. Docker 搭建 etcd 集群

    阅读目录: 主机安装 集群搭建 API 操作 API 说明和 etcdctl 命令说明 etcd 是 CoreOS 团队发起的一个开源项目(Go 语言,其实很多这类项目都是 Go 语言实现的,只能说很 ...

  7. Docker搭建RabbitMQ集群

    Docker搭建RabbitMQ集群 Docker安装 见官网 RabbitMQ镜像下载及配置 见此博文 集群搭建 首先,我们需要启动运行RabbitMQ docker run -d --hostna ...

  8. hadoop-2.6.0集群开发环境配置

    hadoop-2.6.0集群开发环境配置 一.环境说明 1.1安装环境说明 本例中,操作系统为CentOS 6.6, JDK版本号为JDK 1.7,Hadoop版本号为Apache Hadoop 2. ...

  9. Docker安装Consul集群

    Docker 安装Consul集群 使用windows 环境,Docker desktop community 构建consul集群. 1.docker 容器网络 docker安装后,默认会创建三种网 ...

随机推荐

  1. Mvc6 错误Microsoft.AspNet.Http.Features.IRequestIdentifierFeature

    System.TypeLoadException 未能从程序集“Microsoft.AspNet.Http.Features, Version=1.0.0.0, Culture=neutral, Pu ...

  2. SPOJ Favorite Dice(数学期望)

    BuggyD loves to carry his favorite die around. Perhaps you wonder why it's his favorite? Well, his d ...

  3. bzoj 4573 大森林

    bzoj 4573 大森林 由于树上路径是唯一的,查询合法的两个点间路径长度显然与其他加点操作无关,所以可以离线处理,将所有的查询放在加点后. 这样我们可以对每棵树都在上颗树的基础上处理好形态后,处理 ...

  4. 当我们使用 MVVM 模式时,我们究竟在每一层里做些什么?

    这篇文章不会说 MVVM 是什么,因为讲这个的文章太多了:也不会说 MVVM 的好处,因为这样的文章也是一搜一大把.我只是想说说我们究竟应该如何理解 M-V-VM,当我们真正开始写代码时,应该在里面的 ...

  5. 携程阿波罗(Apollo)配置中心

    携程阿波罗(Apollo) https://www.cnblogs.com/xiaxiaolu/p/10025597.html 一.瞎扯点什么 1.1 阿波罗 ​ 阿波罗是希腊神话中的光明之神.文艺之 ...

  6. 隐藏控件HiddenField使用

    HiddenField控件顾名思义就是隐藏输入框的服务器控件,它能让你保存那些不需要显示在页面上的且对安全性要求不高的数据. 增加HiddenField,其实是为了让整个状态管理机制的应用程度更加全面 ...

  7. 简单安装MySQL(RPM方式)

    本次测试使用一台ip为192.168.2.21的虚拟机 下边的步骤虽然多,但是跟着命令或者复制粘贴命令即可完成操作,并无难点 1.安装准备 MySQL-server-5.6.35-1.linux_gl ...

  8. centos7下安装Anaconda3

    下载anaconda3: wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-4.2.0-Linux-x86_64 ...

  9. ThinkPHP 分页功能梳理

    最近在开发一个项目,使用了国内流行的ThinkPHP框架,我之前没怎么用过这个框架,也是临时抱佛脚,用的不怎么样?可能理解不是很深刻,如果有说的不对或不正确的地方,请大家多包涵,多指教. ThinkP ...

  10. python3之es+log+date+timezone

    from dateutil.parser import parse # 使用它可以方便的将字符串解析为datetimefrom tzlocal import get_localzone # 使用它可以 ...