译者按: 实践中会发现,生产环境中使用单个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服务(比如Loggly, Logentries),当费用太高时,则自己搭建一个系统。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. Mobiscroll日期插件使用

    相关资源 官方帮助文档:https://docs.mobiscroll.com/3-0-1 导入资源文件 <link href="${webRoot}/template/green/w ...

  2. java学习笔记 --- 面向对象3

    一.创建对象是做了些什么事情? 图解: 二.static关键字 (1)静态的意思.可以修饰成员变量和成员方法. (2)静态的特点: 1.静态是随着类的加载就加载了.也是随着类的消失而消失了. 2.静态 ...

  3. Memcached十问十答

    1.Memcached是什么,有什么作用? Memcached是一种纯内存的,key-value,CS架构的数据库服务软件,主要用于数据库,web服务器的缓存,以减小数据库,web服务器的访问压力,尤 ...

  4. Windows:将cmd命令行添加到右键中方法

    win10中将命令行cmd添加到右键的方法 Windows cmd 右键 win10 命令行 最近在学python,所以会用到很多库文件,但是有的库文件需要下载whl文件再通过cmd进行安装,所以每次 ...

  5. TensorFlow安装-windows系统

    官方各版本的安装说明:https://www.tensorflow.org/install/ 本文介绍如何在windows环境下安装tensorflow, 跑起来简单的demo. 1.安装python ...

  6. CoreCLR源码探索(五) GC内存收集器的内部实现 调试篇

    在上一篇中我分析了CoreCLR中GC的内部处理, 在这一篇我将使用LLDB实际跟踪CoreCLR中GC,关于如何使用LLDB调试CoreCLR的介绍可以看: 微软官方的文档,地址 我在第3篇中的介绍 ...

  7. JDBC与ArrayList和hashmao

    JDBC帮助类 package work; import java.beans.Statement;import java.sql.Connection;import java.sql.DriverM ...

  8. Unity3D动态读取外部MP3文件给AudioSource

    在PC端VR游戏开发中,需要动态加载本地的MP3文件,但是Unity3D不知道出于什么原因,到5.4.0也不支持MP3文件的外部加载(目前只支持wav和ogg). 因此要想通过www来加载mp3文件就 ...

  9. 老李推荐:第3章3节《MonkeyRunner源码剖析》脚本编写示例: MonkeyImage API使用示例 1

    老李推荐:第3章3节<MonkeyRunner源码剖析>脚本编写示例: MonkeyImage API使用示例   在上一节的第一个“增加日记”的示例中,我们并没有看到日记是否真的增加成功 ...

  10. 云计算之路-阿里云上:RDS数据库连接数过万引发故障,主备库切换后恢复正常

    非常抱歉!今天 12:03-12:52 ,由于数据库连接数异常突增超过1万,达到了阿里云RDS的最大连接数限制,影响了全站的正常访问.由此给您带来麻烦,请您谅解. 在发现数据库连接数突增的问题后,我们 ...