译者按: 实践中会发现,生产环境中使用单个Docker节点是远远不够的,搭建Docker集群势在必行。然而,面对Kubernetes, Mesos以及Swarm等众多容器集群系统,我们该如何选择呢?它们之中,Swarm是Docker原生的,同时也是最简单,最易学,最节省资源的,至少值得我们多了解一下。本文将介绍一些非常实用的建议。

原文: Tips for using Docker Swarm mode in production

译者: Fundebug

为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习

如果你在单个生产节点上用过Docker,然后发现单个节点的资源不够用,那么你会怎么做呢?我也遇到过这种情况! 关于在生产环境中使用Docker Swarm,我会为你提供一些建议,也许能够帮到你。这些都是我一年来积累的一些经验。

另外,如果你对Docker Swam不熟悉的话,可以参考我之前的博客My experience with Docker Swarm - when you may need it?

1. 阅读官方文档

我并不打算重复官方文档。尽管文档非常短,但是通过它可以了解Swarm的基本知识。另外,我也不会写如何搭建Swarm集群,这方面的资料太多了,你可以查看 Digital Ocean或者自己谷歌。PS: 我是使用Ansible搭建Swarm集群的。

2. Docker Swarm要点

Swarm的负载非常低。据我观察,Swarm进行调度和通信的CPU负载非常低。因此,Swarm的管理节点(Manager)可以同时作为工作节点(Worker)。如果你需要搭建一个非常大的集群(1000+ 节点),管理节点需要更多资源,但是对于中小型集群来说,管理节点需要的资源可以忽略不计。另外,这篇博客介绍了Swarm3k(一个4700节点的Swarm集群的实验),不妨了解一下。

Swarm集群的网络通信(服务发现,负载均衡以及容器间通信)非常可靠。当你开启一个服务的端口之后,在Swarm集群中的任何一个节点都可以访问它。负载均衡也是由Swarm提供的。后文会提到一些之前遇到的问题,但是Docker 1.13之后,这些问题都解决了。

使用Swarm只需要掌握少量命令。下面是我每天需要用到的所有命令:

# 创建服务
docker service create \
--image nginx \
--replicas 2 \
nginx # 更新服务
docker service update \
--image nginx:alpine \
nginx # 删除服务
docker service rm nginx # 减少服务实例(这比直接删除服务要好)
docker service scale nginx=0 # 增加服务实例
docker service scale nginx=5 # 查看所有服务
docker service ls # 查看服务的容器状态
docker service ps nginx # 查看服务的详细信息。
docker service inspect nginx

  

实现零宕机部署也非常简单。这样也可以方便地实现持续部署:

# 构建新镜像
docker build -t hub.docker.com/image . # 将新镜像上传到Docker仓库
docker push hub.docker.com/image # 更新服务的镜像
docker service update --image hub.docker.com/image service

  

更新服务要慎重。 你的容器同时运行在多个主机上。更新服务时,只需要更新Docker镜像。合理的测试和部署流程是保证成功的关键。Swarm非常容易入门。分布式系统通常是非常复杂的。与其他容器集群系统(Mesos, Kubernetes)相比,Swarm的学习曲线最低。在没有任何Swarm知识的情况下,我只花了一周时间,就把服务从单个Docker主机迁移到20个节点的Docker集群上。

3. 决定哪些容器部署在Swarm集群

并非所有服务都应该部署在Swarm集群内。数据库以及其他有状态服务就不适合部署在Swarm集群内。理论上,你可以通过使用labels将容器部署到特定节点上,但是这样的话,Swarm集群外的节点就很难访问它们了(Docker 1.12没有很好的方法,但是1.13之后可以使用attachable network)。如果你允许集群外的节点访问数据库,则所有节点都可以访问它,这显然不符合你的需求。另外,Docker Swarm的跨节点数据卷(cross-host mounted volumes)并不可靠,一个简单的文件上传都可能引起问题。

无状态的容器就非常适合部署在Swarm集群中,它们可以由环境变量进行配置(使用ENV指令)。建议为开源工具构建镜像,例如,可以将Nginx的配置文件放到Docker镜像中。

下面是我部署在Swarm集群中的服务:

  • Django channels (网页应用)
  • Nginx(代理)
  • Celery(周期性任务)
  • Sensu(监控)

下面是我部署在Swarm集群之外的容器:

  • Postgres(数据库)
  • Redis(缓存)

由于一个获取真正IP的问题,我很可能会将Nginx运行在Swarm集群之外,或者采用host模式。

4. 配置Docker仓库

Docker仓库,你值得拥有!你可以自己搭建一个,或者使用Docker仓库服务,比如DockerHub或者GitLab Container Registry。不要在服务器上直接构建Docker镜像,因为你有多个节点(在每个节点上构建镜像非常麻烦),而且在创建服务的时候你需要指定镜像(这个镜像所有节点都应该可以下载)。如果你配置了私有Docker仓库,则需要指定--with-registry-auth,否则这些节点将无法下载镜像。

另外,你应该为Docker镜像设置版本,这样更加易于回滚。

5. 将半无状态的服务变得完全无状态

所谓半无状态服务,就是容器需要依赖一些不太重要的外部文件。你可以使用数据卷(volume),但是更好的选择是使用S3或者其他云存储服务。记住,想要获得扩展性,云是最好的选择。

例如,我不得不构建Nginx镜像,将配置文件放到镜像中。使用数据卷挂载Nginx配置文件不是很方便。

6. 配置日志收集服务

使用分布式系统时,集中管理日志是非常必要的。我们有很多方案,包括开源工具或者SaaS服务,比如ELK,Grafana, Graylog…自己搭建完整的系统是非常复杂的,所以我建议搭建先使用SaaS服务(比如LogglyLogentries),当费用太高时,则自己搭建一个系统。ELK可以这样配置:

docker service update \
--log-driver gelf \
--log-opt gelf-address=udp://monitoring.example.com:12201 \
--log-opt tag=example-tag \
example-service

attachable network是一个非常重要的特性。你最好使用它,否则docker run创建的容器将无法接入Swarm集群的网络。这是Docker 1.13之后的版本才有的功能,也许你需要升级。

7. 创建attachable network

创建attachable network的命令如下:

docker network create --driver=overlay --attachable core

如果你按照How to write excellent Dockerfiles构建Docker镜像,你很可能会使用环境变量去配置很多东西。如果你这样做的话,则迁移到Swarm集群时问题会少很多。示例命令如下:

8. 先使用环境变量,再考虑Secrets API

# 创建服务时指定环境变量
docker service create \
--env VAR=VALUE \
--env-file FILENAME \
... # 增加、删除环境变量
docker service update \
--env-add VAR=NEW_VALUE \
--env-rm VAR \
..

  

9. 设置合理的服务容器个数以及并行更新的容器个数

下一步是使用Secrets API

简单地说,你可以将私密数据(比如密码,SSL证书等)以文件的形式挂载到容器中。虽然我还没有用过Secrets API,但是我觉得值得尝试一下。

一方面,你需要保证足够多的容器数来处理负载以及作为灾备,另一方面,太多的容器会导致CPU和内存资源不足。因此,你需要配置合理的服务容器个数,也就是说,某个服务,需要运行合理个数的容器。

另外,默认的update-parallelism 值是1,这就意味着更新服务时,每次只更新1个容器。通常,这个值太小了。我的建议是将它设为 服务容器数 / 2.。

相关命令

# 将同时更新的容器数设为10
docker service update \
--update-parallelism 10 \
webapp # 同时增加多个服务的容器数
docker service scale redis=1 nginx=4 webapp=20 # 查看服务状态
docker service ls # 查看服务的详情(排除关闭的容器)
docker service ps webapp | grep -v "Shutdown"

最佳方式是使用Docker Compose v3 语法,这样可以将服务的所有配置选项代码化。我将 docker-compose.yml用于开发环境, docker-compose.prod.yml用于生产环境。使用docker-compose文件部署服务的话,需要使用 docker stack deploy 命令(参考docker stack

10. 将Swarm配置代码化

docker-compose文件示例

# docker-compose.prod.yml
version: '3'
services:
webapp:
image: registry.example.com/webapp
networks:
- ingress
deploy:
replicas: ${WEBAPP_REPLICAS}
mode: replicated
restart_policy:
condition: on-failure proxy:
image: registry.example.com/webapp-nginx-proxy
networks:
- ingress
ports:
- 80:80
- 443:443
deploy:
replicas: ${NGINX_REPLICAS}
mode: replicated
restart_policy:
condition: on-failure networks:
ingress:
external: true

部署命令:

export NGINX_REPLICAS=2 WEBAPP_REPLICAS=5

docker login registry.example.com
docker stack deploy \
-c docker-compose.prod.yml\
--with-registry-auth \
frontend

  

另外,docker-compse文件支持环境变量(${VARIABLE}),这样你可以动态地调整配置。

11. 设置资源限制

根据我的经验,你需要限制所有服务的CPU使用。这样可以防止单个容器占用主机的所有的CPU资源。

reserve-cpu 选项也非常有用。当我希望平均地将所有容器部署到各个主机时,我会使用reserve-cpu ,它可以保证每个容器都有足够地资源。示例:

# 限制服务占用的CPU资源
docker service update
--limit-cpu 0.25
--reserve-cpu 0.1
webapp

我遇到过Swarm网络方面的问题。有时候所有的请求都被转发到某一个容器,然而还有9个其他容器正在运行。这时,可以尝试减少/增加实例个数,或者改变路由类型(使用--endpoint-mode选项)

13. 监控网络连接

如果没有监控日志的话,这样的问题很难被发现。因此,搭建监控系统是非常必要的。

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。
自从2016年双十一正式上线,Fundebug累计处理了6亿+错误事件,得到了Google、360、金山软件等众多知名用户的认可。欢迎免费试用!

版权声明:

转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/05/08/docker-swarm-suggestion/

生产环境中使用Docker Swarm的一些建议的更多相关文章

  1. 生产环境中使用docker注意点

    是否对容器使用的资源进行合理限制,比如内存 CPU 网络带宽等. 是否设置合理的网络访问限制,如 非root用户 iptables. 是否有在docker无法使用时的备选方案,如提供非docker环境 ...

  2. Kubernetes 在生产环境中常用架构

    Kubernetes 在生产环境中常用架构 首先,我们来梳理下Kubernetes生产架构,其设计适用于绝大多数环境.如下图所示 在该架构中,我们可以将其分为四层,如下: Client层:即Kuber ...

  3. 理解Docker(6):若干企业生产环境中的容器网络方案

    本系列文章将介绍 Docker的相关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...

  4. 在生产环境中使用Compose 【翻译】

    在生产环境中使用Compose 在开发环境中使用Compose定义你的应用,可以使用此定义在不同的环境,(如 CI.暂存和生产)中运行应用程序. 部署应用程序的最简单方法是在单个服务器上运行该应用程序 ...

  5. Kubernetes用户指南(三)--在生产环境中使用Pod来工作、管理部署

    一.在生产环境中使用Pod来工作 本节将介绍一些在生产环境中运行应用非常有用的功能. 1.持久化存储 容器的文件系统只有当容器正常运行时有效,一旦容器奔溃或者重启,所有对文件系统的修改将会丢失,从一个 ...

  6. .NET跨平台之旅:在生产环境中上线第一个运行于Linux上的ASP.NET Core站点

    2016年7月10日,我们在生产环境中上线了第一个运行于Linux上的ASP.NET Core站点,这是一个简单的提供后端服务的ASP.NET Core Web API站点. 项目是在Windows上 ...

  7. .NET跨平台之旅:生产环境中第2个跑在Linux上的ASP.NET Core站点

    今天我们在生产环境中上线了第2个跑在Linux上的ASP.NET Core站点.这是一个简单的Web API站点,通过命令行的方式调用安装在Linux服务器上的程序完成操作.之前用的是nodejs,现 ...

  8. 【原】Storm Local模式和生产环境中Topology运行配置

    Storm入门教程 1. Storm基础 Storm Storm主要特点 Storm基本概念 Storm调度器 Storm配置 Guaranteeing Message Processing(消息处理 ...

  9. 生产环境中CentOS7部署NET Core应用程序

    NET Core应用程序部署至生产环境中(CentOS7) 阅读目录 环境说明 准备你的ASP.NET Core应用程序 安装CentOS7 安装.NET Core SDK for CentOS7. ...

随机推荐

  1. YII contoller控制器之间跳转的方法redirect

    一个contoller CustomerController里怎么调用另一个controller里的action,Acontoller调用SiteContoller的actionShow($id), ...

  2. dos中进入其他盘中的方法

    1.在dos中进入其他盘中直接-->e: 即可,若是进入文件夹中-->cd aaa\bbb 即可. 2.返回上级目录:-->cd..

  3. Docx组件读写Word文档介绍

    Docx介绍 官方原文:DocX is a .NET library that allows developers to manipulate Word 2007/2010/2013 files, i ...

  4. 开源 & 在线免费使用:升讯威 周报系统

    这个周报系统大约写于2015年,缘起当时所带的开发团队需要逐步建立或完善一些项目管理方法. 在调研了网上的诸多项目管理或周报/日报管理系统之后,并没有找到符合当时情况的系统,这里最大的问题不是网上既有 ...

  5. MyBatis使用statementType="STATEMENT"

    statementType="STATEMENT"是使用非预编译,现在我需要动态传人表名和字段名,所以需要用STATEMENT,使用之后所有变量取值都要改成${xxxx},而不是# ...

  6. 实现标签的添加与删除(tags)

    在项目中会遇到,标签(tags)的添加与去除的需求 demo:我们有 tags   '专利','商标','版权','域名' demand:在发布内容的时候,要求可以添加tag,(实现tag的增加与删除 ...

  7. Java ---理解MVC架构

    之间的文章,我们主要是介绍了jsp的相关语法操作,我们可以通过请求某个jsp页面,然后由相对应的servlet实例给我们返回html页面.但是在实际的项目中,我们很少会直接的请求某个页面,一般都是请求 ...

  8. JavaScript基础学习(八)—事件

    一.鼠标移动事件      onmouseover: 鼠标移到了上面.      onmousemove: 鼠标移动了.      onmouseout: 鼠标移走了. window.onload = ...

  9. Windows入门基础:1.关于CreateWindow()函数使用中遇到的问题

    我在实现显示窗口的程序中,遇到一个问题:首先程序没有任何语法错误,编译能够通过,但是就是不能弹出窗口. 后来在MSDN中查询CreateWindow()函数,发现了下面这句话: "If lp ...

  10. 对quartz定时任务的初步认识

    已经好久没有写技术博文了,今天就谈一谈我前两天自学的quartz定时任务吧,我对quartz定时任务的理解,就是可以设定一个时间,然后呢,在这个时间到的时候,去执行业务逻辑,这是我的简单理解,接下来看 ...