Docker 三剑客之 Docker Swarm
<p>上一篇:Docker 三剑客之 Docker Compose</p><p>阅读目录:</p>
<ul>
<li><strong>Docker Machine 创建 Docker 主机</strong></li>
<li><strong>Docker Swarm 配置集群节点</strong></li>
<li><strong>Docker Service 部署单个集群服务</strong></li>
<li><strong>Docker Stack 部署多个集群服务,以及 GUI 管理页面</strong></li>
<li><strong>docker-machine、docker swarm、docker node、docker service 和 docker stack 常用命令</strong></li>
</ul>
<p>Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。</p>
<p>从 Docker 1.12.0 版本开始,Docker Swarm 已经包含在 Docker 引擎中(<code>docker swarm</code>),并且已经内置了服务发现工具,我们就不需要像之前一样,再配置 Etcd 或者 Consul 来进行服务发现配置了。</p>
<h2 id="1-docker-machine-创建-docker-主机">1. Docker Machine 创建 Docker 主机</h2>
<p>在进行 Docker Swarm 配置之前,我们还需要说下 Docker 另外一个官方工具 Docker Machine(也是 Docker 三剑客之一),其作用就是快速帮助我们搭建 Docker 主机环境,比如我们要使用 Docker Swarm,就必须有很多的 Docker 主机来进行操作,Docker Machine 就是最理想的工具。</p>
<p>因为我是在 Mac OS 上进行操作的,并且 Docker for Mac 已经包含了 Docker Machine(<code>docker machine</code>),所以我不需要再额外进行安装了,如果使用 Linux 系统的话,安装也非常简单,命令:</p>
<pre><code class="language-bash">$ sudo curl -L https://github.com/docker/machine/releases/download/v0.13.0/docker-machine-`uname -s`-`uname -m` > /usr/local/bin/docker-machine
$ sudo chmod +x /usr/local/bin/docker-machine
</code></pre>
<p>好了,我们先使用 Docker Machine 创建四个 Docker 主机,命令:</p>
<pre><code class="language-bash">$ docker-machine create -d virtualbox manager1 &&
docker-machine create -d virtualbox manager2 &&
docker-machine create -d virtualbox worker1 &&
docker-machine create -d virtualbox worker2
Running pre-create checks...
(worker1) No default Boot2Docker ISO found locally, downloading the latest release...
(worker1) Latest release for github.com/boot2docker/boot2docker is v17.11.0-ce
(worker1) Downloading /Users/xishuai/.docker/machine/cache/boot2docker.iso from https://github.com/boot2docker/boot2docker/releases/download/v17.11.0-ce/boot2docker.iso...
</code></pre>
<p>执行上面命令,你会发现速度巨慢(如上),原因是从 GitHub 上下载一个<code>boot2docker.iso</code>文件(国内网络没办法),怎么解决呢?很简单,我们使用翻X的浏览器手动下载<code>boot2docker.iso</code>文件,然后拷贝到对应目录下(我电脑的目录<code>/Users/xishuai/.docker/machine/cache/</code>),然后再执行上面的命令,发现速度快的一批。</p>
<p>我们可以查看下创建的 Docker 主机信息,命令:</p>
<pre><code class="language-bash">$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
manager1 - virtualbox Running tcp://192.168.99.100:2376 v17.11.0-ce
manager2 - virtualbox Running tcp://192.168.99.101:2376 v17.11.0-ce
worker1 - virtualbox Running tcp://192.168.99.102:2376 v17.11.0-ce
worker2 - virtualbox Running tcp://192.168.99.103:2376 v17.11.0-ce
</code></pre>
<p>可以看到,我们创建了四个 Docker 主机(两个 Manager 和两个 Worker),我们还可以连接到任何一台服务器进行操作,命令:</p>
<pre><code class="language-bash">$ docker-machine ssh manager1
## .
## ## ## ==
## ## ## ## ## ===
/"""""""""""""""""\___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /===- ~~~
\______ o __/
\ \ __/
\____\_______/
_ _ ____ _ _
| |__ ___ ___ | |_|___ \ __| | ___ ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__| <__/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 17.11.0-ce, build HEAD : e620608 - Tue Nov 21 18:11:40 UTC 2017
Docker version 17.11.0-ce, build 1caf76c
</code></pre>
<h2 id="2-docker-swarm-配置集群节点">2. Docker Swarm 配置集群节点</h2>
<p>我们执行下面命令:</p>
<pre><code class="language-bash">$ docker-machine ssh manager1 "docker swarm init --advertise-addr 192.168.99.100"
Swarm initialized: current node (n0ub7dpn90rxjq97dr0g8we0w) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-envtxo4dl6df2ar3qldcccfdg 192.168.99.100:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
</code></pre>
<p>上面是在<code>manager1</code>主机上,创建一个 Docker Swarm 管理节点(初始化集群的时候,会自动把当前节点设置为管理节点)。</p>
<p>接着,我们在<code>worker1</code>和<code>worker2</code>主机上,创建两个工作节点,并加入到集群中,命令:</p>
<pre><code class="language-bash">$ docker-machine ssh worker1 "docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-envtxo4dl6df2ar3qldcccfdg 192.168.99.100:2377"
This node joined a swarm as a worker.
$ docker-machine ssh worker2 "docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-envtxo4dl6df2ar3qldcccfdg 192.168.99.100:2377"
This node joined a swarm as a worker.
</code></pre>
<p>还有另外一个<code>manager2</code>主机,需要配置为管理节点,我们需要先在<code>manager1</code>主机上,获取管理节点对应的<code>token</code>,然后再配置为管理节点,命令:</p>
<pre><code class="language-bash">$ docker-machine ssh manager1 "docker swarm join-token manager"
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-0koz1b98sco8r5cn3g61eahnu 192.168.99.100:2377
$ docker-machine ssh manager2 "docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-0koz1b98sco8r5cn3g61eahnu 192.168.99.100:2377"
This node joined a swarm as a manager.
</code></pre>
<p>配置好之后,我们进入<code>manager1</code>主机内(上面的命令也可以在主机内执行),然后查看集群节点的信息,命令:</p>
<pre><code class="language-bash">$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
n0ub7dpn90rxjq97dr0g8we0w * manager1 Ready Active Leader
t4cy67qp0bf2spgabsutwxnzt manager2 Ready Active Reachable
if0kmzp4ww3oy57y7cha7v36t worker1 Ready Active
jgg61cujzaeb3du5796fm0x2g worker2 Ready Active
</code></pre>
<p><code>Leader</code>表示当然集群的头,<code>Reachable</code>可以理解为头的候选人,头一挂掉它就顶上去了。</p>
<hr>
<p>需要注意的是,我当天配置好之后,把所有的 Docker 主机都<code>stop</code>了,然后隔天重新<code>start</code>之后,出现了下面问题:</p>
<pre><code class="language-bash">docker node ls
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.
</code></pre>
<p>好像是集群节点丢失了头,相关问题:如何处理 docker swarm 集群"The swarm does not have a leader"问题,按照文章进行解决:</p>
<pre><code class="language-bash">$ docker swarm init --force-new-cluster
Error response from daemon: could not choose an IP address to advertise since this system has multiple addresses on different interfaces (10.0.2.15 on eth0 and 192.168.99.102 on eth1) - specify one with --advertise-addr
$ docker swarm init --force-new-cluster --advertise-addr 192.168.99.102
Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager.
$ docker node ls
卡死
$ docker-machine restart manager1
重启不了,一直转圈
</code></pre>
<p>没办法,后来我只能删掉四个 Docker 主机,重新进行创建了。</p>
<h2 id="3-docker-service-部署单个集群服务">3. Docker Service 部署单个集群服务</h2>
<p>在部署集群服务之前,我们需要做些准备工作,因为 Docker 主机中没有配置 Docker 镜像加速地址,所以在拉取官方镜像的时候,肯定会非常慢,除了配置 Docker 镜像加速地址之外,我们还可以使用 Docker 私有镜像仓库,来解决这个问题。</p>
<p>参考文章:Ubuntu Docker Registry 搭建私有仓库</p>
<p>这边,我再简单说明下配置步骤,首先,在 Mac OS 上执行下面命令:</p>
<pre><code class="language-bash">$ docker run -d -v /Users/xishuai/Documents/Docker:/var/lib/registry -p 5000:5000 --restart=always --name registry registry
$ docker tag nginx 192.168.99.1:5000/nginx:latest &&
docker push 192.168.99.1:5000/nginx:latest &&
docker pull 192.168.99.1:5000/nginx:latest
$ curl http://192.168.99.1:5000/v2/_catalog
{"repositories":["nginx"]}
</code></pre>
<p>我们在 Mac OS 上创建了一个私有仓库容器,并把<code>nginx</code>镜像放到私有仓库中,因为没有使用 Https,所以在拉取和推送镜像的时候,会报如下错误(Mac OS 和 Docker 主机都会报错):</p>
<pre><code class="language-bash">$ docker pull 192.168.99.1:5000/nginx:latest
The push refers to a repository
Get https://192.168.99.1:5000/v1/_ping: http: server gave HTTP response to HTTPS client
</code></pre>
<p>解决方式,我们需要分别在四个 Docker 主机中添加配置(Docker for Mac 在管理界面配置即可),命令:</p>
<pre><code class="language-bash">$ sudo touch /etc/docker/daemon.json &&
sudo chmod 777 /etc/docker/daemon.json &&
sudo echo '{ "insecure-registries": ["192.168.99.1:5000"] }' > /etc/docker/daemon.json
</code></pre>
<p>然后重启四个 Docker 主机(Docker for Mac 也需要重启),命令:</p>
<pre><code class="language-bash">$ docker-machine restart manager1 &&
docker-machine restart manager2 &&
docker-machine restart worker1 &&
docker-machine restart worker2
</code></pre>
<hr>
<p>上面比较啰嗦,我们接下来正式部署集群服务,还是拿<code>nginx</code>镜像做为示例,命令(<code>docker service create</code>命令详细说明):</p>
<pre><code class="language-bash">$ docker service create --replicas 4 -p 8088:80 --name nginx 192.168.99.1:5000/nginx:latest
ap8h8srb8yh3mni0h2nz61njz
overall progress: 4 out of 4 tasks
1/4: running [==================================================>]
2/4: running [==================================================>]
3/4: running [==================================================>]
4/4: running [==================================================>]
verify: Service converged
</code></pre>
<p>需要注意的是,<code>--replicas 4</code>表示创建服务的实例个数(默认是一个),啥意思?比如4,就是在四个 Docker 主机上,分别创建一个<code>nginx</code>服务,如果是3,那就是三个 Docker 主机,或者你可以理解为 Docker 主机的个数,另外,<code>REPLICAS</code>会有进度显示,并且执行是异步的。</p>
<p>我们也可以手动设置实例个数,命令:</p>
<pre><code class="language-bash">$ docker service scale nginx=4
</code></pre>
<p>部署好服务后,我们就可以进行查看了,命令:</p>
<pre><code class="language-bash">$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
ap8h8srb8yh3 nginx replicated 4/4 192.168.99.1:5000/nginx:latest *:8080->8080/tcp
$ docker service ps nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
l2rdrwzs5zog nginx.1 192.168.99.1:5000/nginx:latest manager1 Running Running about a minute ago
vsfczzbwanx3 nginx.2 192.168.99.1:5000/nginx:latest manager2 Running Running about a minute ago
qtbgw5h6dsi9 nginx.3 192.168.99.1:5000/nginx:latest worker Running Running about a minute ago
za2ejnvb3n6z nginx.4 192.168.99.1:5000/nginx:latest worker2 Running Running about a minute ago
</code></pre>
<p>我们任意使用四个 Docker 主机中的一个 IP 地址,浏览器打开:http://192.168.99.100:8088/</p>
<img src="https://images2017.cnblogs.com/blog/435188/201712/435188-20171205185952425-1749261339.png" width="800px">
<h2 id="4-docker-stack-部署多个集群服务以及-gui-管理页面">4. Docker Stack 部署多个集群服务,以及 GUI 管理页面</h2>
<p><code>docker service</code>部署的是单个服务,我们可以使用<code>docker stack</code>进行多服务编排部署,使用的同样是<code>docker-compose.yml</code>配置文件,示例:</p>
<pre><code class="language-yml">version: "3"
services:
nginx:
image: 192.168.99.1:5000/nginx:latest
ports:
- 8088:80
deploy:
mode: replicated
replicas: 4
visualizer:
image: 192.168.99.1:5000/dockersamples/visualizer:latest
ports:
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
replicas: 1
placement:
constraints:
portainer:
image: 192.168.99.1:5000/portainer/portainer:latest
ports:
- "9000:9000"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
replicas: 1
placement:
constraints:
</code></pre>
<p>如上所示,我们总共需要部署三个服务,出了<code>nginx</code>服务作为示例之外,<code>visualizer</code>(官方地址)和<code>portainer</code>(官方地址)都是集群 GUI 管理服务。</p>
<p>部署命令:</p>
<pre><code class="language-bash">$ docker stack deploy -c docker-compose.yml deploy-demo
Creating service deploy-demo_nginx
Creating service deploy-demo_visualizer
Creating service deploy-demo_portainer
</code></pre>
<p>部署成功之后,我们可以查看具体详情,命令:</p>
<pre><code class="language-bash">$ docker stack ls
NAME SERVICES
deploy-demo 3
</code></pre>
<p>查看<code>visualizer</code>GUI 集群管理,浏览器打开:http://192.168.99.100:8080/</p>
<p><img src="https://images2017.cnblogs.com/blog/435188/201712/435188-20171205185941863-985581867.png" alt="" loading="lazy"></p>
<p>查看<code>portainer</code>GUI 集群管理,需要先配置账号信息,浏览器打开:http://192.168.99.100:9000/</p>
<p><img src="https://images2017.cnblogs.com/blog/435188/201712/435188-20171205185920628-290962984.gif" alt="" loading="lazy"></p>
<p>可以看到,<code>portainer</code>比<code>visualizer</code>强大太多了,甚至我们所有的操作都可以在<code>portainer</code>上完成。</p>
<h2 id="5-docker-machinedocker-swarmdocker-nodedocker-service-和-docker-stack-常用命令">5. docker-machine、docker swarm、docker node、docker service 和 docker stack 常用命令</h2>
<h3 id="docker-machine-常用命令">docker-machine 常用命令</h3>
<table>
<thead>
<tr>
<th>命令</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>docker-machine create</td>
<td>创建一个 Docker 主机(常用<code>-d virtualbox</code>)</td>
</tr>
<tr>
<td>docker-machine ls</td>
<td>查看所有的 Docker 主机</td>
</tr>
<tr>
<td>docker-machine ssh</td>
<td>SSH 到主机上执行命令</td>
</tr>
<tr>
<td>docker-machine env</td>
<td>显示连接到某个主机需要的环境变量</td>
</tr>
<tr>
<td>docker-machine inspect</td>
<td>输出主机更多信息</td>
</tr>
<tr>
<td>docker-machine kill</td>
<td>停止某个主机</td>
</tr>
<tr>
<td>docker-machine restart</td>
<td>重启某台主机</td>
</tr>
<tr>
<td>docker-machine rm</td>
<td>删除某台主机</td>
</tr>
<tr>
<td>docker-machine scp</td>
<td>在主机之间复制文件</td>
</tr>
<tr>
<td>docker-machine start</td>
<td>启动一个主机</td>
</tr>
<tr>
<td>docker-machine status</td>
<td>查看主机状态</td>
</tr>
<tr>
<td>docker-machine stop</td>
<td>停止一个主机</td>
</tr>
</tbody>
</table>
<h3 id="docker-swarm-常用命令">docker swarm 常用命令</h3>
<table>
<thead>
<tr>
<th>命令</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>docker swarm init</td>
<td>初始化集群</td>
</tr>
<tr>
<td>docker swarm join-token worker</td>
<td>查看工作节点的 token</td>
</tr>
<tr>
<td>docker swarm join-token manager</td>
<td>查看管理节点的 token</td>
</tr>
<tr>
<td>docker swarm join</td>
<td>加入集群中</td>
</tr>
</tbody>
</table>
<h3 id="docker-node-常用命令">docker node 常用命令</h3>
<table>
<thead>
<tr>
<th>命令</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>docker node ls</td>
<td>查看所有集群节点</td>
</tr>
<tr>
<td>docker node rm</td>
<td>删除某个节点(<code>-f</code>强制删除)</td>
</tr>
<tr>
<td>docker node inspect</td>
<td>查看节点详情</td>
</tr>
<tr>
<td>docker node demote</td>
<td>节点降级,由管理节点降级为工作节点</td>
</tr>
<tr>
<td>docker node promote</td>
<td>节点升级,由工作节点升级为管理节点</td>
</tr>
<tr>
<td>docker node update</td>
<td>更新节点</td>
</tr>
<tr>
<td>docker node ps</td>
<td>查看节点中的 Task 任务</td>
</tr>
</tbody>
</table>
<h3 id="docker-service-常用命令">docker service 常用命令</h3>
<table>
<thead>
<tr>
<th>命令</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>docker service create</td>
<td>部署服务</td>
</tr>
<tr>
<td>docker service inspect</td>
<td>查看服务详情</td>
</tr>
<tr>
<td>docker service logs</td>
<td>产看某个服务日志</td>
</tr>
<tr>
<td>docker service ls</td>
<td>查看所有服务详情</td>
</tr>
<tr>
<td>docker service rm</td>
<td>删除某个服务(<code>-f</code>强制删除)</td>
</tr>
<tr>
<td>docker service scale</td>
<td>设置某个服务个数</td>
</tr>
<tr>
<td>docker service update</td>
<td>更新某个服务</td>
</tr>
</tbody>
</table>
<h3 id="docker-stack-常用命令">docker stack 常用命令</h3>
<table>
<thead>
<tr>
<th>命令</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>docker stack deploy</td>
<td>部署新的堆栈或更新现有堆栈</td>
</tr>
<tr>
<td>docker stack ls</td>
<td>列出现有堆栈</td>
</tr>
<tr>
<td>docker stack ps</td>
<td>列出堆栈中的任务</td>
</tr>
<tr>
<td>docker stack rm</td>
<td>删除堆栈</td>
</tr>
<tr>
<td>docker stack services</td>
<td>列出堆栈中的服务</td>
</tr>
<tr>
<td>docker stack down</td>
<td>移除某个堆栈(不会删除数据)</td>
</tr>
</tbody>
</table>
<p>参考资料:</p>
<ul>
<li>Get Started, Part 4: Swarms</li>
<li>Docker 三剑客之 Docker Swarm</li>
<li>Docker Swarm 入门一篇文章就够了</li>
<li>Docker 的命令之集群节点管理 Swarm node</li>
<li>docker service 命令</li>
<li>Docker 命令行参考(37) – docker service create 创建一个服务</li>
<li>Docker Machine 是什么?</li>
<li>docker swarm 学习命令整理</li>
</ul>
</div>
<div id="MySignature" role="contentinfo">
<div id="xishuai_qianming2">
作者:田园里的蟋蟀
<br>微信公众号:<strong>你好架构</strong>
<br>出处:http://www.cnblogs.com/xishuai/
<br>
公众号会不定时的分享有关架构的方方面面,包含并不局限于:Microservices(微服务)、Service Mesh(服务网格)、DDD/TDD、Spring Cloud、Dubbo、Service Fabric、Linkerd、Envoy、Istio、Conduit、Kubernetes、Docker、MacOS/Linux、Java、.NET Core/ASP.NET Core、Redis、RabbitMQ、MongoDB、GitLab、CI/CD(持续集成/持续部署)、DevOps等等。
<br>
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
</div>
<br>
<div class="jiathis_style">
<span class="jiathis_txt">分享到:</span>
QQ空间
新浪微博
腾讯微博
微信
更多
</div><br><br>
来源:https://www.cnblogs.com/xishuai/p/docker-swarm.html
頁:
[1]