Docker Swarm 是创建服务器集群用的工具。把一堆服务器绑到一块儿用,让它们看起来像是一台服务器,通过统一的接口在这些服务器上运行应用。
集群里的服务器之间相互知道彼此,它们也知道哪些服务器上运行了什么样的服务,如果访问的服务在服务器上不存在,它会把访问转移到集群里的正确的服务器上去处理。一个服务可以用多个容器来支持,这些容器运行在集群里的不同的服务器上,请求可以均衡的分布给这些容器。当有服务器挂掉以后,在它上面运行的服务会被转移到其它的服务器上运行。
Docker Swarm 只需要几行命令就可以为应用创建一个强大的集群,为你的应用提供高可用的服务。宁皓网的 《 Docker:集群 》介绍了使用 Docker Swarm 创建集群服务器的方法。
模拟集群环境
如果你已经有了几台服务器,安装 Docker 以后就可以去创建一个服务器集群了,如果你想在本地测试 Docker Swarm 的功能,可以模拟一个集群环境,也就是在本地创建几台 Linux 系统的虚拟机,安装 Docker ,配置集群。下面介绍使用 Vagrant 创建虚拟机的方法。
安装 Virtualbox:虚拟机软件
安装 Vagrant:管理虚拟机用的工具,它可以管理 Virtualbox 虚拟机
安装 Vagrant Hostmanager 插件
Windows 如果启用了 Hyper-v 以后,就不能再使用 Virtualbox 或者其它的虚拟软件了。
Vagrant Hostmanager 是 Vagrant 的一个插件,设置了虚拟机的主机名以后,这个插件可以帮助我们设置虚拟机中的 /etc/hosts 文件,在里面添加正确的主机记录,这样如果创建了多台虚拟机,这些虚拟机之间可以使用虚拟机的主机名来访问到对方,这个插件并不是必须的,不过它很有用,它也可以设置本地主机上的 hosts 文件,这样你在本地主机上也可以直接使用虚拟机的主机名来访问到它。
# 创建项目目录
cd ~/desktop
mkdir docker-swarm
cd docker-swarm
# 初始化项目,使用 centos/7 这个 box
vagrant init centos/7
# 用编辑器打开项目目录
atom ./
编辑一下项目根目录下的 Vagrantfile,替换成下面的代码,它可以创建三台虚拟机,node1,node2,node3。
Vagrant.configure(2) do |config|
config.vm.box = "centos/7"
# 请安装 vagrant-hostmanager 插件
# https://github.com/devopsgroup-io/vagrant-hostmanager
config.hostmanager.enabled = true
config.hostmanager.manage_host = true
config.hostmanager.manage_guest = true
config.vm.define "node1" do |node1|
node1.vm.network "private_network", ip: "192.168.33.11"
node1.vm.hostname="node1"
end
config.vm.define "node2" do |node2|
node2.vm.network "private_network", ip: "192.168.33.12"
node2.vm.hostname="node2"
end
config.vm.define "node3" do |node3|
node3.vm.network "private_network", ip: "192.168.33.13"
node3.vm.hostname="node3"
end
end
启动虚拟机
vagrant up
安装 Docker
虚拟机启动以后,登录到这些虚拟机,然后在上面安装 Docker:
curl -fsSL https://test.docker.com/ | sh
sudo systemctl enable docker
sudo systemctl start docker
创建集群
集群里的服务器有两种身份,一个是 manager (管理员),一种是 worker(工人),在管理员服务器上可以创建服务,扩展服务,更新服务,管理员服务器本身也可以运行服务。先去初始化一个集群服务器,比如我想在 node1 这台服务器上初始化一下,先登录到这台服务器。
# 登录到 node1 服务器
vagrant ssh node1
# 初始化 Swarm 集群
docker swarm init --listen-addr node1:2377
这样 node1 默认就会是这个集群里的管理员,现在集群里只有一个节点服务器,可以查看一下:
docker node ls
在初始化集群的时候用了 --listen-addr,指定了一下这个集群管理员的地址还有端口号,默认地址应该是 0.0.0.0 ,这里我用了一个主机名来表示,node1。列出这个选项是让展示一下你可以自由的设置服务器的监听地址与端口号,如果使用主机名,你要保证集群里的其它的服务器可以使用这个主机名访问到这台服务器。
加入集群
有了集群以后,你要让其它的服务器加入进来:
# 登录到 node2
vagrant ssh node2
# 让 node2 加入到集群
docker swarm join --listen-addr node2:2377 node1:2377
# 登录到 node3
vagrant ssh node3
# 让 node3 加入到集群
docker swarm join --listen-addr node3:2377 node1:2377
现在集群里一共有三台服务器了,在集群的 manager 里面可以查看一下服务器的列表:
docker node ls
让服务器加入集群的时候,也用到了 --listen-addr 选项,设置了这台服务器监听的地址与端口,其它的服务器会使用这个地址与端口跟它进行交流。后面又指定了让这台服务器加入到的那个集群,也就是通知一下集群里的管理员服务器。
创建集群网络
集群里的服务器使用一种 overlay 类型的网络,我们可以创建一种这样的网络,然后在集群里运行服务的时候可以指定使用这个网络。在集群的 manager 上(node1),执行:
docker network create --driver overlay skynet
这样会创建一个名字是 skynet 的 overlay 类型的网络。
创建服务
在集群的 manger 节点上,可以去创建运行应用的服务,执行一下:
docker service create --name web --network skynet --publish 3000:3000 --replicas 1 ninghao/node
上面命令会基于宁皓网的 ninghao/node 镜像创建一个名字是 web 的服务,使用 skynet 这个名字的网络,发布的端口是 3000 。--replicas 指定了这个服务用一个容器来运行。完成以后,可以打开浏览器,访问一下:
http://node1:3000
http://node2:3000
http://node3:3000
虽然 web 这个服务只有一个容器运行,它会在集群里的某台服务器上,很可能是 node1 这个服务器,不管它在哪个服务器上运行,访问集群里的所有的服务器,都可以正常打开服务提供的页面,你应该会在页面上看到一个 hello ,还有运行这个应用的容器的 id 号。
扩展服务
现在我要用多个容器来运行应用,这些容器会在集群里的不同的服务器上运行。扩展运行服务的容器的数量,在集群的 manager 节点上执行一下:
docker service scale web=6
上面的命令会用 6 个容器同时运行 web 这个服务,这 6 个容器会分布在不同的服务器上,查看运行服务的任务,执行一下:
docker service tasks web
你会看到在哪些服务器上运行了 web 这个服务。在不同的浏览器上再访问一下应用的页面,你会发现,运行应用的容器的 id 号会有变化,也就是用户对应用的请求会被均衡的分布在不同的服务器上。
更新服务
服务被创建以后,可以更新它,比如服务的端口号,数据卷,网络,镜像,这些东西都可以更新。我要更新一下 web 服务用的镜像,在集群的 manager 上执行:
docker service update web --image ninghao/node:hola
它会让 web 服务基于新的镜像 ninghao/node:hola 去创建,更新完成以后,重新打开浏览器,访问一下应用的页面,页面上显示的内容会有变化。