kubernetes实战之consul简单测试环境搭建及填坑
这一节内容有点长,我们将介绍如何基于docker搭建一client一server的consul测试环境,以及如何搭建多server consul测试集群.在基于docker搭建多server的consul集群时出碰到了一些坑,这对我们是很有益的提醒,很多时候我们不能仅仅满足于最小化的环境搭建及简单使用,而是要朝着接近生产环境的方向努力.同时,我们这里基于docker搭建集群其实和在宿主机上直接搭建并没有太大区别,也就是我们仅仅把docker当作类似虚拟机来使用,本系列我们多次强调新瓶装老酒,我们要真正思考新的技术方案到底能为我们的项目带来什么,如何充分利用新技术新方案来更好的服务于我们的项目.后面我们会基于k8s来搭建一个接近生产环境的集群,实现节点节点自动组成集群,某个节点挂掉后新增补的节点如何自动加入原有集群.后来我们还会探索如何使用k8s的服务发现功能,实现consul节点的自动扩容.相比传统的方法手动启动宕掉的节点或者使用脚本来实现自动化,我们完全基于kubernetes的能力来实现自动化.闲言少叙.我们进入正题,开始讲如何使用docker来搭建consul测试集群.后面的具体章节我们再详细介绍这里讨论的内容.
使用docker镜像部署一个client和一个server
前面我们介绍了在windows下部署dev环境的consul,我们仅部署了一个节点,其实这个节点是一个client节点,不对数据做持久化存储,仅保存在内存中.生产环境需要持久化存储数据,因此需要server模式,本篇介绍如何使用consul docker镜像部署一个server和一个client
拉取consul镜像
使用docker pull consul
命令来拉取consul的docker镜像.
启动server 端
通过以下命令启动server端
docker run -d -p 1234:8500 -h node1 --name node1 consul agent -server -bootstrap-expect=1 -node=node1 -client 0.0.0.0 -ui
执行命令后,docker返回容器id
d107a4eda2f84bee09c0ae9044a22aa99249d144a1751e270ef6641fead79884
注意这个数字是随机的,读者要看自己的docker实际返回的id
然后我们执行docker ps查看以上容器是否在运行
λ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d107a4eda2f8 consul "docker-entrypoint.s…" 4 seconds ago Up 3 seconds 8300-8302/tcp, 8301-8302/udp, 8600/tcp, 8600/udp, 0.0.0.0:1234->8500/tcp node1
可以看到它已经在运行了.
此节点是server端,client需要加入它组成集群,client加入需要知道server的ip.我们有两种方式获取server的ip,实际上就是server所在容器的ip
通过
docker inspect -f '{{.NetworkSettings.IPAddress}}' node1
来查看查看server端的ip.通过
docker exec -it node1 /bin/sh
进入到容器内部的交互shell,通过ip a
命令获取容器ip
我获取到的ip为172.17.0.2
.
启动client端
通过以下命令
docker run -d -p 8600:8600 -p 8300:8500 -p 8600:53/udp --name client1 -h client1 consul agent -ui -node=client1 -join=172.17.0.2
启动client端,这里启动时自动加入node1组成集群,启动client和server的区别在于server启动的时候带有-server选项.
通过以上操作,我们在宿主机访问localhost:1234
就可以访问到consul web管理界面了.
docker多server consul集群部署及常用命令讲解
前面我们使用docker部署了一server一client的集群.非常顺利,也很容易理解,本节部署多server集群,其实和前面也基本类似,只要知道了主节点的ip,新的节点便可以在运行时使用join ip
的形式加入到集群中.但是在实际部署中,包括后面的k8s部署,由于节点数增加,很多坑便暴露出来.这里和后面使用k8s部署都会讲到其中的坑.以供大家参考,方便大家在自己的部署中减少不必要麻烦,快速上线产品.
坑一.
* Failed to join X.X.X.X: Member 'consul-deployment-2927201250-tlj1h' has conflicting node ID 'bd203bf1-2d59-42b0-901c-2a5dedf99c86' with this agent's ID)
Failed to join any nodes.
通过以上内容可以看到是节点的id冲突.通过查询官方文档,官方文档里描述说 node id是一个随机生成的uuid.然而这个id并不是每次创建都随机生成的,而是从宿主机获取到的一个随机字符串,这样同一台机器上启动多个consul容器实例就会出现冲突.k8s中部署也同样会有此问题.
需要注意的是,以上问题仅出现在同一个机器上启动多个consul节点,实际生产环境中,为了保证高可用,是要避免在同一台主机上部署多个server的.
以上问题请参看
解决方案有两种第一种是启动consul的时候指定node-id,并生成一个随机nodeid
docker run -d --name=node2 consul agent -server -bind=172.17.0.3 -join=172.17.0.2 -node-id=$(uuidgen | awk '{print tolower($0)}') -node=node2
注意以上生成uuid和awk命令都是在执行命令的时候生成的,也就是在宿主机生成的,而不是在容器生成后执行的,因此需要容器宿主机支持
uuidgen
和awk
命令,在docker for windows下是无法执行通过的.
第二种解决办法是在启动consul时加上-disable-host-node-id
选项.
坑二. 无法访问ui
前面我们在windows上部署时候,直接通过consul agent -dev
命令便可以启动consul,并且可以访问web管理界面.但是在集群部署时如果不指定-ui选项,则无法访问web管理界面(仅仅是web界面不能访问,其它路由还是可以正常访问)
访问web管理界面还必须指定client绑定,否则也无法正常访问
下面我们搭建一个3个server节点,一个client节点的集群.
集群搭建
启动节点一
docker run -d -p 8500:8500 -e --name=node1 consul agent -server -bootstrap-expect=3 -node=node1 -client=0.0.0.0 -ui
以上为了测试方便,防止暴露过多端口出现冲突(同一机器上展示),只暴露了http端口,实际上还需要暴露多个tcp和udp端口.下节在k8s集群中部署我们将完整介绍整个部署方案.
启动节点2和3
docker run -d --name=node2 consul agent -server -join=172.17.0.2 -node=node2 -disable-host-node-id
启动节点和节点3都是使用上面的命令,惟一要修改的是--name=node2
和-node=node2
两处,节点3启动的时候以上两处都要改为node3
(当然也可以是其它名字)
注意,大家不要混淆,--name是docker为容器取的名字,-node是consul运行时给当前启动节点取的名字
以上的-join里的ip为第一个启动节点的ip,大家可以通过docker inspect -f '{{.NetworkSettings.IPAddress}}' node1
或者进入到第一个启动节点里面执行ip a
获取它的ip
启动一个client节点
我们前面说过client和server的区别在于server启动的时候指定-server选项,如果不指定则启动的是client模式
docker run -d -p 8400:8500 --name=node4 consul agent -join=172.17.0.2 -node=node4 -disable-host-node-id -client=0.0.0.0 -ui
这里对client进行端口映射,以方便通过client进行http操作.
我们通过localhost:8400或者localhost:8500
就可以看到整个集群的节点信息了
注 8500是leader映射出来的端口,而8400是client映射出来的端口
常用命令
我们任意进入一个节点内部,这里我们以进入node4(也就是client)为例
docker exec -it node4 /bin/sh
- consul members
此命令可以查看当前节点所在集群中所有节点信息
/ # consul members
Node Address Status Type Build Protocol DC Segment
node1 172.17.0.2:8301 alive server 1.4.4 2 dc1 <all>
node2 172.17.0.3:8301 alive server 1.4.4 2 dc1 <all>
node3 172.17.0.4:8301 alive server 1.4.4 2 dc1 <all>
node4 172.17.0.5:8301 alive client 1.4.4 2 dc1 <default>
/ #
- consul info
查看集群中的信息
/ # consul info
agent:
check_monitors = 0
check_ttls = 0
checks = 0
services = 0
build:
prerelease =
revision = ea5210a3
version = 1.4.4
consul:
acl = disabled
known_servers = 3
server = false
runtime:
arch = amd64
cpu_count = 2
goroutines = 49
max_procs = 2
os = linux
version = go1.11.4
serf_lan:
coordinate_resets = 0
encrypted = false
event_queue = 0
event_time = 2
failed = 0
health_score = 0
intent_queue = 0
left = 0
member_time = 4
members = 4
query_queue = 0
query_time = 1
/ #
以上信息量不小,我们比较关心的是consul
部分的,server=false表明当前节点不是server,known_servers=3表明集群中共有3个server
如果当前执行命令的节点是server,还可以看到server 主(leader)信息
...
consul:
acl = disabled
bootstrap = false
known_datacenters = 1
leader = false
leader_addr = 172.17.0.2:8300
server = true
...
- consul leave
当前节点从集群中离开
注,由于docker在启动容器时指定的要加入的ip,因此当前节点离开后通过
docker start
启动后会重新自动加入到集群.如果在实际生产中,不是以容器部署,当前节点挂掉后,需要再次执行前面我们执行过的命令以加入节点
还有一点需要注意的是,主节点也可能会挂掉,这时候会产生新的节点,这时候就需要知道新的leader的ip,然后把
join
选项里的ip改为新的leader的ip.下节我们使用k8s部署的时候我们将介绍一种新的思路来自动解决易主后节点重新加入集群的问题.
关于命令的详细信息,可以查看官方文档
创建键值存储
consul除了可以用于服务注册外,还可以用作键值存储.下面我们简单介绍一下键值存储用法
consul kv put user/config/connections 5
以上命令会在user目录下的config目录下存储一个键名为connections,值为5的键值对
我们可以通过下图查看其层次
我们可以通过以下命令获取刚存储的值
consul kv get -detailed user/config/connections
输出信息为
/ # consul kv get -detailed user/config/connections
CreateIndex 407
Flags 0
Key user/config/connections
LockIndex 0
ModifyIndex 407
Session -
Value 5
/ #
以上键值写入和读取可以在任意节点上进行操作
http api接口
consul提供了丰富的api接口,由于本教程是偏管理部分的,因此仅对少数对管理有帮助的接口做简单介绍
目前,使用的版本都是v1,因此所有请求地址的固定部分都是
localhost:8500/v1
- 获取集群中成员信息
agent/members
[
...
{
"Name": "node2",
"Addr": "172.17.0.3",
"Port": 8301,
"Tags": {
"acls": "0",
"build": "1.4.4:ea5210a3",
"dc": "dc1",
"id": "1866ce4f-e219-78f9-2bee-64f567a1bf74",
"port": "8300",
"raft_vsn": "3",
"role": "consul",
"segment": "",
"vsn": "2",
"vsn_max": "3",
"vsn_min": "2",
"wan_join_port": "8302"
}
...
]
通过以上返回信息,我们可以看到节点的很多信息
- 获取集群中server列表
/status/peers
[
"172.17.0.2:8300",
"172.17.0.3:8300",
"172.17.0.4:8300"
]
- 查看集群中的leader
/status/leader
"172.17.0.2:8300"
通过执行命令查看主节点信息只能在server端执行,client无法获取到leader信息,而http api则可以在任意节点执行,都能获取到主节点信息
查询注意的服务
catalog/services
查询某一个服务
catalog/service/服务名
获取键值
kv/key的路径
比如我们要获取我们刚才添加的key,则请求路径为kv/user/config/connections
[
{
"LockIndex": 0,
"Key": "user/config/connections",
"Flags": 0,
"Value": "NQ==",
"CreateIndex": 407,
"ModifyIndex": 407
}
]
以上的值是base64编码过的字符串
- 列举出所有的值
kv/?keys
kubernetes实战之consul简单测试环境搭建及填坑的更多相关文章
- kubernetes实战之consul篇及consul在windows下搭建consul简单测试环境
consul是一款服务发现中间件,1.12版本后增加servicemesh功能.consul是分布式的,可扩展的,高可用的根据官方文档介绍,目前已知最大的consul集群有5000个节点,consul ...
- iOSIPV6简单测试环境搭建
应苹果官方要求,iOS应用必须适配IPV6才能通过审核,这里分享一个简单的ipv6测试方法 一.工具原料 1.1 Mac电脑一台 1.2 iPhone手机两部 1.3 数据线一根 二.步骤方法 2.1 ...
- 测试环境部署之填坑记录-Expected one result (or null) to be returned by selectOne(), but found: 2
最近在部署性能测试环境的时候,环境 部署好以后,部分功能出现接口查询异常,问题现象: 拿到错误,肯定要先判断是前端还是后端代码的问题,最简单的方式是抓包查看: 以上是报错页面捕获的接口报错,很明显的接 ...
- Python+selenium测试环境成功搭建,简单控制浏览器(firefox)接下来,继续学习其他浏览器上的测试环境搭建;学习Python语言,利用Python语言来写测试用例。加油!!!
Python+selenium测试环境成功搭建,简单控制浏览器(firefox)接下来,继续学习其他浏览器上的测试环境搭建:学习Python语言,利用Python语言来写测试用例.加油!!!
- Linux测试环境搭建的学习建议
随着Linux应用的扩展许多朋友开始接触Linux,根据学习Windwos的经验往往有一些茫然的感觉:不知从何处开始学起.这里介绍学习Linux测试环境搭建的一些建议. 一.Linux测试环境搭建从基 ...
- 【转2】Appium 1.6.3 在Xcode 8 (真机)测试环境搭建 经验总结
Appium 1.6.3 在Xcode 8 (真机)测试环境搭建经验总结 关于 Appium 1.6.3 在Xcode 8, 1真机上环境搭建问题更多,写此文章,供大家参考,让大家少走弯路. 在开始i ...
- 【转1】Appium 1.6.3 在Xcode 8, iOS 10.2(模拟器)测试环境搭建 经验总结
Appium 1.6.3 在Xcode 8, iOS 10.2(模拟器)测试环境搭建 经验总结 关于 Appium 1.6.3 在Xcode 8, 10.2 的iOS模拟器上的问题很多,本人也差点放弃 ...
- Activiti Workflow HelloWorld 示例与测试环境搭建
作者:Rock 出处:http://www.ecmkit.com/zh-hans/2012/03/21/activiti-workflow-hell Activiti Workflow HelloWo ...
- Selenium Grid分布式测试环境搭建
Selenium Grid简介 Selenium Grid实际上是基于Selenium RC的,而所谓的分布式结构就是由一个hub节点和若干个node代理节点组成.Hub用来管理各个代理节点的注册信息 ...
随机推荐
- Alamofire - 优雅的处理 Swift 中的网络操作
网络处理,应该是我们平时开发的时候最常用到的操作.比如读取 JSON 数据,下载图片,这些操作都要和网络打交道,一个高效稳定的网络操作库对于提升我们日常的开发效率有着非常关键的作用.Alamofire ...
- JSONObject 解析
前解析json已使用get方法,但是,假设抛出将解决很烦人中断. 今天发现JSONObject还提供了一个更好用的方法opt.看来以后文档还是要更加认真的读的.以下是文档中的原文. A JSONObj ...
- 【转载】MySQL双主双从高可用集群架构
双浮动VIP 原文地址:http://www.linuxcache.com/archives/2907 转载请注明原文地址.
- Hermite曲线插值
原文 Hermite Curve Interpolation Hermite Curve Interpolation Hamburg (Germany), the 30th March 1998. W ...
- 一款好用的视频转换gif的小软件——抠抠视频秀
在平常生活中,我们拍下来精彩的视频想要转换为gif动画,或是想要录制网页上的视频.电脑上的鼠标操作等等,大家可以使用以下这款很好用的视频转换gif的小软件——抠抠视频秀,这个软件操作简单 ...
- SQLServer 可更新订阅数据冲突的一个原因
原文:SQLServer 可更新订阅数据冲突的一个原因 可更新订阅为什么有冲突? 可更新订阅中,当升级增加一个字段时,通常在发布服务器的发布数据库中增加,对表增加字段后,发布自动同步到订阅数据库中(复 ...
- 队列读取器代理 遇到错误 Row handle is invalid
原文:队列读取器代理 遇到错误 Row handle is invalid 今天测试在发布中更改表名称,在发布数据库更改后重新发布这个表. 但是原来的表在订阅没有删除,不小心插入数据到原表中,队列读取 ...
- Android手机导出文件
因为要写联系人相关的东西,所以得把db导出来看看 第一步:Root手机 尝试了几个Root工具,发现就KingRoot能root 第二个:编写bat脚本 脚本内容是先将DB文件从/data/data ...
- Android零基础入门第25节:最简单最常用的LinearLayout线性布局
原文:Android零基础入门第25节:最简单最常用的LinearLayout线性布局 良好的布局设计对于UI界面至关重要,在前面也简单介绍过,目前Android中的布局主要有6种,创建的布局文件默认 ...
- 有未经处理的异常(在 xx.exe 中): 堆栈 Cookie 检测代码检测到基于堆栈的缓冲区溢出。
一般这个问题是数组越界. 我产生这个异常的代码是这句:memcpy(tmp_cert.byKey, m_row[2], 255); 255的长度超过了char数组tmp_cert.byKey的长度.