技术流ken

运维拯救世界

docker三剑客之Swarm(十七)–技术流ken

Swarm 简介

 

Docker Swarm Docker 公司推出的官方容器集群平台 基于 Go 语言实现,代码开源在 https :// github.com/ docker swarm 目前,包括 Rackspace等平台都采用了 Swarm ,用户也很容易在 AWS 等公有云平台使用 Swarm。Swarm 的前身是 Beam 项目和 libswarm 项目,首个正式版本( Swarm Vl )在 2014年12 月初发布,为了提高可扩展性, 2016 月对架构进行重新设计,推出了 V2 版本,支持超过 lK 个节点。最新的 Dock Engine ( 1.12后)已经集成了 SwarmKit 内嵌了对 Swarm 模式的支持。

作为容器集群管理器, Swarm 最大的优势之一就是原生支持 Docker API ,给用户使用带来极大的便利 各种基于标准 凹的工具比如 Compose Docker SDK 、各 管理软件, 甚至Docker 本身等都可以很容易的与 Swarm 进行集成 这大大方便了用户将原先基于单节点的系统移植到 Swarm上。同时 Swarm 置了对 Docker 网络插件的支持,用户可以很容易地部署跨主机的容器集群服务。

Swarm 也采用了典型的“主从”结构(如图 所示 ),通过Raft 协议来在多个管理节点(Manager )中实现共识 工作节点( Worker )上运行 agent 接受管理节点的统一管理和任务分配 用户提交服务请求只需要发给管理节点即可,管理节点会按照调度策略在集群中分配节点来运行服务相关的任务

在Swarm V2 中,集群中会自动通过 Raft 协议分布式选举出 Manager 节点,无须额外的发现服务支持,避免了单点瓶颈 同时, V2 中内置了基于 DNS 的负载均衡和对外部负载均衡机制的集成支持。

本章将以 Swarm V2 为主进行介绍

 

基本概念

 

Swarm Docker 基础上扩展了支持多节点的能力,同时兼容了大部分的 Docker 操作。Swarm 中以集群为单位进行管理,支持服务层面的操作。下面首先介绍 Swarm 使用中的 些基本概念。

 

1.Swarm 集群

Swarm 集群( Cluster )为 组被统一管理起来的 Docker 主机 集群是 Swarm 所管理的对象 这些主机通过 Docker 引擎的 Swarm 模式相互沟通,其中部分主机可能作为管理节点(manager )响应外部的管理请求,其他主机作为工作节点( worker )来实际运行 Docker 容器。当然,同一个主机也可以即作为管理节点,同时作为工作节点。

当用户使用 Swarm 集群时,首先定义 个服务(指定状态、复制个数、网络、存储、暴露端口等),然后通过管理节点发出启动服务的指令,管理节点随后会按照指定的服务规则进行调度,在集群中启动起来整个服务,并确保它正常运行。

 

2.节点

节点(Node )是 Swarm 集群的最小资源单位 每个节点实际上都是一台 Docker 主机。

Swarm 集群中节点分为两种:

第一种:管理节点(manager node ):负责响应外部对集群的操作请求,并维持集群中资源,分发任务给工作节点 同时,多个管理节点之间通过 Raft 协议构成共识 一般推荐每个集群设置5个或 7个管理节点;

第二种:工作节点( worker node ):负责执行管理节点安排的具体任务 默认情况下,管理节点自身也同时是工作节点 每个工作节点上运行代理( agent )来汇报任务完成情况。用户可以通过 docker node promote 命令来提升一个工作节点为管理节点;或者通过docker node demote 命令来将一个管理节点降级为工作节点

 

3.服务

服务( Se ice )是 Docker 支持复杂多容器协作场景的利器。一个服务可以由若干个任务组成,每个任务为某个具体的应用 服务还包括对应的存储、网络、端口映射、副本个数、访问配置、升级配置等附加参数。

一般来说,服务需要面向特定的场景,例如一个典型的 Web 服务可能包括前端应用、后端应用,以及数据库等,这些应用都属于该服务的管理范畴。

Swarm 集群中服务类型也分为两种(可以通过-mode 指定):

第一种:复制服务( replicated services )模式:默认模式,每个任务在集群中会存在若干副本,

这些副本会被管理节点按照调度策略分发到集群中的工作节点上,此模式下可以使用–replicas 参数设置副本数量。

第二种:全局服务( global services )模式 调度器将在每个可用节点都执行一个相同的任务。该模式适合运行节点的检查,如监控应用等

 

4.任务

任务是 Swarm 集群中最小的调度单位,即一个指定的应用容器。例如仅仅运行前端业务的前端容器 任务从生命周期上将可能处于创建( NEW)、等待( PENDING)、分配( ASSIGNED )、接受( ACCEPTED )、准备( PREPARING )、开始( STARTING )、运行(RUNNING)、完成(COMPLETE )、失败(FAILED )、关闭( SHUTDOWN)、 拒绝(REJECTED)、孤立(ORPHANED )等不同状态。

Swarm 集群中的管理节点会按照调度要求将任务分配到工作节点上。例如指定副本为2时,可能会被分配到两个不同的工作节点上。一旦当某个任务被分配到 一个工作节点,将无法被转移到另外的 作节点,即 Swarm 中的任务不支持迁移。

 

5.服务的外部访问

Swarm 集群中的服务要被集群外部访问,必须要能允许任务的响应端口映射出来。

Swarm 中支持入口负载均衡( ingress load baancing )的映射模式,该模式下,每个服务都会被分配一个公开端口( PublishedPort ),该端口在集群中任意节点上都可以访问到,并被保留给该服务。

当有请求发送到任意节点的公开端口时,该节点若并没有实际执行服务相关的容器,则会通过路由机制将请求转发给实际执行了服务容器的工作节点。

 

使用 Swarm

 

用户在安装 Docker 1.12 更新的版本后 ,即可直接尝试 Swarm 模式的相关功能。假定分别准备两个 Linux 主机,作为管理节点(实际上也同时具备 作节点功能)和工作节点。

下面来演示 Swarm 集群的主要操作,包括:

  1. swarm init :            在管理节点上 建一个集群;
  2. node list :                  列出集群中的节点信息;
  3. swarm join                加入一个新的节点到已有集群中;
  4. swarm update :     更新一个 Swar 集群;
  5. swarm leave :         离开 Swarm 集群

此外,还可以使用 docker service 命令部署 Docker 应用服务到集群中;

1.创建集群

[root@ken1 ~]# docker swarm init  --advertise-addr 192.168.64.4
Swarm initialized: current node (70k014efwg9fiwsy8x83qm5g2) is now a manager.

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

    docker swarm join --token SWMTKN-1-0uunq2g8r48b2bm47b9x5xqmkhmzesoi9grwjroh4y3w5q9yek-5jalfma30b0bx36lyxs09ppw8 192.168.64.4:2377

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

 

注意返回的 token 串,这是集群的唯 id 加人集群的各个节点将需要这个信息。另外,默认的管理服务端口为 2377 ,需要能被工作节点访问到;另外,为了支持集群的成员发现和外部服务映射,还需要再所有节点上开启 7946 TCP/UDP 端口和 4789 UDP 端口。

 

2.查看集群信息

 

[root@ken1 ~]# docker info
...
 Swarm: active
  NodeID: 70k014efwg9fiwsy8x83qm5g2
  Is Manager: true
  ClusterID: l7dgzb3ec2uwcpimjktv5gs33
  Managers: 1
  Nodes: 1
  Default Address Pool: 10.0.0.0/8  
  SubnetSize: 24
  Data Path Port: 4789
  Orchestration:
   Task History Retention Limit: 5
...

 

还可以查看集群中已经加入的节点情况,此时只有 个管理节点:

[root@ken1 ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
70k014efwg9fiwsy8x83qm5g2 *   ken1                Ready               Active              Leader              19.03.2

 

3.加入集群

在所有要加入集群的普通节点上面执行 warm joi 口命令,表示把这台机器加入指定集群当中,例如,在工作节点上,将其加入刚创建的集群, 则可以通过:

[root@ken2 ~]# docker swarm join --token SWMTKN-1-0uunq2g8r48b2bm47b9x5xqmkhmzesoi9grwjroh4y3w5q9yek-5jalfma30b0bx36lyxs09ppw8 192.168.64.4:2377
This node joined a swarm as a worker.

 

此时,在管理节点上再次查看集群中节点情况,可以看到新加入的工作节点:

[root@ken1 ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
70k014efwg9fiwsy8x83qm5g2 *   ken1                Ready               Active              Leader              19.03.2
2uah6pnxtntaim4kfyzal5enn     ken2                Ready               Active                                  19.03.2

 

4.使用集群服务

那么,怎么使用 Swarm 提供的服务呢?

实际上有两种方法,一种是使用 Docker 原来的客户端命令,只要指定使用 Swarm manager 务的监昕地址即可 例如, manager 服务监听的地址为 manager ip:2377 ,则可以通过指定–<manager ip >:2377 选项来继续使用 Docker 客户端,执行任意 Docker 命令,例如 ps、info、run等

另外一种方法,也是推荐的做法,是使用新的 docker ervice 命令,可以获得包括多主机网络等更高级的特性支持。

建好 Swarm 集群后,可以在管理节点上执行如下命令来快速创建一个应用服务,并制定服务的复制份数为2, 如下命令所示,默认会自动检查确认服务状态都正常:

[root@ken1 ~]# docker service create --replicas 2 --name busybox1 busybox  sleep 5000
xojgs96mpw17tgowr445t82p5
overall progress: 2 out of 2 tasks 
1/2: running   [==================================================>] 
2/2: running   [==================================================>] 
verify: Service converged 

 

1.查看服务

此时使用 service ls 查看集群中服务情况,会发现新创建的busybox1服务;

[root@ken1 ~]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
xojgs96mpw17        busybox1            replicated          2/2                 busybox:latest     

 

还可通过service inspect 命令来查看服务的具体信息:

[root@ken1 ~]# docker inspect busybox1
[
    {
        "ID": "xojgs96mpw17tgowr445t82p5",
        "Version": {
            "Index": 16
        },
        "CreatedAt": "2019-09-17T14:46:57.080074484Z",
        "UpdatedAt": "2019-09-17T14:46:57.080074484Z",
        "Spec": {
            "Name": "busybox1",
            "Labels": {},
            "TaskTemplate": {
                "ContainerSpec": {
                    "Image": "busybox:latest@sha256:fe301db49df08c384001ed752dff6d52b4305a73a7f608f21528048e8a08b51e",
                    "Args": [
                        "sleep",
                        "5000"
                    ],
                    "Init": false,
                    "StopGracePeriod": 10000000000,
                    "DNSConfig": {},
                    "Isolation": "default"
                },
                "Resources": {
                    "Limits": {},
                    "Reservations": {}
                },
                "RestartPolicy": {
                    "Condition": "any",
                    "Delay": 5000000000,
                    "MaxAttempts": 0
                },
                "Placement": {
                    "Platforms": [
                        {
                            "Architecture": "amd64",
                            "OS": "linux"
                        },
                        {
                            "OS": "linux"
                        },
                        {
                            "OS": "linux"
                        },
                        {
                            "OS": "linux"
                        },
                        {
                            "Architecture": "arm64",
                            "OS": "linux"
                        },
                        {
                            "Architecture": "386",
                            "OS": "linux"
                        },
                        {
                            "Architecture": "ppc64le",
                            "OS": "linux"
                        },
                        {
                            "Architecture": "s390x",
                            "OS": "linux"
                        }
                    ]
                },
                "ForceUpdate": 0,
                "Runtime": "container"
            },
            "Mode": {
                "Replicated": {
                    "Replicas": 2
                }
            },
            "UpdateConfig": {
                "Parallelism": 1,
                "FailureAction": "pause",
                "Monitor": 5000000000,
                "MaxFailureRatio": 0,
                "Order": "stop-first"
            },
            "RollbackConfig": {
                "Parallelism": 1,
                "FailureAction": "pause",
                "Monitor": 5000000000,
                "MaxFailureRatio": 0,
                "Order": "stop-first"
            },
            "EndpointSpec": {
                "Mode": "vip"
            }
        },
        "Endpoint": {
            "Spec": {}
        }
    }
]

 

同时 ,管理节点和工作节点上都运行了一个容器

[root@ken1 ~]# docker service ps busybox1
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
sbintlu2r2xv        busybox1.1          busybox:latest      ken2                Running             Running 2 minutes ago                       
fantjwn1sx5h        busybox1.2          busybox:latest      ken1                Running             Running 2 minutes ago        

 

2.扩展服务

用户还可以通过 docker service scale <SERVICE-ID>=<NUMBER-OF-TASKS>命令来对服务进行伸缩, 例如将服务复制个数从 改为 1:

[root@ken1 ~]# docker service scale busybox1=1
busybox1 scaled to 1
overall progress: 1 out of 1 tasks 
1/1: running   [==================================================>] 
verify: Service converged 

 

查看服务

[root@ken1 ~]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
xojgs96mpw17        busybox1            replicated          1/1                 busybox:latest   

 

3.删除服务

服务使用完成后可以通过 docker service rm <SERVICE-ID> 命令来进行删除,服务命令更多的参数可以通过 docker service help 进行查看

[root@ken1 ~]# docker service rm busybox1
busybox1
[root@ken1 ~]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS

 

4.使用外部服务地址

Swarm 通过路由机制支持服务对外映射到指定端口,该端口可 以在集群中任意节点上进行访问,即使该节点上没有运行服务实例 需要在创建服务时使用–publish 参数:

[root@ken1 ~]# docker service create --name nginx --publish published=80,target=80 nginx
fwbclecrj9es6yu64ttflb7fa
overall progress: 1 out of 1 tasks 
1/1: running   [==================================================>] 
verify: Service converged 

 

查看服务

[root@ken1 ~]# docker service ps nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
s49uxbq8gxix        nginx.1             nginx:latest        ken1                Running             Running 47 seconds ago            

 

可以发现在ken1节点和ken2节点都开启了80端口,在浏览器可以指定任意一个节点IP都可以访问。

ken1节点

[root@ken1 ~]# ss -tnl
State      Recv-Q Send-Q                      Local Address:Port                                     Peer Address:Port              
LISTEN     0      128                                     *:22                                                  *:*                  
LISTEN     0      100                             127.0.0.1:25                                                  *:*                  
LISTEN     0      128                                    :::2377                                               :::*                  
LISTEN     0      128                                    :::7946                                               :::*                  
LISTEN     0      128                                    :::80                                                 :::*                  
LISTEN     0      128                                    :::22                                                 :::*                  
LISTEN     0      100                                   ::1:25                                                 :::*         

 

ken2节点

[root@ken2 ~]# ss -tnl
State      Recv-Q Send-Q                      Local Address:Port                                     Peer Address:Port              
LISTEN     0      128                                     *:22                                                  *:*                  
LISTEN     0      100                             127.0.0.1:25                                                  *:*                  
LISTEN     0      128                                    :::7946                                               :::*                  
LISTEN     0      128                                    :::80                                                 :::*                  
LISTEN     0      128                                    :::22                                                 :::*                  
LISTEN     0      100                                   ::1:25                                                 :::*  

 

之后,用户访问集群中任意节点的,都会被 Swarm 的负载均衡器代理到对应的服务实例。用户也可以配置独立的负载均衡服务,后端指向集群中各个节点对应的外部端口,获取高可用特性。

 

5.离开集群

节点可以在任何时候通过 warm leave 命令离开一个集群 命令格式为 docker swarm leave [OPT ONS ], 支持-f ,–force意味着强制离开集群.

 

使用服务命令

 

Swarm 提供了对应用服务的良好的支持,使用 Swarm 集群可以充分满足应用服务可扩展、高可用的需求。 Docker 通过 servic 命令来管理应用服务,主要包括 create,inspect,logs,ls,ps,rm,rollback scale,update 等若干子命令

 

总结

用户可以将若Docker 主机节点组成的集群当作一个大的虚拟 Docker 主机使用,并且,原先基于单机的Docker 应用,可以无缝地迁移到 Swarm 上来。通过使用服务, Swarm 集群可以支持多个应

用构建的复杂业务,并很容易对其进行升级等操作。在生产环境中, Swarm 管理节点要考虑高可用性和安全保护,一方面多个管理节点应该分配到不同的容灾区域,另一方面服务节点应该配合数字证书等手段限制访问。Swarm 功能已 经被无缝嵌入到了 Docker 1.12+版本中,用户今后可 直接使用 Docker命令来完成相关功能 配置,对 Swarm 集群的管理更加简便.

 

 

 

发表评论

电子邮件地址不会被公开。