从零开始,使用Docker Swarm部署集群教程

 

本文首先从Dockerfile创建了一个简单web镜像

然后将web镜像推送到了远程仓库,以备后面集群中不同机器自动下载

之后使用docker-compose.yml配置了一个应用

而后新建了2台虚拟机作为swarm节点,并部署应用的5个实例在这两台虚拟机上

最后还讲了如何如果更改集群配置、如何扩容您的集群和如重新发布您的应用

一、创建一个简单web镜像,并推送到docker仓库

1、创建Dockerfile

创建一个空目录, 然后CD到新目录,创建名为Dockerfile的文件,将以下内容复制并粘贴到该文件中,然后保存。 注意Dockerfile中每个语句的注释。

# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

这个Dockerfile使用了我们尚未创建的几个文件,即app.py和requirements.txt。 下面让我们创建他们。

我们的赢

2、创建应用程序

再创建两个文件,requirements.txt和app.py,并将它们与Dockerfile放在同一个文件夹中。 至此完成了我们的应用程序,您可以看到它非常简单。 当上面的Dockerfile构建成镜像后,由于Dockerfile的ADD命令,app.py和requirements.txt将会被加入到镜像中,并且由于EXPOSE命令暴露了80端口,我们可以通过HTTP访问app.py的输出。

requirements.txt

Flask
Redis

app.py

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

3、构建镜像

我们准备构建应用程序。 确保您仍处于创建的目录的顶层。 这是ls应该显示的内容:

$ ls
Dockerfile		app.py			requirements.txt

现在运行build命令。 这将创建一个Docker镜像,我们使用-t为它取了一个友好的名称。

$ docker image ls

REPOSITORY            TAG                 IMAGE ID
friendlyhello         latest              326387cea398

4、运行应用

运行应用程序,使用-p将计算机的端口4000映射到容器的已发布端口80:

docker run -p 4000:80 friendlyhello

您应该在http://0.0.0.0:80看到Python正在为您的应用程序提供服务的消息。 但是该消息来自容器内部,它不知道您将该容器的端口80映射到4000,从而生成正确的URL http:// localhost:4000。

在Web浏览器中转到该URL,以查看在网页上提供的显示内容。

您还可以在shell中使用curl命令来查看相同的内容。

$ curl http://localhost:4000

<h3>Hello World!</h3><b>Hostname:</b> 8fc990912a14<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>

到此镜像创建完成,当然你也可以使用自己的其它web镜像

5、推送镜像到远程仓库

1、首先到https://hub.docker.com/注册一个账号,保存下用户名密码

2、控制台登陆dockerhub账户

$ docker login
    输入刚注册的用户名密码

3、查看镜像

$ docker image ls

REPOSITORY            TAG                 IMAGE ID
friendlyhello         latest              326387cea398

3、选择需要上传的镜像,重命名为指定的格式

$ docker  tag friendlyhello abs52121/friendlyhello:v1
abs52121:为我自己的dockerhub账户名称,替换成你刚注册的名称

friendlyhello:为自己为镜像取的名字

v1:为任意设置的版本号

4、完成上述操作后,即可提交镜像到自己的仓库

$ docker push abs52121/friendlyhello:v1

二、创建docker-compose.yml文件

docker-compose.yml文件是一个YAML文件,用于定义Docker容器在生产中的行为方式。

将下面内容保存为docker-compose.yml, 确保已将第一部分中创建的镜像推送到远程仓库,并将username/repo:tag替换为你自己的镜像信息。

version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: username/repo:tag
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "4000:80"
    networks:
      - webnet
networks:
  webnet:

这个docker-compose.yml文件告诉Docker执行以下操作:

从注册中心中提取我们在步骤1中上传的镜像。

从此镜像运行5个实例作为一个服务,服务名为web,限制每个实例使用最多10%的CPU(所有核心)和50MB的RAM。

如果如果容器出错,立即重启。

将主机上的端口4000映射到Web的端口80。

指示Web容器通过称为webnet的负载平衡网络共享端口80。 (在内部,容器发布在web的80端口)

默认使用Webnet网络(负载平衡网络)。

三、运行你的带负载均衡集群应用

1、初始化swarm

$ docker swarm init

2、现在让我们来运行吧,您需要为您的应用程序命名,在这里它被设置为getstartedlab:

$ docker stack deploy -c docker-compose.yml getstartedlab

3、我们的单个服务在一台主机上运行已部署5个容器实例, 让我们来看一下吧。

$ docker service ls 
s31sqx0dmkdh        getstartedlab_web          replicated          5/5                 abs52121/friendlyhello:v1         *:80->80/tcp


$ docker service ps getstartedlab_web
ID                  NAME                  IMAGE                       NODE                    DESIRED STATE       CURRENT STATE                ERROR               PORTS
rzk868yrs1zm        getstartedlab_web.1   abs52121/friendlyhello:v1   linuxkit-025000000001   Running             Running about a minute ago
tmp93inu2bu9        getstartedlab_web.2   abs52121/friendlyhello:v1   linuxkit-025000000001   Running             Running about a minute ago
jeasl6c1pah1        getstartedlab_web.3   abs52121/friendlyhello:v1   linuxkit-025000000001   Running             Running about a minute ago
ik2wb1986qxf        getstartedlab_web.4   abs52121/friendlyhello:v1   linuxkit-025000000001   Running             Running about a minute ago
s3dgi0lr7clf        getstartedlab_web.5   abs52121/friendlyhello:v1   linuxkit-025000000001   Running             Running about a minute ago

#查看所有容器id
$ docker container ls -q

4、您可以连续多次运行curl -4 http://localhost:4000,或者在浏览器中转到该URL并点击刷新几次。

无论哪种方式,容器ID都会发生变化,从而证明负载均衡; 对于每个请求,以循环方式选择5个任务中的一个来响应。 容器ID与上一个命令(docker container ls -q)的输出匹配。

5、扩展你的应用

您可以通过更改docker-compose.yml文件,并重新运行docker stack deploy命令来扩展应用程序:

$ docker stack deploy -c docker-compose.yml getstartedlab

Docker执行就地更新,无需杀死任何容器。

现在,重新运行docker container ls -q以查看已重新配置的已部署实例。 如果增加副本数量,则会启动更多任务,从而启动更多容器。

6、退出应用程序和swarm

通过 docker stack rm退出程序:

$ docker stack rm getstartedlab

退出swarm

$ docker swarm leave --force

7、了解Swarm集群
swarm是一组运行Docker并加入群集的计算机。在此之后,您继续运行您习惯使用的Docker命令,但现在它们由群集管理器在群集上执行。集群中的机器可以是物理的或虚拟的。加入swarm后,它们被称为节点。

Swarm 管理器可以使用多种策略来运行容器,例如“emptiest node”  - 它使用容器填充利用率最低的机器。或“global”,它确保每台机器只获得指定容器的一个实例。您可以指示swarm管理器在Compose文件中使用这些策略,就像您上面已经使用的那样。

Swarm 管理器是群中唯一可以执行命令的机器,或授权其他机器作为工作者加入群集。工作者只是在那里提供能力,并且没有权力告诉任何其他机器它能做什么和不能做什么。

到目前为止,您一直在本地计算机上以单主机模式使用Docker。但是Docker也可以切换到swarm模式,这就是使用群集的能力。立即启用群集模式使当前计算机成为swarm管理器(swarm init命令)。之后,Docker就会运行您在管理的swarm上执行的命令,而不仅仅是在当前机器上。

四、在不同的机器上运行你的集群应用

1、首先通过docker-machine创建2个虚拟机(当然也可以使用你目前已经有的物理机或者虚拟机)

现在使用docker-machine创建几个VM,使用VirtualBox驱动程序,在运行命令前请确保你安装了virtualbox虚拟机:

$ docker-machine create --driver virtualbox myvm1
$ docker-machine create --driver virtualbox myvm2

墙内用户可以自行百度下载boot2docker.iso 文件,并使用--virtualbox-boot2docker-url参数指定文件位置

$ python-docker huhaichao$ docker-machine create --driver virtualbox --virtualbox-boot2docker-url=/path/to/boot2docker.iso myvm3

2、您现在创建了两个名为myvm1和myvm2的VM。

使用此命令列出计算机并获取其IP地址。

$ docker-machine ls
NAME    ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
myvm1   -        virtualbox   Running   tcp://192.168.99.100:2376           v18.03.1-ce
myvm2   -        virtualbox   Running   tcp://192.168.99.101:2376           v18.03.1-ce

3、初始化swarm并且为其增加节点

您可以使用docker-machine ssh向VM发送命令。 使用docker swarm init指示m

yvm1成为一个swarm管理器:

$ docker-machine ssh myvm1 "docker swarm init --advertise-addr 192.168.99.100"
Swarm initialized: current node (rxdphwlo6tpo60ql4k1mby8zx) is now a manager.

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

    docker swarm join --token SWMTKN-1-63xho3dyvfjt76ivusisk6j1nsrwo9thto8frgja83jl7k04mp-eyopgohzj6agbox1o53swpj38 192.168.99.100:2377

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

也可以使用以下命令进入myvm1虚拟机,然后再然后再执行swarm初始化操作

//进入虚拟机
$ docker-machine --native-ssh ssh myvm1

//初始化swarm
$ docker swarm init --advertise-addr 192.168.99.100

如您所见,对docker swarm init的输出包含一个docker swarm join命令,您可以在要添加的任何节点上执行此命令,加入swarm作为一个worker节点。

复制此命令,并通过docker-machine ssh将其发送到myvm2,让myvm2作为worker加入你的新swarm:

$ docker-machine ssh myvm2 "docker swarm join --token SWMTKN-1-63xho3dyvfjt76ivusisk6j1nsrwo9thto8frgja83jl7k04mp-eyopgohzj6agbox1o53swpj38 192.168.99.100:2377"
This node joined a swarm as a worker.

恭喜你,你已经创建了你的第一个swarm!

在管理器上运行docker node ls以查看此swarm中的节点:

$ docker-machine ssh myvm1 "docker node ls"
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
rxdphwlo6tpo60ql4k1mby8zx *   myvm1               Ready               Active              Leader              18.03.1-ce
tbkcetrx4y6bpbl55hvjgqhaj     myvm2               Ready               Active                                  18.03.1-ce

4、离开一个swarm

如果你想重新开始,可以在每个节点运行docker swarm leave。

5、在swarm群集上部署您的应用程序

困难的部分结束了。 现在,您只需重复第2部分中使用的过程即可部署到新的swarm上。 请记住,只有像myvm1这样的群体管理器才能执行Docker命令; worker只是为了提供能力。

与以前一样,运行以下命令在myvm1上部署应用程序。

//复制文件到myvm1
$ docker-machine scp docker-compose.yml myvm1:/home/docker
//在myvm1执行命令,部署集群应用
$ docker-machine ssh myvm1 "docker stack deploy -c docker-compose.yml getstartedlab"

现在您可以使用第2部分中使用的相同docker命令。只是这次注意到服务(和相关容器)已在myvm1和myvm2之间分配

$ docker service ps getstartedlab_web
ID                  NAME                  IMAGE                       NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
m09niqvz3me5        getstartedlab_web.1   abs52121/friendlyhello:v1   myvm1               Running             Running 7 minutes ago
dqe31n93su10        getstartedlab_web.2   abs52121/friendlyhello:v1   myvm2               Running             Running 7 minutes ago
qe8ltg98230g        getstartedlab_web.3   abs52121/friendlyhello:v1   myvm1               Running             Running 7 minutes ago
u830cf28y0d2        getstartedlab_web.4   abs52121/friendlyhello:v1   myvm2               Running             Running 7 minutes ago
q8csws9zijtu        getstartedlab_web.5   abs52121/friendlyhello:v1   myvm2               Running             Running 7 minutes ago

6、访问您的群集

您可以从myvm1或myvm2的IP地址访问您的应用程序。

您创建的网络在它们之间共享并进行负载平衡。 运行docker-machine ls获取虚拟机的IP地址,并在浏览器上访问其中任何一个,点击刷新(或只是通过curl访问)。

访问时有5个容器ID随机展示,这表明了负载平衡。两个IP地址都能访问的原因是swarm中的节点参与入口路由网格。 这可确保部署在swarm中某个端口的服务始终将该端口保留给自身,无论实际运行容器的是哪个节点。 下面是一个图表,说明在三节点群上的端口8080上发布的名为my-web的服务的路由网格是什么样子的:

routing mesh diagram

7、迭代和扩展您的应用程序

  • 在这里您可以使用上面提到的所有知识。
  • 通过更改docker-compose.yml文件来扩展应用程序。
  • 通过编辑代码更改应用程序行为,然后重建并推送新镜像。 (为此,请按照您之前用于构建应用程序并发布镜像的相同步骤)。
  • 在任何一种情况下,只需再次运行docker stack deploy来部署这些更改。
  • 您可以使用myvm2上使用的相同docker swarm join命令将任何机器(物理或虚拟)加入此群,并将容量添加到群集中。 之后只需运行docker stack deploy,您的应用就可以利用新资源。

五、清理和退出

你可以用docker stack rm拆掉堆栈。 例如:

$ docker stack rm getstartedlab


原文地址:https://www.cnblogs.com/cblogs/p/docker-swarm.html
posted @ 2018-08-06 19:29  程序员阿超的博客  阅读(6511)  评论(0编辑  收藏  举报