Docker swarm部署微服务及利用portainer管理集群

1.微服务部署

在前面部署的集群上部署服务,以前通过docker run可以部署一个容器,通过docker-compose文件可以编排一组容器,现在可以利用docker service在swarm集群中通过服务下发任务到节点的方式部署容器副本集,甚至可以利用docker-compose文件来部署多个服务,每个服务再下发任务到各个节点

下面往集群中部署一个副本集
cat docker-compose.yml

version: "3"
services:
  web:
    image: nginx:1.7.9
    ports:
      - "80:80"
    networks:
      - webnet
    deploy:
      mode: replicated
      replicas: 3
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
networks:
  webnet:    

docker stack deploy -c docker-compose.yml myservice部署一个服务名叫myservice,该服务会往节点分发3个一样的应用,使用集群中的任意一台机器的ip加上发布的端口就会访问不同容器服务的结果,体现了负载均衡,这是因为集群中的每一个节点参与入口路由网格route mesh,这可以确保集群中某个端口部署的服务始终将该端口保留给自身,无论实际运行的是哪个节点

一般来说web端会连接数据库,比如连接redis数据库,修改docker-compose.yml文件
cat docker-compose.yml

version: "3.6"
services:
  web:
    image: nginx:1.7.9
    ports:
      - "80:80"
    networks:
      - webnet
    deploy:
      mode: replicated
      replicas: 3
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
  redis:
    image: redis
    deploy:
      placement:
        constraints: [engine.labels.host_ip==172.19.159.7]
      replicas: 1
      restart_policy:
        condition: on-failure
    ports:
      - "6379:6379"
    networks:
      - webnet
networks:
  webnet:
    driver: overlay

上面的redis约束constraints: [engine.labels.host_ip==172.19.159.7] 需要事先在相应节点engine打上标签
vi /etc/docker/daemon.json

"labels": ["host_ip=172.19.159.7"]

systemctl restart docker

如前面所说,虽然虽然redis只部署了一个任务,并且只会在打了标签的docker主机上启用任务,但是swarm集群会在所有节点发布6379端口,任何一个节点访问6379端口都会通过网格路由到redis服务上

2.docker可视化管理工具portainer

当swarm集群节点数以及部署的微服务数量增多,有一个图形界面管理工具来管理集群就会方便很多
portainer是一款轻量级的docker容器管理工具,支持原生的docker api,可以管理swarm 集群

2.1.部署portainer

将portainer部署在swarm集群中
cat portainer-stack.yml

version: '3.2'

services:
  portainer:
    image: portainer/portainer
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    ports:
      - target: 9000
        published: 9000
        protocol: tcp
        mode: host
    networks:
      - portainer
    deploy:
      mode: global
      placement:
        constraints: [node.platform.os == linux]

networks:
  portainer:
    driver: overlay

上面文件中有两个参数需要注意:

  • port下的mode值为host表示在每一个节点发布端口9000,但是该端口无负载均衡的功能,默认的ingress才有负载均衡功能,可以通过部署一个类似的nginx测试服务来测试,这里附上swarm文档中相关说明port的host模式与ingress模式
  • deploy下的mode值为global表示在每一个节点必须有一个任务启动,新增加的swam节点会自动发现并启动服务,而replicated是只保证总的任务数量,并不会强制要求每一个节点的任务数,所以global模式特别适合部署需要在每一个节点运行的应用,比如监控的agent

针对第一点可以编写一个类似的nginx测试文件
cat nginx-test.yml

version: '3.2'

services:
  test:
    image: nginx
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    ports:
      - target: 80
        published: 8080
        protocol: tcp
        mode: host
    networks:
      - test
    deploy:
      mode: global
      placement:
        constraints: [node.platform.os == linux]

networks:
  test:
    driver: overlay

docker stack deploy nginx-test.yml test
进入每一个任务节点上的test任务容器中,以node-1为例
docker exec -it test_test.vz0nu11cjz530dwg7347qcmk9.0hk0nht9cgsnezzohrzbrg41i bash
echo "node-1" > /usr/share/nginx/html/index.html

node-2与node-3类似
然后访问http://节点主机ip:8080 并没有出现负载均衡的情况,说明下发的任务只在节点上起作用

可以看看两种方式启动的服务端口的绑定状态
04swarm17

针对第二点可以直接删除某个的test任务容器,几秒后服务会再次在该节点启用一个任务

2.2.管理docker主机

管理docker主机分为三种:

  • 管理本地docker主机
  • 管理远程docker主机
  • 管理swarm集群

管理本地主机
以node-1为例
访问http://node-1IP:9000 设置账号密码登录
04swarm18

04swarm19

这样就可以管理node-1上的容器了

管理远程主机
在node-1上管理node-2,首先需要开启node-2的2375端口
node-2上
vi /usr/lib/systemd/system/docker.service

ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock

systemctl daemon-reload
systemctl restart docker

node-1portainer管理界面添加endpoint
04swarm20

重复操作添加node-3

管理swarm集群
要添加swarm集群管理需要在每个节点安装agent,编写yml文件
cat agent-stack.yml

version: '3.2'

services:
  agent:
    image: portainer/agent
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/volumes:/var/lib/docker/volumes
    ports:
      - target: 9001
        published: 9001
        protocol: tcp
        mode: host
    networks:
      - portainer_agent
    deploy:
      mode: global
      placement:
        constraints: [node.platform.os == linux]

networks:
  portainer_agent:
    driver: overlay

docker stack deploy -c agent-stack.yml portainer-agent
部署完后,添加endpoint,连接地址需要些swarm集群manager节点的agent地址
04swarm21

最后我们就可以通过一个界面来统一管理三种docker主机了
04swarm22