前言

这篇文章介绍Docker生态中的常被提到的Engine、Machine和Swarm,大家以了解为主,工作需要再深入。

Engine

Docker Engine其实就是我们常说的「Docker」,它是一个C/S模型(Client/Server)的应用,包含如下组件:

  • Daemon。守护进程,属于C/S中的Server( dockerd)

  • REST API。Daemon向外暴露的REST 接口

  • CLI。向外暴露的命令行接口(Command Line API: docker)

客户端访问服务端的方式有三种:

  • 使用命令行工具,如 docker run、 docker ps等等

  • 直接通过调用REST API,如发送一个 curl请求

  • 通过脚本直接和Daemon交互

用户通过Docker CLI向Docker Daemon发送REST API请求。Daemon创建和管理Docker objects(对象),如:

  • images。镜像

  • containers。容器

  • networks。网络

  • volumes。数据卷

Machine

在没有Machine之前,Docker的安装流程非常复杂,首先需要登录到相应的主机上,根据官方的安装和配置指南来安装Docker,而且不同的操作系统的安装步骤也不同。

Machine是一个简化Docker Engine安装和管理的命令行工具,这样通过一个简单的命令即可在相应的平台上安装Docker,如本地(macOS、Linux和Windows)、虚拟化平台(VirtualBox、macOS xhyve等),公有云(AWS、Azure、Digital Ocean等)等。使用Machine可以启动、审查、停止和重新启动托管的宿主机、升级 Docker 客户端和守护程序、并配置 Docker 客户端与宿主机通信。

通过图示可以看出来,Machine是管理本地/远程带有Docker Engine的主机的工具, docker-machine create创建的「machine」包含了Daemon和REST API这2部分,Machine自己包含CLI。

我大概演示一下使用Machine的方法:

  • 创建machine。 docker-machine create--driver virtualboxdefault,这就会可以创建一个叫做 default的「机器」,它是Virtualbox类型的,所以可以在Virtualbox管理器里面看到这个虚拟机。

  • 连接到machine。 eval"$(docker-machine env default)",其实就是做了对应的环境变量设置

  • 使用Docker CLI。之后就可以使用 docker ps等命令查看和管理这个主机里面的镜像/容器等内容了

Swarm Mode

Docker Swarm是Docker 官方的集群管理和编排工具,可以将多个Docker主机封装为单个大型的虚拟Docker主机,成为一个容器平台。从 Docker1.12.0+开始 SwarmMode已经内嵌入 Docker Engine,成为子命令 docker swarm可以直接使用。

SwarmMode主要特性如下:

  • 具有容错能力的去中心化设计

  • 服务发现。可以做到Docker集群中节点的动态加入和退出的感知,支持主流的etcd、consul和zookeeper。

  • 负载均衡。让资源分配负载,以达到最优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载。

  • 动态伸缩。服务在判断监测指标超出所设定的上下限时,会按照你的设置触发扩容或缩容。

  • 滚动更新(Rolling updates)。可以实现「零停机时间部署」,下节我们还会再说。

  • 安全传输。集群中的每个节点都执行TLS的相互认证和加密,以确保自己与所有其他节点之间的通信安全。

  • 确保期望状态。Swarm会在后台进行轮训检查,确保实际状态能够满足期望状态的要求。

Swarm 是使用SwarmKit构建的 Docker 引擎内置(原生)的集群管理和编排工具。它包含如下三个重要概念: 节点、服务和任务,我们挨个看。

节点(Node)

运行 Docker 的主机可以主动初始化一个 Swarm 集群或者加入一个已存在的 Swarm 集群,这样这个运行 Docker 的主机就成为一个 Swarm 集群的节点。节点分为管理 (manager) 节点和工作 (worker) 节点。

管理节点用于 Swarm 集群的管理,管理节点分发工作单元(称为Task「任务」)到工作节点。docker swarm 命令基本只能在管理节点执行(节点退出集群命令 docker swarm leave 可以在工作节点执行)。一个 Swarm 集群可以有多个管理节点,但只有一个管理节点可以成为领导(leader, 通过Raft协议实现)。管理节点还要通过leader执行维护集群所需状态所需的编排和集群管理任务。

工作节点接收并执行从管理节点分派的任务。默认情况下,管理器节点也作为工作节点运行服务(Service),但是你可以将它们配置为专门运行管理器任务,并且只运行管理器节点。代理在每个工作节点上运行,并报告分配给它的任务。工作节点通知管理节点其分配任务的当前状态,以便管理器可以维护每个工作的所需状态。

任务(Task)

任务是Swarm中的最小的调度单位,任务携带Docker容器和在容器中运行的命令。管理节点根据服务中设置的副本(Replicas)数量将任务分配给工作节点。一旦任务被分配给一个节点,它就不能移动到另一个节点。它只能在指定的节点上运行或失败

任务是这么调度的:

服务(Service)

服务是指一组任务的集合,它定义了任务的属性,是Swarm系统的中心结构:

服务有两种模式:

  • Replicated services。按照一定规则在各个工作节点上运行指定个数的任务

  • Global services。每个可用节点上运行一个任务

PS: 两种模式通过 docker service create--mode参数指定。

基本用法

我们创建一个最小的 Swarm 集群,包含一个管理节点和两个工作节点。创建Docker 主机使用Docker Machine:

# 管理节点

❯ docker-machine create -d virtualbox manager # 创建管理节点,名字为manager

❯ docker-machine ssh manager # 登录到管理节点

docker@manager:~$ /sbin/ifconfig eth1 | grep 'inet addr' | cut -d: -f2 | awk '{print $1}'

192.168.99.104 # 获得IP

docker@manager:~$ docker swarm init --advertise-addr 192.168.99.104 # 在管理节点初始化一个Swarm集群,另外Docker主机有多个网卡,所以有多个IP,必须使用 --advertise-addr 指定IP

Swarm initialized: current node (k8cdrnrylrkxpsk4qoyybwpca) is now a manager.

To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-2gfzia6yrk172e8352jxpolevjr9gx1a9xu95hg0ibkhqat52p-d6j79273adew38s5mzmewgwoo 192.168.99.104:2377 # 记住这句命令

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

❯ docker-machine create -d virtualbox worker1 # 创建工作节点,名字worker1

❯ docker-machine ssh worker1

docker@worker1:~$ docker swarm join --token SWMTKN-1-2gfzia6yrk172e8352jxpolevjr9gx1a9xu95hg0ibkhqat52p-d6j79273adew38s5mzmewgwoo 192.168.99.104:2377 # 从上面直接粘贴来

This node joined a swarm as a worker.

❯ docker-machine create -d virtualbox worker2 # 创建工作节点,名字worker2

❯ docker-machine ssh worker2

docker@worker2:~$ docker swarm join --token SWMTKN-1-2gfzia6yrk172e8352jxpolevjr9gx1a9xu95hg0ibkhqat52p-d6j79273adew38s5mzmewgwoo 192.168.99.104:2377

This node joined a swarm as a worker.

这样集群就做好了,在管理节点看一下状态:

❯ docker-machine ssh manager

docker@manager:~$ docker node ls

ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION

k8cdrnrylrkxpsk4qoyybwpca * manager Ready Active Leader 18.09.9

puzrum9ixbt6holgfk5d8aokl worker1 Ready Active 18.09.9

sqwpb00zh5fp9z2o6r7vnebbt worker2 Ready Active 18.09.9

然后部署Nginx(只能在管理节点运行):

docker@manager:~$ docker service create --replicas 3 -p 80:80 --name nginx nginx:1.17.4-alpine # 创建服务,三个副本,服务监听在80端口

pydkv5ffwfqiv1aua1ylmwhum

overall progress: 3 out of 3 tasks

1/3: running [==================================================>]

2/3: running [==================================================>]

3/3: running [==================================================>]

verify: Service converged

docker@manager:~$ docker service ls # 查看当前Swarm集群运行的服务

ID NAME MODE REPLICAS IMAGE PORTS

pydkv5ffwfqi nginx replicated 3/3 nginx:1.17.4-alpine *:80->80/tcp

# 现在我们使用浏览器,输入任意节点IP(如管理节点的192.168.99.104),都能看到nginx默认页面

docker@manager:~$ docker service logs nginx # 查看Nginx服务的日志

... # 省略输出

docker@manager:~$ docker service scale nginx=5 # 业务高峰期时,扩展服务运行的容器数量

nginx scaled to 5

overall progress: 5 out of 5 tasks

1/5: running [==================================================>]

2/5: running [==================================================>]

3/5: running [==================================================>]

4/5: running [==================================================>]

5/5: running [==================================================>]

verify: Service converged

docker@manager:~$ docker service ps nginx # 查看服务详情

i6xkgnneqbbq nginx.1 nginx:1.17.4-alpine worker2 Running Running 4 minutes ago

f517ogp705ne nginx.2 nginx:1.17.4-alpine manager Running Running 5 minutes ago

... # 省略输出

docker@manager:~$ docker service scale nginx=2 # 业务平稳期时,减少服务运行的容器数量

在Swarm集群中使用Compose文件

在第一篇中我使用 docker-compose.yml一次配置、启动多个容器,在Swarm集群中也可以使用compose文件来配置、启动多个服务。在上一小节中,使用 docker service create一次只能部署一个服务(Nginx),使用 docker-compose.yml可以一次启动多个关联的服务。还是拿lyanna项目的docker-compose.yml体验一下,不过需要修改配置项,添加deploy(如mode和副本数等项),也要去掉一些stack不支持的项(如build、restart等):

version: '3'

services:

db:

image: mysql

environment:

MYSQL_DATABASE: 'test'

MYSQL_USER: 'root'

MYSQL_PASSWORD: ''

MYSQL_ROOT_PASSWORD: ''

MYSQL_ALLOW_EMPTY_PASSWORD: 'true'

volumes:

- my-datavolume:/var/lib/mysql

deploy:

placement:

constraints: [node.role == manager]

redis:

image: redis:alpine

deploy:

mode: replicated

replicas: 3

memcached:

image: memcached:1.5-alpine

deploy:

mode: replicated

replicas: 3

web:

image: 127.0.0.1:5000/lyanna-app

build: .

ports:

- '8000:8000'

volumes:

- .:/app

- ./local_settings.py.tmpl:/app/local_settings.py

depends_on:

- db

- redis

- memcached

environment:

PYTHONPATH: $PYTHONPATH:/usr/local/src/aiomcache:/usr/local/src/tortoise:/usr/local/src/arq:/usr/local/src

command: sh -c './setup.sh && python app.py'

visualizer:

image: dockersamples/visualizer:stable

ports:

- "8080:8080"

stop_grace_period: 1m30s

volumes:

- "/var/run/docker.sock:/var/run/docker.sock"

deploy:

placement:

constraints: [node.role == manager]

volumes:

my-datavolume:

其中有3个需要着重说明的点:

  • visualizer服务提供一个可视化页面,可以从浏览器中很直观的查看集群中各个服务的运行节点,一会会感受到

  • db/redis/memcached/visualizer这几项都添加了deploy项, mode指服务模式, replicas指副本数, placement可以限定满足条件的Node,而避免在不合适的Node进行部署,这里限制db/visualizer都要在管理节点上

  • web加了image项,是一个注册服务的API地址,下面会看到如何注册和推送镜像上去

接着部署:

❯ eval "$(docker-machine env manager)" # 本机切换到管理主机

❯ git clone https://github.com/dongweiming/lyanna # 下载lyanna项目源码,如果原来已经clone了不用再做

❯ cd lyanna

❯ docker service create --name registry --publish published=5000,target=5000 registry:2 # 创建注册服务(名字叫registry),启动在5000端口上

❯ docker-compose -f docker-compose.swarm.yml build # 用Compose的方式启动,这个过程会构建lyanna-app镜像

❯ docker-compose -f docker-compose.swarm.yml push # 把lyanna-app推送给本地的注册服务

❯ docker stack deploy -c docker-compose.swarm.yml lyanna # 部署服务

Ignoring unsupported options: build

Creating network lyanna_default

Creating service lyanna_web

Creating service lyanna_visualizer

Creating service lyanna_db

Creating service lyanna_redis

Creating service lyanna_memcached

现在在浏览器输入 任一节点IP:8080 即可看到各节点运行状态,类似如下效果:

可以看到:

  • db、visualizer限定在管理节点manager

  • redis/memcached由于副本数和节点数一致,所以每个节点都有一个

  • web和registry由于负载平衡的作用分配到了2个工作节点上,让服务整体看起来比较均衡

在浏览器新的标签页输入 任一节点IP:8000 即可看到lyanna博客效果!

延伸阅读

  1. https://docs.docker.com/engine/docker-overview/

  2. https://www.docker.com/products/container-runtime

  3. https://docs.docker.com/machine/

  4. https://docs.docker.com/engine/swarm/key-concepts/

  5. https://docs.docker.com/engine/swarm/how-swarm-mode-works/services/

  6. https://docs.docker.com/engine/swarm/stack-deploy/

re.containerbase.startinternal 子容器启动失败_Python项目容器化实践(二) Docker Machine和Docker Swarm...相关推荐

  1. re.containerbase.startinternal 子容器启动失败_微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计(微服务架构实施原理)...

    走过路过不要错过 点击蓝字关注我们 基于微服务架构和Docker容器技术的PaaS云平台建设目标是给我们的开发人员提供一套服务快速开发.部署.运维管理.持续开发持续集成的流程.平台提供基础设施.中间件 ...

  2. Tomcat启动报错子容器启动失败

    在复习JavaWeb时,想让自己的工作空间变得干净一点,于是清理了Tomcat安装目录webapps中以前留下来的web项目,在双击bin目录下的start.bat文件时CMD窗口一闪而过,顿时觉得奇 ...

  3. tomcat启动子容器启动失败tomcat org.apache.catalina.LifecycleException异常的解决办法

    博主最近写一个web项目将jar包加载到了libraries下面持续报错 子容器启动失败tomcat org.apache.catalina.LifecycleException 最终将jar包加入到 ...

  4. Mysql容器启动失败-解决方案

    Mysql容器启动失败-解决方案 参考文章: (1)Mysql容器启动失败-解决方案 (2)https://www.cnblogs.com/mjiu/p/10040661.html 备忘一下.

  5. 容器启动失败 ERROR: for log Cannot start service log: OCI runtime create failed: container_linux.go:346

    完整错误信息: ERROR: for log Cannot start service log: OCI runtime create failed: container_linux.go:346: ...

  6. Servlet实例化异常以及tomcat子级启动失败的可能原因

    Servlet实例化异常 1.可能是jar没有放在Web-INF下面的lib目录里面以及lib包名写错了 首先是检查对应的jar包是否部署在WEB-INF的lib目录下面,如果没有需要按照要求部署 如 ...

  7. docker容器启动失败(Error response from daemon: error creating overlay mount to /app/docker/overlay2/)

    docker容器启动失败 问题描述 服务器断电,异常关机,重启后,发现无法正常启动docker容器,提示错误: $ docker start mysql-server Error response f ...

  8. docker mysql容器启动不_Mysql容器启动失败-解决方案

    在看问题之前首先熟悉几个命令 相关命令 1.docker attach 连接到正在运行中的容器: 命令:docker attach --sig-proxy=falsemynginx 2.docker ...

  9. docker容器启动失败:Error response from daemon: Container xxx is not running

    启动容器: Error response from daemon: Container 0a1dfb5472726f79056202e9d140b6c28189d326fb595a539f7cc151 ...

最新文章

  1. 可恶的.NET FRAME,将一切变得更简单,还是更复杂?
  2. java xml 实体类_XML和JAVA实体类的相互转化(微信例子)
  3. Please set spring.main.web-application-type=reactive or remove spring-boot-starter-web dependency
  4. 40 行代码搞定主题词提取
  5. 返回一个循环数组中最大子数组的和
  6. python字典购物车实现的功能_python购物车功能实现
  7. python3 读写json文件,python3没有读取JSON文件righ
  8. matlab练习程序(Prim最小生成树)
  9. mysql安装手册(2)
  10. 使用flask开发web应用
  11. 算法第四版 高清完整中文版(非纸质版)
  12. kvaser在linux下的二次开发
  13. 自适应求积算法 MatLab版
  14. 360wifi使用方法|360wifi使用教程
  15. 澳洲学计算机难毕业吗,澳洲新南威尔士大学计算机专业好吗
  16. step7设置pcpg_怎么安装STEP7编程软件及PG/PC接口设置
  17. 微信公众平台接口测试账号网址
  18. 竞态条件的赋值_信号-sunshine225-51CTO博客
  19. 一人之辩,重于九鼎之宝
  20. echarts图表中增加一条警戒线【平均值】

热门文章

  1. 企业是否应该实现对客户需求的快速响应_如何做好企业服务?
  2. Mat的初始化以及Mat与数组的相互转化
  3. Linux密码是一个回文,usermod命令和用户密码管理
  4. Wine下完美安装QQ 2010:
  5. mac php gd库,mac下安装GD库FreeType
  6. 基于PyMC的贝叶斯建模实战
  7. 产品认知:如何选择产品经理的产品方向?
  8. idea 运行单个main方法_IntelliJ IDEA 运行你的第一个Java应用程序 idea运行main方法
  9. Bash脚本教程之引号和转义
  10. 微信小程序实战–集阅读与电影于一体的小程序项目(八)