查看原文
其他

容器技术|Docker三剑客之docker-swarm

霸都民工哥 民工哥技术之路 2019-05-10

接之前的文章:

容器技术|Docker三剑客之docker-machine

容器技术|Docker三剑客之Compose

docker-swarm简介

Swarm是Docker官方提供的一款集群管理工具,其主要作用是把若干台Docker主机抽象为一个整体,并且通过一个入口统一管理这些Docker主机上的各种Docker资源。Swarm和Kubernetes比较类似,但是更加轻,具有的功能也较kubernetes更少一些。
swarm集群提供给用户管理集群内所有容器的操作接口与使用一台Docker主机基本相同。
Swarm集群目前有两个版本:V1、V2

1、Swarm v1它是master-slave架构。需要通过服务发现来选举出管理节点,其它各个节点通过运行agent来接受管理节点的统一管理
2、Swarm v2集群是自动通过Raft协议分布式选举出管理节点,不需要配置发现服务,从而避免发现服务的单点故障问题。且它自带了DNS负载均衡和对外部负载均衡机制的支持

Swarm的基本架构如下图所示

Swarm一些概念说明

  • 1、Swarm
    使用swarmkit嵌入docker Engine中的集群管理和编排功能。docker容器初始化启动的一种模式

  • 2、Node
    节点,是一个已加入到docker swarm集群中的一个容器实例。

  • 3、Service
    服务主要是在工作节点上执行任务,创建服务时,需要指定容器的镜像。

  • 4、Task
    任务是在容器中执行的命令

Swarm 工作方式

  • 1、节点

  • 2、服务、任务、容器

  • 3、任务与调度

  • 4、服务副本与全局服务

Swarm 调度策略

Swarm在scheduler节点(leader 节点)运行容器的时候,会根据指定的策略来计算最适合运行容器的节点,目前支持的策略有:spread, binpack, random.
1)Random
顾名思义,就是随机选择一个 Node 来运行容器,一般用作调试用,spread 和 binpack 策略会根据各个节点的可用的 CPU, RAM 以及正在运行的容器的数量来计算应该运行容器的节点。
2)Spread
在同等条件下,Spread 策略会选择运行容器最少的那台节点来运行新的容器,binpack 策略会选择运行容器最集中的那台机器来运行新的节点。使用 Spread 策略会使得容器会均衡的分布在集群中的各个节点上运行,一旦一个节点挂掉了只会损失少部分的容器。
3)Binpack
Binpack 策略最大化的避免容器碎片化,就是说 binpack 策略尽可能的把还未使用的节点留给需要更大空间的容器运行,尽可能的把容器运行在一个节点上面。

Swarm Cluster模式的特性

1)批量创建服务
建立容器之前先创建一个 overlay 的网络,用来保证在不同主机上的容器网络互通的网络模式
2)强大的集群的容错性
当容器副本中的其中某一个或某几个节点宕机后,cluster 会根据自己的服务注册发现机制,以及之前设定的值–replicas n,在集群中剩余的空闲节点上,重新拉起容器副本。整个副本迁移的过程无需人工干预,迁移后原本的集群的 load balance 依旧好使!
不难看出,docker service 其实不仅仅是批量启动服务这么简单,而是在集群中定义了一种状态。Cluster 会持续检测服务的健康状态并维护集群的高可用性。
3)服务节点的可扩展性
Swarm Cluster不光只是提供了优秀的高可用性,同时也提供了节点弹性扩展或缩减的功能。当容器组想动态扩展时,只需通过 scale参数即可复制出新的副本出来。仔细观察的话,可以发现所有扩展出来的容器副本都 run 在原先的节点下面,如果有需求想在每台节点上都 run 一个相同的副本,方法其实很简单,只需要在命令中将”–replicas n”更换成”–mode=global”即可!复制服务(–replicas n)将一系列复制任务分发至各节点当中,具体取决于您所需要的设置状态,例如“–replicas 3”。全局服务(–mode=global)适用于集群内全部可用节点上的服务任务,例如“–mode global”。如果大家在 Swarm 集群中设有 7 台 Docker 节点,则全部节点之上都将存在对应容器。
4)调度机制
所谓的调度其主要功能是 cluster 的 server 端去选择在哪个服务器节点上创建并启动一个容器实例的动作。它是由一个装箱算法和过滤器组合而成。每次通过过滤器(constraint)启动容器的时候,swarm cluster 都会调用调度机制筛选出匹配约束条件的服务器,并在这上面运行容器。

Swarm cluster的创建过程

  • 1)发现 Docker 集群中的各个节点,收集节点状态、角色信息,并监视节点状态的变化

  • 2)初始化内部调度(scheduler)模块

  • 3)创建并启动 API 监听服务模块
    一旦创建好这个 cluster,就可以用命令 docker service 批量对集群内的容器进行操作,在启动容器后,docker 会根据当前每个 swarm 节点的负载判断,在负载最优的节点运行这个 task 任务,用”docker service ls” 和”docker service ps + taskID”可以看到任务运行在哪个节点上。容器启动后,有时需要等待一段时间才能完成容器创建。

Swarm命令行说明

docker swarm:集群管理
init          #初始化集群
join          #将节点加入集群
join-token    #管理加入令牌
leave         #从集群中删除某个节点,强制删除加参数--force 
update        #更新集群
unlock        #解锁集群

docker node:节点管理,
demote      #将集群中一个或多个节点降级
inspect     #显示一个或多个节点的详细信息
ls          #列出集群中的节点
promote     #将一个或多个节点提升为管理节点
rm          #从集群中删除停止的节点,--force强制删除参数
ps          #列出一个或多个节点上运行的任务
update      #更新节点

docker service:服务管理,
create      #创建一个新的服务
inspect     #列出一个或多个服务的详细信息
ps          #列出一个或多个服务中的任务信息
ls          #列出服务
rm          #删除一个或多个服务
scale       #扩展一个或多个服务
update      #更新服务

docker stack/deploy:试验特性,用于多应用部署

安装布署swarm集群服务

1、修改主机名,配置hosts文件
[root@manager ~]# cat >>/etc/hosts<<EOF
192.168.22.177 manager
192.168.22.175 node1
192.168.22.178 node2
EOF
[root@manager ~]# tail -3 /etc/hosts
192.168.22.177 manager
192.168.22.175 node1
192.168.22.178 node2
[root@manager ~]# ping node1
PING node1 (192.168.22.175) 56(84) bytes of data.
64 bytes from node1 (192.168.22.175): icmp_seq
=1 ttl=64 time=3.64 ms
64 bytes from node1 (192.168.22.175): icmp_seq=2 ttl=64 time=1.64 ms
^C
--- node1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1006ms
rtt min/avg/max/mdev = 1.648/2.644/3.641/0.997 ms
[root@manager ~]# ping node2
PING node2 (192.168.22.178) 56(84) bytes of data.
64 bytes from node2 (192.168.22.178): icmp_seq
=1 ttl=64 time=9.70 ms
64 bytes from node2 (192.168.22.178): icmp_seq=2 ttl=64 time=1.95 ms
^C
--- node2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1003ms
rtt min/avg/max/mdev = 1.951/5.826/9.701/3.875 ms
#node1 node2配置同上一致即可
2、安装docker环境

具体安装过程参考前面的文章

配置docker

[root@manager ~]# vim /etc/sysconfig/docker
# /etc/sysconfig/docker

# Modify these options if you want to change the way the docker daemon runs
OPTIONS='-H 0.0.0.0:2375 -H unix:///var/run/docker.sock --selinux-enabled --log-driver=journald --signature-verification=false'
#所有节点加上上面标记的部分,开启2375端口

[root@manager ~]# systemctl restart docker
[root@manager ~]# ps -ef|grep docker
root      11981      1  1 10:55 ?        00:00:00 /usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --init-path=/usr/libexec/docker/docker-init-current --seccomp-profile=/etc/docker/seccomp.json -H 0.0.0.0:2375 -H unix:///var/run/docker.sock --selinux-enabled --log-driver=journald --signature-verification=false --storage-driver overlay2
root      11986  11981  0 10:55 ?        00:00:00 /usr/bin/docker-containerd-current -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --shim docker-containerd-shim --runtime docker-runc --runtime-args --systemd-cgroup=true
root      12076  11823  0 10:55 pts/0    00:00:00 grep --color=auto docker
[root@manager ~]# lsof -i :2375
COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
dockerd-c 11981 root    5u  IPv6  41829      0t0  TCP *:2375 (LISTEN)
3、所有节点下载swarm镜像文件
[root@manager ~]# docker pull swarm
Using default tag: latest
Trying to pull repository docker.io/library/swarm ... 
latest: Pulling from docker.io/library/swarm
d85c18077b82: Pull complete 
1e6bb16f8cb1: Pull complete 
85bac13497d7: Pull complete 
Digest: sha256:406022f04a3d0c5ce4dbdb60422f24052c20ab7e6d41ebe5723aa649c3833975
Status: Downloaded newer image for docker.io/swarm:latest
[root@manager ~]# docker images
REPOSITORY       TAG      IMAGE ID      CREATED      SIZE
docker.io/swarm  latest   ff454b4a0e84  12 days ago  12.7 MB
4、创建swarm并初始化
[root@manager ~]# docker swarm init --advertise-addr 192.168.22.177
Swarm initialized: current node (elyfa6h1lx5o2s98une5vas4x) is now a manager.

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

    docker swarm join \
    --token SWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya \
    192.168.22.177:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
#执行上面的命令后,当前的服务器就加入到swarm集群中,同时会产生一个唯一的token值,其它节点加入集群时需要用到这个token。
#--advertise-addr 表示swarm集群中其它节点使用后面的IP地址与管理节点通讯,上面也提示了其它节点如何加入集群的命令。
5、查看下当前的信息
[root@manager ~]# docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 1
Server Version: 1.13.1
Storage Driver: overlay2
 Backing Filesystem: xfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: journald
Cgroup Driver: systemd
Plugins: 
 Volume: local
 Network: bridge host macvlan null overlay
**Swarm: active
 NodeID: elyfa6h1lx5o2s98une5vas4x
 Is Manager: true
 ClusterID: vi716cgvw33gzicrfqopasf9p
 Managers: 1
 Nodes: 1
 Orchestration:
  Task History Retention Limit: 5
 Raft:
  Snapshot Interval: 10000
  Number of Old Snapshots to Retain: 0
  Heartbeat Tick: 1
  Election Tick: 3
 Dispatcher:
  Heartbeat Period: 5 seconds
 CA Configuration:
  Expiry Duration: 3 months
 Node Address: 192.168.22.177
 Manager Addresses:
  192.168.22.177:2377
Runtimes: docker-runc runc
Default Runtime: docker-runc
Init Binary: /usr/libexec/docker/docker-init-current
containerd version:  (expected: aa8187dbd3b7ad67d8e5e3a15115d3eef43a7ed1)
runc version: e9c345b3f906d5dc5e8100b05ce37073a811c74a (expected: 9df8b306d01f59d3a8029be411de015b7304dd8f)
init version: 5b117de7f824f3d3825737cf09581645abbe35d4 (expected: 949e6facb77383876aeff8a6944dde66b3089574)
Security Options:
 seccomp
  WARNING: You're not using the default seccomp profile
  Profile: /etc/docker/seccomp.json
Kernel Version: 3.10.0-693.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
Number of Docker Hooks: 3
CPUs: 1
Total Memory: 2.238 GiB
Name: manager
ID: 653Y:7CME:GFPW:35SX:IGZL:UJP7:YSPZ:4OMV:J4EV:Z6FS:WFW2:YYHS
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
WARNING: bridge-nf-call-ip6tables is disabled
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false
Registries: docker.io (secure)

[root@manager ~]# docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
elyfa6h1lx5o2s98une5vas4x *  manager   Ready   Active        Leader
#当前节点的信息,这个*表示当前连接在这个节点上
6、将node1,node2加入到集群中
[root@node1 ~]#  docker swarm join --token SWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya 192.168.22.177:2377
This node joined a swarm as a worker.
[root@node2 ~]# docker swarm join --token SWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya 192.168.22.177:2377
This node joined a swarm as a worker.
#如果加入集群时报错如下
[root@node1 ~]#  docker swarm join --token SWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya  192.168.22.177:2377
Error response from daemon: rpc error: code = 13 desc = connection error: desc = "transport: x509: certificate has expired or is not yet valid"
#注意服务器时间同步问题,解决即可。
7、管理节点查看集群节点状态
[root@manager ~]# docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
elyfa6h1lx5o2s98une5vas4x *  manager   Ready   Active        Leader
tcuv2p8wd6rvmwg39pdav5ozk    node1     Ready   Active        
twytwc5dlp77vu1b7cakks9w2    node2     Ready   Active  
#swarm集群中node的AVAILABILITY状态有两种:Active、drain。其中actice状态的节点可以接受管理节点的任务指派;drain状态的节点会结束任务,也不会接受管理节点的任务指派,节点处于下线状态。

[root@manager ~]# docker node update --availability drain node2
node2
[root@manager ~]# docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
elyfa6h1lx5o2s98une5vas4x *  manager   Ready   Active        Leader
tcuv2p8wd6rvmwg39pdav5ozk    node1     Ready   Active        
twytwc5dlp77vu1b7cakks9w2    node2     Ready   Drain  
[root@manager ~]# docker node update --availability active node2
node2
[root@manager ~]# docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
elyfa6h1lx5o2s98une5vas4x *  manager   Ready   Active        Leader
tcuv2p8wd6rvmwg39pdav5ozk    node1     Ready   Active        
twytwc5dlp77vu1b7cakks9w2    node2     Ready   Active 

#在manager节点上查看状态信息
[root@manager ~]# docker node inspect self
[
    {
        "ID": "elyfa6h1lx5o2s98une5vas4x",
        "Version": {
            "Index": 9
        },
        "CreatedAt": "2018-06-14T15:01:19.850821157Z",
        "UpdatedAt": "2018-06-14T15:01:20.472379584Z",
        "Spec": {
            "Role": "manager",
            "Availability": "active"
        },
        "Description": {
            "Hostname": "manager",
            "Platform": {
                "Architecture": "x86_64",
                "OS": "linux"
            },
            "Resources": {
                "NanoCPUs": 1000000000,
                "MemoryBytes": 2402566144
            },
            "Engine": {
                "EngineVersion": "1.13.1",
                "Plugins": [
                    {
                        "Type": "Network",
                        "Name": "bridge"
                    },
                    {
                        "Type": "Network",
                        "Name": "host"
                    },
                    {
                        "Type": "Network",
                        "Name": "macvlan"
                    },
                    {
                        "Type": "Network",
                        "Name": "null"
                    },
                    {
                        "Type": "Network",
                        "Name": "overlay"
                    },
                    {
                        "Type": "Volume",
                        "Name": "local"
                    }
                
]
            }
        },
        "Status": {
            "State""ready",
            "Addr""127.0.0.1"
        },
        "ManagerStatus": {
            "Leader"true,
            "Reachability""reachable",
            "Addr""192.168.22.177:2377"
        }
    }
]

Swarm 的Web管理

[root@manager ~]# docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
Unable to find image 'portainer/portainer:latest' locally
Trying to pull repository docker.io/portainer/portainer ... 
latest: Pulling from docker.io/portainer/portainer
d1e017099d17: Pull complete 
0d90a7ef0797: Pull complete 
Digest: sha256:2933caa6e578e94b5d91429ea7f47ae9741ee11b71d7cb740e76c5f234cc1d87
Status: Downloaded newer image for docker.io/portainer/portainer:latest
798b3bea009792321519f5b7144e357ce9c5cea3b9341b5276a4d29f7571684a
[root@manager ~]# docker ps
CONTAINER ID  IMAGE                 COMMAND        CREATED        STATUS        PORTS                    NAMES
798b3bea0097  portainer/portainer   "/portainer"   6 seconds ago  Up 5 seconds  0.0.0.0:9000->9000/tcp   amazing_snyder

浏览器访问

docker-swarm布署服务

1、布署服务前创建于个用于集群内不同主机之间容器通信的网络
[root@manager ~]# docker network create -d overlay dockernet
pmn1fi6lj421hn1nk7652m41h
[root@manager ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
d913c7a275fe        bridge              bridge              local
c737cf269524        docker_gwbridge     bridge              local
pmn1fi6lj421        dockernet           overlay             swarm
eac1d68d35d7        host                host                local
wxshzhdvq52y        ingress             overlay             swarm
c5986aec6119        none                null                local
2、创建服务(nginx为例)
[root@manager ~]# docker service create --replicas 1 --network dockernet --name nginx-cluster -p 80:80 nginx
k7lupo9xu0cnd5ng1g4f7i7jx
#--replicas 指定副本数量
[root@manager ~]# docker service ls
ID            NAME           MODE        REPLICAS  IMAGE
k7lupo9xu0cn  nginx-cluster  replicated  1/1       nginx:latest
[root@manager ~]# docker service ps nginx-cluster
ID            NAME             IMAGE         NODE     DESIRED STATE  CURRENT STATE           ERROR  PORTS
7t7xjpmao533  nginx-cluster.1  nginx:latest  manager  Running        Running 17 seconds ago         
[root@manager ~]# docker ps
CONTAINER ID   IMAGE                                                                           COMMAND                  CREATED             STATUS              PORTS     NAMES
a9d78079fdc7  nginx@sha256:3e2ffcf0edca2a4e9b24ca442d227baea7b7f0e33ad654ef1eb806fbd9bedcf0   "nginx -g 'daemon ..."   22 seconds ago      Up 22 seconds       80/tcp     nginx-cluster.1.7t7xjpmao5335zaa8wp0c896a
3、在线动态扩容服务
[root@manager ~]# docker service scale nginx-cluster=5
nginx-cluster scaled to 5
[root@manager ~]# docker service ps nginx-cluster
ID            NAME             IMAGE         NODE     DESIRED STATE  CURRENT STATE            ERROR  PORTS
7t7xjpmao533  nginx-cluster.1  nginx:latest  manager  Running        Running 2 hours ago             
vitsgxpdf3bn  nginx-cluster.2  nginx:latest  manager  Running        Running 2 seconds ago           
o9w529mmttsw  nginx-cluster.3  nginx:latest  node1    Running        Preparing 2 seconds ago         
cfz8dkx9p6ih  nginx-cluster.4  nginx:latest  node2    Running        Preparing 2 seconds ago         
9p35iunijoro  nginx-cluster.5  nginx:latest  node2    Running        Preparing 2 seconds ago    
#从输出结果可以看出已经将服务动态扩容至5个,也就是5个容器运行着相同的服务
[root@node2 ~]# docker ps
CONTAINER ID   IMAGE                                                                           COMMAND                  CREATED         STATUS        PORTS   NAMES
f3a4fb24480a   nginx@sha256:3e2ffcf0edca2a4e9b24ca442d227baea7b7f0e33ad654ef1eb806fbd9bedcf0   "nginx -g 'daemon ..."   3 minutes ago   Up 3 minutes  80/tcp  nginx-cluster.5.9p35iunijorol1d2ikhyj11oi
f8b0b2e514eb   nginx@sha256:3e2ffcf0edca2a4e9b24ca442d227baea7b7f0e33ad654ef1eb806fbd9bedcf0   "nginx -g 'daemon ..."   3 minutes ago   Up 3 minutes  80/tcp  nginx-cluster.4.cfz8dkx9p6ih40lwwwvd96xdg
#登录node2查看正在运行的容器,发现与管理节点上显示的结果相同,node2上运行两个容器
4、节点故障
[root@manager ~]docker service ps nginx-cluster
ID            NAME                 IMAGE         NODE     DESIRED STATE  CURRENT STATE           ERROR                             PORTS
7t7xjpmao533  nginx-cluster.1      nginx:latest  manager  Running        Running 2 hours ago                                       
vitsgxpdf3bn  nginx-cluster.2      nginx:latest  manager  Running        Running 10 minutes ago                                    
f13cun1wyxlt  nginx-cluster.3      nginx:latest  manager  Running        Running 9 minutes ago                                     
q60fo5mja1ab   \_ nginx-cluster.3  nginx:latest  node1    Shutdown       Failed 9 minutes ago    "starting container failedsh…"  
mao4htxp7afr   \_ nginx-cluster.3  nginx:latest  node1    Shutdown       Failed 9 minutes ago    "starting container failedsh…"  
fhiecco742y4   \_ nginx-cluster.3  nginx:latest  node1    Shutdown       Failed 10 minutes ago   "starting container failedsh…"  
8qp5kryo62ha   \_ nginx-cluster.3  nginx:latest  node1    Shutdown       Failed 10 minutes ago   "starting container failedsh…"  
cfz8dkx9p6ih  nginx-cluster.4      nginx:latest  node2    Running        Running 9 minutes ago                                     
9p35iunijoro  nginx-cluster.5      nginx:latest  node2    Running        Running 9 minutes ago  
#如果集群中节点发生故障,会从swarm集群中被T除,然后利用自身的负载均衡及调度功能,将服务调度到其它节点上
5、其它常用命令介绍

除了上面使用scale来实现在线动态扩容、缩容之外,还可以使用update来对服务进行调整

[root@manager ~]# docker service ls
ID            NAME           MODE        REPLICAS  IMAGE
k7lupo9xu0cn  nginx-cluster  replicated  5/5       nginx:latest
[root@manager ~]# docker service update --replicas 2 nginx-cluster
nginx-cluster
[root@manager ~]# docker service ls
ID            NAME           MODE        REPLICAS  IMAGE
k7lupo9xu0cn  nginx-cluster  replicated  2/2       nginx:latest
#将服务缩减到2个

[root@manager ~]# docker service update --image nginx:new nginx-cluster
#更新服务的镜像版本

[root@manager ~]# docker service --help 

Usage:    docker service COMMAND

Manage services

Options:
      --help   Print usage

Commands:
  create      Create a new service
  inspect     Display detailed information on one or more services
  ls          List services
  ps          List the tasks of a service
  rm          Remove one or more services
  scale       Scale one or multiple replicated services
  update      Update a service

Run 'docker service COMMAND --help' for more information on a command.
[root@manager ~]# docker rm nginx-cluster
#将所有节点上的所有容器全部删除,任务也将全部删除

推荐阅读

聊几个与赚钱相关的小事情

史上最详细、最全面的Hadoop环境搭建

MySQL太慢?试试这些诊断思路和工具

Jenkins与Docker的自动化CI/CD实战

2018互联网科技公司中秋月饼大PK,福利争霸

送你 8 张图,好好理解一下。

·end·

—写文不易,你的转发就是对我最大的支持—

我们一起愉快的玩耍吧

目前40000+人已关注加入我们

       

       

关注公众号点击菜单“微信群” 入群一起交流吧!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存