【09】循序渐进学 docker:docker swarm
写在前面的话
至此,docker 的基础知识已经了解的差不多了,接下来就来谈谈对于 docker 容器,我们如何来管理它。
docker swarm
在学习 docker swarm 之前,得先知道容器编排工具的作用:提供了基于容器调度和集群的技术,并编排容器之间如何进行交互。
docker swarm 不是唯一的容器编排工具,但却是 docker 自带的容器编排工具。
可以看看它的主要结构(图片来自互联网):
docker swarm 以集群的形式运行,包括两个角色:Manager 和 worker。
Manager 是 swarm 的集群的核心,所以一般会有多个,而且建议是奇数个,避免出现脑裂的情况。
多个 Manager 之间通过 Raft 协议进行信息同步。
Worker 就是干活的节点,节点之间通过 GOSS 网络进行信息同步。
Service 和 Replicas:每一个应用就是一个 Service,而每一次该应用的运行就是 Replicas。
创建 docker swarm
准备 3 台虚拟机:
IP | 主机名 | 说明 |
---|---|---|
192.168.100.100 | docker-node1 | Manager |
192.168.100.101 | docker-node2 | Worker |
192.168.100.102 | docker-node3 | Worker |
初始化 Manager 节点并将两个 Worker 节点加入:
node1 执行:
docker swarm init --advertise-addr=192.168.100.100
结果如图:
复制红色部分到另外两个节点执行!
node2 和 node3 执行:
docker swarm -4423bymu0axfzp7cr1df6jjq36d5errbhetzlg3zz722lzt2j5-4nopnics4j267mh1gidf8z7nm
结果如图:
在 node1 节点上查看 Swarm 信息:
docker node ls
结果如图:
类似相关集群的命令在 Worker 节点上执行一般都会报错:
This node is not a swarm manager
常见错误:
1. 初始化或者加错了节点想退出:
docker swarm leave --force
2. node2 和 node3 加入 swarm 时候报错:
Error response from daemon: error while validating Root CA Certificate: x509: certificate has expired or is not yet valid
这种问题一般是几台服务器的时间不一致,同步下时间一般就好了:
yum -y install ntp ntpdate -u ntp.api.bz
3. node2 和 node3 加入 swam 很久没反应,报错:
connect: no route to host
这种问题一般是防火墙原因,关闭服务器的防火墙即可:
systemctl stop firewalld.service systemctl disable firewalld.service
操作 docker swarm
在 docker swarm 中,命令都是基于 service 运行,而且所有服务都是运行在 Manager 节点。
【1】创建运行容器:
docker service create --name demo busybox sh -c "while true;do sleep 300; done"
【2】查看运行信息:
docker service ls
结果如图:
【3】查看该容器运行在哪个节点:
docker service ps demo
结果如图:
通过 create 时候的名字查找,但这个名字并不是容器名字。
【4】将容器运行多个节点:
docker service scale demo=
查看:
docker service ps demo
结果如图:
可以看到,3个容器被平均分配到了各个节点。
【5】删除容器:
docker container rm -f a98aad768cb9
先随便删除一个容器,再查看,结果如图:
可以发现,容器在短时间内会少掉一个节点,但是随即再度恢复成 3 个节点。
docker service ps demo
查看详细信息,结果如图:
可以看到一个被 Shutdown 的容器。值得注意的是,这个容器并不存在了已经。
【6】删除整个 Service:
docker service rm demo
结果如图,啥都不剩:
实战 - docker swarm 部署 wordpress
注意:在做这个实战之前,最好将 3 个节点的 docker 都重启一下,确保每个节点都存在:docker_gwbridge 和 ingress 网络。
【1】在 Manager 节点创建 overlay 网络和 MySQL:
network create -d overlay demo
结果如图:
该创建只存在于 Manager 节点。
docker service create --name mysql -- --env MYSQL_DATABASE=wordpress --network demo --mount type=volume,source=mysql_data,destination=/var/lib/mysql mysql:5.7
和直接 docker run 有着明显的不同,-e 参数变成了 --env,-v 参数变成了 --mount。
查看创建结果:
docker service lsdocker service ps mysql
结果如图:
【2】创建 wordpress:
docker service create --name wordpress -p : --network demo -- --env WORDPRESS_DB_HOST=mysql wordpress
查看结果:
【3】访问测试:
这里使用 Manager 节点的 IP 进行访问的,你也可以使用 Worker 节点的 IP 访问,三个 IP 都是没问题的。基于这一点,就可以实现很多骚操作。
同样,可以启动多个节点:
docker service scale wordpress=
结果如图:
Routing Mesh
为啥同一 overlay 网络中的多个容器之间能够互相通信,切访问的时候每个 IP 都能访问?
这就是 Routing Mesh,其主要的两种体现:Internal 和 Ingress。
Internal:容器与容器之间访问通过 overlay 网络
【1】通过创建两个容器进行测试,分别是 busybox 和 jwilder/whoami:
# 创建测试 overlay 网络 docker network create -d overlay ov-demo1 # 创建两个容器 docker service create --name busybox --network ov-demo1 busybox sh -c "while true;do sleep 3000;done" docker service create --name whoami --network ov-demo1 -p 8000:8000 -d jwilder/whoami # 将 whoami 创建成多个节点 docker service scale whoami=3
【2】进入 busybox 测试:
docker exec -it 1e68d97b6cda sh
结果如图:
记住上面这个 IP。然后去查看几个 whoami 容器的 IP,都不是这个 IP。
那这个 IP 是啥?
学过 LVS 的就知道有个东西叫做 VIP,也就是虚拟 IP,而这里的原理就是 LVS 实现,而这个 IP 就是 VIP,所有才会有访问哪个 IP 都行的结果,而且负载均衡。
Ingress: 如果服务有绑定端口,则可以通过任意节点的这个端口访问。
原理在于:当访问指定端口的时候,请求被 gwbridge 转发带 ingress-sbox 的 namespace 中,然后让 LVS 调度给了任意一台机器。
docker swarm 中的 docker-compose.yml
上面学习的 docker swarm 虽然很爽,但是还是没有摆脱手动写很长的命令的束缚。所以有了接下来的专门用于 docker swarm 的 docker-compose.yml。
具体可以参照官方文档:
https://docs.docker.com/compose/compose-file/
这里以部署 wordpress 为例的 docker-compose.yml:
version: '3' services: web: image: wordpress ports: - 8888:80 environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_PASSWORD: 123456 networks: - ov-test depends_on: - db deploy: mode: replicated replicas: 3 restart_policy: condition: on-failure delay: 5s max_attempts: 3 update_config: parallelism: 2 delay: 10s db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: 123456 MYSQL_DATABASE: wordpress volumes: - mysql_test_data:/var/lib/mysql networks: - ov-test deploy: mode: global placement: constraints: - node.role == manager volumes: mysql_test_data: networks: ov-test: driver: overlay
相比于之前 docker-comse 时写的文件,这里主要多了 deploy 项,具体可以根据官方文档学习。
删除掉之前建立的所有容器,运行该配置文件,启动服务:
docker stack deploy wordpess --compose-file=docker-compose.yml
结果如图:
可以发现,在 docker swarm 中管理 docker compose 服务,不是使用 docker service 命令,而是换成了 docker stack 命令进行管理。
查看容器的相关信息:
# 查看 docker stack 运行情况 docker stack ls # 查看运行状态 docker stack services wordpess # 也可以用 service 查看 docker service ls # 查看更详细的信息 docker stack ps wordpess
结果如图:
访问测试:
删除服务:
docker stack rm wordpess
实战 - docker swarm 中的复杂项目实战
这是一个投票系统,工作原理如下图:
docker-compose 文件:
version: ' services: redis: image: redis:alpine ports: - " networks: - frontend deploy: replicas: update_config: parallelism: delay: 10s restart_policy: condition: on-failure db: image: postgres:9.4 volumes: - db-data:/var/lib/postgresql/data networks: - backend deploy: placement: constraints: [node.role == manager] vote: image: dockersamples/exampleenvotingapp_vote:before ports: - : networks: - frontend depends_on: - redis deploy: replicas: update_config: parallelism: restart_policy: condition: on-failure result: image: dockersamples/exampleenvotingapp_result:before ports: - : networks: - backend depends_on: - db deploy: replicas: update_config: parallelism: delay: 10s restart_policy: condition: on-failure worker: image: dockersamples/exampleenvotingapp_worker networks: - frontend - backend labels: [APP=VOTING] deploy: placement: constraints: [node.role == manager] restart_policy: condition: on-failure delay: 10s max_attempts: visualizer: image: dockersamples/visualizer:stable ports: - : stop_grace_period: 1m30s volumes: - "/var/run/docker.sock:/var/run/docker.sock" deploy: placement: constraints: [node.role == manager] networks: frontend: backend: volumes: db-data:
由于这个项目会去下载几个镜像,特别慢,有兴趣的可以自己尝试一下。
docker 中的密码管理
在实际生产中,很多时候数据库的密码不适合直接以明文的形式写出来,比如写在 docker-compose.yml 文件中,所以这就需要对密码进行处理。
对于 docker 中的密码,有两点需要明确:
1. 密码存在 Manager 节点的 Raft database 中,能够同步到其它节点。
2. Secert 在容器内部是以文件的形式保存的。
【1】创建 secert:
方法 1:从文件创建,创建一个 passwd 的文件,内容是密码:admin123
# 创建密码 docker secret create pass-demo passwd # 查看 docker secret ls
结果如图:
方法 2:从用户输入创建:
echo "admin123" | docker secret create pass-demo1 -
注意最后的 - 符号,结果如图:
【2】删除密码:
docker secret rm pass-demo1
【3】给创建的容器指定密码:
docker service create --name demo --secret pass-demo busybox sh -c "while true;do sleep 300;done"
找到容器的节点,进入容器查看密码:
docker exec -it e80ae4cfdf15 sh
结果如图:
【4】如何使用这个文件,以 MySQL 为例:
docker service create --name mysql --secret pass-demo -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/pass-demo -d mysql
MySQL 镜像有个环境变量是可以指定密码文件的,但是这个特性是 MySQL 8 才具有的。结果如图:
【5】如何在 docker-compose.yml 中使用:
version: '3.7' services: web: image: wordpress ports: - : secrets: - my-password environment: WORDPRESS_DB_HOST: mysql WORDPRESS_DB_PASSWORD_FILE: /run/secrets/my-password networks: - demo depends_on: - mysql deploy: mode: replicated replicas: restart_policy: condition: on-failure delay: 5s max_attempts: update_config: parallelism: delay: 10s mysql: image: mysql:5.7 secrets: - my-password environment: MYSQL_ROOT_PASSWORD_FILE: /run/secret/my-password MYSQL_DATABASE: wordpress volumes: - mysql-data:/var/lib/mysql networks: - demo deploy: mode: global placement: constraints: - node.role == manager volumes: mysql-data: networks: demo: driver: overlay secrets: my-password: file: ./password
有几个地方值得注意:
1. 配置密码的时候指定的是文件。
2. 多了一个顶层配置,secerts
3. docker-compose.yml 版本是当前最新的,否则可能不支持该语法。
服务更新
服务搭建起来了,那如何在不停止服务的情况下灰度更新它?docker swarm 提供了自己方法。
这里以 Flask 项目为例:
【1】在三个节点的新建目录,app.py 和 Dockerfil:
mkdir docker-update cd docker-update
app.py:
from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Hello Flask version 1.0\n" if __name__=="__main__": app.run(host=)
Dockerfile:
FROM python:2.7 COPY app.py /app/ RUN pip install flask WORKDIR /app/ EXPOSE CMD ["python", "app.py"]
【2】将 3 个节点构建成镜像:
docker build -t dylan/flask-test:v1. .
【3】将 3 个节点 app.py 里面的 1.0 换成 2.0,重新构建镜像:
docker build -t dylan/flask-test:v2. .
【4】部署 1.0 版本:
docker service create --name flask --publish : --network demo dylan/flask-test:v1.
【5】找到对应的节点访问测试:
sh -c "while true;do curl 127.0.0.1:9999&&sleep 1;done"
结果如图:
【6】在线升级:
# 扩展节点 docker service scale flask= # 更新 docker service update --image dylan/flask-test:v2. flask
结果如图:
再看看访问的效果:
可以看出在升级过程中,有段时间是双版本并行的,更新完成后都是新的了。这就实现了业务的不中断。
写到这里,docker swarm 的知识差不多了,如果想更深入的学习,可以自己再去研究。
小结
docker swarm 给我们打开了容器编排的大门,但是最终目标还是 K8S,如果感兴趣,可以关注后面的 K8S 内容。
【09】循序渐进学 docker:docker swarm的更多相关文章
- 小白学Docker之Swarm
承接上篇文章:小白学Docker之Compose,自学网站来源于https://docs.docker.com/get-started 系列文章: 小白学Docker之基础篇 小白学Docker之Co ...
- docker kubernetes Swarm容器编排k8s CICD部署
1docker版本 docker 17.09 https://docs.docker.com/ appledeAir:~ apple$ docker version Client: Docker En ...
- 【Docker】 Swarm简单介绍
[Swarm] Swarm是Docker官方提供的一款集群管理工具,其主要作用是把若干台Docker主机抽象为一个整体,并且通过一个入口统一管理这些Docker主机上的各种Docker资源.Swarm ...
- Docker And Swarm Mode(一)
(一)节点的创建和配置 前言 虽然工作中一直在用Docker和Docker Swarm,但是总感觉有点陌生,总想自己亲手来写写和配置Docker 容器相关的事情,这篇文章主要是参考了Los Tech ...
- Docker - 使用 swarm 部署 services
前言 经过之前一段时间学习与思考,我们已经大概明确了一些感念: Docker image/container, service and node 简单来说,swarm允许我们以节点(node)的方式 ...
- 新一代Java程序员必学的Docker容器化技术基础篇
Docker概述 **本人博客网站 **IT小神 www.itxiaoshen.com Docker文档官网 Docker是一个用于开发.发布和运行应用程序的开放平台.Docker使您能够将应用程序与 ...
- Docker - Docker基础讲义
Docker Docker - 官网 Docker - Hub GitHub - Docker Docker中文社区 虚拟化技术 硬件级虚拟化(hardware-level-virtualizatio ...
- Docker: docker container常用命令实战
容器管理,容器常用选项 选项 描述 -i, –interactive 交互式 -t, –tty 分配一个伪终端 -d, –detach 运行容器到后台 -e, –env 设置环境变量 -p, –pub ...
- Docker: docker image常用命令实战
#docker列出镜像[root@192 ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEnginx latest 881bd08c0b08 ...
- docker: docker安装和镜像下载
1 安装docker的apt源 apt-get install apt-transport-https ca-certificates curl software-properties-common ...
随机推荐
- C++虚函数表理解
一,思维模式图 二,代码验证 class A { public: A(int x) { fProtected = x; } float GetFProtected() { return fProtec ...
- (转) iphone开发资源汇总
如何用Facebook graphic api上传视频: http://developers.facebook.com/blog/post/532/ Keychain保存数据封装: https://g ...
- 【冷门】 C# 小技巧之获取变量名称
今天在自我规范程序设计的时候,变量名匹配字符串来自配置文件,网上找了一会儿发现也有朋友在找寻这种方式,很不容易找到一个解决方案来自http://www.th7.cn/Program/net/20140 ...
- [codevs3981]动态最大子段和不带修改(线段树)
解题关键:最大子段和需要多个信息维护. 注意查询时的pushup. #include<cstdio> #include<cstring> #include<algorit ...
- Nginx 事件基本处理流程分析
说明:本文章重点关注事件处理模型.有兴趣的同学可以去http://tengine.taobao.org/book/查找更多资料.Tengine应该是淘宝基于Nginx自己做的修改.这个地址的文档还在不 ...
- 洛谷 P2986 [USACO10MAR]伟大的奶牛聚集Great Cow Gat…(树规)
题目描述 Bessie is planning the annual Great Cow Gathering for cows all across the country and, of cours ...
- Python爬虫入门四之Urllib库的高级用法
1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Headers 的属性. 首先,打开我们的浏览 ...
- fgetc()
fgetc() 函数从文件指针中读取一个字符.
- Spring Boot☞ 使用Thymeleaf模板引擎渲染web视图
静态资源访问 在我们开发Web应用的时候,需要引用大量的js.css.图片等静态资源. 默认配置 Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则: /s ...
- python 输入输出,file, os模块
Python 输入和输出 输出格式美化 Python两种输出值的方式: 表达式语句和 print() 函数. 第三种方式是使用文件对象的 write() 方法,标准输出文件可以用 sys.stdout ...