俗话说鸡蛋不要都放在一个篮子里面,把各种集群的节点拆分部署,应该把各种节点分机器部署,多个宿
主机这样部署。在自建集群之前,由于不同应用的依赖环境千差万别,每添加一个应用,不得不考虑主机上的现有环境和已经在跑的服务,而且部署和测试也是比较繁琐,没有办法满足我快速尝试新点子的需求。而 Docker 恰好可以解决应用部署的环境问题,自建 Docker 集群可以充分利用我手上的闲置 VPS,并且提高应用的可用性。下面就由 新网小编和大家聊一聊docker集群化自建方案。,
, ,
俗话说鸡蛋不要都放在一个篮子里面,把各种集群的节点拆分部署,应该把各种节点分机器部署,多个宿主机这样部署。在自建集群之前,由于不同应用的依赖环境千差万别,每添加一个应用,不得不考虑主机上的现有环境和已经在跑的服务,而且部署和测试也是比较繁琐,没有办法满足我快速尝试新点子的需求。而 Docker 恰好可以解决应用部署的环境问题,自建 Docker 集群可以充分利用我手上的闲置 VPS,并且提高应用的可用性。下面就由新网小编和大家聊一聊docker集群化自建方案。
一、硬件资源
自建集群有 8 台 VPS,其中 4 台性能比较好的 Vultr 中低配小鸡,一台
腾讯云低配 VPS,一台搬瓦工 CN2 小鸡,一台 CloudCone 低配小鸡,还有一台朋友送的 VirMach 小鸡。
手上还有几台谷歌
云服务器,不过考虑到用不长久,而且流量贵,就没在自建集群的考虑范围内。
[root@ctrl-bwh-01 scripts]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION q0kllzk1ezr9h449cjatak17z GLBS-CC-01 Ready Active 18.09.5 ioacz1khl94m01wul1z70qatu * ctrl-bwh-01 Ready Active Reachable 18.09.5 1sj867qzlrgdp72705pcnvleb db-vultr-01 Ready Active 18.09.5 dua8lh9h6yt5b58jwwn5vtlu6 db-vultr-02 Ready Active 18.09.5 rk4newk0r7z51lvgjil564bar web-qq-01 Ready Active 18.09.5 xaq6d5n4kzcxj7phnvc32xw21 web-virmach-01 Ready Active 18.09.5 1e2a4scv0eskgq0og3xqpedco web-vultr-01 Ready Active Reachable 18.09.5 5jw8pe7vkzr2iwo3m1rrr1ef5 web-vultr-02 Ready Active Leader 18.09.5
二、集群方案
说到 Docker 集群,一般都会提到鼎鼎有名的 k8s。而我觉得 k8s 太重了,我的众多低配 VPS 跑 k8s 之后,能分配给应用的资源就少得可怜,所以 k8s 是直接就被我 pass 掉的。
虽然也有 k3s 之类的轻量级 k8s 解决方案,不过我还是选择了原生的 docker swarm。VPS 安装好 Docker 之后,不需要额外安装软件,就可以马上建立集群。
# 集群初始化,节点成为 manager 节点 docker swarm init --advertise-addr=x.x.x.x # 集群丢失 Leader 时,强制重建集群 docker swarm init --advertise-addr=x.x.x.x --force-new-cluster # 获取作为 worker 节点加入集群的命令 docker swarm join-token worker # 获取作为 manager 节点加入集群的命令 docker swarm join-token manager # 加入集群 docker swarm join --token xxx x.x.x.x:xxx --advertise-addr=x.x.x.x
官方文档中有提到,Docker 会自动设置--advertise-addr,该参数非必填。不过根据个人经验来看,还是强烈建议显式指定该参数,尤其当 VPS 有多个网卡时。
三、统一的服务入口
在集群内部通过docker service create xxx的命令创建服务之后,如果有设置对外暴露端口,那么可以向集群中任意一台 VPS 的指定端口请求服务。
手上的应用还是 Web 应用居多,而它们都需要 80 或 443 端口,为了让它们都能正常提供服务,集群需要一个统一的前端应用提供负载均衡服务,根据一定的规则(比如 域名)转发给后端应用。
虽然 nginx 也可以比较方便地实现负载均衡,但是我此处选用的是相对专业的、功能更完善的 traefik。traefik 提供服务自动发现、HTTPS 证书自动生成、服务监测指标数据 等功能,感兴趣的同学可以前往官网了解详情。
Traefik 还提供了简易的 Web UI,可以看到当前集群的服务数量和服务状态。
四、集群管理面板
虽然可以登录到 manager 节点,敲命令行管理集群节点、服务,但还是稍麻烦些,而且不太希望所有维护人员都有权限直接操作机器。
可以管理 Docker Swarm 集群管理面板也不少,能入法眼的就 Rancher 和 Portainer,然而由于 Rancher 对宿主机配置要求比较高,消耗资源较多,我最终选择了轻量级的 Portainer。
Portainer 官网提供了比较多的管理方式,踩了比较多的坑之后,我采用的是 agent + portainer 这种方式。以 global 模式在每个节点部署 agent 服务,portainer 部署时需要指定连接 agent 服务。欲知详情,请看官方文档。
Portainer 还提供了服务更新的 WebHook,我现在的博客和部分站点的代码仓库更新后,通过在 GitLab 设置的 CI-CD 配置,自动打包镜像,然后触发 WebHook 自动更新,省时省力。
当然,Portainer 也是有不完善的地方,比如查看集群服务时,会偶尔出现「无法连接」的报错,而且不能连接数据库,所以部署 Portainer 服务时,要限制它固定在某台宿主机上。不然,会出现频繁设置密码等现象。
五、监控和告警系统
traefik 提供的管理面板是非常简单的,仅能查看一些基础数据,比如某个服务有多少后端,整体的服务状态。为了能够定制化监控集群中的服务,并且在需要的时候触发告警,让物理人介入进行维护,需要一个监控和告警系统。
而 Grafana 恰好可以满足需求,配合 Prometheus 以及 Prometheus 相关的 Exporter,一个五脏俱全的监控告警系统呼之欲出。
因为腾讯 云主机的带宽极小、性能又比较一般,提供对外服务不太合适,为了充分利用资源,我便把监控和告警系统相关的大多服务都部署在上面。本来还想搞一个 ES 在腾讯上,无奈配置太低,只好作罢。
有了监控面板,可以清楚地知道具体服务的服务状态和服务数据规律,下图中的柱状图表示了以 5 分钟为统计周期的「每秒处理请求数」。注:该面板的标题Total requests over容易产生误解。
下图是站点升级结束时,Redis 的服务数据。一般情况下,Clients 会在 10 以下,当 Clients 飙升到 50 以上,就要额外关注站点的服务状态。通过合理设置阈值,可以让 Grafana 在超过阈值时发送告警通知,提醒维护人员对服务进行扩容等操作。
原有服务都是单机部署,需要改造并打包 Docker 镜像。改造难点其实在于持久化数据的存储与读写,比如 Web 应用的 Session 存储、图片存储、附件存储等。
对于 Session 存储,可以搭建中心化的数据中心解决,或者是改用 token 方式进行登录验证。对于图片存储、附件存储,我的改造方案是,将全量数据存放在 BackBlaze 云存储中,每个应用按需从云存储中心拉取数据,并定期删除冷门数据。小伙伴们要想获得更多docker集群化的内容,请关注新网!