前言
Docker Swarm可以看做是多个Docker Engines的集群方式,是docker的一种编排工具,当前版本的Docker包含swarm模式,用于本地管理称为Swarm的Docker引擎集群。 使用Docker CLI创建集群,将应用程序服务部署到集群以及管理集群行为。
Docker Engine中嵌入的集群管理和编排功能是使用swarmkit构建的。 Swarmkit是一个单独的项目,用于实现Docker的业务流程层,并直接在Docker中使用。
一个群集由多个Docker主机组成,这些Docker主机以群集模式运行,并充当管理员(用于管理成员资格和委派)和工作人员(运行群集服务)。 给定的Docker主机可以是管理员,工作人员或同时担任这两个角色。 创建服务时,您要定义其最佳状态(可用副本,网络和存储资源的数量,服务向外界公开的端口等)。 Docker致力于维持所需状态。 例如,如果一个工作节点不可用,则Docker会将该节点的任务安排在其他节点上。 任务是一个运行中的容器,它是群集服务的一部分,由群集管理器管理,而不是独立的容器。
![5cb176ce88d66b1d34c2ee75be23a9ce.png](https://i-blog.csdnimg.cn/blog_migrate/4c03984d3e62d2b65f4b8509e55a1603.jpeg)
更多表示请参考官方文档https://docs.docker.com/engine/swarm/key-concepts/
部署方式
首先准备两台或者三台可以使用的主机,比如manager1、manager2、manage3
登录主机manager1用来创建swarm集群管理节点。
docker swarm init --advertise-addr 192.168.99.1
这里的-- advertise-addr表示集群对外暴露的ip,后续所有的节点要加入到要通过
此ip加入。如果不指定,则机器会自动选择合理的ip,如下所示:
docker swarm initSwarm initialized: current node (ulypq2b3eb176aka0rtzjmnnp) is now a manager.To add a worker to this swarm, run the following command:docker swarm join --token SWMTKN-1-4b0aux48r0yib3jt5kuhw12cbd73a8vxh4vo6zt3nlpcpz7o26-9xs3ss6s5odmvx9cxw7k1vxu4 172.21.0.10:2377To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
到此一个swarm集群管理创建成功。
然后分别登录manager2、manager3执行如下命令将另外两个节点加入到此管理节点中。
docker swarm join --token SWMTKN-1-4b0aux48r0yib3jt5kuhw12cbd73a8vxh4vo6zt3nlpcpz7o26-9xs3ss6s5odmvx9cxw7k1vxu4 172.21.0.10:2377命令加入到此节点当中
如果以上命令找不到可以使用docker swarm join-token worker命令将其找回。
到此执行docker info查看swarm当前节点的状态
Swarm: active NodeID: ulypq2b3eb176aka0rtzjmnnp Is Manager: true ClusterID: gcrsq6qqaqhwiekecirdmldco Managers: 1 Nodes: 1 Default Address Pool: 10.0.0.0/8 SubnetSize: 24 Orchestration: Task History Retention Limit: 5
执行docker node ls查看连接到的节点
![39afb6266cba8a412564eec21ce675c1.png](https://i-blog.csdnimg.cn/blog_migrate/d64a7d0120bff6ba978f606d2a0d01bb.jpeg)
部署服务到swarm节点
docker service create --replicas 1 --name helloworld alpine ping docker.com
-- replaicas 1表示期望一个服务实例
-- name 表示运行的服务名称
alpine ping docker.com 表示运行的镜像是alpine 命令为ping,如下图,创建成功一个服务实例
![20fd793020931e8a695c797bc4b41e0f.png](https://i-blog.csdnimg.cn/blog_migrate/ee2cbe39a302524943da6f803fbca480.jpeg)
可以使用docekr service ls来查看运行的服务实例。
![c3685a08c6b434dba3b6a9bc3b32982b.png](https://i-blog.csdnimg.cn/blog_migrate/81a93d7a856c1737d8bd8234ddb47130.jpeg)
运行命令docker service inspect --pretty 服务id
来查看优化显示的服务详情 去掉以joson显示
docker service inspect --pretty b9cmmraop0tbID:b9cmmraop0tbrcc6z6ld47fnhName:helloworldService Mode:Replicated Replicas:1Placement:UpdateConfig: Parallelism:1 On failure:pause Monitoring Period: 5s Max failure ratio: 0 Update order: stop-firstRollbackConfig: Parallelism:1 On failure:pause Monitoring Period: 5s Max failure ratio: 0 Rollback order: stop-firstContainerSpec: Image:alpine:latest@sha256:185518070891758909c9f839cf4ca393ee977ac378609f700f60a771a2dfe321 Args:ping docker.com Init:falseResources:Endpoint Mode:vip
运行docker service ps 服务id 将查看到哪些节点在运行该服务实例
docker service ps b9cmmraop0tbID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTSp5vnvit9gbp9 helloworld.1 alpine:latest zhaoyd
同时使用docekr ps也可以看到运行的容器
![ec97479908037b8074893bff0931dd59.png](https://i-blog.csdnimg.cn/blog_migrate/a8bebace1bb125aed1c552070d436b8b.jpeg)
swarm集群删除应用
docker service rm helloworld
swarm的滚动更新
docker service create --replicas 3 --name redis --update-delay 10s redis:3.0.7-alpine
这里使用redis镜像测试滚动更新任务--update-delay 表示更新服务对应的任务或一组任务之间的时间间隔。时间间隔用数字和时间单位表示,m 表示分,h 表示时,所以 10m30s 表示 10 分 30 秒的延时。
默认情况下,调度器一次更新一个任务。你可以使用 --update-parallelism 标志配置调度器每次同时更新的最大任务数量。
默认情况下,如果更新某个任务返回了RUNNING状态,调度器会转去更新另一个任务,直到所有任务都更新完成。如果在更新某个任务的任意时刻返回了FAILED,调度器暂停更新。我们可以在执行 docker service create 命令和 docker service update 命令时使用 --update-failure-action 标志来覆盖这种默认行为
更新redis镜像
swarm管理节点会根据UpdateConfig策略来更新节点
docker service update --image redis:3.2.5-alpine redis
调度器根据下面默认的策略来应用滚动更新:
- 停止第一个任务。
- 未停止的任务应用更新。
- 为更新的任务启动容器。
- 如果更新任务时返回RUNNING,等待一个指定的延时后停止下一个任务。
- 如果,在更新的任意时刻,某个任务返回FAILED,暂停更新
docker service inspect --pretty redis 查看状态可以看到已经更新到期望版本。
下线某个swarm节点
从前面的示例中可以看出swarm的状态为avtive,表示所有节点可以接受任务有时候,比如到了计划的维护时间,你需要将节点的可用性设为DRAIN。可用性为DRAIN的节点不会从 swarm 接收任何新任务。同时,管理器将停止运行在该节点上的任务,并在另外可用性为 ACTIVE 的节点上启动相应的任务副本。
通过docker node ls命令查看可用节点使用docker node update --availability drain manager2下线
此时查看被下线的服务,则可以看到状态已经变更为drain
$ docker node lsID HOSTNAME STATUS AVAILABILITY MANAGER STATUS4rkvaeauhftolat98u5ty01iz worker02 Ready Drain 7ik7wqhe5wcag8k5tp816c7ck * manager01 Ready Active Leadercashcvy4qzcq3lvtnix4trqu7 worker01 Ready Activ
那么如何修改为活动状态呢。使用如下命令即可恢复
docker node update --availability active manager2
swarm模式下的覆盖网络
当Docker在swarm模式下运行时,您可以在管理节点上创建覆盖网络,而无需外部key-value存储。swarm使覆盖网络仅可用于需要服务的swarm节点。 当您创建使用覆盖网络的服务时,管理节点会自动将覆盖网络扩展到运行服务任务的节点。
下面的示例显示了如何创建网络并将其用于来自swarm管理节点的服务:
$ docker network create --driver overlay --subnet 10.0.9.0/24 my-multi-host-network400g6bwzd68jizzdx5pgyoe95$ docker service create --replicas 2 --network my-multi-host-network --name my-web nginx716thylsndqma81j6kkkb5aus
上述代码创建的服务就是使用的my-multi-host-network自定义的覆盖网络。
只有swarm服务可以连接到覆盖网络,而不是独立的容器
非swarm模式下的覆盖网络
如果您不是在swarm模式下使用Docker Engine,那么overlay网络需要有效的key-value存储。 支持的key-value存储包括Consul,Etcd和ZooKeeper(分布式存储)。 在以这种方式创建网络之前,您必须安装并配置您所选择的key-value存储服务。 网络中的Docker宿主机、服务必须能够进行通信。
注意 :以swarm模式运行的Docker Engine与使用外部key-value存储的网络不兼容。
自定义网络插件
如果任何上述网络机制无法满足您的需求,您可以使用Docker的插件基础架构编写自己的网络驱动插件。 该插件将在运行Docker deamon的主机上作为单独的进程运行。 使用网络插件是一个高级主题。
网络插件遵循与其他插件相同的限制和安装规则。 所有插件都使用插件API,并具有包含了安装,启动,停止和激活的生命周期。
创建并安装自定义网络驱动后,您可以使用--driver 标志创建一个使用该驱动的网络。
docker network create --driver weave mynet
内嵌DNS服务器
Docker daemon运行一个嵌入式的DNS服务器,从而为连接到同一用户自定义网络的容器之间提供DNS解析——这样,这些容器即可将容器名称解析为IP地址。 如果内嵌DNS服务器无法解析请求,它将被转发到为容器配置的任意外部DNS服务器。 为了方便,当容器创建时,只有127.0.0.11 可访问的内嵌DNS服务器会列在容器的resolv.conf文件中。
暴露和发布端口
在Docker网络中,有两种不同的机制可以直接涉及网络端口:暴露端口和发布端口。 这适用于默认网桥和用户定义的网桥。
- 您使用Dockerfile 中的EXPOSE 关键字或 docker run 命令中的--expose 标志来暴露端口。 暴露端口是记录使用哪些端口,但实际上并不映射或打开任何端口的一种方式。 暴露端口是可选的。
- 您可以使用Dockerfile 中的PUBLISH 关键字或 docker run 命令中的--publish标志来发布端口。 这告诉Docker在容器的网络接口上打开哪些端口。当端口发布时,它将映射到宿主机上可用的高阶端口(高于30000 ),除非您在运行时指定要映射到宿主机的哪个端口。 您不能在Dockerfile中指定要映射的端口,因为无法保证端口在运行image的宿主机上可用。此示例将容器中的端口80发布到宿主机上的随机高阶端口(在这种情况下为32768 )。 -d 标志使容器在后台运行,因此您可以发出docker ps 命令。
docker run -it -d -p 80 nginx$ docker ps64879472feea nginx "nginx -g 'daemon ..." 43 hours ago Up About a minute 443/tcp, 0.0.0.0:32768->80/tcp blissful_mclean
下一个示例指定80端口应映射到宿主机上的8080端口。 如果端口8080不可用,将失败。
$ docker run -it -d -p 8080:80 nginx$ docker psb9788c7adca3 nginx "nginx -g 'daemon ..." 43 hours ago Up 3 seconds 80/tcp, 443/tcp, 0.0.0.0:8080->80/tcp goofy_brahmagupta
容器与代理服务器
如果您的容器需要使用HTTP、HTTPS或者FTP代理,你可以使用如下两种方式进行配置:
- 对于Docker 17.07或更高版本,你可以配置Docker客户端从而将代理信息自动传递给容器。
- 对于Docker 17.06或更低版本,你必须在容器内设置环境变量。你可以在构建镜像(这样不太好移植)或启动容器时执行此操作。
在Docker客户端上,在启动容器所使用的用户的主目录中创建或编辑~/.config.json 文件。在其中添加如类似下所示的JSON,如果需要,使用httpsproxy 或ftpproxy 替换代理类型,然后替换代理服务器的地址和端口。 您可以同时配置多个代理服务器。
您可以通过将noProxy 键设置为一个或多个逗号分隔的IP地址或主机名来选择将指定主机或指定范围排除使用代理服务器。 支持使用*字符作为通配符,如此示例所示。
{ "proxies": { "httpProxy": "http://127.0.0.1:3001", "noProxy": "*.test.example.com,.example2.com" }}
保存文件
2、当您创建或启动新容器时,环境变量将在容器内自动设置。
手动设置环境变量
在构建映像时,或在创建或运行容器时使用--env 标志,可将下表中的一个或多个变量设置为适当的值。 这种方法使镜像不太可移植,因此如果您使用Docker 17.07或更高版本,则应该配置Docker客户端。
变量 Dockerfile示例 docker run示例HTTP_PROXYENV HTTP_PROXY "http://127.0.0.1:3001" --env HTTP_PROXY "http://127.0.0.1:3001"HTTPS_PROXYENV HTTPS_PROXY "https://127.0.0.1:3001" --env HTTPS_PROXY "https://127.0.0.1:3001"FTP_PROXYENV FTP_PROXY "ftp://127.0.0.1:3001" --env FTP_PROXY "ftp://127.0.0.1:3001"NO_PROXY `ENV NO_PROXY “*.test.example.com,.example2.com” -env NO_PROXY“* .test.example.com,.example2.com”
在Docker包含“用户自定义网络”功能之前,您可以使用Docker --link 功能来允许容器将另一个容器的名称解析为IP地址,还可以访问你所链接的容器的环境变量。 如果可以,您应该避免使用 --link 标志。
当您创建连接时,当您使用默认bridge 或用户自定义网桥时,它们的行为会有所不同
Docker和iptables
Linux主机使用内核模块iptables 来管理对网络设备的访问,包括路由,端口转发,网络地址转换(NAT)等问题。 Docker会在启动或停止发布端口的容器、创建或修改网络、attach到容器或其他与网络相关的操作时修改iptables 规则。
对iptables 全面讨论超出了本主题的范围。 要查看哪个iptables 规则在任何时间生效,可以使用iptables -L 。 如存在多个表,例如nat , prerouting 或postrouting ,您可以使用诸如iptables -t nat -L 类的命令列出特定的表。 有关iptables 的完整文档,请参阅netfilter / iptables 。
通常, iptables规则由初始化脚本或守护进程创建,例如firewalld 。 规则在系统重新启动时不会持久存在,因此脚本或程序必须在系统引导时执行,通常在运行级别3或直接在网络初始化之后运行。请参阅您的Linux发行版的网络相关的文档,了解如何使iptables 规则持续存在。
Docker动态管理Docker daemon、容器,服务和网络的iptables 规则。 在Docker 17.06及更高版本中,您可以向名为DOCKER-USER的新表添加规则,这些规则会在Docker自动创建任何规则之前加载。 如果您需要在Docker运行之前预先设置需要使用的iptables 规则,这将非常有用
到此本篇文章就说完了,可能有点长,不过建议收藏,后续还可以拿来参考。