本帖最后由 adminlily 于 2018-10-19 10:16 编辑  
 
随着微服务的发展,DevOps的流行,以前每周或每月一次的更新变成了现在几乎每天都在更新上线产品了,最后一公里的线上更新部署的保障至关重要,今天借社群这个平台,跟大家分享下个人的经验。  
  
 因为DevOps打通了开发和运维之间以前不可逾越的鸿沟,使得线上部署已经不再仅仅是运维部门的事情了,所以要保障更新部署能顺利进行,就需要开发和运维一起共同配合才能很好地完成。因此,本次分享我将从开发侧和运维侧共同介绍的,主要包括三个方面的内容:  
  
 1.发布更新常用技术 
 
 
2.线上项目部署拓扑结构 
 
 
3.网关层和服务层的灰度发布实战 
 
  
 一、发布更新常用技术 
 
  
 本次分享主要以干货为主,所以让我们直接开始今天的主题吧。首先我给大家介绍下更新发布的一些常用技术,主要有以下几种:  
  
  
 
 
 
 
 1、首先,什么是蓝绿部署?  
  
概念 
  
 蓝绿部署是不停老版本,部署新版本然后进行测试,确认新版本没有问题了,再将流量切到新版本,然后老版本同时也升级到新版本。其特点是部署无需停机,并且风险较小,不过对服务器成本有点浪费,毕竟要同时部署两个版本。  
  
部署过程 
  
  
 
 
  
 
 
  
 2、其次,什么是滚动部署?  
  
概念 
  
 滚动部署一般是取出一个或者多个服务器停止服务,然后执行更新,并重新将其投入使用,周而复始地直到集群中所有的实例都更新到新的版本。这种部署方式相对于蓝绿部署,更加节约资源,因为它不需要运行两个集群、两倍的实例数。  
  
 不过滚动部署有个最大的缺点,就是在更新的时候没有一个稳定的正式环境,如果在更新过程中出现了问题很难立即回滚。  
  
部署过程 
  
 假设我们线上有100个服务实例,现在进行滚动更新。  
  
  
 
 
 3、最后,什么是灰度/金丝雀发布?  
  
概念 
 
 灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度,而我们平常所说的金丝雀部署也就是灰度发布的一种方式。  
  
 补充:17世纪,英国矿井工人发现,金丝雀对瓦斯这种气体十分敏感。空气中哪怕有极其微量的瓦斯,金丝雀也会立即发现,而当瓦斯含量超过一定限度时,虽然人类毫无察觉,但金丝雀却早已毒发身亡。在当时在采矿设备相对简陋的条件下,工人每次下井都会带上一只金丝雀作为“瓦斯检测指标”,以便在危险状况下紧急撤离。  
 图一 灰度/金丝雀发布/金丝雀  
  
 
 
 
 
部署过程 
 
 
  
 
 
 
 
 
 
 
 
二、线上项目部署拓扑结构 
 
  
 介绍完常用的几种更新发布技术后,我将介绍一个线上实际项目的部署结构,先看看两张图:  
 图二 游戏服架端构图  
  
  
 SOA架构模式是一个经典的分布式软件架构模式,服务之间使用RPC运程调用功能,而服务的注册和发现则使用ZooKeeper这样的目录服务器。这样游戏服务就拆分为三层结构:最前边的网关(gate)服务器、中间为各游戏服务器(gameServer),最后边的数据库(DB)服务器。这样把网络功能单独提取出来,让用户统一去连接网关服务器,再由网关服务器转发数据到后端游戏服务器。而游戏服务器之间数据交换也统一连接到网关服进行交换。所有与DB交互的都连接到DB服务器来代理处理。  
  
 我们在介绍完服务的架构后,再来看看具体的运维部署结构是什么样的?  
 图三 服务部署拓扑结构  
  
 从这张服务器部署拓扑结构图中我们可以看出,更新部署的关键痛点主要在ELB到gateway,gateway到sever的过程中。Gateway是通过ELB负责均衡实现的流量分发,而server和gateway主要通过zookeeper实现的服务注册与发现功能,所以接下来我将主要分成两部分来介绍它们的具体实现过程。  
  
 三、网关层和服务层的灰度发布实战 
 
  
 1、网关层的高可用自动发现实现方案  
  
 在网关层我们主要采用Etcd+Confd+Nginx或Consul+Consul-Template+Nginx两种方式来实现,两种方式都差不多,我在这里主要介绍下后者如何实现的。  
 图四 网关层的自动发现服务  
  
  
 从上图可以看到,我们可以添加服务或移除服务,然后consul通过服务健康检测来实现的网关层服务自动发现,最后Nginx通过自动加载consul-template生成的新的配置文件来进行流量切换和负载。下面我将简单介绍下Consul+Consul-Template+Nginx的安装过程,其步骤如下:  
  
  
 wget [  /consul/1.0.0/consul_1.0.0_linux_amd64.zip]c ... 0.0_linux_amd64.zip[/url] unzip consul_1.0.0_linux_amd64.zip mv consul /bin rm consul_1.0.0_linux_amd64.zip  
  
 在/etc/consul/目录下添加配置项config.json文件,并且设置server=true,代表以服务启动。同时指定Consul机群中所有的ip来加入机群。  
 {                                               "datacenter": "test-dc",                                             "data_dir": "/tmp/consul",   "log_level": "DEBUG",                                               "node_name": "consul00",   "server": true,                                                 "bootstrap_expect": 3,                                                 "ui_dir": "/opt/consul-ui",                                          "bind_addr": "192.168.0.101",                                            "leave_on_terminate": true,   "start_join": [                                                       "192.168.0.101",                                                       "192.168.0.102",                                                         "192.168.0.103"   ]                                               }  
  
 sudo service consul start  
  
  
 安装客户端和安装服务端方法一样,还在是在/etc/consul/目录下添加配置项config.json文件,只是不需要设置server属性(server默认为false)。  
 {   "datacenter": "test-dc",   "data_dir": "/tmp/consul",   "log_level": "DEBUG",   "node_name": "web-1",   "leave_on_terminate": true,   "start_join": [     "192.168.0.101",     "192.168.0.102",     "192.168.0.103"   ] }  
  
  
  
 {   "service": {     "name": "apache",     "tags": ["foo"],     "address": "192.168.0.105",     "port": 80,     "enableTagOverride": false,     "checks": [       {         "tcp": "localhost:80",         "interval": "10s"       }     ]   } }  
  
 wget [  /consul-template/0.13.0/consul-template_0.13.0_linux_amd64.zip]c ... 3.0_linux_amd64.zip[/url] $ unzip consul-template_0.13.0_linux_amd64.zip $ rm consul-template_0.13.0_linux_amd64.zip $ mv consul-template /bin  
  
 使用Consul-Template实现服务自动化添加和移除。  
  
 首先启动consul-template,并指定模板地址和生成文件地址,以及执行nginx -s reload操作。  
  
 sudo ./consul-template -template "/etc/consul-template/nginx.tmpl:/etc/nginx/sites-available/default:nginx -s reload" 
  
 然后在/etc/consul-template/nginx.tmpl文件中添加Consul-Template模板配置,每次服务有变化都会自动生成ngnix配置文件/e  
 tc/nginx/sites-available/default。 server {   listen 80 default_server;   location / {     proxy_pass http://frontend;   } } upstream frontend { {}   server {{.Address}};{} }  
 当然除了上面介绍的从Consul主动去检测服务健康外,我们还可以通过程序主动向Consul注册服务,其Java代码如下。  
  
 首先在pom.xml文件中引用Consul的依赖库。  
 <dependency>      <groupId>com.orbitz.consul</groupId>      <artifactId>consul-client</artifactId>      <version>0.17.0</version>  </dependency>   
 然后在Java启服代码中实现注册功能。  
  
  
 介绍完网关层的实现后,接下来我们看看服务层又是如何实现的呢?  
  
 2、服务层灰度发布方案  
  
 由于服务层我们主要使用的是d o实现的RPC功能,d o的架构图如下:  
 图五 d o架构图  
 而d o可以使用group的方式进行灰度发布,具体步聚如以下三步:  
  
  
 
 
 
 
 
 
 这样就实现中服务层的灰度发,其中消费者(consumer)对应到我们服务架构中的网关服(gateway)。  
  
 通过本次的分享,我们介绍了更新部署的技术和流程,并实现了服务的灰度发布功能,虽然还有很多可以继续优化提升的地方,不过它也能有效的保障了服务部署的稳定性和安全性。感谢大家今晚在百忙之中能参加我的分享,谢谢!  
  
 Q&A 
  
 Q1:问ELB这层一般用什么软件实现?  
  
 A1:这里可以使用的解决方案挺多,比如我们使用的AWS的ELB服务,如果小的项目可以直接使用Nginx就足够了的,当然还有像LVS等。  
  
 Q2:「问题1」服务器批量增加和删除怎么实现注入Consul的?  
  
 A2:我在分享中有介绍过,分为两种:一种是Consul主动的检测,另一种为程序在启动的时候向Consul中注册。可看看我前面的介绍。  
  
 Q3:问现在常提的API网关怎么理解?  
  
 A3:网关层,主要是用于和前端直接产生交互的,是各种服务的统一入口,它屏蔽了服务直接 到前端。它最重要的是路由和过滤器功能,同时还会用来提供监控、授权、安全、调度等。  
  
 原创: 杨彪  
 
 |