Docker+Jenkins持续集成环境(4) 使用etcd+confd实现容器服务注册与发现

前面我们已经通过jenkins+docker搭建了基本的持续集成环境,实现了服务的自动构建和部署,但是,我们遇到一个问题,jenkins构建出来的镜像部署后,需要通过ip:port去访问,有什么更好的方法吗?肯定是通过域名啊!前提是你注册一个域名,或者修改机器hosts文件。
本文介绍通过引入etcd+confd实现部署服务的自动注册,自动生成nginx配置文件,实现每个服务独立域名访问。

配置域名

假设你的域名是: example.com,那么我们可以规划

  • dev.$servicename.example.com作为开发环境,
  • test.$servicename.example.comz作为服务的测试环境。

配置步骤:

  • 首先将*.example.com 指向一台nginx服务器
  • 增加vhost配置文件,假设86.6,86.8,86.11 是docker swarm集群中的机器,服务的名称为allinoneservice,那么我们可以增加一个配置文件nginx_vhosts/service.conf:
    upstream test_service_allinoneservice {
        server 192.168.86.11:10091;
        server 192.168.86.6:10091;
        server 192.168.86.8:10091;
    }

    server {
        listen       80;
        server_name test.allinoneservice.example.com;
        location / {
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_read_timeout 300;
            proxy_set_header X-Real-IP $http_x_forwarded_for;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://test_service_allinoneservice;
        }
    }

  • 修改nginx配置文件nginx.conf,在最后一个大括号前,将刚新建的配置文件包含进去:

      include nginx_vhosts/*.conf;
    
  • 重启nginx,就可以通过test.allinoneservice.example.com访问服务了

通过服务注册自动生成配置文件

第一步里,我们需要手动编写配置文件,有更好的方式吗?答案是通过服务注册+confd,自动生成配置文件。

docker 安装etcd集群

首先,docker安装etcd作为注册中心,我们安装一个包含3个实例的集群,编写docker-compose.yml:

version: '3'
services:
  etcd0:
    image: 192.168.86.8:5000/etcd
    ports:
      - "2379:2379"
    volumes:
      - etcd0:/etcd_data
    command:
      - /usr/local/bin/etcd
      - -name
      - etcd0
      - --data-dir
      - /etcd_data
      - -advertise-client-urls
      - http://etcd0:2379
      - -listen-client-urls
      - http://0.0.0.0:2379
      - -initial-advertise-peer-urls
      - http://etcd0:2380
      - -listen-peer-urls
      - http://0.0.0.0:2380
      - -initial-cluster
      - etcd0=http://etcd0:2380,etcd1=http://etcd1:2380,etcd2=http://etcd2:2380
  etcd1:
    image: 192.168.86.8:5000/etcd
    ports:
      - "2380:2379"
    volumes:
      - etcd1:/etcd_data
    command:
      - /usr/local/bin/etcd
      - -name
      - etcd1
      - --data-dir
      - /etcd_data
      - -advertise-client-urls
      - http://etcd1:2379
      - -listen-client-urls
      - http://0.0.0.0:2379
      - -initial-advertise-peer-urls
      - http://etcd1:2380
      - -listen-peer-urls
      - http://0.0.0.0:2380
      - -initial-cluster
      - etcd0=http://etcd0:2380,etcd1=http://etcd1:2380,etcd2=http://etcd2:2380
  etcd2:
    image: 192.168.86.8:5000/etcd
    ports:
      - "2381:2379"
    volumes:
      - etcd2:/etcd_data
    command:
      - /usr/local/bin/etcd
      - -name
      - etcd2
      - --data-dir
      - /etcd_data
      - -advertise-client-urls
      - http://etcd2:2379
      - -listen-client-urls
      - http://0.0.0.0:2379
      - -initial-advertise-peer-urls
      - http://etcd2:2380
      - -listen-peer-urls
      - http://0.0.0.0:2380
      - -initial-cluster
      - etcd0=http://etcd0:2380,etcd1=http://etcd1:2380,etcd2=http://etcd2:2380
volumes:
  etcd0:
  etcd1:
  etcd2:

注意,上面的image: 192.168.86.8:5000/etcd 是用的私有仓库,大家可以使用官方版本quay.io/coreos/etcd

然后启动etcd:

docker stack deploy -c docker-compose.yml etcd

服务注册

etcd注册就简单了,可以通过etcd的rest api,例如:

curl http://192.168.86.11:2379/v2/keys/services/test/allinoneservice/service1 -XPUT -d value="192.168.86.8:10091"

所以,我们修改一下jenkins里的docker部署脚本,服务部署后自动向etcd注册,由于是swarm集群,因此我们可以注册多个ip。

echo "start remove old service"
docker service rm  ${service_name}-${env}
echo "start create new service with latest builded image"
docker service create --name ${service_name}-${env} --replicas ${replicas} --publish ${service_port}:${docker_expose_port} 192.168.86.8:5000/${service_name}-${env}
echo "publish service to nginx"
curl http://192.168.86.11:2379/v2/keys/services/${env}/${service_name}/service1 -XPUT -d value="192.168.86.8:${service_port}"
curl http://192.168.86.11:2379/v2/keys/services/${env}/${service_name}/service2 -XPUT -d value="192.168.86.11:${service_port}"
curl http://192.168.86.11:2379/v2/keys/services/${env}/${service_name}/service3 -XPUT -d value="192.168.86.6:${service_port}"

注意,上面的service_name是jenkins参数化构建里定义的参数:

jenkins参数化构建
jenkins参数化构建

通过confd生成nginx配置文件

confd 是一个配置文件生成工具,可以从etcd、consul等注册中心读取数据根据模板生成配置文件,并在配置发生变化后自动更新配置文件,还能自动重启服务,是服务自动发现的居家必备良药。

首先讲下怎么安装,根据官方文档:

wget https://github.com/kelseyhightower/confd/releases/download/v0.14.0/confd-0.14.0-linux-amd64
mkdir -p /opt/confd/bin
mv confd-0.14.0-linux-amd64 /opt/confd/bin/confd
chmod +x /opt/confd/bin/confd
export PATH="$PATH:/opt/confd/bin"

为了方便使用,最好修改下/etc/profile,加入export PATH="$PATH:/opt/confd/bin",然后source /etc/profile让配置生效。

然后编写confd配置文件/etc/confd/conf.d/myapp-nginx.toml:

[template]
src = "nginx.conf.tmpl"
dest = "/opt/third_party/nginx_vhosts/service.conf"
keys = [
    "/services/dev",
    "/services/test",
]
reload_cmd = "/opt/third_party/sbin/nginx -s reload"

上面配置了,会读取的keys,以及dest目标配置文件地址,和配置文件更新后的reload_cmd,用于重启nginx

接着编写模板文件

{{range $dir := lsdir "/services/test"}}
upstream test_service_{{base $dir}} {
    {{$custdir := printf "/services/test/%s/*" $dir}}{{range getvs $custdir}}
    server {{.}};
    {{end}}
}

server {
    listen       80;
    server_name test.{{base $dir}}.iflyresearch.com;
    location / {
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_read_timeout 300;
        proxy_set_header X-Real-IP $http_x_forwarded_for;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://test_service_{{base $dir}};
    }
}
{{end}}

上面的模板比较简单,通过lsdir指令读取服务列表,然后通过range getvs获取服务对应的负载地址。

然后启动confd,需要指定etcd的地址:

nohup confd -backend etcd -node http://192.168.86.11:2379 &

搞定!

延伸阅读

Jenkins+Docker 搭建持续集成环境:


作者:Jadepeng
出处:jqpeng的技术记事本--http://www.cnblogs.com/xiaoqi
您的支持是对博主最大的鼓励,感谢您的认真阅读。
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • Docker — 云时代的程序分发方式 要说最近一年云计算业界有什么大事件?Google Compute Engi...
    ahohoho阅读 15,514评论 15 147
  • from http://www.infoq.com/cn/articles/etcd-interpretation...
    小树苗苗阅读 13,940评论 3 38
  • 1、导读 如果你在大量接触或使用微服务的话,你可能会碰到一个问题:当你创建的服务数量越来越多时,这些服务之间的通信...
    点融黑帮阅读 15,498评论 4 54
  • 我们都有许多回忆,快乐的,悲伤的,平静的,难堪的,尤其是我们的思维安静下来时,它们就会像个精灵跳入你的脑海。快乐的...
    黑文字阅读 144评论 0 1