Docker入门(五):Swarms
这个《Docker入门系列》文档,是根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成。主要是作为个人学习记录。有错误的地方,Robin欢迎大家指正。分为如下几个部分:
1 Docker入门:简介
2 Docker入门:安装运行
3 Docker入门:容器(Containers)
4 Docker入门:服务(Services)
5 Docker入门:Swarms
6 Docker入门:Stacks
7 Docker入门:部署app
8 Docker入门:稍高级的话题
5.1 引言
在上一节,我们使用上上一节里写的app,通过将它转化为一个service,来定义该app在产品中的运行方式,并在进程中scale到5个副本。
在本节,我们将这个app部署到一个cluster上,使其在多个机器上运行。通过将多个机器加入到这个”Dockerized” cluster,我们实现了多容器、多机器环境中运行的应用程序。这个”Dockerized” cluster被称为swarm。
5.2 理解swarm集群
一个swarm是一组机器,这些机器上运行着Docker,并加入到一个集群中。经过这些配置后,你仍然像之前那样运行Docker命令,但不同的是,这些命令由swarm manager在集群上执行。这些机器可以是真实的机器,也可以是虚拟机。机器加入到一个swarm后,可以称这些机器为节点(node)。
Swarm manager可以使用多种策略来运行容器。比如策略”emptiest node”:在最少的机器上运行容器;比如策略”global”:确保每个机器之运行一个特定容器的实例。通过修改Compose文件,告诉swarm manager使用哪些策略。
在一个swarm里,只有swarm manager能够执行Docker命令,也只有swarm manager可以批准其他机器作为worker节点加入到swarm中。Worker只提供服务能力,并没有权利干涉其他机器的工作。
到现在为止,我们只是在本地机器上使用Docker的single-host模式。只要使能swarm的使用,Docker也可以切换到swarm模式。在某机器上使能swarm模式,可以使该机器立即成为一个swarm manager。然后,Docker不只是运行当前机器上的命令,也会运行在swarm上执行的命令。
5.3 构建一个swarm
一个swarm由多个节点组成,这些节点可以是物理上的,也可以是虚拟的。要做的只是简单的两步。首先,运行docker swarm init来使能swarm模式,从而使当前的机器成为一个swarm manager;然后在其他机器上运行docker swarm join,使这些机器作为worker节点加入到swarm中。
下面将采用虚拟机方式(VMs)来快速创建两个机器的集群(cluster),然后将集群转为一个swarm。
5.3.1 安装VirtualBox
不同的平台,创建虚拟机的方式不同。如在MAC/LINUX/WINDOWS7/WINDOWS8系统上,需要使用hypersisor来创建虚拟机;在WINDOWS10平台上,使用Hyper-V来创建虚拟机(Hyper-V会默认安装在WINDOWS10上)。
由于本人用的是CentOS系统,使用hypersisor,需要安装VirtualBox。
进入VirtualBox的官网,选择版本及安装方式。本人使用yum源安装:
yum install VirtualBox-5.2
不过使用该命令安装时提示没有可以的VirtualBox-5.2。
在/etc/yum.repos.d下建立VirtualBox-5.2.repo源,源中输入内容:
[virtualbox] name=Oracle Linux / RHEL / CentOS-$releasever / $basearch - VirtualBox baseurl=http://download.virtualbox.org/virtualbox/rpm/el/$releasever/$basearch enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://www.virtualbox.org/download/oracle_vbox.asc
然后再运行命令yum install VirtualBox-5.2,安装成功。
5.3.2 安装Docker Machine
创建虚拟机时使用docker machine。对于macOS和Windows系统,安装对应版本的Docker时,会自动安装Docker machine。但在Linux系统下,需要手动安装。Centos系统下,运行命令:
curl -L https://github.com/docker/machine/releases/download/v0.13.0/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine &&
chmod +x /tmp/docker-machine &&
sudo cp /tmp/docker-machine /usr/local/bin/docker-machine
显示machine版本号来确认是否安装成功:
$ docker-machine version
docker-machine version 0.13.0, build 9371605
5.3.3 创建虚拟机
使用VirtualBox驱动,创建两个VMs:
docker-machine create --driver virtualbox myvm1
docker-machine create --driver virtualbox myvm2
5.3.4 列出所有VMs并获取它们的IP
上面创建了两个虚拟机:myvm1和myvm2。
使用命令docker-machine ls列出这些虚拟机和它们的IP地址:
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 - virtualbox Running tcp://192.168.99.100:2376 v17.06.2-ce
myvm2 - virtualbox Running tcp://192.168.99.101:2376 v17.06.2-ce
5.3.5 初始化swarm并添加节点
将第一个虚拟机作为manager节点,用以执行管理命令并准许其他worker加入到swarm中;将第二个虚拟机作为worker节点。
通过使用命令docker-machine ssh,将命令发送到虚拟机上。命令中使用docker swarm init,使myvm1成为manager:
$ docker-machine ssh myvm1 "docker swarm init --advertise-addr <myvm1 ip>"
Swarm initialized: current node <node ID> is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token <token> \
<myvm ip>:<port>
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
◆ 关于端口2377和2376。
2377是swarm管理端口,运行命令docker swarm init和docker swarm join时会用到该端口。运行命令时不使用端口号,会采用默认端口。
命令docker-machine ls的返回结果包括端口2376,这是Docker daemon port。使用这个端口会导致错误。
命令docker swarm init的执行结果中,包含已配置好的命令docker swarm join,在其他机器上运行这个,从而使该机器加入到swarm中。复制这个命令,通过docker-machine ssh将该命令发送到myvm2,使myvm2作为worker节点加入到这个新swarm中:
$ docker-machine ssh myvm2 "docker swarm join \
--token <token> \
<ip>:2377"
This node joined a swarm as a worker.
恭喜,现在已经创建好了一个swarm。
在manager节点上运行命令docker node ls来查看这个swarm中的节点:
$ docker-machine ssh myvm1 "docker node ls"
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
brtu9urxwfd5j0zrmkubhpkbd myvm2 Ready Active
rihwohkh3ph38fhillhhb84sk * myvm1 Ready Active Leader
5.3.6 节点脱离swarm
如果想让某一节点脱离swarm,在该节点上运行命令docker swarm leave即可。
5.4 在swarm集群上部署app
我们已经完成最难的部分,下面只要重复第4部分(Docker入门:服务)中的步骤,就可以在swarm上部署app了。记住一点:只有像myvm1这样的manager节点才可以执行Docker命令,worker节点只是提供服务能力。
5.4.1 配置一个和swarm manager对话的docker-machine shell
到目前为止,我们是通过将Docker命令包裹在docker-machine ssh中的方式,来和VMs进行对话。
还有一种更好的办法。首先运行docker-machine env <machine>来获取一个新命令,然后通过运行这个新命令来配置当前的shell,从而使当前的shell和VM上的Docker deamon进行对话。这种方法更好,因为它允许我们使用本地的docker-compose.yml文件来“远程”部署app,从而避免拷贝这个Compose文件。
运行命令docker-machine env myvm1会有结果输出,将结果输出的最后一行作为命令再执行,从而配置当前的shell可以和myvm1(swarm manager)对话了。
平台不同,配置shell的命令也会不同。下面展示Linux平台下Docker machine shell环境的配置过程,其他平台查看Docker官网。
运行命令docker-machine env myvm1:
$ docker-machine env myvm1
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/sam/.docker/machine/machines/myvm1"
export DOCKER_MACHINE_NAME="myvm1"
# Run this command to configure your shell:
# eval $(docker-machine env myvm1)
然后运行提供的命令来配置当前shell和myvm1对话:
eval $(docker-machine env myvm1)
现在运行docker-machine ls来验证myvm1就是当前的活跃机器,会有星号标识:
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 * virtualbox Running tcp://192.168.99.100:2376 v17.06.2-ce
myvm2 - virtualbox Running tcp://192.168.99.101:2376 v17.06.2-ce
5.4.2 在swarm manager上部署app
现在拥有了虚拟机myvm1,并将其作为了swarm manager。就像第4部分所做的一样,通过在myvm1上使用命令docker stack deploy并利用本地文件docker-compose.yml,从而在swarm上部署app。
经过docker-machine shell配置后,你可以连接到myvm1,但你仍然有权限来访问你本机上的文件。
和之前一样,通过运行如下命令,在myvm1上部署app:
docker stack deploy -c docker-compose.yml getstartedlab
OK了,app在swarm集群上部署成功。
现在可以使用上一部分的那些命令。不同的是,service(及其关联的容器)已经分布到myvm1和myvm2两个节点上了。
$ docker stack ps getstartedlab
ID NAME IMAGE NODE DESIRED STATE
jq2g3qp8nzwx getstartedlab_web.1 robin/get-started:part2 myvm1 Running
88wgshobzoxl getstartedlab_web.2 robin/get-started:part2 myvm2 Running
vbb1qbkb0o2z getstartedlab_web.3 robin/get-started:part2 myvm2 Running
ghii74p9budx getstartedlab_web.4 robin/get-started:part2 myvm1 Running
0prmarhavs87 getstartedlab_web.5 robin/get-started:part2 myvm2 Running
5.4.3 访问集群
无论使用myvm1或myvm2的IP地址,都可以访问到你的app。
你所创建的网络在这些节点间能够共享并负载均衡。运行docker-machine ls来获取所有的虚拟机IP地址,在浏览器中访问任何一个IP地址,并刷新页面。
不停刷新后,可以看到5个容器ID随机循环显示,从而展示了负载均衡。
为什么两个IP地址都可以工作呢?这是因为两个节点都参与到了这个ingress routing mesh。因此,在你的swarm中,如果一个service部署在特定的端口,该service自己也会保留那个端口,而不管到底哪个节点上运行着容器。
下面这张图,展示了my-web这个service的routing mesh是什么样子,其中,my-web在端口8080上发布,并运行在一个3节点swarm上。
如果你遇到连接问题,请记住如下事项。为了在swarm中使用ingress network,在你使能swarm模式前,要保证如下端口在swarm的节点之间是打开的:
- 7946:TCP/UDP,用于容器网络发现;
- 4789:UDP,用于容器ingress network。
5.4.4 和VMs的连接方式
和VMs有两种连接方式。本文展示了docker-machine ssh和docker-machine env两种方式。通过docker-machine CLI,所有的平台都支持这两种方式。
(1)如果想让你的shell和另一个机器(如myvm2)对话,只要在当前shell(或另一个shell)中运行docker-machine env myvm2命令,再运行给出的命令后,就可以将shell指向myvm2。这只对当前的shell有效。如果更换到一个未配置的shell或一个新打开的shell,需要重新运行上述命令。使用docker-machine ls来列出所有的机器,观察它们的状态,获取它们的IP地址,或者查看你连的是哪个机器。
(2)同样,你可以将Docker命令封装到命令docker-machine ssh <machine> “<command>”中,这样可以直接登到虚拟机上,但没有权限访问你本机上的文件。
(3)在Mac或Linux上,可以使用命令docker-machine scp <file> <machine>:~在机器间拷贝文件;在Windows平台上,需要使用Git Bash这样的Linux终端模拟器。
5.5 scale你的app
现在你就可以做任何你在第三部分和第四部分学的东西:
通过修改docker-compose.yml文件来scale你的app。
如果想修改app的行为,可以修改代码,然后重新构建映像,并推送这个新的映像。
无论采用哪种修改,只是简单的再运行一下docker stack deploy就可以部署这些变化。
通过使用命令docker swarm join(之前我们在myvm2上使用过该命令),我们可以将任何机器(物理上的或虚拟的)加入到swarm中,从而增加这个集群的服务能力。然后运行docker stack deploy,我们的app就可以使用这些新加入的资源。
5.6 清理和重启
5.6.1 Stack和Swarm
使用命令docker stack rm来关闭stack,例如:
docker stack rm getstartedlab
接下来是要保留还是删除我们的swarm?
可以通过如下步骤来删除这个swarm:在worker节点上使用命令docker-machine ssh myvm2 "docker swarm leave";在manager节点上使用命令docker-machine ssh myvm1 "docker swarm leave --force"。
后面的部分还需要使用这个swarm,暂时先别删除它。
5.6.2 重置docker-machine shell环境变量
要在当前的shell中重置docker-machine环境变量,可以使用如下命令:
eval $(docker-machine env -u)
这会断开shell和docker-machine所创建的虚拟机之间的连接,并允许你继续使用这个shell,并运行原生的docker命令。
5.6.3 重启Docker machines
如果关闭了主机,Docker machine也将停止运行。可以通过命令docker-machine ls来检测这些machine的状态:
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 - virtualbox Stopped Unknown
myvm2 - virtualbox Stopped Unknown
想重启这些停止的machine,运行命令:
docker-machine start <machine-name>
例如:
$ docker-machine start myvm1
Starting "myvm1"...
(myvm1) Check network to re-create if needed...
(myvm1) Waiting for an IP...
Machine "myvm1" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.
$ docker-machine start myvm2
Starting "myvm2"...
(myvm2) Check network to re-create if needed...
(myvm2) Waiting for an IP...
Machine "myvm2" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.
5.7 总结
在这一部分,我们学习了许多知识:什么是swarm;在swarm中怎样让一个节点成为manager节点或worker节点;创建一个swarm并将app部署在其上。可以看到使用的核心Docker命令和第四部分没有区别,只是命令需要运行在swarm master上。你也看到了Docker网络功能的威力,即便容器运行在不同的机器上,依然能够将请求负载均衡到这些容器上。最后,我们学习了在集群上怎样去迭代开发app以及scale你的app。
5.8 本节命令列表
如果你想和你的swarm或者你的虚拟机进行交互,可以使用下面的一些命令:
docker-machine create --driver virtualbox myvm1 # Create a VM (Mac, Win7, Linux) docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm1 # Win10 docker-machine env myvm1 # View basic information about your node docker-machine ssh myvm1 "docker node ls" # List the nodes in your swarm docker-machine ssh myvm1 "docker node inspect <node ID>" # Inspect a node docker-machine ssh myvm1 "docker swarm join-token -q worker" # View join token docker-machine ssh myvm1 # Open an SSH session with the VM; type "exit" to end docker node ls # View nodes in swarm (while logged on to manager) docker-machine ssh myvm2 "docker swarm leave" # Make the worker leave the swarm docker-machine ssh myvm1 "docker swarm leave -f" # Make master leave, kill swarm docker-machine ls # list VMs, asterisk shows which VM this shell is talking to docker-machine start myvm1 # Start a VM that is currently not running docker-machine env myvm1 # show environment variables and command for myvm1 eval $(docker-machine env myvm1) # Mac command to connect shell to myvm1 & "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression # Windows command to connect shell to myvm1 docker stack deploy -c <file> <app> # Deploy an app; command shell must be set to talk to manager (myvm1), uses local Compose file docker-machine scp docker-compose.yml myvm1:~ # Copy file to node's home dir (only required if you use ssh to connect to manager and deploy the app) docker-machine ssh myvm1 "docker stack deploy -c <file> <app>" # Deploy an app using ssh (you must have first copied the Compose file to myvm1) eval $(docker-machine env -u) # Disconnect shell from VMs, use native docker docker-machine stop $(docker-machine ls -q) # Stop all running VMs docker-machine rm $(docker-machine ls -q) # Delete all VMs and their disk images
备注:由于写这篇文章时,无法访问gitlab,所以本文的后面部分只是翻译。
Docker入门(五):Swarms的更多相关文章
- Docker入门(六):Stacks
这个<Docker入门系列>文档,是根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指 ...
- Docker入门(七):部署app
这个<Docker入门系列>文档,是根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指 ...
- Docker入门(四):服务(Services)
这个<Docker入门系列>文档,是根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指 ...
- Docker入门(三):容器(Containers)
这个<Docker入门系列>文档,是根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指 ...
- Docker入门(二):安装/卸载
这个<Docker入门系列>文档,是根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指 ...
- Docker入门(一):简介
这个<Docker入门>系列文档,是我根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家 ...
- Docker 入门 第四部分: Swarms
目录 Docker 入门 第四部分: Swarms 先决条件 介绍 理解Swarm集群 部署swarm 创建一个集群 在swarm集群上部署你的app应用 为 swarm管理器配置一个docker-m ...
- Docker入门教程(五)Docker安全
Docker入门教程(五)Docker安全 [编者的话]DockOne组织翻译了Flux7的Docker入门教程,本文是系列入门教程的第五篇,介绍了Docker的安全问题,依然是老话重谈,入门者可以通 ...
- Docker 入门 第五部分:Stacks
目录 Docker 入门 第五部分:Stacks 先决条件 介绍 添加一个新的服务并重新部署 保存数据 回顾 Docker 入门 第五部分:Stacks 先决条件 安装 Docker 1.13 或更高 ...
随机推荐
- Socket的UDP协议在erlang中的实现
现在我们看看UDP协议(User Datagram Protocol,用户数据报协议).使用UDP,互联网上的机器之间可以互相发送小段的数据,叫做数据报.UDP数据报是不可靠的,这意味着如果客户端发送 ...
- TP 接收post请求使用框架自带函数I()防止注入
<input id="dele_id[]" value="1" type="checkbox" /> <input id= ...
- Python中urllib2总结
使用Python访问网页主要有三种方式: urllib, urllib2, httpliburllib比较简单,功能相对也比较弱,httplib简单强大,但好像不支持session1. 最简单的页面访 ...
- php部分--题目:投票 重点:两个div套用,显示百分比;
1.建立两个表格:要显示百分比的话,就要在选项表中加上一列标记number 2.链接数据库,并对题目和选项进行显示 <?php $db=new MySQLi("localhost&qu ...
- c++编码习惯
1 大驼峰命名法 类名和函数名由单词构成,每个单词的首字母大写. 2 函数命名 大驼峰命名法. 3 类命名 大驼峰命名,但是为了和函数名区分开,在前面加上一个大写的C.
- Latex 4: WinEdt 10试用时间限制的破解+注册码激活
方法1:我发现这个方法1,现在(2018.06.05)在winedt 10.2上已经不能用了,在低版本(10.1及以下版本)上还可以用,所以如果方法1不行,请看方法2. WinEdt 是目前我发现最好 ...
- python调试利器:最直观简洁的错误日志
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Date : 2018-08-30 17:12:27 # @Author : Sheldon (thi ...
- Java中的内存泄漏
[转]介绍Java中的内存泄漏 1. 什么是内存泄漏? 内存泄漏的定义:对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还在被引用着. 要想理解这个定义,我们需要先了解一下对象在内存中的 ...
- MVC+Ext.net零基础学习记录(四)
在上一篇文章[MVC+Ext.net零基础学习记录(三)]中提到了利用MVC的Area可以做到项目分离,但是实际操作起来还是有很多问题的.比如,对于物理资源的访问,会报:没有相关资源 开始的时候,我在 ...
- Macaca,app-inspector安装
1.安装brew 软件包管理工具:/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/inst ...