今天又看到邮箱里阿里云提示ECS实例要迁移的消息,想了想早晚都要迁,还不如早点迁移了事。

心说如果迁移后服务起不来了,那么就把国内国外的服务都改成微服务模式好了。

顺手点击了迁移,没过多久看到短信通知服务迁移完毕,尝试性的打开网站,发现服务果然起不来了,于是就开始了架构简化之旅。

本文以更新网站架构为例,展示如何使用Traefik进行微服务化的站点快速启停,应用迭代,如果你想直接获取示例配置,请跳转第三小节:实战迁移。

历史问题

从14年把Apache迁移到Nginx之后,就开始用Nginx当服务网关,不管后面的网站和应用怎么拆,前面都势必会起一个Nginx,或者“变种”版本提供一些特殊能力:

  • Tengine: 文件合并、内存缓存、页面内容替换、动态模块…
  • OpenResty: 文件合并、内存缓存、Lua WebHook接口…

但是这里有一个很悲催的事情,使用Nginx当“前排”,后面的内容修改之后:

  • 要么得额外清除一遍文件&内存缓存。
  • 要么得把该进程重载或者重启一遍。
  • 个人使用的都是自己编译的版本,打成容器文件尺寸惊人,不适合服务器之间传递,失去装箱交付的价值。

而且即使使用了容器技术,这个前排的Nginx也不适合使用容器执行:

  • Nginx和Docker耦合过重,升级其中一个模块的时候,整体是不可用的。
  • 不利于日志的记录和分析。
  • 完全没必要让流量多绕一层:Docker->Nginx Proxy->Docker App

然后整体结构就变成了这小节内容开头的样子:

静态编译一个功能强大的Nginx服务,使用反向代理功能代理后面的Docker App,并在Nginx + Redis中进行强缓存。

配合发布脚本定时重载&重启进行倒是也使用了一阵,但是个人感觉“脏”了许多,使用体验不太舒服。

拥抱未来

基于Nginx的服务发现也不是没有,比如大名鼎鼎的Consul、Etcd,有不少公司就在使用,也有一些公司使用一些动态upstream的模块进行内部服务域名注册。

但是有两个额外的问题:

  • 对Nginx的依赖过重,很多场景下,我们是可以不需要Nginx来提供服务的。
  • 对于我之前的玩法,Nginx每次升级都要重新编译一次,开发体验很不友好,还有额外维护成本。

而且 Tengine、OpenResty 毕竟过度定制,很多内容打补丁比较麻烦,比如每次升级OpenSSL的时候。五月的时候,做过了网站应用的简化,拔掉了很多对Nginx的能力的依赖,现在直接使用官方的Nginx Alpine镜像就能满足我的需求。

在寻找简单高效的工具的过程,我发现了Traefik: 官方网站

软件介绍官方写了很多,在使用了几个月后,个人体会是:

  • Nginx能做的事情,多数它都能做,它做起来更简单。
  • Nginx不能做的服务发现,是它的主打功能之一。
  • 如果你要定制header或者进行redirect,编写Nginx规则会给Traefik写规则写着顺手。
  • 可折腾程度,Traefik没有Nginx高,所以如果追求极致的性能,还是选择Nginx吧。
  • 支持一堆主流的服务商和容器编排工具和服务发现工具,包括开头提到的Consul,Etcd…

实战迁移

因为是个人服务,使用的实例越少,模块之间的隔离性越好,今后维护起来的成本就越低,于是我采用最简单的架构:

  • 服务后端:Docker
  • 编排工具:docker-compose (不使用的话,直接使用docker原生命令也行)
  • 服务网关:Traefik
  • 具体应用:Nginx + 静态文件 、 compose编排起来的容器应用

启动 Traefik 实例

安装docker和docker-compose请参考官方网站文档,这里就略过了。

当docker和docker-compose就绪后,创建一个docker-compose.yml,输入一下内容:

这个编排文件虽然短短几行,但是做了好几件事:

  1. 创建一个叫做traefik的具名容器,方便今后直接使用 docker cmd traefik 进行操作。
  2. 拉取目前最新的 traefik:1.6.3-alpine 镜像,未来升级,如果API没有变化,直接修改这里的版本,就能获取新版本的软件了。
  3. 使用Docker简化掉supervisor维护进程守护。
  4. 将宿主机的配置文件和证书挂载到容器Traefik容器内部。
  5. 使用用户自定义的配置启动Traefik。

接着创建一个名为traefik.toml的配置文件(我已经做了简单汉化,你可以参考使用):

关于证书,你可以直接使用acme.sh进行申请,下面演示如何使用CloudFlare DNS验证方式申请ecc证书:

如果你有多个证书,想开启SNI,copy一份证书配置,在下面再重复书写一次就可以了。

当你准备好了docker-compose中依赖的ssl证书,上面的toml配置文件后,执行:

然后访问 https://d.yourdomain.com/ 输入你在配置文件中指定的账号密码,就能看到traefik的管理界面了。

启动应用实例

同样的,为你的应用创建一个docker-compose.yml文件:

可以看到,相比较之前的配置文件,这个配置文件多了一堆labels属性。

那么它做了哪些事情呢:

  1. 使用轻量的Nginx Alpine镜像提供Web服务。
  2. 配置对外提供服务的域名为www.soulteary.com和soulteary.com。
  3. 默认启用Https作为服务协议,对Http进行跳转。
  4. 默认将www.soulteary.com重写为soulteary.com。
  5. 设置一个宽松的CROS,开启HTTPS严格模式。
  6. 将数据文件挂载到容器内部。
  7. 上述的路由暴露相关的操作,全部交给Traefik的服务发现来进行操作,不需编码。

当你准备好网站数据文件之后,同样执行compose命令,你会看到网站很欢脱的启动了起来,并且在刚刚的dashboard中多了一组“前后端程序”,如果你的网站是使用PHP、Java作为backend,可以使用Traefik轻松启用多实例负载。

最后

至此,海外服务器和国内服务器的服务器软件架构就一致了,现在所有的应用升级迁移终于可以完美体验秒级操作,迁移扩展也可以变的更轻松简单,哦也。

此外,完全使用了容器技术和服务发现模式进行应用维护,可用性监控和性能数据收集十分重要,接下来考虑分享一个Docker轻量管理系统以及强大的Prometheus。

–EOF