实战案例——Docker容器编排

Docker容器编排

一、实验目标

  1. 了解Docker容器主流的编排技术
  2. 掌握Docker Swarm 的部署和基本使用
  3. 掌握Docker Compose的部署和基本使用

二、实验准备

规划节点:三台节点分别命名为master(Swarm集群mange节点)node(Swarm集群node节点)compose(compose节点),三台节点网络配置同一网段,提前关闭防火墙(关闭后重启docker),所有节点都已安装好Docker-ce

三、实验步骤

3.1、Docker Swarm的部署和基本使用

3.1.1、配置主机映射
vi /etc/hosts 
#添加三台主机的IP映射-三台同步
192.168.200.10 master
192.168.200.20 node
192.168.200.30 compose
3.1.2、配置Docker API

master节点node节点均需开启Docker API

# vi /lib/systemd/system/docker.service
将ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
修改为ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

# 重新加载配置文件并重启docker
# systemctl daemon-reload
# systemctl restart docker
3.1.3、拉取Swarm镜像

所有节点拉取Swarm镜像

# master和node同步拉取Swarm镜像
docker pull swarm
# 查看镜像
docker images
3.1.4、初始化集群

在master节点创建Swarm集群,注意记录报文,稍后用到

# docker swarm init --advertise-addr 192.168.200.10
Swarm initialized: current node (yqhx1ox536skwql7o9wb860ls) is now a manager.

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

    docker swarm join --token SWMTKN-1-2e3dba9j8fbu6tx4gjv1d4gqk9j7cu70s0retx9db20owajn1u-4w8r9l6uogjxlbqukxkkhzw82 192.168.200.10:2377

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

初始化命令中--advertise-addr参数表示管理节点公布它的IP是多少。输出结果中包含了Swarm命令,通过--token参数来判断加入集群时,是作为管理节点还是工作节点。

3.1.5、node节点加入集群

node节点执行加入Swarm集群的命令(上个步骤的报文结果),如果加入失败,尝试清空iptables和关闭防火墙。

docker swarm join --token SWMTKN-1-2e3dba9j8fbu6tx4gjv1d4gqk9j7cu70s0retx9db20owajn1u-4w8r9l6uogjxlbqukxkkhzw82 192.168.200.10:2377
3.1.6、验证集群

master节点查看各节点状态

# docker node ls #状态为Active
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
yqhx1ox536skwql7o9wb860ls *   master              Ready               Active              Leader              18.09.6
6d5uqxz97gavemwoz9onnqipm     node                Ready               Active                                  18.09.6
3.1.7、安装Portainer(Docker的图形化管理工具)

master节点安装Portainer

# docker volume create portainer_data
portainer_data
# docker service create --name portainer --publish 9000:9000 --replicas=1 --constraint 'node.role == manager' --mount type=bind,src=//var/run/docker.sock,dst=/var/run/docker.sock --mount type=volume,src=portainer_data,dst=/data portainer/portainer -H unix:///var/run/docker.sock
#正确报文
vyljj48etqotxhd6oa082ona9
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged
3.1.8、浏览器登录Portainer

访问地址:http://192.168.200.10:9000/
Portainer初始页面
首次登录时需设置用户名和密码,输入设置的用户名和密码(必须12位)例如:admin、admin0000000
ps:(设置账号密码后如果提示超时-如下图)
Portainer验证超时
则切换到master节点重启Portainer,步骤如下:

# 1、查询Portainer的容器名称
docker ps -a
# 2、拷贝Portainer的name字段
portainer.1.xxxxxxxxxxxxxxx
# 3、拼接重启命令
docker restart portainer.1.xxxxxxxxxxxxxxxxxxxxx

重启Portainer示例图
然后刷新浏览器配置账户登录,如下图所示:
Portainer首页示例图

3.1.9、运行service
docker service create --name web --replicas 2 nginx
# --name为service命名,nginx为镜像的名字,--replicas参数指定此服务在工作节点上的运行的任务数
#正确报文
02urum8zwtp4k9e0uko1b9q1q
overall progress: 2 out of 2 tasks
1/2: running
2/2: running
verify: Service converged

# 查看当前Swarm中的service
docker service ls
# 报文
ID                  NAME                MODE                REPLICAS            IMAGE                    PORTS
vyljj48etqot        portainer           replicated          1/1                 portainer/portainer:latest   *:9000->9000/tcp
02urum8zwtp4        web                 replicated          2/2                 nginx:latest

REPLICAS参数为当前副本信息,2/2的含义是service期望的容器副本数量为2,目前已经启动的副本数量为2,也即当前的service已经部署完成。命令docker service ps可以查看service每个副本的状态。

# 查看web服务
docker service ps web
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
w3kw6jrx69s5        web.1               nginx:latest        node                Running           Running 26 minutes ago
c276mupso514        web.2               nginx:latest        master              Running           Running 26 minutes ago

查看到两个副本分别被分派到master和node节点,当前状态都为Runing

3.1.10、service的弹性伸缩

ps:web服务通常会运行多个实例,用以达到负载均衡以及高可用
命令docker service scale 服务名=副本数量可以增加service的副本数。在master上执行:

# docker service scale web=5
web 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

#副本数增加到5 再次查看副本详细信息
[root@master ~]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                    PORTS
vyljj48etqot        portainer           replicated          1/1                 portainer/portainer:latest   *:9000->9000/tcp
02urum8zwtp4        web                 replicated          5/5                 nginx:latest

[root@master ~]# docker service ps web
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
w3kw6jrx69s5        web.1               nginx:latest        node                Running           Running 45 minutes ago
c276mupso514        web.2               nginx:latest        master              Running           Running 45 minutes ago
kmfkx4iean3o        web.3               nginx:latest        node                Running           Running 10 minutes ago
pd5v047r27jd        web.4               nginx:latest        master              Running           Running 10 minutes ago
2ryv2lsx751a        web.5               nginx:latest        node                Running           Running 10 minutes ago
#可以看到5个副本都已分布到Swarm的各个节点上
3.1.11、调度节点

ps:默认配置下master节点也是worker node,所以master上也运行了副本,如果不希望在master上运行service,可以进行如下配置:(目前该操作会导致Portainer页面无法访问)

[root@master ~]# docker node update --availability drain master
master

# 再次查看各个节点状态
# Drain代表不负责运行service
[root@master ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY MANAGER STATUS      ENGINE VERSION
yqhx1ox536skwql7o9wb860ls *   master              Ready               Drain Leader              18.09.6
6d5uqxz97gavemwoz9onnqipm     node                Ready               Active                     18.09.6

# 查看之前由master负责运行的service会如何处理
[root@master ~]# docker service ps web
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE               ERROR               PORTS
w3kw6jrx69s5        web.1               nginx:latest        node                Running           Running about an hour ago
e3522ykvk23r        web.2               nginx:latest        node                Running           Running 7 minutes ago
c276mupso514         \_ web.2           nginx:latest        master              Shutdown           Shutdown 7 minutes ago
kmfkx4iean3o        web.3               nginx:latest        node                Running           Running 26 minutes ago
mzi3jh9s01sx        web.4               nginx:latest        node                Running           Running 7 minutes ago
pd5v047r27jd         \_ web.4           nginx:latest        master              Shutdown           Shutdown 7 minutes ago
2ryv2lsx751a        web.5               nginx:latest        node                Running           Running 26 minutes ago
# 可以看到master负责的两个副本(2、4)已经关闭,为了确保5个副本,在node节点上又新增了2个相同的副本
3.1.12、外部网络访问service

ps:要访问service,首先要保证网络联通,其次服务的IP需要知道,每个副本都是一个容器,可以先查看容器的网络配置:(node节点)

[root@node ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
17b48fb5a31d        nginx:latest        "/docker-entrypoint.…"   19 minutes ago      Up 19 minutes       80/tcp              web.2.e3522ykvk23r5mm63cyayejpn
144ebf56bb17        nginx:latest        "/docker-entrypoint.…"   19 minutes ago      Up 19 minutes       80/tcp              web.4.mzi3jh9s01sx7uke37kt0xjhr
45a54804e013        nginx:latest        "/docker-entrypoint.…"   37 minutes ago      Up 37 minutes       80/tcp              web.3.kmfkx4iean3oi758mkukll737
dab2aa327f57        nginx:latest        "/docker-entrypoint.…"   37 minutes ago      Up 37 minutes       80/tcp              web.5.2ryv2lsx751av8h6uz3sxv2vf
ed31fd0f0b0c        nginx:latest        "/docker-entrypoint.…"   About an hour ago   Up About an hour    80/tcp              web.1.w3kw6jrx69s5xxc3ktknmi22h
# 在node节点上运行了5个容器,是web的副本,容器监听了80端口,但是并没有映射到DockerHost。
# 服务并没有暴露给外部网络,只能在Docker主机上访问。

# 将service暴露到外部,执行以下步骤:
[root@master ~]# docker service update --publish-add 8080:80 web
web
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

浏览器访问两个节点的8080端口:(会发现所有节点的IP都能正常访问,这是Swarm的优势之一,被称为routing mash,routing mash会将外部请求路由到不同主机的容器,从而实现外部网络对service的访问

ps:如果是新建的service,可以直接使用--publish参数,例如:
docker service create --name web_server --publish 8080:80 --replicas=2 httpd
容器在80端口上监听http请求,--publish-add 8080:80将容器的80映射到主机的8080端口,这样外部就能访问到service了。
外部网络访问master节点的8080端口
外部网络访问node节点的8080端口

3.2、Docker-Compose的部署和基本使用

3.2.1、安装Docker-Compose(compose节点)
# 拷贝指定版本docker-compose文件(docker引擎安装实验中解压的文件之一)到/usr/local/bin/目录下
[root@client ~]# cp -rvf compose/docker-compose /usr/local/bin/

# 添加可执行权限
chmod +x /usr/local/bin/docker-compose

# 查看软件版本信息
docker-compose --version
# 报文
docker-compose version 1.25.0-rc2, build 661ac20e
3.2.2、创建项目目录
#root目录下创建测试项目的文件夹并进入
mkdir composetest
cd composetest/
3.2.3、定义app.py文件

由于python语言严苛的缩进问题,请务必选择纯手写或本地使用专业软件编辑完成后直接上传文件,直接拷贝粘贴可能会导致缩进异常

import time
import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis',port=6379)

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return "Hello World! I have been seen {} times.\n".format(count)
if __name__ == '__main__':
	app.run(host='0.0.0.0', debug=True)
3.2.4、定义requirements.txt
# 创建并编辑requirements.txt文件
[root@compose composetest]# vi requirements.txt
# 编写以下内容
flask
redis
3.2.5、定义Dockerfile文件
# 创建并编辑Dockerfile文件
[root@compose composetest]# vi Dockerfile
# 编写以下内容
FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python","app.py"]

#参数解释:
#1、构建一个基于Python3.4的镜像
#2、把当前目录添加到镜像中的/code路径下
#3、把工作路径设置成/code
#4、安装Python依赖
#5、设置容器的默认命令为python app.py
3.2.6、定义服务
# 编写docker-compose.yml文件
[root@compose composetest]# vi docker-compose.yml
version: "3"
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"                
# 该文件定义两个服务web和redis:
# web服务使用当前目录Dockerfile构建出来的镜像,并且将容器上暴露的5000端口转发到主机的5000端口,使用Flask Web服务器的默认端口5000;
# redis服务使用从Docker Hub注册表中拉取的镜像。
3.2.7、运行服务

在项目路径下通过docker-compose up命令启动应用

[root@client composetest]# docker-compose up
#省略...
...
Attaching to composetest_redis_1, composetest_web_1
redis_1  | 1:C 01 Nov 2023 06:06:11.610 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 01 Nov 2023 06:06:11.610 # Redis version=6.2.6, bits=64, commit=00000000,
redis_1  | 1:C 01 Nov 2023 06:06:11.610 # Warning: no config file specified, using the derver /path/to/redis.conf
redis_1  | 1:M 01 Nov 2023 06:06:11.610 * monotonic clock: POSIX clock_gettime
redis_1  | 1:M 01 Nov 2023 06:06:11.610 * Running mode=standalone, port=6379.
redis_1  | 1:M 01 Nov 2023 06:06:11.610 # WARNING: The TCP backlog setting of 511 cannothe lower value of 128.
redis_1  | 1:M 01 Nov 2023 06:06:11.610 # Server initialized
redis_1  | 1:M 01 Nov 2023 06:06:11.610 # WARNING overcommit_memory is set to 0! Backgrouue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command
redis_1  | 1:M 01 Nov 2023 06:06:11.611 * Ready to accept connections
web_1    |  * Serving Flask app "app" (lazy loading)
web_1    |  * Environment: production
web_1    |    WARNING: This is a development server. Do not use it in a production deploy
web_1    |    Use a production WSGI server instead.
web_1    |  * Debug mode: on
web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web_1    |  * Restarting with stat
web_1    |  * Debugger is active!
web_1    |  * Debugger PIN: 977-468-128
# 该命令是前台运行所以不会主动退回交互窗口,如需继续操作需要另起一个窗口进行交互

另外打开一个新窗口进行查看:

[root@client ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
0f7f0a887e15        redis:alpine        "docker-entrypoint.s…"   About an hour ago   Up About an hour    6379/tcp                 composetest_redis_1
d4311cad5856        composetest_web     "python app.py"          About an hour ago   Up About an hour    0.0.0.0:5000->5000/tcp   composetest_web_1
# redis和app.py都是up状态
# redis是compose拉取的镜像,然后以代码构建一个本地镜像,并启动定义的服务。

# 构建本地镜像时,代码被静态拷贝到镜像中。查看所有镜像:
[root@client ~]# docker images ls
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
composetest_web                latest              6f94e71d96e0        About an hour ago   49.9MB
nginx                          latest              605c77e624dd        22 months ago       141MB
192.168.200.10/library/nginx   latest              605c77e624dd        22 months ago       141MB
redis                          alpine              3900abf41552        23 months ago       32.4MB
python                         3.5-alpine          6d034ccc54a2        3 years ago         38MB
3.2.8、验证服务
[root@client ~]# curl 127.0.0.1:5000
Hello World! I have been seen 1 times.
[root@client ~]# curl 127.0.0.1:5000
Hello World! I have been seen 2 times.
# 也可以直接浏览器打开上述地址,如下:

外部网络访问web服务

3.2.9、停止服务

方式1:项目目录下执行docker-compose down命令停止服务
方式2:在之前的运行窗口按Ctrl+C组合键停止当前启动着的应用

# 停止服务(测试项目目录下)
[root@client composetest]# docker-compose down
3.2.10、更新服务文件

在项目路径下编辑docker-compose.yml文件为Web服务添加一个绑定挂载路径。

[root@client composetest]# vi docker-compose.yml
version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
  redis:
    image: "redis:alpine"

新的volumes键将当前路径(项目路径)与容器中的/code路径挂载到一起,允许用户及时修改代码而不用重新构建镜像。

3.2.11、重建服务

在项目路径下,使用docker-compose up命令启动服务,使用更新后的Compose文件构建应用并启动。

# 后台启动
[root@client composetest]# docker-compose up -d
# 再次访问测试
[root@client composetest]# curl 127.0.0.1:5000
Hello World! I have been seen 4 times.
3.2.12、免重构更新服务内容

ps:因为应用程序的代码通过volumes挂载到容器中,用户可以更改其代码并立即查看更改,而不必重新生成镜像。

# 修改app.py中的欢迎语并保存。例如修改为Hello from Docker!
[root@client composetest]# vi app.py
...省略
@app.route('/')
def hello():
    count = get_hit_count()
    return "Hello from Docker! I have been seen {} times.\n".format(count)
if __name__ == '__main__':
	app.run(host='0.0.0.0', debug=True)
# 再次测试
[root@client composetest]# curl 127.0.0.1:5000
Hello from Docker! I have been seen 5 times.
# 报文已经成功更新为Hello from Docker!......

外部网络访问服务验证更新内容

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦南司

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值