一, Docker 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 集群之外的容器:
- MySQL(数据库)
- Redis(缓存)
由于一个获取真正 IP 的问题 https://github.com/moby/moby/issues/25526 , 我很可能会将 Nginx 运行在 Swarm 集群之外, 或者采用 host 模式.
二, 设置资源限制
就经验而言, 可以为所有服务设置 CPU 使用限制. 当某一个容器应用占用掉所有主机资源时, 此限制可以避免这种情况发生.
当想把所有容器均匀地发布在所有主机上或是想确保有足够的资源来响应操作时, 需使用 Reserve-CPU 这个参数.
例如:
- # 限制服务占用的 CPU 资源
- docker service update
- --limit-CPU 0.25
- --reserve-CPU 0.1
- webapp
三, 将半无状态的服务变得完全无状态
所谓半无状态服务, 就是容器需要依赖一些不太重要的外部文件. 你可以使用数据卷(volume), 但是更好的选择是使用 S3 或者其他云存储服务.
记住, 想要获得扩展性, 云是最好的选择.
例如, 我不得不构建 Nginx 镜像, 将配置文件放到镜像中. 使用数据卷挂载 Nginx 配置文件不是很方便.
四, 创建可附加的网络
network 是一个非常重要的特性. 你最好使用它, 否则 docker run 创建的容器将无法接入 Swarm 集群的网络, 特别是跨宿主机通讯时.
这是 Docker 1.13 之后的版本才有的功能, 也许你需要升级.
创建 network 的命令如下:
docker network create --driver=overlay --attachable core
五, 增加环境变量
如果创建 Docker 镜像的时候, 遵循了最佳实践原则(), 允许在运行的时候通过环境变量设置一切配置项, 那么把应用迁到 Swarm 的过程完全没有问题.
相关命令:
- # 创建服务时指定环境变量
- docker service create \
- --env VAR=VALUE --env-file FILENAME ...
- # 增加, 删除环境变量
- docker service update \
- --env-add VAR=NEW_VALUE --env-rm VAR ..
六, 设置适当实例和批量更新
保持适当数量的实例, 以应对高流量和实例或者节点不可用的情况. 同时太多的实例数也会占用 CPU 和内存, 并且导致争抢 CUP 资源.
update-parallelism 的默认值是 1, 默认只有一个实例在运行. 但这个更新速度太慢了, 建议是 replicas / 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"
七, 把 Swarm 配置保存为代码
最好使用 Docker Compose v3 版本的语法().
他允许使用代码指定几乎所有的服务选项. 作者在开发的时候使用 Docker-compose.YAML, 在生产环境 (swarm) 配置使用 Docker-compose.prod.YAML . 部署 Docker-compose 文件中所描述的服务, 需要 Docker stack deploy 命令(属于新版本 Stack 命令集合中的一部分[)
Docker compose v3 例子:
- 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.YAML --with-registry-auth frontend
提示: Docker-compose 文件支持环境变量 (${VARIABLE}), 所以, 可以动态调整配置作为测试等.
八, 配置日志收集服务
使用分布式系统时, 集中管理日志是非常必要的. 我们有很多方案, 包括开源工具或者 SaaS 服务, 比如 ELK,Grafana, Graylog... 自己搭建完整的系统是非常复杂的, 所以我建议搭建先使用 SaaS 服务(比如 Loggly https://loggly.com/ , Logentries https://logentries.com/ ), 当费用太高时, 则自己搭建一个系统. ELK 可以这样配置:
- docker service update \
- --log-driver gelf --log-opt gelf-address=udp://monitoring.example.com:12201 --log-opt tag=example-tag example-service
参考: https://www.cnblogs.com/fundebug/p/6823897.html
Docker Swarm(十一)生产环境使用的一些建议
来源: http://www.bubuko.com/infodetail-3452376.html